195 lines
6.4 KiB
PHP
195 lines
6.4 KiB
PHP
<?php
|
||
namespace BsPaySdk\core;
|
||
use BsPaySdk\config\MerConfig;
|
||
|
||
class BsPayRequestV2 {
|
||
# 请求头
|
||
private $httpHeaders;
|
||
# 网络应答码
|
||
private $httpStateCode;
|
||
# 请求数据
|
||
private $reqDatas;
|
||
# 应答数据
|
||
private $rspDatas;
|
||
|
||
# 请求报错
|
||
private $error = null;
|
||
|
||
public function curlRequest(MerConfig $merConfig, $url, $postFields = null, $file = null, $headers=null, $is_json=false) {
|
||
// $postFields['needSign'] 是否需要添加签名, $postFields['needVerfySign'] 是否需要验证签名
|
||
$needSign = isset($postFields['needSign']) ? $postFields['needSign'] : true;
|
||
$needVerfySign = isset($postFields['needVerfySign']) ? $postFields['needVerfySign'] : true;
|
||
unset($postFields['needSign'],$postFields['needVerfySign']);
|
||
BsPay::writeLog("curl方法参数:". json_encode(func_get_args(), JSON_UNESCAPED_UNICODE));
|
||
$ch = curl_init();
|
||
curl_setopt($ch, CURLOPT_URL, $url);
|
||
curl_setopt($ch, CURLOPT_FAILONERROR, false);
|
||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||
if (is_array($postFields) && 0 < count($postFields)) {
|
||
curl_setopt($ch, CURLOPT_POST, true);
|
||
|
||
$body = $this->createBody($merConfig, $postFields, $file);
|
||
if (!$needSign) {
|
||
unset($body['sign']);
|
||
}
|
||
if ($is_json) {
|
||
$json_data = json_encode($body);
|
||
BsPay::writeLog("post-json请求参数:" . json_encode($body, JSON_UNESCAPED_UNICODE));
|
||
array_push($headers, "Content-Length:" . strlen($json_data));
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
|
||
} else {
|
||
BsPay::writeLog("post-form请求参数:" . json_encode($body, JSON_UNESCAPED_UNICODE));
|
||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||
}
|
||
|
||
$this->reqDatas = $body;
|
||
}
|
||
|
||
# 拼装请求头
|
||
$this->httpHeaders = $this->createHeaders($headers);
|
||
BsPay::writeLog("curl请求头:". json_encode($this->httpHeaders, JSON_UNESCAPED_UNICODE));
|
||
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->httpHeaders);
|
||
|
||
# 执行网络请求
|
||
$resultString = curl_exec($ch);
|
||
|
||
# 处理系统的报错
|
||
if (curl_errno($ch)) {
|
||
$this->error = curl_error($ch);
|
||
BsPay::writeLog($this->error, "ERROR");
|
||
|
||
# 这里报错直接就关闭本次会话return了
|
||
curl_close($ch);
|
||
return $this;
|
||
}
|
||
|
||
# http应答码
|
||
$this->httpStateCode = curl_getinfo($ch,CURLINFO_HTTP_CODE);
|
||
|
||
# 关闭本次会话
|
||
curl_close($ch);
|
||
|
||
$this->rspDatas = json_decode($resultString, true);
|
||
BsPay::writeLog("curl返回参数:". $this->httpStateCode. " ". $resultString);
|
||
$resp_sign = isset($this->rspDatas['sign']) ? $this->rspDatas['sign'] : '';
|
||
|
||
# 不需要对应答数据验签的逻辑分支,斗拱存在一些不用验签的接口,例如:页面版的快捷支付、手机网页支等
|
||
if (!$resp_sign || $this->httpStateCode == 401) {
|
||
if ($needVerfySign) {
|
||
$this->error = array(
|
||
'code' => 'RESP_SIGN_VERIFY_UNDO',
|
||
'msg' => '无法对应答数据进行验签',
|
||
);
|
||
}
|
||
|
||
if (!$this->rspDatas) {
|
||
# 无法解析出json格式的情况,就直接就把应答数据返回出去,针对返回数据为html页面的接口,例如:页面版的快捷支付等
|
||
$this->rspDatas = $resultString;
|
||
}
|
||
return $this;
|
||
}
|
||
|
||
$resp_data = isset($this->rspDatas['data']) ? $this->rspDatas['data'] : '';
|
||
|
||
// TODO response 应答错误 hardcode 待优化 --- Charles.huang 2021/09/09
|
||
|
||
# 对返回数据验签失败的逻辑分支
|
||
if (!BsPayTools::verifySign_sort($resp_sign, $resp_data, $merConfig->rsa_huifu_public_key)) {
|
||
$this->error = array(
|
||
'code' => 'RESP_SIGN_VERIFY_FAILED',
|
||
'msg' => '接口结果返回签名验证失败',
|
||
);
|
||
return $this;
|
||
}
|
||
|
||
# 应答码异常情况
|
||
if ($this->httpStateCode < 200 || $this->httpStateCode >= 400) {
|
||
$this->error = array(
|
||
'code' => 'HTTP_REQUEST_FAILED',
|
||
'msg' => "请求失败: HTTP_STATE_CODE-".$this->httpStateCode,
|
||
);
|
||
return $this;
|
||
}
|
||
|
||
return $this;
|
||
}
|
||
|
||
private function createHeaders($header_data = array()){
|
||
$headers = $header_data;
|
||
if (empty($header_data)){
|
||
$headers = array('Content-type: application/x-www-form-urlencoded');
|
||
}
|
||
|
||
array_push($headers, 'sdk_version:' . SDK_VERSION);
|
||
array_push($headers, 'charset:UTF-8');
|
||
return $headers;
|
||
}
|
||
|
||
private function createBody(MerConfig $merChantConfig, $post_data, $file = null){
|
||
$body = array();
|
||
$body['sys_id'] = $merChantConfig->sys_id;
|
||
$body['product_id'] = $merChantConfig->product_id;
|
||
ksort($post_data); // 根据key排序
|
||
$body['data'] = $post_data;
|
||
# 执行签名
|
||
$sign = BsPayTools::sha_with_rsa_sign(
|
||
json_encode($post_data, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE), // 数据里有中文和斜杠都不转码
|
||
$merChantConfig->rsa_merch_private_key);
|
||
$body['sign'] = $sign;
|
||
if(!empty($file)){
|
||
$body['file'] = $file;
|
||
$body['data'] = json_encode($post_data, JSON_UNESCAPED_UNICODE);
|
||
}
|
||
return $body;
|
||
}
|
||
|
||
/**
|
||
* 本次请求的http头信息
|
||
*/
|
||
public function getHttpHeaders()
|
||
{
|
||
return $this->httpHeaders;
|
||
}
|
||
|
||
/**
|
||
* 本次请求应答的 http状态码
|
||
*/
|
||
public function getHttpStateCode()
|
||
{
|
||
return $this->httpStateCode;
|
||
}
|
||
|
||
/**
|
||
* 本次请求的数据
|
||
*/
|
||
public function getReqDatas()
|
||
{
|
||
return $this->reqDatas;
|
||
}
|
||
|
||
/**
|
||
* 本次请求的应答数据
|
||
*/
|
||
public function getRspDatas()
|
||
{
|
||
return $this->rspDatas;
|
||
}
|
||
|
||
/**
|
||
* 获取请求执行失败信息
|
||
*/
|
||
public function getErrorInfo()
|
||
{
|
||
return $this->error;
|
||
}
|
||
|
||
/**
|
||
* 请求是否成功执行
|
||
*/
|
||
public function isError()
|
||
{
|
||
return $this->error != null;
|
||
}
|
||
} |