前面提到 微信创建支付分订单报错:“Http头缺少Accept或User-Agent” 解决,在解决了 $header 构建之后,对于处理请求返回数据犯了难。

正常情况下 CURL 返回数据是够用了的,但微信支付分将后续 验签 需要的签名部分信息存放到了响应头部中。这就需要对初始版的 CURL 请求(一般的 CURL 请求只返回响应 body 部分)做一定的修改。

参考 php CURL 请求头和响应头获取 - tianye_guazi ,自己写了一个 Http 请求类:

class Http
{

    // 
    public static function headerHandler($curl, $headerLine) {
        $len = strlen($headerLine);
        // HTTP响应头是以:分隔key和value的
        $split = explode(':', $headerLine, 2);
        if (count($split) > 1) {
            $key = trim($split[0]);
            $value = trim($split[1]);
            // 将响应头的key和value存放在全局变量里
            $GLOBALS['G_HEADER'][$key] = $value;
        }
        return $len;
    }

    public static function headerHandler2($headerStr) {

        // HTTP响应头是以:分隔key和value的
        $split = array_filter(explode(PHP_EOL, $headerStr), function($v) {
            return $v;
        });
        $headers = [];
        for ($i=0; $i < count($split); $i++) {
            $pair = explode(':', $split[$i], 2);
             // 舍弃掉 HTTP/1.1 200 OK
            if (!isset($pair[1])) {
                continue;
            }
            $headers[trim($pair[0])] = trim($pair[1]);
        }
        return $headers;
    }

    public static function PostWithHeaders($curlPost, $curlHeader, $url)
    {
        $curl = curl_init();
        // curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, true); // 同时返回响应头
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $curlHeader);
        // curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE); // 拿到请求头
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $curlPost);

        // curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerHandler"); // 设置header处理函数
        
        $return_str = curl_exec($curl);
        // $request_header = curl_getinfo($curl);


        // 获得响应结果里的:头大小
        $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        // 根据头大小去获取头信息内容
        $headerStr = substr($return_str, 0, $headerSize);
        $response_header = static::headerHandler2($headerStr);

        $response_body = json_decode(substr($return_str, $headerSize), true);

        // $curl_info = curl_getinfo($curl);


        curl_close($curl);
        return [
            'return_str' => $return_str,
            // 'request_header' => $request_header,
            'response_header_str' => $headerStr,
            'response_header' => $response_header,
            'response_body' => $response_body,
            // 'curl_info' => $curl_info,
        ];
    }

}

首先是 curl_setopt($curl, CURLOPT_HEADER, true); 将响应头信息与 body 部分一起返回。

之后就需要分离头部和 body。通过 curl_getinfo($curl, CURLINFO_HEADER_SIZE) 先拿到头部信息,再从整个返回字串中截取出 body 部分。headerHandler2 是将头部信息转化为数组,方便读取 Wechatpay-NonceWechatpay-SignatureWechatpay-TimestampWechatpay-Serial 验签需要的参数。