先说一个题外话:
银联支付接起来,相对有点麻烦,尤其是网上关于银联手机控件支付PHP后端的DEMO少之又少,今天接入银联手机空间支付发起请求的时候,报了个一个错误
代码语言:javascript复制{"Invalid request.":""}
一直找不到问题原因,打印请求参数,才发现证书ID certId为null,但接入方法都是用的SDK上的DEMO,证书路径也都配对了,certId怎么会是null呢,一直找不到问题,后咨询了客服,客服给我发了一个图片,提示用错证书,我还再三向客服确认了是不是那几个证书,确认了问题,也知道报错原因后,决定自己研究SDK代码,后来终于找到了,我犯了一个很傻的错误,由于我用的是docker环境,证书路径居然是用的宿主机的证书路径,然后我把证书路径改为docker容器路径后,终于请求并验签成功了。
银联手机控件支付PHP端接入方法:
1.将下载的PHP SDK代码的sdk目录(PHP Version SDK/upacp_demo_app/sdk)拷贝到vendor/union目录下
2.将测试环境证书(PHP Version SDK/upacp_demo_app/assets/测试环境证书)复制到服务器上,正式环境用生产环境证书,生产环境证书有三个,外加一个入网签约时银联颁发的验签私钥证书
3.修改sdk配置文件(vendor/union/acp_sdk.ini)中的证书路径和地址等等
4.请求方法:
代码语言:javascript复制public function pay($orderNo, $money, $subject="订单描述")
{
$config = [
"callback" => "",
"merId" => "88888888",
];
$params = [
//以下信息非特殊情况不需要改动
'version' => SDKConfig::getSDKConfig()->version, //版本号
'encoding' => 'utf-8', //编码方式
'txnType' => '01', //交易类型
'txnSubType' => '01', //交易子类
'bizType' => '000201', //业务类型
//'frontUrl' => SDKConfig::getSDKConfig()->frontUrl, //前台通知地址
'backUrl' => $config['callback'], //后台通知地址
'signMethod' => SDKConfig::getSDKConfig()->signMethod, //签名方法
'channelType' => '08', //渠道类型,07-PC,08-手机
'accessType' => '0', //接入类型
'currencyCode' => '156', //交易币种,境内商户固定156
//TODO 以下信息需要填写
'orderDesc' => $subject, //订单描述
'merId' => $config['merId'], //商户代码,请改自己的测试商户号,此处默认取demo演示页面传递的参数
'orderId' => $orderNo, //商户订单号,8-32位数字字母,不能含“-”或“_”,此处默认取demo演示页面传递的参数,可以自行定制规则
'txnTime' => date('YmdHis'), //订单发送时间,格式为YYYYMMDDhhmmss,取北京时间,此处默认取demo演示页面传递的参数
'txnAmt' => $money*100, //交易金额,单位分,此处默认取demo演示页面传递的参数
];
AcpService::sign($params); //获取证书ID和签名
$url = SDKConfig::getSDKConfig()->appTransUrl; //获取银联请求地址
$result_arr = AcpService::post($params, $url);
if(count($result_arr)<=0) { //没收到200应答的情况
return "";
}
//验签通过,返回授权码给客户端
if(AcpService::validate($result_arr)){
return $result_arr['respCode'] == "00" ? $result_arr["tn"] : '';
}
}
5.异步通知回调(回调功能还没测试,测试后再来修改,先把代码写在这里)
代码语言:javascript复制public function notify(Request $request)
{
$post = $request->post();
$flag = $this->notify($post);
if($flag){
//处理订单信息,修改数据库订单支付状态
echo '302';
}
}
//验签
public function notify($post)
{
if(isset($post['signature'])){
$res = AcpService::validate($post);
$orderId = $post['orderId'];
$respCode = $post['respCode'];
//涉及到资金交易,需查询订单情况,这一点和支付宝、微信不同
return $this->query($orderId);
}
}
//查询订单交易状态
public function query($orderId)
{
$params = [
//以下信息非特殊情况不需要改动
'version' => SDKConfig::getSDKConfig()->version, //版本号
'encoding' => 'utf-8', //编码方式
'signMethod' => SDKConfig::getSDKConfig()->signMethod, //签名方法
'txnType' => '00', //交易类型
'txnSubType' => '00', //交易子类
'bizType' => '000000', //业务类型
'accessType' => '0', //接入类型
'channelType' => '08', //渠道类型
//TODO 以下信息需要填写
'orderId' => $orderId, //请修改被查询的交易的订单号,8-32位数字字母,不能含“-”或“_”,此处默认取demo演示页面传递的参数
'merId' => $this->merId, //商户代码,请改自己的测试商户号,此处默认取demo演示页面传递的参数
'txnTime' => date('YmdHis'), //请修改被查询的交易的订单发送时间,格式为YYYYMMDDhhmmss,此处默认取demo演示页面传递的参数
];
AcpService::sign ( $params ); // 签名
$url = SDKConfig::getSDKConfig()->singleQueryUrl;
$result_arr = AcpService::post($params, $url);
if(count($result_arr)<=0) { //没收到200应答的情况
return false;
}
if(AcpService::validate($result_arr)){
return $result_arr['respCode'] == "00" && $result_arr['origRespCode'] == "00" ? true : false;
}
}