资讯专栏INFORMATION COLUMN

微信支付JSAPI,实测!终极方案

邹立鹏 / 2180人阅读

摘要:在用开发微信支付的时候,遇到了很多坑,我也对朋友说过,一步一坑。在安卓手机上也能回调出错误信息。需要引用,也需要使用,而且在安卓手机上面的提示特别不友好。结语微信支付文档说实话真的很坑很坑。

在用JSAPI开发微信支付的时候,遇到了很多坑,我也对朋友说过,一步一坑。最后终于算是走出来了。期间翻阅过很多网友写的教程,但是都不实用,JAVA,Python都有看过,大多数都是复制粘贴,倍感失望。

开发环境

thinkphp5.0 php

(开始使用JSAPI需要一个概念,就是在整个JSAPI的逻辑里面,只存在一个随机字符串 和一个 时间戳。相当于JSAPI类里的全局。)

注意:由于我这里用的http_build_query()body里面的中文会被格式化,所以这里先建议body使用非中文,至于中文解决,可以用正则去替换,或者不用http_build_query()

开始开发 全局初始化

</>复制代码

  1. public function __construct($total_fee, $body, $openid)
  2. {
  3. $rand = rand(11, 99);
  4. $mp_info = get_mpid_info();//获取微信信息
  5. $this->appid = $mp_info["appid"];
  6. $this->nonce_str = nonceStr(32);
  7. $this->spbill_create_ip = Request::instance()->ip();
  8. $this->mch_id = $mp_info["mch_id"];
  9. $this->key = $mp_info["paykey"];
  10. $this->timestamp = time();
  11. $this->sign;//一次签名
  12. $this->total_fee = $total_fee;
  13. $this->out_trade_no = time() . $rand;
  14. $this->notify_url = "http://uedream.cn/index.php";
  15. $this->body = $body;
  16. $this->openid = $openid;
  17. $this->sign_type = "MD5";
  18. $this->createsign(); //生成签名方法,需要结合createsign方法
  19. }

以上是初始化签名结构体

获取签名

</>复制代码

  1. 文档:https://pay.weixin.qq.com/wik...

</>复制代码

  1. public function createsign()
  2. {
  3. $build = [
  4. "appid" => $this->appid,
  5. "body" => $this->body,
  6. "mch_id" => $this->mch_id,
  7. "nonce_str" => $this->nonce_str,
  8. "notify_url" => $this->notify_url,
  9. "openid" => $this->openid,
  10. "out_trade_no" => $this->out_trade_no,
  11. "sign_type" => $this->sign_type,
  12. "spbill_create_ip" => $this->spbill_create_ip,
  13. "timeStamp" => $this->timestamp,
  14. "total_fee" => $this->total_fee,
  15. "trade_type" => $this->trade_type,
  16. "key" => $this->key,
  17. ];
  18. $string = http_build_query($build);
  19. $string = str_replace("%2F", "/", $string); //格式化网址
  20. $string = str_replace("%3A", ":", $string); //格式化网址
  21. $md5 = md5($string);
  22. $this->sign = strtoupper($md5);
  23. }
统一下单

</>复制代码

  1. 文档:https://pay.weixin.qq.com/wik...

</>复制代码

  1. public function unifiedorder()
  2. {
  3. $data = [
  4. "appid" => $this->appid,
  5. "body" => $this->body,
  6. "mch_id" => $this->mch_id,
  7. "nonce_str" => $this->nonce_str,
  8. "notify_url" => $this->notify_url,
  9. "openid" => $this->openid,
  10. "out_trade_no" => $this->out_trade_no,
  11. "sign" => $this->sign,
  12. "sign_type" => "MD5",
  13. "spbill_create_ip" => $this->spbill_create_ip,
  14. "timeStamp" => $this->timestamp,
  15. "total_fee" => $this->total_fee * 1,
  16. "trade_type" => $this->trade_type,
  17. ];
  18. $xml = arrayToXml($data);
  19. $result = http_post(self::UNIFIEDORDER, $xml);
  20. $return = xmlToArray($result);
  21. $this->package = "prepay_id=" . $return["prepay_id"];
  22. $this->renCreatesign();//这是二次签名。文档里面我是没有看到,反正我是卡到这里了。
  23. $returns = [
  24. "appid" => $this->appid,
  25. "noncestr" => $this->nonce_str,
  26. "signtype" => $this->sign_type,
  27. "package" => $this->package,
  28. "sign" => $this->resign,
  29. "timestamp" => $this->timestamp,
  30. ];
  31. return $returns;
  32. }

统一下单请忽略的所有的回调参数,只要prepay_id,其它的参数暂时看做障眼法,获取到了统一下单,还需要进行二次签名,上面代码里面有一个$this->renCreatesign(),就是调用的二次签名方法

二次签名

</>复制代码

  1. 文档:https://pay.weixin.qq.com/wik...

所谓的二次签名就是,appId,nonceStr,package,signType,timeStamp,key的加密。一样的签名方式,可以参考签名文档,进行签名。(上面参数已经按照ASCII进行排序,大小写也请按照给出的进行加密)
注意: package格式为prepay_id=xxxxxxxxxxxx。xxxx部分为统一下单获取的prepay_id

代码参考:

</>复制代码

  1. public function renCreatesign()
  2. {
  3. $build_data = [
  4. "appId" => $this->appid,
  5. "nonceStr" => $this->nonce_str,
  6. "package" => $this->package,
  7. "signType" => $this->sign_type,
  8. "timeStamp" => $this->timestamp,
  9. "key" => $this->key,
  10. ];
  11. $result = http_build_query($build_data);
  12. $put_data = str_replace("%3D", "=", $result); //格式化网址
  13. $signatrue = md5($put_data);
  14. $this->resign = strtoupper($signatrue);
  15. }

至此,所有的签名应经完成,控制器使用unifiedorder()进行参数获取。

前端

这里开始使用jsapi做支付动作

</>复制代码

  1. WeixinJSBridge.invoke(
  2. "getBrandWCPayRequest",
  3. {
  4. appId: res.appid, //公众号名称,由商户传入
  5. timeStamp: res.timeStamp, //时间戳,自1970年以来的秒数
  6. nonceStr: res.nonce_str, //随机串
  7. package: res.package,
  8. signType: res.signType, //微信签名方式:
  9. paySign: res.sign //微信签名
  10. },
  11. function(res) {
  12. alert(JSON.stringify(res));
  13. if (res.err_msg == "get_brand_wcpay_request:ok") {
  14. // 使用以上方式判断前端返回,微信团队郑重提示:
  15. //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
  16. }
  17. }
  18. );

前端所有需要调用的参数均在unifiedorder()可以获取到。

这里提一下WeixinJSBridge.invokewx.chooseWXPay 的区别。WeixinJSBridge.invoke可以不用引用weixinjs便可使用,也不需要config。在安卓手机上也能回调出错误信息。wx.chooseWXPay需要引用weixinjs,也需要使用config,而且在安卓手机上面的提示特别不友好。

结语

微信支付文档说实话真的很坑 很坑。貌似写文档的小哥这天情绪不好。写出来的让人也感觉到了情绪不好。以上为本人切身操作写出的教程。如还有补充的地方可以随时留言评论。

彩蛋

</>复制代码

  1. 文档:https://github.com/datalinkag...

下载地址:

</>复制代码

  1. composer require datalinkage/wxpay

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29909.html

相关文章

  • 微信支付开发中遇到的两个神坑

    微信支付本身是提供了三大Web开发语言的SDK下载的,按理说应该很Easy怎么会有坑呢?其实坑大多出在文档上,文档不完善,很多东西都得你去摔一跤才明白,事先绝不告诉你,整个微信的文档都跟屎一样其次是参数命名,一会儿要用timeStamp一会儿却又要用timestamp的,命名混乱就算了还非得区分大小写,百度一下就知道坑过多少人了 这些都忍了,跌跌撞撞也就过来了。但最近做支付又遇到两个大坑。经过数小...

    adam1q84 评论0 收藏0
  • 个人申请官方微信支付接口,即时到账!还支持个人小程序支付!附支付demo

    摘要:那么有微信支付的能力吗以上就是能力,可以做扫码支付,例如我上面的,还可以做支付,也就是在微信里面访问的页面,点击按钮发起支付的方式,还有一个能力就是支持个人微信小程序的,个人微信小程序无需认证也可以使用支付接口实现。 个人微信支付宝免签约支付解决方案 https://www.likeyunba.com/pay/ 我们知道要想使用微信支付,要具备以下条件 1、申请服务号2、要有企业资料(...

    zhoutk 评论0 收藏0
  • beecloud对接——微信支付

    摘要:微信支付方式付款码支付适用于线下场所支付支付是指商户通过调用微信支付提供的接口,在支付场景中调起微信支付模块完成收款。主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。 微信支付方式(https://pay.weixin.qq.com/sta...): 1、付款码支付————————适用于线下场所 2、JSAPI支付————————JSAPI支付是指商户...

    FingerLiu 评论0 收藏0
  • 微信公众号开发中的支付流程

    摘要:今天聊一下微信公众号开发在授权网页中的支付流程。前端获得签名后,再请求微信服务器,下面的支付流程就可以继续下去了。 今天聊一下微信公众号开发在授权网页中的支付流程。 微型公众号开发有以下几个步骤:1.获取全局access_token2.获取网页授权的access_token和refresh_token3.获取网页授权的签名(前端用于获取调用JSSDK的权限)4.公众号支付-调用统一下单...

    苏丹 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<