PHP 利用 curl 转发接口遇到的问题

2023-02-09  本文已影响0人  VioletJack

今天又一次捡起了老 PHP 项目来维护,遇到需要转发 Java 项目后端接口的需求。

接口转发

   private function _req_data ($path, $params = null) {
      $url =  $this->rootUrl . $path;
      if ($params) {
          $first = true;
          foreach ($params as $k => $v) {
              if ($first) {
                  $url .= '?';
                  $first = false;
              } else {
                  $url .= '&';
              }

              $url .= "$k=$v";
          }
      }
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_TIMEOUT,60);
      $output = json_decode(curl_exec($ch), true);
      curl_close($ch);

      if (!isset($output['code'])) {
          throw  new Exception("no code in datasvc resp");
      }

      if ($output['code'] != 200) {
          throw  new Exception("bad code in datasvc resp " . $output['code'] . " " . $output['message']);
      }

      return $output['data'];
    }

CSV 下载

其中有一个接口是下载表格文件的,直接用上面的接口必然出错。于是新建了接口干了两件事:

  1. 将 JSON 解析的行为去掉
  2. 在返回响应的时候将 Content-Type 文件类型头改掉。
    private function _req_data_csv ($path, $params = null) {
      $url =  $this->rootUrl . $path;
      if ($params) {
          $first = true;
          foreach ($params as $k => $v) {
              if ($first) {
                  $url .= '?';
                  $first = false;
              } else {
                  $url .= '&';
              }

              $url .= "$k=$v";
          }
      }

      header('Content-Type: text/csv');
      header('Content-Disposition: attachment; filename=download.csv');

      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_TIMEOUT,60);
      $output = curl_exec($ch);
      $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);

      if (!($httpcode >= 200 && $httpcode < 400)) {
        Log::error("proxy_dsc error get " . $baseurl . " " . $httpcode . " " . $raw_output);
        return response(['msg' => '内部错误'], 500);
      }

      return $output;
    }

中文字符转发异常

由于我们是 vue前端 => PHP后端 => Java后端 这个流程,所以我在 Vue 传过去的中文字符,到了 Java 这里变成了一串十六进制字符,解决方法是在 PHP 层转发的时候调用 urlencode() 函数

统一封装和使用

在 controller 中进行封装和使用。

 private function getCsData(Request $request, $path, $isCsv = false) {
      $reqCtx = $request->all();

      $params = [
          "game_id" => $reqCtx['game_id'],
          "date1" => $reqCtx['date1'],
          "date2" => $reqCtx['date2'],
      ];

      if (isset($reqCtx['add_or_reduce'])) {
          $params['add_or_reduce']  = urlencode($reqCtx['add_or_reduce']);
      }
      if (isset($reqCtx['money_types'])) {
          $params['money_types']  = urlencode($reqCtx['money_types']);
      }
      if (isset($reqCtx['vdesc'])) {
        $params['vdesc']  = urlencode($reqCtx['vdesc']); 
      }
      if (isset($reqCtx['zone_ids'])) {
          $params['zone_ids']  = urlencode($reqCtx['zone_ids']);
      }

      if ($isCsv) {
        return $this->_req_data_csv($path, $params);
      }
      return ['data' => $this->_req_data($path, $params)];
    }

    public function getCsTable(Request $request) {
      return $this->getCsData($request, '/api/v1/web/game/cs-live/table');
    }

    public function getCsTableCsv(Request $request) {
      return $this->getCsData($request, '/api/v1/web/game/cs-live/table/csv', true);
    }

思考

接口的转发其实就是进行了两次接口请求和响应的过程,所以在 PHP 层使用 curl 来发起的请求。

参考资料

上一篇下一篇

猜你喜欢

热点阅读