查看原文
其他

【干货】微信支付,银联支付,支付宝支付——三大支付总结你get到了吗

2017-05-24 于亚豪 终端研发部

前言介绍

银联支付,支付宝支付,微信支付的三大支付总结,之前也有写过两篇。

三大支付总结:

支付宝植入总结:

微信支付总结:

正文

之前有做过支付宝支付和微信支付,所以这次做起来碰到的问题很少,key申请下来之后很快就搞定了。吼吼

效果图:

由于用鲁大师去截屏获取gif,鲁大师一针一针绘制图片的时候应该没做好处理,导致跳转到相应的界面出现黑屏现象。在手机上正常跳转,无黑屏现象。大家不用担心这个

备注:出于安全考虑,验签我们都是放到后台进行验签的。对于我们移动端节省了很多的劳动力。

准备

需要以公司名义,在支付宝,微信等平台上开通公司账户并且认证,如:支付过程中需要公司的帐号和商户号。

支付宝支付

如果碰到一些坑的话,请参考我之前写过的意一篇支付宝踩坑的文章:

  • 参考文档:

  1. 首先支付宝申请并集成支付宝SDK 这里不再详细介绍

  • 如:

    price=12.5&num=12 //价格为12.5,数量为12
  1. 获取订单信息(根据自己公司的实际情况:可以在服务端完成,也可以在本地完成)


    1. 客户端拿这些订单信息向服务器后台进行请求,返回支付签名信息signInfo


    1. app携带支付信息,调用支付接口请求支付宝客户端,从而调起支付界面

    /**         * 支付宝进行请求         *         * @param signInfo         */        private void payToOrderService(final String signInfo) {            new Thread() {                @Override                public void run() {                    super.run();                    
                       PayTask payTask = new PayTask(MyScannerPayActivity.this);                    // String result = payTask.pay(signInfo, true);                  
                        Map<String, String> result = payTask.payV2(signInfo, true);                
                        Message message = mHandler.obtainMessage();                    message.what = SDK_PAY_FLAG;                    message.obj = result;                    mHandler.sendMessage(message);                    }            }.start();        }

    1. 用户操作,输入密码支付,支付成功;直接返回取消支付;出现错误,支付失败;进入支付界面,但输入密码支付,支付待确认;


    1. 支付宝客户端将支付结果告诉app客户端,商户服务器通知app服务器支付结果;


    1. app客户端处理支付结果;


    1. app服务器处理支付结果。

    处理结果通知:

    private Handler mHandler = new Handler() {        
    @Override        public void handleMessage(Message msg) {        
                   super.handleMessage(msg);          
                    switch (msg.what) {  
                     case SDK_PAY_FLAG:                    PayResult payResult = null;                                                 try {                        payResult = new PayResult((Map<String, String>) msg.obj);                    } catch (Exception e) {                        e.printStackTrace();                    }                    /**                     对于支付结果,请商户依赖服务端的异步通知结果。同步通知结果,仅作为支付结束的通知。                     */                    String resultInfo = payResult.getResult();// 同步返回需要验证的信息                    String resultStatus = payResult.getResultStatus();                    // 判断resultStatus 为9000则代表支付成功                    if (TextUtils.equals(resultStatus, PAY_OK)) {                        ActivityUtils.showActivity(MyScannerPayActivity.this, ScannerPaySuccessActivity.class);                        finish();                    } else if (TextUtils.equals(resultStatus, PAY_FAILED)) {//------------------------->支付失败                        // 该笔订单真实的支付结果,需要依赖服务端的异步通知。                        Toast.makeText(MyScannerPayActivity.this, "" + payResult.getMemo(), Toast.LENGTH_LONG).show();                    } else if (TextUtils.equals(resultStatus, PAY_CANCLE)) {//-------------------------->交易取消                        Toast.makeText(MyScannerPayActivity.this, "" + payResult.getMemo(), Toast.LENGTH_LONG).show();                    } else if (TextUtils.equals(resultStatus, PAY_NET_ERR)) {//------------------------->网络出现错误                        Toast.makeText(MyScannerPayActivity.this, "" + payResult.getMemo(), Toast.LENGTH_LONG).show();                    } else if (TextUtils.equals(resultStatus, PAY_WAIT_CONFIRM)) {//--------------------->交替等待                    }  
                      break;            }        }    };

    银联支付

    先看一下官方给我们的银联支付流程图:

    大家不要被这张图片搞懵逼的了,其实很简单,这里我将其分为5小步。

    • 第一步:根据官方文档选择符合自己的sdk

      官方文档:

    • 第二步:将相对应的.so文件copy到 自己的工程里面去。

      特别注意:

      .so文件要放在src/main 目录下,和Java文件并行。还有就是把用到的权限复制到自己项目中)

    • 第三步: 和支付宝一样,APP客户端带着这些订单号向服务器后台请求订单号orderNo

    • 第四步:服务器后台接收到购买信息之后,将信息提交给银联后台,银联接收到后台之后给服务器返回tn号

    • 第五步:开启调用银联支付。APP客户端带着这个流水号,也就是第三步中服务器返回的tn号,调用银联SDK所提供的方法

      注意:

      这个订单流水号为21位纯数字号

      调用方法: UPPayAssistEx.startPay(this, null, null, tn, mMode);

    结果返回

    处理银联手机支付控件返回的支付结果 调用银联支付后,返回app的时候用了,看返回结果传,成功,失败,或者是什么返回。 如图所示:

    最后注意在调用: /***************************************************************** * mMode参数解释: "00" - 启动银联正式环境 "01" - 连接银联测试环境 *****************************************************************/ private final String mMode = "00";

    注意:

    tn值就是上面第三后台给的tn,给到服务器那里, 这里我这边是通过后台请求下来的,关于mMode,看第一步骤,自己改一下就行了,00开发环境,01测试环境。但是要注意,这个只是个回调接口方法。

    总感觉银联支付的SDK调用起来怪怪的,貌似回到了原始深林。

    微信支付:

    • 建议先参考我之前写的 Android 微信支付总结的一篇博文:

    微信支付总结:

    接入流程图:

    • 接入流程:

    1. 申请开发者账号 地址: 进入管理中心,创建移动应用

    2. 申请支付能力

    3. 代码集成微信支付

  • 代码集成微信支付

  • HashMap<String ,String> params = getHeadMap();  
     params.put("appid", appID);// 微信appid,选择性上传,服务器写死亦可    params.put("money", money);// 支付金额,单位:分    params.put("goodName", goodsName);// 商品名称    params.put("productNum", String.valueOf(12));// 商品的数量
    • 2.app服务器调用微信“统一下单”接口,得到prePayId订单号并返回prePayId给手机客户端;

      3.手机客户端使用prePayId及商品信息调起微信客户端进行支付;

      3.1用户操作:输入密码进行支付;返回键取消支付;网络无连接支付失败等;

      4.微信客户端回调支付结果给咱们的APP客户端;

      5.微信服务器异步通知咱们公司app服务器支付结果(服务器的工作,与客户端无关)

    • 1.客户端代码得到用户购买的商品信息,将之传给自己公司app服务器,参数包含但不限于以下:

    相关的支付调用代码:

    IWXAPI mWxApi = WXAPIFactory.createWXAPI(mContext, WX_APPID, true); mWxApi.registerApp(WX_APPID);         /**          * 请求app服务器得到的回调结果          */         @Override         public void onGet(JSONObject jsonObject) {            
               if (mWxApi != null) {                 PayReq req = new PayReq();                 req.appId = WX_APPID;// 微信开放平台审核通过的应用APPID                 try {                     req.partnerId = jsonObject.getString("partnerid");// 微信支付分配的商户号                     req.prepayId = jsonObject.getString("prepayid");// 预支付订单号,app服务器调用“统一下单”接口获取                     req.nonceStr = jsonObject.getString("noncestr");// 随机字符串,不长于32位,服务器小哥会给咱生成                     req.timeStamp = jsonObject.getString("timestamp");// 时间戳,app服务器小哥给出                     req.packageValue = jsonObject.getString("package");// 固定值Sign=WXPay,可以直接写死,服务器返回的也是这个固定值                     req.sign = jsonObject.getString("sign");// 签名,服务器小哥给出,他会根据:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3指导得到这个                 } catch (JSONException e) {                     e.printStackTrace();                 }                 mWxApi.sendReq(req);                 Log.d("发起微信支付申请");             }         }
    注意事项:
    • 1.首先如果要使用微信支付的话

      • 必须先到微信开放平台注册应用,具体地址为https://open.weixin.qq.com/

      • 注册时需要填应用的包名和签名,注意这里的签名是App正式版的签名,可以找一个已上线的包或打一个正式包,使用微信提供的工具(签名工具下载地址为https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk)来获取,获取后填上即可。

      • 待审核通过后,会得到一个AppID和AppSecret,AppID分享和支付都要用到,AppSecret没什么实际用途,此时微信分享能力是直接拥有的,支付能力还要额外申请,其中涉及到财务信息等

      • 最好让公司财务部门去申请,申请成功后会拿到一个商户id,后面生成sign时会用到。

      • 只有所有审核都通过后,才可调用微信支付功能,这点是前提。

    • 2.微信分享和微信支付SDK是同一个架包,名为libammsdk.jar。

    • 3.官方开发文档中有一处错误,需要注意下,如下图最后一行参数req应该为request,照搬代码的估计IDE也不会放过你,哈哈

    • 4.测试微信支付时,务必对自己的App做正式签名,因为一开始就在微信平台注册过签名信息,微信SDK会做校验,只有这样才能调起微信分享和微信支付,直接debug版的包则绝对调不起来,这点务必注意,很多人是跌在这里了!当初做微信分享曾遇到过,所以会很留心,也因为如此,如果微信分享能调起来,微信支付不行,那就不要怀疑签名问题了。

    • 5.还是签名,网上有人说要注意大小写,这点其实是不必的。在微信开放平台看到审核通过的App的签名是大写的,而用微信签名获取工具获得的则显示小写,这个没关系,不要贸然改动平台注册信息,不然又可能导致漫长的审核等待,上面也说了,微信分享如可以,那就不是签名问题。

    • 6.来说下官方demo,这东西害人不浅啊!很多人参考其写法,如生成sign放在客户端啊,调支付的Activity添加intent-filter啊,最主要的还是签名问题。其实客户端逻辑很简单,直接上手集成即可,demo看看逻辑就行,照抄小心掉坑里。

    • 7.网上有人说需要给调用支付的Activity配置如下intent-filter(见下图),可能也是被demo误导了

    • 8.对于errCode返回-1,有人说清除微信缓存或切换账户就好了,这种解决方案治标不治本啊,根本不能算解决方案。虽然我没遇到能用这方法解决的问题,但目测是签名的问题,建议还得找到真正的问题所在。

    • 9.生成sign时特别需要注意:

      • 首先将key-value键值对拼成字符串,注意key都要小写,如appid,noncestr,package,partnerid,prepayid,timestamp,key,并且名字得按上述名称

      • 我们遇到的错误就是因为partnerid写成了partnerId,prepayid写成了PrepayId,当然我们是在服务端写的,如果在客户端生成sign的话,也需要注意大小写及名称,详细信息请参考官方文档。

      • 还有这里的key并非AppID或AppSectet,而是在商户平台设置的,官方描述为“key设置路径:微信商户平台()-->账户设置-->API安全-->密钥设置”。对于noncestr,申请prepayid和生成sign时两次需要用到,由于iOS同事看到相关文章说noncestr前后需要一致,因此这个随机字符串我们是设置成一样的了,这样做Android平台也是OK的,不过个人感觉这里可以不一致,由于这个逻辑在服务器端,我并没有验证,方便的同学可以验证下。

    • 10.req.packageValue=”Sign=WXPay”,一般都是这样写死这个参数值。也有人说写成req.packageValue=”prepay_id=” + prepayid,经测试Android两种写法都是可以调起微信支付的,至少最新版本SDK是可以的,以后则不清楚,官方也建议写Sign=WXPay,据说iOS只支持这种写法。

    以上是我之前做微信支付的时候的一些总结,今天再次拿出来供大家参考

    之前的历史文章:

    支付宝植入总结:

    微信支付总结:



    让心,在阳光下学会舞蹈

    让灵魂,在痛苦中学会微笑

    —终端研发部—



    如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809   

    微信公众号:终端研发部


                

    Hello,伙伴们

    长按二维码就可以关注我们啦


    (欢迎关注学习和交流)

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存