#PHP#微信支付 第二篇 JSAPI 调用统一下单接口获取预支付交易数据
上一篇讲到成功获取 openid,本篇要调用微信统一接口创建预支付交易单
除付款码支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易会话标识后再按Native、JSAPI、APP等不同场景生成交易串调起支付。
第三步,调用微信统一下单接口创建预支付交易单
微信统一下单API是微信支付的一个“统一”处理入口,官方给出的地址是
https://api.mch.weixin.qq.com/pay/unifiedorder
https://api2.mch.weixin.qq.com/pay/unifiedorder(备用域名)
首先先按照 统一下单 接口一问中给的 请求参数 准备必要的参数,在本例(JSAPI)中至少需要参数如下
- appid,公众号AppID
- mch_id,商户号,一串10位数字
- device_info,设备号,非必填但有一定作用,PC网页或公众号内支付可以传"WEB",本例中就设置为"WEB"
- nonce_str,随机字符串,请求方提供的随机信息,主要保证签名不可预测
- sign,通过签名算法计算得出的签名值,详见签名算法
- sign_type,签名类型,截止编辑时支持(默认)"MD5"和"HMAC-SHA256",用哪种算法进行的签名要通过该字段表示
- body,商品描述,商户按规范创建
- out_trade_no,商户系统内部订单号,按微信的规则生成
- total_fee,整型,单位分,订单总金额
- spbill_create_ip,"用户的客户端IP",这个词儿是微信给出的截止到编辑时从字面上我并不确定指的是请求服务器的服务器地址还是访问商户服务器的某个用户"手机"的地址,但通过代码应该是后者,详见之后的代码示例
- notify_url,异步接收微信支付结果通知的回调地址
- trade_type,交易类型的标识,JSAPI-JSAPI支付,NATIVE-Native支付,APP-APP支付,MWEB-H5支付
- openid,第一篇中来自微信用户的openid值
按照 签名算法 计算签名
- 把所有要传递的参数键值对去掉值是空的,剩下的参数名ASCII码从小到大排序后,使用URL键值对格式(key1=value1&key2=value2...)拼接成StringA
- 把StringA后面多加一组键值 &key=商户平台密钥 获得StringB
- 把StringB按要求做"MD5"或"HMAC-SHA256"计算,并将结果字符转为大写
- 微信甚至还提供了一个在线校验工具帮助开发者检查生成的签名是否正确,跳到工具。使用方法是选择好 签名类型,校验方式选择 XML (不是必须只是为了省事儿),XML源串 输入不带 sign 信息的部分如
<xml>
<appid>wxcxxxxx5bbf</appid>
<mch_id>15xxxxxxxxxxxx61</mch_id>
<device_info>WEB</device_info>
<nonce_str>6743482E92E61DE587B52D6C7DEBFE79</nonce_str>
<body>xx科技-测试</body>
<out_trade_no>TY-OUTTRADENO-TEST-1561440044</out_trade_no>
<total_fee>1</total_fee>
<spbill_create_ip>36.xx.xx.185</spbill_create_ip>
<notify_url>http://wxpay.txxxt.com/jsapi/unifiedOrderNotify.php</notify_url>
<trade_type>JSAPI</trade_type>
<openid>100003</openid>
</xml>
再输入正确的 商户密钥,点击按钮即可计算出结果,与自己计算的结果进行比对。
- 本例中 Sign 方法接收两个参数,$arrayobj 为数组类型,保存了所有参数名和参数值组成的字符串数组,方法输出计算后的签名结果。ToUrlParams 方法将参数数组拼接为URL格式字符串。
/**
* 生成签名
* @param 参与签名的内容组成的数组
* @param 是否使用 HMAC-SHA256算法,否则使用MD5
* @return 签名字符串
* @author 试试手气
* @version test pass
*/
public static function Sign($arrayobj, $hmacsha256 = true)
{
//步骤一:字典排序
ksort($arrayobj);
//步骤二:在
$str = Util::ToUrlParams($arrayobj);
//步骤三:在$str后面加KEY
$mchKey = "asdxxxxxxxxxxxxxxN82"; // 商户支付秘钥,生产代码中是不可能如此硬编码到这里的
$str .= "&key=" . $mchKey;
//步骤四:MD5或HMAC-SHA256C加密
if ($hmacsha256) {
$str = hash_hmac("sha256", $str, $mchKey);
} else {
$str = md5($str);
}
//步骤五:所有字符转大写
$result = strtoupper($str);
return $result;
}
public static function ToUrlParams($arrayobj)
{
$buff = "";
foreach ($arrayobj as $k => $v) {
if ($k != "sign" && $v != "" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
将签名结果作为最后的参数一起创建XML格式的POST数据
除 sign 签名外,其它的参数要么是现成的,要么是可以运行时获取到的如 spbill_create_ip。计算完签名,所有的参数就都准备好了,把它们加工成XML,参数顺序没有提到有限制。
function toXML($paramsobj)
{
$xml = "<xml>\n";
foreach ($paramsobj as $key => $value) {
$xml .= "<" . $key . ">" . $value . "</" . $key . ">\n";
}
$xml .= "</xml>";
return $xml;
}
出来是这个样子的
<xml>
<appid>wxcxxxxx5bbf</appid>
<mch_id>15xxxxxxxxxxxx61</mch_id>
<device_info>WEB</device_info>
<nonce_str>6743482E92E61DE587B52D6C7DEBFE79</nonce_str>
<body>xx科技-测试</body>
<out_trade_no>TY-OUTTRADENO-TEST-1561440044</out_trade_no>
<total_fee>1</total_fee>
<spbill_create_ip>36.xx.xx.185</spbill_create_ip>
<notify_url>http://wxpay.txxxt.com/jsapi/unifiedOrderNotify.php</notify_url>
<trade_type>JSAPI</trade_type>
<openid>100003</openid>
<sign>42DDF6C558EC05E24AAD0Cxxxxxxxx1DC3A53C0053D4A6F42E31036132F74481</sign>
</xml>
向微信统一下单API提交XML
用POST方式向统一下单接口地址提交数据,本例中使用的是微信SDK中的 postXmlCurl 方法改造了一下,用的是 curl 访问网络
function postXmlCurl($config, $xml, $url, $useCert = false, $second = 30)
{
$ch = curl_init();
//$curlVersion = curl_version();
//$ua = "WXPaySDK/".self::$VERSION." (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']." "
// .$config->GetMerchantId();
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
// $proxyHost = "0.0.0.0";
// $proxyPort = 0;
// $config->GetProxy($proxyHost, $proxyPort);
// //如果有配置代理这里就设置代理
// if($proxyHost != "0.0.0.0" && $proxyPort != 0){
// curl_setopt($ch,CURLOPT_PROXY, $proxyHost);
// curl_setopt($ch,CURLOPT_PROXYPORT, $proxyPort);
// }
curl_setopt($ch, CURLOPT_URL, $url);
//curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
//curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
//curl_setopt($ch,CURLOPT_USERAGENT, $ua);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if ($useCert == true) {
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
//证书文件请放入服务器的非web目录下
$sslCertPath = "";
$sslKeyPath = "";
$config->GetSSLCertPath($sslCertPath, $sslKeyPath);
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERT, $sslCertPath);
curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLKEY, $sslKeyPath);
}
//试试手气新增,增加之后 curl 不报 60# 错误,可以请求到微信的响应
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //不验证 SSL 证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//不验证 SSL 证书域名
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
//返回结果
if ($data) {
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
return "curl error, error code ".$error;
//throw new WxPayException("curl出错,错误码:$error");
}
}
没有删掉代码,不用的注释掉了,并增加了关于 CURLOPT_SSL_VERIFYPEER 和 CURLOPT_SSL_VERIFYHOST 的明确设置,在增加这两句之前curl本身会报60错误。
返回值
按微信文档,访问(非业务)成功将返回(至少)包含 return_code 和 return_msg 两个字段的XML文档,对照统一下单接口文档内的返回结果即可判断请求是否成功,如下例
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wxccxxxxbbf]]></appid>
<mch_id><![CDATA[15xxx61]]></mch_id>
<device_info><![CDATA[WEB]]></device_info>
<nonce_str><![CDATA[SMIpZtHhPPyTezlY]]></nonce_str>
<sign><![CDATA[7215B1BAB1C08A4887AAB0ECB2A6044729FE8A8BC6E70591660A6BCC11D7DC9A]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx251xxxxxxxxxxxxxxxxxxxxxxxxxxxxx078700]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
很明显是访问也成功了,业务也成功了,也就是接口业务成功生成了 预支付交易会话 wx251xxxxxxxxxxxxxxxxxxxxxxxxxxxxx078700 ,后面就该使用该会话标识调起H5支付了。
#PHP#微信支付 第二篇 JSAPI 调用统一下单接口获取预支付交易数据的更多相关文章
- 微信支付 第一篇 JSAPI 支付配置与获取 OpenID
开通微信支付支付产品 首先要在微信支付申请成为 微信支付商户. 选择开通具体的支付产品 成为微信支付商户后在管理后台选择微信支付中的具体支付产品并申请开通如 JSAPI . 将支付商户与公众号关联 这 ...
- 微信支付 第三篇 微信调用H5页面进行支付
上一篇讲到拿到了 预支付交易标识 wx251xxxxxxxxxxxxxxxxxxxxxxxxxxxxx078700 第四步,是时候微信内H5调起支付了! 先准备网页端接口请求参数列表 微信文档中已经明 ...
- 在.net core上,Web网站调用微信支付-统一下单接口(xml传参)一直返回错误:mch_id参数格式错误
这是 微信支付-统一下单 接口文档 一.问题描述 在调用统一下单接口时,报mch_id参数格式错误,但商户ID确实是10位数字正确的,可就是一直报这个错误 返回的错误xml如下: 二.排错过程 1.多 ...
- SpringBoot项目后台对接微信支付开发——微信统一下单接口开发
开始没找到微信支付的sdk.自己根据官方给的接口文档纯手写,各种xml转JSON,JSON转xml,加密解密,签名....整个人都是崩溃的 开发的第三天,发现有官方的sdk.心情一下子豁然开朗,整个人 ...
- [88221008]调用新下单接口失败,result:162020004,resInfo
[88221008]调用新下单接口失败,result:162020004,resInfo
- php微信支付(仅Jsapi支付)详细步骤.----仅适合第一次做微信开发的程序员
本人最近做了微信支付开发,是第一次接触.其中走了很多弯路,遇到的问题也很多.为了让和我一样的新人不再遇到类似的问题,我把我的开发步骤和问题写出来,以供参考. 开发时间是2016/8/2,所以微信支付的 ...
- asp.net微信支付发起页面jsapi.aspx
jsapi.aspx 后台核心代码 //创建支付应答对象 RequestHandler packageReqHandler = new RequestHandler(Context); //初始化 p ...
- 微信支付中的jsapi返回提示信息
jsapi中跳转到微信支付中触发的方法是js中的getBrandWCPayRequest方法. 改方法中的返回结果msg提示信息如下: err_msg:get_brand_wcpay_request: ...
- 微信支付(公众号支付APIJS、app支付)服务端统一下单接口java版
一.微信公众号支付APIJS: 要完整的实现微信支付功能,需要前后端一起实现,还需要微信商户平台的配置.这里只是涉及服务端的代码. jar包:pom.xml <!-- ↓↓↓↓↓↓↓↓ 支付相关 ...
随机推荐
- relative和absolute
relative 相对定位 1. 幻影瞬移 absolute属性也有瞬移技能,不同之处在于:absolute属性以天空或其他外界限制计算瞬移位置:而relative属性由于是凡人肉体,偏移能力有限,只 ...
- 【旧文章搬运】Windows句柄分配算法(二)
原文发表于百度空间,2009-04-04========================================================================== 在创建句柄 ...
- caffe 入门实例3 fine-turning
占坑,使用fine-turning初始化参数...
- Spring Boot 学习系列(序)—Spring Boot
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot? Spring Boot 是由pivotal团队提供的一个基于Spring的全新框架 ...
- [WPF自定义控件库] 自定义控件的代码如何与ControlTemplate交互
1. 前言 WPF有一个灵活的UI框架,用户可以轻松地使用代码控制控件的外观.例设我需要一个控件在鼠标进入的时候背景变成蓝色,我可以用下面这段代码实现: protected override void ...
- (水题)Codeforces - 650A - Watchmen
http://codeforces.com/contest/650/problem/A 一开始想了很久都没有考虑到重复点的影响,解欧拉距离和曼哈顿距离相等可以得到 $x_i=x_j$ 或 $y_i=y ...
- (水题)洛谷 - P1583 - 魔法照片
https://www.luogu.org/problemnew/show/P1583 设计一个strcut cmp用来比较,就可以了. #include<bits/stdc++.h> u ...
- 框架基础:关于ajax设计方案(三)---集成ajax上传技术
之前发布了ajax的通用解决方案,核心的ajax发布请求,以及集成了轮询.这次去外国网站逛逛,然后发现了ajax level2的上传文件,所以就有了把ajax的上传文件集成进去的想法,ajax方案的l ...
- Mac下怎么运行python3的py文件
我的Mac现在是10.14.6系统,默认自带的python版本是2.7.(怎么查看版本?打开终端,输入python即可看到版本号) 由于现在需要运行python3写的py文件,需要将自带的python ...
- 2017百度之星资格赛 1003:度度熊与邪恶大魔王(DP)
.navbar-nav > li.active > a { background-image: none; background-color: #058; } .navbar-invers ...