时间:2020-04-03 21:32:18
阅读对象
本文阅读对象为:商户自有系统(包括但不限于:在线购物平台、人工收银系统、自动化智能收银系统、APP应用等)负责微信支付功能验收的测试及开发人员。
验收说明
一、概述
为保证商户接入质量,提升交易安全及用户体验,微信支付的合作服务商在正式上线交易前,必须先根据本文指引完成验收。验收完成后,服务商在验收公众平台(微信号:WXPayAssist)提交验收通过申请,审核通过后,才能开通相应的支付权限(如:付款码支付)。否则,请根据审核驳回提示,重新完成验收。
注:仿真测试环境中的商户号(父子商户号)需使用真实商户号。
二、仿真测试系统
为降低商户测试门槛,微信支付团队开发了一套独立的仿真测试系统。该系统根据验收用例金额的不同返回不同的响应报文,以满足商户正常功能测试、安全/异常测试及性能测试的需求。
图1 微信支付仿真测试系统
图1为微信支付仿真测试系统(后简称仿真系统)的简化原理图。仿真系统的API协议与正式API完全相同(API接口文档)。商户开发者只需将正式API的调用URL增加一层sandboxnew路径,即可对接到仿真系统。
例如,付款码支付URL:https://api.mch.weixin.qq.com/pay/micropay
变更为:https://api.mch.weixin.qq.com/sandboxnew/pay/micropay。
仿真系统与生产环境完全独立,包括存储层。商户在仿真系统所做的所有交易(如下单、支付、查询)均为无资金流的假数据,即:用户无需真实扣款,商户也不会有资金入账。代金券同理,沙箱环境中无需商户真实制券与发券,亦不会出现真实扣券情况。
### 官方文档
[支付验收指引](公益404
[刷卡支付验收用例](公益404
[扫码支付验收用例](公益404
[公众号支付验收用例](公益404
[免充值产品功能使用指引](公益404
主要配置项:
APPID:绑定支付的APPID(必须配置,开户邮件中可查看) MCHID:商户号(必须配置,开户邮件中可查看) KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置), 请妥善保管, 避免密钥泄露 APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置), 请妥善保管, 避免密钥泄露
本文以扫码支付为例如下步骤:
-
获取验签秘钥KEY
通过正式的KEY获取沙箱密钥,获取成功后替换正式的KEY(上面标红的配置项)
/** * 获取仿真测试环境下的key * @param $configs * @return * @throws WxPayException */ public static function getSignKeyBySandBoxNew($configs){ $url = 'https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey'; $arrPost = [ 'mch_id' => $configs['MCHID'], // 微信支付分配的微信商户号 'nonce_str' => self::getNonceStr(), // 随机字符串 ]; //签名步骤一:按字典序排序参数 ksort($arrPost); $string = self::ToUrlParams($arrPost); //签名步骤二:在string后加入KEY $string = $string . "&key=".$configs['KEY']; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $arrPost['sign'] = strtoupper($string); $startTimeStamp = self::getMillisecond();//请求开始时间 $toXml = self::ToXml($arrPost); $response = self::postXmlCurl($toXml, $url, false); //将XML转为array //禁止引用外部xml实体 libxml_disable_entity_loader(true); $result = json_decode(json_encode(simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA)), true); if($result['return_msg'] && isset($result['sandbox_signkey'])){ return $result['sandbox_signkey']; } throw new WxPayException("获取仿真测试环境的Key失败!".$result['return_msg']); } /** * 格式化参数格式化成url参数 */ public static function ToUrlParams($data) { $buff = ""; foreach ($data as $k => $v) { if($k != "sign" && $v != "" && !is_array($v)){ $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } /** * 输出xml字符 * @throws WxPayException **/ public static function ToXml($data) { if(!is_array($data) || count($data) <= 0) { throw new WxPayException("数组数据异常!"); } $xml = "<xml>"; foreach ($data as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; }
-
微信接口API变更
扫码支付也是走的统一下单接口,
https://api.mch.weixin.qq.com/pay/unifiedorder
变更为:https://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder
-
数据提交
带sandboxnew 的https请求会被nginx路由到仿真系统。商户平台弹出二维码
注意:不用扫码,就是扫码也会永远提示你"码已过期,请重新生成。"
-
二维码弹出后,给眼睛做五下保键操,异步通知就会来,订单支付成功
注意:所有测试项均按官方测试用例步骤进行
比如我要测r扫码支付,打开支付测试用例https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_12
下载用例文档,按测试用例输入金额否测会报错哦!!
-
支付回调验证需修改为:
调用 https://api.mch.weixin.qq.com/pay/orderquery
变更为:调用 https://api.mch.weixin.qq.com/sandboxnew/pay/orderquery
当前查询参数 微信订单号(transaction_id)或商户内部单号(out_trade_no)
这里是一个坑,仿真环境报“out_trade_no”无效
class PayNotifyCallBack extends WxPayNotify { //查询订单 public function Queryorder($data) { $input = new WxPayOrderQuery(); $input->SetTransaction_id($data["transaction_id"]); $input->SetOut_trade_no($data["out_trade_no"]); $result = WxPayApi::orderQuery($input); //Log::DEBUG("query:" . json_encode($result)); if(array_key_exists("return_code", $result) && array_key_exists("result_code", $result) && $result["return_code"] == "SUCCESS" && $result["result_code"] == "SUCCESS") { return true; } return false; } //重写回调处理函数 public function NotifyProcess($data, &$msg) { //Log::DEBUG("call back:" . json_encode($data)); $notfiyOutput = array(); if(!array_key_exists("transaction_id", $data)){ $msg = "输入参数不正确"; return false; } if(!array_key_exists("out_trade_no", $data)){ $msg = "输入参数不正确"; return false; } //查询订单,判断订单真实性 if(!$this->Queryorder($data)){ $msg = "订单查询失败"; return false; } return array('status'=>true,'data'=>$data); } }
-
完成
百度说有的接口会有不同需要注意:
注意:有的接口沙箱环境的接口并不只是在链接中增加 sandboxnew
,整个链接都会改变,在实际操作中我们应该查看官方文档一一对照,如支付退款接口,正式线接口为:/secapi/pay/refund
,而沙箱环境接口为:/sandboxnew/pay/refund
,在沙箱环境中去掉了 secapi
这一路径,请小伙伴一定要注意。