先说一个题外话:
银联支付接起来,相对有点麻烦,尤其是网上关于银联手机控件支付PHP后端的DEMO少之又少,今天接入银联手机空间支付发起请求的时候,报了个一个错误
{"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.请求方法:
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.异步通知回调(回调功能还没测试,测试后再来修改,先把代码写在这里)
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; } }