获取到 prepay_id 后将参数再次签名传输给 APP 发起支付

news/2025/6/19 17:42:31

获取到 prepay_id 后将参数再次签名传输给 APP 发起支付。

相信有不少同学因为看到统一下单返回的结果中有 sign 字段,会直接将结果返回给 APP 端,结果 APP 端没办法调起微支付。其实需要对 APP 端用到的字段数据按 “统一下单的签名方式” 签名后得到的 sign,才是 APP 端需要的 sign。

微信支付 App支付 在服务端调用统一下单接口后,服务端需要将返回的订单数据进行二次签名后才能返回给 App 端。开发文档中说的并不是很明确,因为统一下单的返回数据和二签的原数据上存在一些重叠。

微信支付服务端 sdk 提供了 WxPayResults 类,类中也的确提供了生成签名方法,即对结果集签名,源码如下:

以 PHP 版为例,其他语言自行对照。

class WxPayResults extends WxPayDataBase
{/*** 生成签名 - 重写该方法* @param WxPayConfigInterface $config 配置对象* @param bool $needSignType 是否需要补signtype* @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值*/public function MakeSign($config, $needSignType = false){//签名步骤一:按字典序排序参数ksort($this->values);$string = $this->ToUrlParams();//签名步骤二:在string后加入KEY$string = $string . "&key=" . $config->GetKey();//签名步骤三:MD5加密或者HMAC-SHA256if (strlen($this->GetSign()) <= 32) {//如果签名小于等于32个,则使用md5验证$string = md5($string);} else {//是用sha256校验$string = hash_hmac("sha256", $string, $config->GetKey());}//签名步骤四:所有字符转为大写$result = strtoupper($string);return $result;}
}

注意步骤三,是需要获取 sign 来判断使用什么方式生成 sign 的,是不是有种鸡生蛋,蛋生鸡的短路既视感。在 APP 端调起支付的参数列表的 sign 参数里有提示 “注意:签名方式一定要与统一下单接口使用的一致”,所以这里的逻辑是要你将统一下单返回的 sign 传递进来,以便于统一签名方式。签名后一定要用真的签名去覆盖用来传递签名方式的“签名”。

在统一下单接口中,生成签名的流程是 $obj->setSign() 调用 $obj->makeSign(),而后我们可以 $obj->getSign() 将签名加到请求数据中。但在结果集类中,makeSign 却直接调用了 getSign 来判断使用何种方式生成签名,所以对结果集签名时,需确保结果集中包含了同一下单返回的 sign 字段数据,这样结果集才能满足 “注意:签名方式一定要与统一下单接口使用的一致” 的要求。

所以这个类对签名进行了重写的目的,主要是为了保证二次签名的签名方式与统一下订单的签名方式一致,将统一下单的签名作为 sign 传递给
WxPayResults 然后调用 makeSign,makeSign 就能判断出统一下单的签名方式,与之保持一致。

统一下单成功接口返回的数据

$uniorder = array ('appid' => 'wxd930ea5d5a258f4f',//appid'device_info' => 'WEB','mch_id' => '1900000109',// 商户id'nonce_str' => 'g6OZoULWyliPmiPm','prepay_id' => 'wx12143635206473d0a53e80f14278847815','result_code' => 'SUCCESS','return_code' => 'SUCCESS','return_msg' => 'OK','sign' => 'E91035CA24EDF115374BD2B4C4F9B419',//统一下单的签名'trade_type' => 'APP',
)

服务端需要二签的数据

文档地址:https://pay.weixin.qq.com/wik...

clipboard.png

  • package 暂填写固定值Sign=WXPay
  • noncestr 并不一定要统一下单返回的 nonce_str,自己生成 32位 的也可以
  • timestamp 自己生成即可
  • sign 传递统一下单返回的签名,以使得结果集签名和统一下单签名方式一致(或者你清楚的知道你对结果集签名的方式同下单的一致)

如果自己写,二不用 sdk 的话,我们需要对

<?php
// 传递的数据
$app_result = array ('appid' => $uniorder['appid'],//从统一下单的结果中取'partnerid' => $uniorder['mch_id'],//从统一下单的结果中取'prepayid' => $uniorder['prepay_id'],//从统一下单的结果中取'package' => 'Sign=WXPay',//自己写'noncestr' => WxPayApi::getNonceStr();,//自己写'timestamp ' => time(),//自己写
);
// 与统一下单的签名方式一致即可
$sign = signMethodConsistWithUniOrder($app_result);
$app_result['sign'] = $sign;// 返回给 APP 端
return $$app_result;

如果用 sdk 的务必要将 统一下单返回的数据里的签名 sign 也传递给 WxPayResults 类,已使得保证签名方式一致

<?php
// 传递的数据
// 传递的数据
$app_result = array ('appid' => $uniorder['appid'],//从统一下单的结果中取'partnerid' => $uniorder['mch_id'],//从统一下单的结果中取'prepayid' => $uniorder['prepay_id'],//从统一下单的结果中取'sign' => $uniorder['sign'],//用来使结果集签名方式与统一下单签名方式一致'package' => 'Sign=WXPay',//自己写'noncestr' => WxPayApi::getNonceStr();,//自己写'timestamp ' => time(),//自己写
);$wxPayResults = new WxPayResults();
// 构建 WxPayResults 对象
$wxPayResults->FromArray($app_result);// 真正的返回数据的签名 覆盖用来统一签名方式的“签名”
$app_result['sign'] = $wxPayResults->makeSign($wxPayConfig);//然后更新成二签后的sign// 返回给 APP 端
return $$app_result;

App 端调用微信支付的方式为

IWXAPI api;
PayReq request = new PayReq();
request.appId = "wxd930ea5d5a258f4f";
request.partnerId = "1900000109";
request.prepayId= "1101000000140415649af9fc314aa427",;
request.packageValue = "Sign=WXPay";
request.nonceStr= "1101000000140429eb40476f8896f4c9";
request.timeStamp= "1398746574";
request.sign= "7FFECB600D7157C5AA49810D2D8F28BC2811827B";
api.sendReq(request);

使用服务端提供的数据发起支付请求即可。


https://dhexx.cn/news/show-156337.html

相关文章

Duplicate entry '0' for key 'PRIMARY'的一种可能的解决办法

在MySQL设计好数据库往往数据库中插入数据的时候&#xff0c; 因为主键ID默认是不赋值的&#xff0c;只给其他项目赋值了&#xff0c;相关的SQL代码是这样的 StringBuilder strSql new StringBuilder(); strSql.Append("insert into tb_enterprise_product…

前端脚本!网站图片素材中文转英文

写网页的时候, 我们经常需要使用图片素材, 图片素材如果是中文名, 挂到服务器会会引发乱码, 我们需要将图片名称改为英文字符才可以使用而起名是一个世界级难题, 为图片素材起英文名更是一件极其蛋疼的事有些人英语不好, 直接用拼音命名, 而拼音闹出的笑话更是无法计量...最近接…

c# XML和实体类之间相互转换(序列化和反序列化)[砖]

link: http://blog.okbase.net/haobao/archive/62.html by: 好饱 我们需要在XML与实体类&#xff0c;DataTable&#xff0c;List之间进行转换&#xff0c;下面是XmlUtil类&#xff0c;该类来自网络并稍加修改。 1234567891011121314151617181920212223242526272829303132333435…

andoid的socket测试为什么出现这个错误:java.net.ConnectException: failed to connect to /192.168.0.8

基于android的Socket通信: Android与服务器的通信方式主要有两种&#xff0c;一是Http通信&#xff0c;一是Socket通信。两者的最大差异在于&#xff0c;http连接使用的是“请求—响应方式”&#xff0c;即在请求时建立连接通道&#xff0c;当客户端向服务器发送请求后&#x…

ABAP OO练习

继续我们的看实例学习abap面向对象编程.在此次的例子中,我们以雇员的工资为蓝图,设计一个程序,然后再一步一步的改进我们写的程序,使其有更好的扩展性以及维护性.该例中所使用的基类是employee类,其子类包括:boss类,不管工作多长时间,他总是有固定的周薪(好爽!).销售员类commis…

[Github 项目推荐] 一个更好阅读和查找论文的网站

机器学习发展到现在&#xff0c;已经积累了非常多的文章&#xff0c;特别是深度学习火起来后&#xff0c;每年新增加的论文非常多&#xff0c;如果需要研究某个领域&#xff0c;不仅需要阅读这个领域经典的论文&#xff0c;也必须时刻关注最新的学术进展&#xff0c;比如最近两…

解决: java.net.ConnectException: Connection refused: connect

java.net.ConnectException: Connection refused: connect 1. 报错如上。 2. 原因和解决&#xff1a; 1&#xff09;端口号被占用&#xff1a;杀死占用端口号&#xff08;一般为8080&#xff09;的进程&#xff0c;释放端口&#xff1b;彻底关闭 Tomcat 服务器&#xff0c;或…

Spring中的@Transactional(rollbackFor = Exception.class)属性详解

序言 今天我在写代码的时候&#xff0c;看到了。一个注解Transactional(rollbackFor Exception.class)&#xff0c;今天就和大家分享一下&#xff0c;这个注解的用法&#xff1b; 异常 如下图所示&#xff0c;我们都知道Exception分为运行时异常RuntimeException和非运行时异常…

Python面向对象编程学习笔记2

以上方式不推荐使用 以上方式不推荐使用 转载于:https://www.cnblogs.com/chickenwrap/p/10264932.html

更改Eclipse下Tomcat的部署目录

使用eclipse开发是因为机器不够用myeclipse&#xff0c;eclipse也比myeclipse清爽很多&#xff0c;启动速度也快。这里的搭建开发环境使用&#xff1a; Jdk1.6Tomcat6Eclipse JEE&#xff0c; 工作目录如下环境目录如下&#xff1a; 安装路径&#xff1a; C:\Java\Jdk1.6.0 C:\…