一个网名
一个网名
  • 发布:2018-08-15 10:35
  • 更新:2020-04-05 10:15
  • 阅读:7085

实力解决微信支付问题~

分类:HTML5+

关于微信支付的时候,一直提示-1的问题,我也是整理了半天,才弄出来个原因,

首先,准备工作要做好,要保证:
1、menifest.json中配置了微信的appid
2、服务端请求prepareid正确返回;
3、服务端返回数据格式与官方一致:
4、android版云打包,数字签名,与微信开放平台配置一致(不会的用百度);
这四个要保证

一、确保APP端代码没有问题
先保证用官方的基座然后模拟器测试,可以正常调起微信支付,这一点是为了保证APP里面的代码是正常的,
因为微信支付不能真机调试,而且我用自定义基座也不能正常更新,不知道是不是BUG
官方文档:支付插件配置
注意:此文章里面,官方中微信接口的链接改成这个:http://demo.dcloud.net.cn/payment/wxpayv3.HBuilder/?total=

二、将APP端请求的代码改成自己的
如果你是用上面的文档的代码的话,将WXPAYSERVER的值改成自己的服务器接口链接,然后自己证书打包安装在手机上

然后就是处理服务器端就可以了,此时安利几个工具:Fiddler(抓包)、PostMan(模拟请求)以及一款可以内网穿透的工具(如Ngrok)
有了上面三个工具,可以开心愉快的测试了

三、服务器端处理
我用的是TP5,但是其他的也一样,使用的是微信的SDK;
这一点,咱官方也是有一个github文档微信支付示例
关于这一点,如果你只按上面的文档来的话,你不会成功的,因为微信支付有两个点:1、先生成prepareid(预订单),2、根据prepareid再进行一次签名才可以返回给app!
1、生成预订单:
使用微信的SDK,要在config中配置四个参数:APPID、MCHID、KEY、APPSECRET,四个参数是什么意思在SDK中有,注意,key这个参数在下面也要使用到
我的是这样的:

        $wxOrderData = new \WxPayUnifiedOrder();  
        $wxOrderData->SetOut_trade_no($this->orderNo); //这个换成自己的订单号  
        $wxOrderData->SetTrade_type('APP');//这个参数是固定的,必须是APP  
        $wxOrderData->SetTotal_fee($orderPrice * 100); //这个是支付金额(单位是分)  
        $wxOrderData->SetBody('XXX商城'); //这个自己随意  
        $wxOrderData->SetNotify_url( $backUrl ); //这个回调,这个地址也是你自己的  
        $result = \WxPayApi::unifiedOrder($wxOrderData); //此时$result就是返回的prepareid的信息  
        // 请先确保这里请求成功,成功的话是预订单这个$result ['prepay_id'],然后调用$this->sign($result ['prepay_id']);,返回的数组就是要向app返回的信息
 2、生成签名并返回详细信息  
   之前做过小程序支付,也有这一步,于是就将小程序的代码复制过来了,结果失败,就一直没找到原因,直到我看到微信APP开发文档的时候,有这么一句话:不好意思,刚才去找了一下,,,,找不到了,反正就是签名是由五个参数生成的:timestamp、appid、partnerid、prepayid、noncestr、package,这五个少一个都不行!
    private function sign($prepayid) //$prepayid这个参数就是第1步里面获取的预订单id  
    {  
        $time = (string)time();  
        $rand = md5(time() . mt_rand(0, 1000));  
        $data = [];  
        $data['timestamp'] = $time;  
        $data['appid'] = '这是你的appid';  
        $data['partnerid'] = '这是你的商户号';  
        $data['prepayid'] = $prepayid;  
        $data['noncestr'] = $rand;  
        $data['package'] = 'Sign=WXPay';  //介个是固定的  
  
        $sign = $this->MakeSign( $data );  
  
        $data['sign'] = $sign;  
        return $data;  //这个数组就是返回给app的信息  
    }  
    private function ToUrlParams($data)  
    {  
        $buff = "";  
        foreach ($data as $k => $v)  
        {  
            if($k != "sign" && $v != "" && !is_array($v)){  
                $buff .= $k . "=" . $v . "&";  
            }  
        }  
  
        $buff = trim($buff, "&");  
        return $buff;  
    }  
    private function MakeSign( $data )  
    {  
        //签名步骤一:按字典序排序参数  
        ksort($data);  
        $string = $this->ToUrlParams($data);  
        //签名步骤二:在string后加入KEY  
        $string = $string . "&key=你的key";  //注意,敲黑板了,这里还要加上在config中配置过的key  
        //签名步骤三:MD5加密  
        $string = md5($string);  
        //签名步骤四:所有字符转为大写  
        $result = strtoupper($string);  
        return $result;  
    }

四、对比官方返回的参数,官方返回的参数是下面这样的:

{  
    "appid": "wx0411fa6a39d61297",  
    "noncestr": "9p5hdwtt0jsoYw22",    
    "package": "Sign=WXPay",   
    "partnerid": "1230636401",  
    "prepayid": "wx121809269549694a9dde5a333322923488",  
    "timestamp": 1534068566,  
    "sign": "19174B7A2EE5463007FFFF8298F4538E"  
}
  可以将自己的返回信息和上面的进行对比,发现是一样的,都是7个参数,且参数都一样  
 注:有的时候,第一次拉取成功了,但是并没有支付而是返回了,然后再拉取的时候会报错,因为订单号重复了,这时候有抓包的工具的话,是可以看到prepayid是null,因为预订单是有时效的,这个需要自己在做一下判断。  
 还有一个注意点:plus.payment.request发起支付的时候,接收到的参数是json格式的字符串而不是对象,这点要注意一下,因为我封装了ajax请求,默认将json格式转为对象,所以在用的时候要将参数再转为字符串  

以上是我自己的经验,有啥问题大家都可以分享一下。

3 关注 分享
7***@qq.com 湖东呀 skysowe

要回复文章请先登录注册

微风细雨

微风细雨

使用官方的提示未定义数组索引: appid
2020-04-05 10:15
一个网名

一个网名 (作者)

回复 1***@163.com :
先看第一步,确保app端没有问题,剩下的就是后端的问题了
2020-02-19 22:49
1***@qq.com

1***@qq.com

感谢分享!
2019-07-20 09:32
1***@163.com

1***@163.com

哥 您好我这边基座选择的标准基座运行 还是出现-1 是我前端代码问题 还是后端的
2019-05-23 16:59
小资电脑

小资电脑

谢谢分享!!!
2018-08-15 16:02
7***@qq.com

7***@qq.com

感谢分享~~
2018-08-15 13:09
s***@126.com

s***@126.com

谢谢分享!!!
2018-08-15 10:39