一、拼建行支付URL获取支付参数
这一步本来是最简单的,但是里面有个mac参数,需要md5加密处理,但又未说明对哪些参数加密,造成多次测试失败
正确的url应该是:
$host = 'https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6&'; $string = 'MERCHANTID=00000&POSID=0000&BRANCHID=000&ORDERID=0000&PAYMENT=0.01&CURCODE=01&TXCODE=530590&REMARK1=&REMARK2=&TYPE=1&PUB=00000000&GATEWAY=0&CLIENTIP=127.0.0.1®INFO=&PROINFO=%u94bb%u77f3%u4f1a%u5458%u4f18%u60E0%u5927%u4fC3&REFERER=&TRADE_TYPE=MINIPRO&SUB_APPID=0000&SUB_OPENID=0000'; echo $host.$string."&MAC=".md5($string);
注意字符串里参数顺序一定要正确,顺序错了,一样得不到结果
二、回调数据
一般回调数据不是json就是xml之类的,建行的技术指导也是言之凿凿说是json数据,所以我使用
file_get_contents('php://input')
来接收数据,但这次建行搞的是直接post过来的是数组,搞得测试了很久,还怀疑域名地址有问题,最后使用laravel里接收参数的方式
request()->input();
获取的数组信息才算解决。
三、数据验签
验签的原因就是保存数据来源的正确性,不然万一有人知道你的回调地址,往你地址里post正确的参数信息,未支付的信息也能给你处理支付了,那可就亏大了
验签的方法,建行并没有详细说明,文档也是语焉不详,我也是各种百度查询资料,首先是参数参与签名运算的字符串有顺序,要按文档上说明的顺序来做,因为我收的数据是数组,所以刚开始使用的是http_build_query函数把接收的数组拼成字符串,如果你也和我一样接收的是数组,千万不要用这个方法,不然进坑半天出不来,因为这个函数有个弊端,如果有数组里的值是null的话,这个数组里的key是不会组成字符串里的参数的,而建行支付要求字符串里参数即使是为空,也要参与到验签的,所以自己写个循环,拼接字符串
$http_build_query = ''; foreach ($inputMsg as $key => $value) { $http_build_query .= $key.'='.$value."&"; } $http_build_query = trim($http_build_query,'&');
最后验签的核心代码如下:
$key = '你的公钥'; $data = 'POSID=000&BRANCHID=000&ORDERID=000&PAYMENT=0.01&CURCODE=01&REMARK1=&REMARK2=&ACC_TYPE=WX&SUCCESS=Y&ACCDATE=20210730'; function checkSign($data, $key) { $sign = '你收到的建行发来的签名'; $pubkey = "-----BEGIN PUBLIC KEY----- " . wordwrap(base64_encode(Hex2String($key)), 64, " ", true) . " -----END PUBLIC KEY-----"; $pkeyId = openssl_pkey_get_public($pubkey); $verify = openssl_verify($data, Hex2String($sign), $pkeyId, OPENSSL_ALGO_MD5); openssl_free_key($pkeyId); return (bool) $verify; } function Hex2String($hex){ $string = ''; for ($i = 0; $i < strlen($hex) - 1; $i += 2) { $string .= chr(hexdec($hex[$i] . $hex[$i + 1])); } return $string; } if(!checkSign($data,$key)){ echo "bad"; }else{ echo "good"; }