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的唯一性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章