最近有朋友需要在微信小程序内使用招商银行一网通支付,目前能支持的支付类型只有H5支付接口,所以记录下整个调试流程和调试过程可能出现的问题,写测试报告时需要注意的事项也记录下,以备以后需要时,可以及时找出,免踩坑。
微信小程序下H5支付,用户操作流程,小程序(小程序原生)内通过点击—》访问到提交订单页面(webview包含的订单外链页)-》跳转到一网通H5支付页面——》支付成功回到支付成功页面(webview包含的订单外链页)——》点击支付完成回到小程序页面(小程序原生)
一网通H5操作流程图
以下流程采用PHP进行调试和测试
先定义一个总配置数组
$config = [
'use_sandbox' => true, // 是否使用 招商测试系统
'branch_no' => 'xxxx', // 商户分行号,4位数字
'mch_id' => 'xxxx', // 商户号,6位数字
'mer_key' => '1234567890123456', // 秘钥16位,包含大小写字母 数字
// 招商的公钥,建议每天凌晨2:15发起查询招行公钥请求更新公钥。
'cmb_pub_key' => 'xxxx',
'op_pwd' => 'xxxxxx', // 操作员登录密码。
'sign_type' => 'SHA-256', // 签名算法,固定为“SHA-256”
'limit_pay' => 'A', // 允许支付的卡类型,默认对支付卡种不做限制,储蓄卡和信用卡均可支付 A:储蓄卡支付,即禁止信用卡支付
'notify_url' => 'http://cmb.admin.com/cmb_tz.php', // 支付成功的回调
'sign_notify_url' => 'http://cmb.admin.com/cmb_tz.php', // 成功签约结果通知地址
'sign_return_url' => 'http://cmb.admin.com', // 成功签约结果通知地址
'return_url' => 'http://cmb.admin.com/cmb_ok.php', // 如果是h5支付,可以设置该值,返回到指定页面
];
一网通支付时需要一个sign签名字段,签名内容是reqData内容,定义一个签名函数
//签名
function make_sign($mer_key,$str){
$reqData = arraySort($str);
$signStr = createLinkString($reqData);
$signStr .= '&'.$mer_key;
//SHA-256签名
$baSrc = mb_convert_encoding($signStr,"UTF-8");
$baResult = hash('sha256', $baSrc);
//转为16进制字符串(可选)
//$sign = bin2hex($baResult);
return $baResult;
}
1.一网通支付中H5类型,可能用到的接口有3个,获取公钥接口、一网通下单接口、查询订单接口
//一网通获取公钥地址(测试)
$QueryKeyAPI_test = 'http://mobiletest.cmburl.cn/CmbBank_B2B/UI/NetPay/DoBusiness.ashx';
//一网通下单地址(测试)
$OneCardPayAPI_test = 'http://121.15.180.66:801/netpayment/BaseHttp.dll?MB_EUserPay';
//$OneCardPayAPI_test ='http://paytest.cmburl.cn:801/netpayment/BaseHttp.dll?MB_EUserPay';
//查询订单
$DoBusiness_test = 'http://121.15.180.66:801/netpayment_directlink_nosession/BaseHttp.dll?QuerySingleOrder';
2.获取公钥目的套用一网通自己的话:使用招行公钥验签(用于对“成功签约结果通知”和“成功支付结果通知”接收到的通知报文进行验签)
(1)公钥获取的数组
$pub_get_data = [
'version' => '1.0',
'charset' => 'UTF-8',
'signType' => $config['sign_type'],
'reqData' => [
'dateTime' => date('YmdHis', $nowTime),
'txCode' => 'FBPK',
'branchNo' => $config['branch_no'],
'merchantNo' => $config['mch_id'],
],
];
公钥获取方式可以直接采用CURL方式获取。
对reData内容进行签名,Json后然后放入jsonRequestData字段:
$baResult = make_sign($config['mer_key'],$pub_get_data['reqData']);
$pub_get_data['sign']=$baResult;
$formParams['jsonRequestData']=json_encode($pub_get_data, JSON_UNESCAPED_UNICODE);
最后采用Curl请求,获取公钥。(go_curl函数文章后面提供)
go_curl($QueryKeyAPI_test,'POST',$formParams);
2.提交订单(一网通支付)
订单结构:
$tradeNo = time() . rand(1000, 9999);
$timeExpire = "30";
//数据结构
$pay_get_data = [
'version' => '1.0',
'charset' => 'UTF-8',
'signType' => $config['sign_type'],
'reqData' => [
'dateTime' => date('YmdHis', $nowTime),
'branchNo' => $config['branch_no'],
'merchantNo' => $config['mch_id'],
'date' => date('Ymd', $nowTime),
'orderNo' => $tradeNo,
'amount' => "0.01", // 固定两位小数,最大11位整数
'expireTimeSpan' => $timeExpire,
'payNoticeUrl' => $config['notify_url'],
//'payNoticePara' => '',
'returnUrl' => $config['return_url'],
//'clientIP' => '',
//'cardType' => $config['limit_pay'], // A:储蓄卡支付,即禁止信用卡支付
// 'agrNo' => '',
// 'merchantSerialNo' => '',
//'userID' => '',
// 'mobile' => '',
// 'lon' => '',
// 'lat' => '',
// 'riskLevel' => '',
'signNoticeUrl' => $config['sign_notify_url'],
// 'signNoticePara' => '',
],
];
注释部分不是必填的,具体参考一网通官方接口说明。
获取请求报文:
$baResult1 = make_sign($config['mer_key'],$pay_get_data['reqData']);
$pay_get_data['sign']=$baResult1;
$formParams1['charset'] = 'UTF-8';
$formParams1['jsonRequestData']=json_encode($pay_get_data);
这里和取得公钥的方法不太一样,需要直接采用form表单的方式提交跳转(可使用js自动提交)
<form action="<?php echo $OneCardPayAPI_test?>" method="post" />
<input type="hidden" name="jsonRequestData" value='<?php echo $formParams1['jsonRequestData']?>' />
<input type="hidden" name="charset" value='UTF-8' />
<input type="submit" value="提交订单">
</form>
结构无误的情况下,提交后自动跳转支付页面。
3.查询订单
$reqData = [
'dateTime' => date('YmdHis', $nowTime),
'branchNo' => $config['branch_no'],
'merchantNo' => $config['mch_id'],
'date' => date('Ymd', time()),
'type' => 'B',
// 'bankSerialNo' => '',
'orderNo' => $tradeNo
];
$baResult2 = make_sign($config['mer_key'],$reqData);
$jsonRequestData = [
'version' => '1.0',
'charset' => 'UTF-8',
'signType' => $config['sign_type'],
'sign' => $baResult2,
'reqData' => $reqData
];
$formParams2['charset'] = 'UTF-8';
$formParams2['jsonRequestData']=json_encode($jsonRequestData);
查询订单采用Type中的B类型,商户自己的订单编号,这里需要注意的是,如果要查询真实(测试)订单时,需要订单编号orderNo和支付时间date完全正确哦,如你查询今天的订单号,用了昨天的时间那就会查不到。(测试报告需要 查询1给正确订单和1个失败订单)
注意事项:
‘branch_no’ => ‘xxxx’, // 商户分行号,4位数字 ‘mch_id’ => ‘xxxx’, // 商户号,6位数字 ‘mer_key’ => ‘1234567890123456’, // 秘钥16位,包含大小写字母 数字
这3个参数需要联系一网通获取,服务器ip需要过一网通白名单ip,否则无法测试成功哦
关于测试报告:
招行一网通主要测试项目有4个,正常这4个测试通过(H5支付商户测试验收报告),就可以申请正式账号了。 分别是: CMB_test003CMB_test004 和 CMB_test008CMB_test009
3和4分别通过步骤2 提交2个订单,分别用储蓄卡和信用卡进行提交(一网通提供测试卡号)。 8输入3或4提交通过的订单,查询返回并截图。 9输入任意不存在订单号,截图就可以了
附录:
go_curl函数
//提交
function go_curl($url, $type, $data = false, &$err_msg = null, $timeout = 20, $cert_info = array())
{
$type = strtoupper($type);
if ($type == 'GET' && is_array($data)) {
$data = http_build_query($data);
}
$option = array();
if ( $type == 'POST' ) {
$option[CURLOPT_POST] = 1;
}
if ($data) {
if ($type == 'POST') {
$option[CURLOPT_POSTFIELDS] = $data;
} elseif ($type == 'GET') {
$url = strpos($url, '?') !== false ? $url.'&'.$data : $url.'?'.$data;
}
}
$option[CURLOPT_URL] = $url;
$option[CURLOPT_FOLLOWLOCATION] = TRUE;
$option[CURLOPT_MAXREDIRS] = 4;
$option[CURLOPT_RETURNTRANSFER] = TRUE;
$option[CURLOPT_TIMEOUT] = $timeout;
//设置证书信息
if(!empty($cert_info) && !empty($cert_info['cert_file'])) {
$option[CURLOPT_SSLCERT] = $cert_info['cert_file'];
$option[CURLOPT_SSLCERTPASSWD] = $cert_info['cert_pass'];
$option[CURLOPT_SSLCERTTYPE] = $cert_info['cert_type'];
}
//设置CA
if(!empty($cert_info['ca_file'])) {
// 对认证证书来源的检查,0表示阻止对证书的合法性的检查。1需要设置CURLOPT_CAINFO
$option[CURLOPT_SSL_VERIFYPEER] = 1;
$option[CURLOPT_CAINFO] = $cert_info['ca_file'];
} else {
// 对认证证书来源的检查,0表示阻止对证书的合法性的检查。1需要设置CURLOPT_CAINFO
$option[CURLOPT_SSL_VERIFYPEER] = 0;
}
$ch = curl_init();
curl_setopt_array($ch, $option);
$response = curl_exec($ch);
$curl_no = curl_errno($ch);
$curl_err = curl_error($ch);
curl_close($ch);
// error_log
if($curl_no > 0) {
if($err_msg !== null) {
$err_msg = '('.$curl_no.')'.$curl_err;
}
}
return $response;
}
以上代码可以Gitee上下载,地址:一网通H5支付测试Demo
如果对您有帮助,麻烦给个Star吧,谢谢!