Android app 微信支付爬坑

Android app 微信支付爬坑

2018-12-09    
本来开开心心的上班,安安静静的撸代码,偶尔幻想一下美好的人生多好,让我做微信支付,说没有支付的购物流程是没有灵魂的。。。当然,这是实话    

前序

先说说在做这个功能前我的状态(对微信支付的认知),四个字:一脸懵逼。 完全不知道思路,不知道专用名词的意思,不知道调试,不知道该有的步骤和思路是什么,有的只是百度(后面有了翻墙的本领,也用了谷歌)。 所以先总结一下需要用到的东西和思路。

准备

所搭建的app是基于ionic 和 cordova框架下的。app开发的时候可以在本地网页上f12调试就可以了。但要调试apk,可不会那么方便。我选择的是谷歌:chrome://inspect/#devices来进行调试。 调试需要:

  • 安卓手机一部
  • 能传数据的安卓数据线一根
  • 翻墙
  • debug.apk(调试问题的时候需要使用未签名的debug.apk,最后要调用支付的时候需要正式签名的apk)

微信支付需要:

  • AppID
  • 应用签名
  • 开发的包名
  • 商户id
  • key

这里需要详细讲一下这四个东西是咋搞来的,还有他们之间的关系是啥,有啥用。需要访问微信开放平台:https://open.weixin.qq.com

AppID

访问微信开放平台,申请app应用,申请的时候,里面所需要填的几个关键的东西是:包名,签名。包名就是我们打包的时候,项目根目录下的config.xml文件中的顶部,那里所需要填的包名,要写一致。关于这个签名,见下一步。申请完了审核过了后会有一个对应的AppId和AppSecret

应用签名

我们可以访问应用签名生成工具,下载后安装到手机上。然后打开输入正式版的apk应用的包名。可以获取到签名。包名见下一步

开发的包名

包名是和在微信开放平台申请的app所填的包名一致。也可以使用已经存在的app的包名,到时候生成签名后将该签名替换成改的签名就可以了。主要签名是用来验证这个app是不是合法的。

商户id

商户平台:https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F,这个和下面的key,是需要在商户平台下申请的,要大洋的。在api安全那里,获取权限后可以获取到。

key

这个key很重要,如果不对会得不到正确的sign签名的。在我们后台代码的处理中是必须字段。

具体关键术语和支付流程已经思路,在官方文档这里有写:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_1。

以上的准备做好后,下面就开始安装插件了。

##安装微信支付的插件

为了环境干净不会有其他的问题出现,我们可以先rm掉之前的android工程。下面是相关的命令

npm清除缓存:
npm cache clean -f

ionic移除android项目工程:
ionic platform remove android

ionic添加android项目工程:
ionic platform add android

移除微信支付插件:
cordova plugin remove cordova-plugin-wechat

添加2.0.1版本的微信支付插件:
cordova plugin add cordova-plugin-wechat@2.1.0 --variable wechatappid=wx3ee4998829defa64

cordova-android@6.4.0以下:
cordova plugin add cordova-plugin-wechat@2.1.0 --variable wechatappid=YOUR_WECHAT_APPID

cordova-android@7.0.0以上:
cordova plugin add cordova-plugin-wechatv2 --variable wechatappid=YOUR_WECHAT_APPID

index.html中添加:
<script src="cordova.js"></script>

config.xml中添加微信支付插件的说明:
<plugin name="cordova-plugin-wechat" spec="~2.1.0">
    <variable name="WECHATAPPID" value="" />
</plugin>

打包debug包:
ionic build android

如上可以看到安装完了插件后需要在config.xml中声明一下插件。然后还要在index.html中引用该插件。 安装成功后可以在plugins文件夹中看到cordova-plugin-wechat。 下面的一个注意的地方很重要,也是我花了不少时间谷歌找到的,就是在项目中需要引入cordova.js,且其路径是直接引用就可以了,因为在项目build后,在assets/www下面就有该js。注意这里的apk代码是项目工程里打包好的代码,在assers/www下的,而不是我们前面的根目录下的www。所以引入的路径要注意。 以上的步骤成功后,获得的debug.apk,可以在调试的网页上可以看到引入了wechat.js。有看到这个引入了,就说明插件安装没有问题了。

代码的实现

前端调用接口的代码

$scope.pay = function () {
                if ($scope.type == 1) {
                    Wechat.isInstalled(function (installed) {
                        if (installed) {
                            ClientOpt.opt({
                                act: 'wxpay',
                                op: 'pay',
                                orderIds: $scope.orderIds,
                                order_amount: $scope.order_amount
                            }, function (json) {
                                if (!StringUtil.isEmpty(json.datas.error)) {
                                    MyDialog.error(json.datas.error);
                                }
                                else {
                                    var params = {
                                        partnerid: json.datas.partnerid,
                                        prepayid: json.datas.prepayid,
                                        noncestr: json.datas.noncestr,
                                        timestamp: json.datas.timestamp,
                                        sign: json.datas.sign
                                    };
                                    Wechat.sendPaymentRequest(params, function () {
                                        MyDialog.tip("支付成功");
                                        $rootScope.gotoPage('/mine_order/0');
                                    }, function (reason) {
                                        MyDialog.tip("Failed: " + reason);
                                        $rootScope.gotoPage('/mine_order/0');
                                    });
                                }
                            });
                        }
                        else {
                            MyDialog.tip("尚未安装微信");
                        }
                    }, function (reason) {

                    });
                }

上面的代码中我们传的参数有订单的id号,和需要支付的金额。也可以在前端这里传appid,但建议在后端用三元处理。

后端微信支付相关代码

public function payOp(){
        $app_id=empty($_REQUEST['appID'])?"自己的appid":$_REQUEST['appID'];
        $mch_id='商户id';
        $app_key='商户的那个key';
        $openid=$_REQUEST['openid'];
        // order_info
        $orderIds=$_REQUEST['orderIds'];
        if(empty($orderIds)){
            output_error("网络繁忙");
        }
        $orderIds=getRandChar(5)."_".$orderIds;
        $order_amount=(float)$_REQUEST['order_amount'];
        // get prepay id
        $prepay_id = $this->generatePrepayId($app_id, $mch_id, $app_key,$orderIds,$order_amount,$openid);
        // re-sign it
        if($_REQUEST['platform'] == "wxmini"){ //小程序的支付接口
            $response = array(
                'appId' => $app_id,
                'timeStamp' => ''.time(),
                'nonceStr' => $this->generateNonce(),
                'package' => 'prepay_id='.$prepay_id,
                'signType' => 'MD5'
            );
            $response['paySign'] = $this->calculateSign($response, $app_key);
        }
        else{
            $response = array(
                'appid'     => $app_id,
                'partnerid' => $mch_id,
                'prepayid'  => $prepay_id,
                'package'   => 'Sign=WXPay',
                'noncestr'  => $this->generateNonce(),
                'timestamp' => time(),
            );
            $response['sign'] = $this->calculateSign($response, $app_key);
        }
        output_data($response);
    }

具体代码已保存在百度云(wxpay.php和wxpaynotify.php回调验证数据是否正确文件,用于检验数据库的数据是否是正确的,从而避免只使用了前端js来判断支付的成败)

在接下来调用微信支付

调用微信支付

需要使用我们填在开放平台那个app下面的签名的那个keystore来进行签名。得到签名后的apk安装运行,才可以调起支付接口。

完整做好上面的步骤就可以完成支付的全流程了。当然,在后台代码的实现上还是需要注意很多地方的,有时间的话会再单独写一个里面的坑(主要是官方文档中的巨坑)。然后再后面做微信分享和登陆等,再一一写到来。

相关参考链接:

  • https://blog.csdn.net/m00123456789/article/details/56481656
  • https://pay.weixin.qq.com/wiki/tools/signverify/
  • https://blog.csdn.net/ws1836300/article/details/53893102
  • https://blog.csdn.net/xinluqishi123/article/details/74596357
  • https://www.cnblogs.com/porter/p/6364633.html
  • https://blog.csdn.net/qq_34815528/article/details/78264958
  • https://blog.csdn.net/nnmmbb/article/details/50533138
  • https://segmentfault.com/q/1010000012787760