Android就业面试技巧系列-技术篇11 (支付相关)

Android就业面试技巧系列-技术篇(支付相关)

关于支付,相信很多同学都不陌生,而且这也是找工作面试官问的高频问题,这一篇文章主要就是向大家详细介绍一下支付的一些流程。
支付难不难?
> 不难,都是属于第三方的东西.难度不大
支付安不安全?
> 肯定是安全的.因为这些都是大公司的产品.都有自己的安全策略;
做一个支付需要多久?
项目评估时间和实际开发有出入的,一般是两倍关系
比如你一天能搞完,那你至少评估2天
前期准备工作可能就是 一周左右
程序员实际集成时间
* 项目评估
* 支付宝:大概5分钟.
* 银联支付:大概5分钟.
* 微信支付:大概10分钟.

支付流程_从生活出发
1. 选择商品
2. 选择支付方式
3. 处理支付结果
    1. 成功
    2. 失败
    3. 取消

支付流程_从app开发角度(保证可以先完成功能)
1. 拼接支付信息,post到服务器;-->request
    1. 支付信息包含支付方式
    2. 服务器:***是我们自己的服务器***
    3. 支付协议:`http://mobileif.maizuo.com/version3/orderform/order?version=2`
2. 服务器返回`支付串码`;--->reponse
        请求的url(支付协议/确认订单协议):  http://mobileif.maizuo.com/version3/orderform/order?version=2
        请求方式:post
        post参数形式:jsonString
        输入参数:

[Java]  纯文本查看  复制代码
?
1
2
{ "goodInfos" :[{ "goodCounts" : "1" , "goodExtInfo" :{}, "goodIDs" : "361" , "goodType" : "1" }], "loginFlag" : "0" , "mobile" : "18682036558" , "orderId" : "0" , "otherInfo" :{ "agentID" : "0-maizuo" , "channelID" : "31" , "clientID" : "31" }, "payDatas" :{ "discountInfo" :{ "activeID" : "0" , "discountID" : "0" , "discountPrice" : "" }, "payInfo" :[{ "bankType" : "7" , "payCount" : "3200" , "payTicketCount" : "1" , "payType" : "1" }], "payPass" : "" , "returnUrl" : "" , "totalPrice" : "3200" }, "processPath" : "1" , "sessionKey" : "mqneaadqapkpkqshxvdj" , "userID" : "200394160" }
         输出结果{ "result" : "ok" , "payExtInfo" :{ "alipayVerifyKey" : "_input_charset=\"UTF-8\"&body=\"卖座网电子影票\"&it_b_pay=\"1h\"¬ify_url=\"http%3A%2F%2Fpay.maizuo.com%2FmobileBack.htm\"&out_trade_no=\"201507238712113008\"&partner=\"2088411628331920\"&payment_type=\"1\"&seller_id=\"2088411628331920\"&service=\"mobile.securitypay.pay\"&subject=\"深圳金逸影城沙井店(2D通兑票1张)\"&total_fee=\"32.00\"&sign=\"M0O0Ej5J13A25SAWupc5a6vAGmJnblx2CvuWF2dwFGxMZ%2BxlRWmp%2F6ZDfI8Y%2FFJbjiEqE99MAsKh%0AfIBQqP4Y1TyNkbY0XixQFPgAAqsqwGqYJSDtqUFWRgje%2B8pI1KuxfPE3UcDZs4hxDZoP%2Bdof%2Bldf%0AKQmximUyqT5Crtwj1Ag%3D\"&sign_type=\"RSA\"" }, "bankType" : "" , "userId" : "200394160" , "resource" :{ "rel" : "view" , "link" : "/orderform/200394160/201507238712113008" }, "payType" : "7" , "payUrl" : "" , "orderId" : "201507238712113008" , "uniqueKey" : "D5585vO8624915A11z" , "timeNow" : "1437622208552" }

3. 拿着支付串码,调用第三方服务,完成支付-->5分钟    (调用支付宝服务)
   下载文档和 demo 来处理
4. 处理支付结果
    1. 同步返回:支付后通知我们自己的apk
    2. 异步通知:支付后通知我们的server

什么是支付串码
这个是自己定义的一个概念.其实就是第三步调用起第三方支付平台`核心支付方法所需要的参数`
集成支付宝流程
1. 我们自己要和支付宝签约(商户签约).-->运营去签合同
2. 秘钥配置-->协助运营完成秘钥的配置(公钥互换),可能程序员会参与
   
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
// 合作身份者ID,以2088开头由16位纯数字组成的字符串
    public static final String ALIPAY_PartnerID = "" ;
    // 商户签约支付宝账号
    public static final String ALIPAY_SellerID = "" ;
    // 商户的私钥(MD5)
    public static final String ALIPAY_MD5_KEY = "" ;
    // 商户私钥(RSA),用户自动生成
    public static final String ALIPAY_PartnerPrivKey = "" ;
    // 支付宝公钥,无需修改该值  demo里面有的
    public static final String ALIPAY_PubKey = "" ;

3. 集成支付宝-->必须是程序员去做.
    1. 下载sdk/demo/文档
    2. demo尝试的去运行
        1. 出现了错误:因为缺少运行必须的,DEFAULT_PARTNER,DEFAULT_SELLER,如果1,2步完成的话,我们在这个时候就可以有`DEFAULT_PARTNER,DEFAULT_SELLER`
    3. 开始集成-->`参照移动快捷支付应用集成接入包支付接口接入与使用规则.pdf`
        1. 添加jar,alipay.jar
        2. 添加lib,alipay_lib
        3. 添加了一个activity
        4. 添加了一些权限
        5. 调用支付的核心代码
               
[Java]  纯文本查看  复制代码
?
1
2
3
4
5
6
//    3.调用第三方服务,完成支付
                //获取Alipay对象,构造参数为当前Activity和Handler实例对象
                AliPay alipay = new AliPay(MainActivity. this , mHandler);
                //调用pay方法,将订单信息传入
                //同步返回    取消操作  支付成功  支付失败(网络异常)
                String payResult = alipay.pay(alipayVerifyKey);

        6. 处理支付结果--->支付宝处理支付结果用的handler机制
               
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**---------------demo里面处理支付结果的代码---------------**/
    
                /*Result result = new Result((String) msg.obj);
                switch (msg.what) {
                case RQF_PAY:
                case RQF_LOGIN: {
                    Toast.makeText(ExternalPartner.this, result.getResult(), Toast.LENGTH_SHORT).show();
    
                }
                    break;
                default:
                    break;
                }
                */
                /**---------------老师实际开发处理支付结果的代码---------------**/
                
                /*Result.sResult = (String) msg.obj;
                Logger.i(TAG, "strRet:" + Result.sResult);
                try {
                    String errorMsg = Result.getPayResult();
                    Logger.i(TAG, "errorMsg:" + errorMsg);
                    if (!"".equals(errorMsg)) {
                        Toast.makeText(getApplicationContext(), errorMsg, 0).show();
                        if ("操作成功".equals(errorMsg)) {
                            payOk();//支付成功可以调到订单界面
                        } else {
                            payFail();//可以弹出对话框进行重复支付
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    if (!PayActivity.this.isFinishing()) {
                        BaseHelper.showDialog(PayActivity.this, "提示", Result.sResult + ",如有疑问请联系卖座客服:4001808400", R.drawable.infoicon);
                    }
                }
            }
            };*/

支付宝demo分析
* 查看demo发现他的`支付串码`,是在客户端生成的.这个和老师所讲的.支付串码由服务器生成.有出入;
* 为了不暴露我们privatekey,我们应该把生成支付串码的过程交给我们的服务器
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
/**---------------生成支付串码的过程  begin---------------**/
         Log.i( "ExternalPartner" , "onItemClick" );
         String info = getNewOrderInfo(position);
         //其实下面的操作应该是server端去完成.不然我们会暴露privatekey---begin---add_by_billy
         //所有我们会把info的具体内容用jsonString的形式.post给server进行签名.然后返回签名后的结果---add_by_billy
         String sign = Rsa.sign(info, Keys.PRIVATE);
         sign = URLEncoder.encode(sign);
         info += "&sign=\"" + sign + "\"&" + getSignType();
         Log.i( "ExternalPartner" , "start pay" );
         // start the pay.
         Log.i(TAG, "info = " + info);
         //其实下面的操作应该是server端去完成.不然我们会暴露privatekey---end---add_by_billy
         final String orderInfo = info;
         /**---------------生成支付串码的过程  end---------------**/
  
支付串码_自己定义的一个概念
> 支付串码就是调用第三方应用的时候需要的一些核心的参数   按照第三方支付的规范码
支付串码在支付宝就相当于订单信息
支付串码在银联就相当于交易流水号
支付串码在微信就相当于订单信息

银联支付
* 银联支付,就`只需要一个交易流水号`就可以,而且看代码比较简单,重点是,`银联强制要求生产支付串码的过程必须交给我们的服务端`
* 集成形式
    * 内嵌apk形式:就是把一个apk放到我们的assets目录下面-->老的方式
    * 新版本so库形式:在libs下面就有很多的so库.已经不需要在assets目录下面放置apk
* 模式:
    * 测试模式:银联会给我们提供一个测试环境+提供了一个银联的账号/密码
    * 正式模式:就必须使用真实的账号/密码
* 运行demo看效果:
* 集成步骤:
    * 1.添加libs里面相关的东西;
    * 2.添加activity配置
  
[XML]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
< activity
             android:name = "com.unionpay.uppay.PayActivityEx"
             android:configChanges = "orientation|keyboardHidden|screenSize"
             android:excludeFromRecents = "true"
             android:label = "@string/app_name"
             android:screenOrientation = "portrait"
             android:windowSoftInputMode = "adjustResize" />
             < activity
                 android:name = "com.unionpay.uppay.PayActivity"
                 android:configChanges = "orientation|keyboardHidden|screenSize"
                 android:excludeFromRecents = "true"
                 android:screenOrientation = "portrait" />


    * 3.添加权限
           
[XML]  纯文本查看  复制代码
?
1
2
3
4
<!-- uupay -->
            < uses-permission android:name = "android.permission.CHANGE_NETWORK_STATE" />
            < uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
            < uses-permission android:name = "android.permission.READ_PHONE_STATE" />

    * 4.调用核心的支付方法
        
[Java]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
8
//拿着支付串码
         System.out.println( "alipayVerifyKey:" + alipayVerifyKey);
         //    3.调用第三方服务,完成支付
         // “00” – 银联正式环境
         // “01” – 银联测试环境,该环境中不发生真实交易
         //tn 交易流水号 
         UPPayAssistEx.startPayByJAR(MainActivity. this , PayActivity. class , null , null ,
                 alipayVerifyKey, "00" );

    * 5.处理支付结果
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**---------------银联处理支付结果---------------**/
          protected void onActivityResult( int requestCode, int resultCode, Intent data) {
          /*************************************************
           *
           * 步骤4:处理银联手机支付控件返回的支付结果
           *
           ************************************************/
          if (data == null ) {
              return ;
          }
  
          String msg = "" ;
          /*
           * 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消
           */
          String str = data.getExtras().getString( "pay_result" );
          if (str.equalsIgnoreCase( "success" )) {
              msg = "支付成功!" ;
          } else if (str.equalsIgnoreCase( "fail" )) {
              msg = "支付失败!" ;
          } else if (str.equalsIgnoreCase( "cancel" )) {
              msg = "用户取消了支付" ;
          }
  
          AlertDialog.Builder builder = new AlertDialog.Builder( this );
          builder.setTitle( "支付结果通知" );
          builder.setMessage(msg);
          builder.setInverseBackgroundForced( true );
          // builder.setCustomTitle();
          builder.setNegativeButton( "确定" , new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int which) {
                  dialog.dismiss();
              }
          });
          builder.create().show();
          }

微信支付
* 直接运行demo,发现最后提示错误,发现工程下面有一个debug.keystore
* 想要运行.可以如下操作
    * 自定义keystore
    * 或者直接导出的时候用工程下面的debug.keystore去签名
    window-----Android----Build----Custom debug keystore:微信debug.keystore的路径
如果上面的apk用微信支付还报错的话,那么就需要把apk签名(debug.keystore)打包生成的apk
先将该app注册到微信,然后再调用支付界面支付就可以了
* 微信支付的安全策略之一:必须包名和keystore签名需要一致  即利用包名和keystore(sha1值)生成安全码
* demo里面定义的步骤
    * 一、获取  access_token
    * 二、生成预支付订单,需要用到第一步的access_token,得到的是prepayId
    * 三、调起微信支付
    * 四、处理支付结果
    * 这个时候一看.感觉微信支付很难.但是我们看到demo里面这样的一句话`注意:不能hardcode在客户端,建议genPackage这个过程由服务器端完成`,所以,其实我们的微信支付,一、二步骤为了安全起见应该交给Server
* 实际开发,只需关心3,4步就可以
    * 三、调起微信支付  
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
            * @author Administrator
            * 支付的时候真正关心的数据
            * 这个对象是我自己封装的.和微信支付的sdk没有关系
            */
           public class WXPayData {
           private String sign_method;
           private String timestamp;
           private String noncestr;
           private String partnerid;
           private String app_signature;
           private String prepayid;
           private String package1;
           private String appid;
           }
           
           //核心支付方法
           private void sendPayReq(WXPayData info) {
           api = WXAPIFactory.createWXAPI( this , info.getAppid());
           PayReq req = new PayReq();
           req.appId = info.getAppid();
           req.partnerId = info.getPartnerid();
           req.prepayId = info.getPrepayid(); //预支付id
           req.nonceStr = info.getNoncestr(); //32位内的随机串,防重发
           req.timeStamp = String.valueOf(info.getTimestamp()); //时间戳,为 1970 年 1 月 1 日 00:00 到请求发起时间的秒数
           req.packageValue = info.getPackage1();
           req.sign = info.getApp_signature();
           // 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
           api.sendReq(req);
   }

    * 四、处理支付结果:微信支付支付的回调是在`net.sourceforge.simcpux.wxapi.WXPayEntryActivity.class`里面
         
[Java]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
@Override
           public void onResp(BaseResp resp) {
           Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
   
           if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
               AlertDialog.Builder builder = new AlertDialog.Builder( this );
               builder.setTitle(R.string.app_tip);
               builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
               builder.show();
           }
           }

安全码策略
> 安全码的组成规则为:Android签名证书的sha1值+“;”+packagename(即:数字签名+分号+包名)
* 作用:确定apk的唯一性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值