国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android支付寶支付設計開發

2020-04-11 10:46:51
字體:
來源:轉載
供稿:網友

     在移動支付領域,支付寶支付占用巨大份額,根據艾瑞咨詢公布的報告數據:2014Q3,支付寶斬獲了82.6%的市場份額,在移動支付的霸主地位越來越穩固。財付通支付的發力點在微信支付和手Q支付,在移動支付格局中取得了10.0%的市場份額,排名第二。

     支付寶在移動支付領域的統治地位,使得我們有必要梳理支付寶移動開發流程。本文寫作的目的就是梳理支付流程,從架構層面講述如何在移動應用中嵌入支付寶支付功能,以及指出哪些地方存在開發陷阱。

準備 
     按照說明,首先需要申請支付寶支付賬號。這方面根據網站說明進行申請即可。一般需要2周左右的時間批準下來。

申請成功后賬號信息包括 合作者身份ID partner, 賣家支付寶賬號 seller_id,以及私鑰 privateKey等。這三項將用于開發過程。

     在官網上下載移動支付集成開發包。解壓后, 發現其下包括三個文件夾(在英文Mac系統下文件名顯示為亂碼):

  • “商戶接入支付寶收銀臺界面展示標準”:講的是如何使用支付寶Logo。
  • “支付寶錢包支付接口開發包2.0標準版”:用于支付,包括客戶端和服務器端開發。
  • “即時到賬批量退款有密接口refund_fastpay_by_platform_pwd”:用于到賬及批量退款,只需要服務器端操作處理。

后兩個文件夾,都包括4方面內容:接口文檔,接入與使用規則,demo代碼,以及版本更新說明。
架構設計
首先,對于一個實際的App應用而言,可能會包括多種支付方式,因此可以采用設計模式中的策略Strategy模式來設計支付功能模塊,支付寶支付作為其中的一個策略,pay方法是支付算法。
如果除了支付方式payment method變化,訂單order也可能會有不同的形式,如格式可能不同,有些支持可退款,有的不允許退款等,在這種多維度可變的情況下,支付模塊的架構可以基于橋接模式。
其次,可以把支付寶支付的各個操作步驟,比如獲取訂單號,生成訂單數據,進行支付,獲取支付結果,處理異常等操作,根據狀態進行劃分。這樣采用狀態模式,提供設計的靈活性和擴展性。另外也可以設計狀態機進行統一的狀態切換管理。下面為參考代碼:

public class PayStateMachine {  /* all possible state of payment */  public enum PayState { PAY_INIT, PAY_GOT_CONTEXT, PAY_UPDATED_ORDER, PAY_APPLIED_   ID, PAY_ORDER_CREATED, PAY_SUCCEED, ERROR_OCCURRED}            /* errors may occurred during payment */  public enum PayError {    PAY_GET_CONTEXT_FAIL, PAY_UPDATE_ORDER_FAIL, PAY_APPLY_ID_FAIL, PAY_FAIL  }            private static PayStateMachine instance;  private PayState state;  private IOrder order;  private IPayment payment;            private PayStateMachine() {  }            public static PayStateMachine getInstance() {    if (instance == null) {      instance = new PayStateMachine();    }              return instance;  }            public void initPayment(IOrder order, IPayment payment) {    this.order = order;    this.payment = payment;    this.state = PayState.PAY_INIT;  }            public void startPay() {    changeState(PayState.PAY_INIT);  }            public void changeState(PayState state) {    onStateChanged(this.state, state);  }            public void reportError(PayError error, String detail) {    LogUtil.printPayLog("the error id is:" + error + " " + detail);    changeState(PayState.ERROR_OCCURRED);  }            private void onStateChanged(PayState oldState, PayState newState) {    LogUtil.printPayLog("oid state:" + oldState + " new state:" + newState);    this.state = newState;         handlePayStateChange();  }            private void handlePayStateChange() {    if (this.order == null || this.payment == null) {      LogUtil.printPayLog("Have not initiated payment");      return;    }              switch (this.state) {      case PAY_INIT:        order.getPayContext();        break;      case PAY_GOT_CONTEXT:        order.createOrder();        break;      case PAY_UPDATED_ORDER:      case PAY_APPLIED_ID:      case PAY_ORDER_CREATED:        payment.pay(order);        break;                case PAY_SUCCEED:      case ERROR_OCCURRED:        finishProcess();        break;      default:        LogUtil.printPayLog("state is not correct!");        finishProcess();     }  }            private void finishProcess() {    this.order = null;    this.payment = null;    this.state = PayState.PAY_INIT;  }}

最后,訂單類層次可以參考模板模式來設計,例如抽象基類負責定義訂單的操作框架和流程,具體訂單數據的生成延遲到子類中實現。

支付流程
本文針對Android版進行講解主要的支付流程,IOS版流程類似。
1、客戶端實現
本文結合操作流程和數據流程,講述主要的實現方案。
首先假設訂單數據都已經存儲在OrderPayModel中。
第一步:App客戶端訪問應用服務器,后者生成訂單編號并返回客戶端。

private void getOrderIdRequest() { JSONObject ob = new JSONObject(); ob.put("amount", orderPayModel.getOrderPriceTotal());         ob.put("productDescription", orderPayModel.getOrderName());                 ob.put("userId", orderPayModel.getUserId()); ob.put("barCoupon", orderPayModel.getOrderId()); ob.put("barId", orderPayModel.getBarId()); ob.put("count", orderPayModel.getOrderNums()); LogUtil.printPayLog("get order id request data:"  + orderPayModel.toString());                 HttpRequestFactory.getInstance().doPostRequest(Urls.ALI_PAY_APPLY, ob,  new AsyncHttpResponseHandler() {                   @Override   public void onSuccess(String content) {   super.onSuccess(content);                   LogUtil.printPayLog("get order id request is handled");                   PayNewOrderModel rm = new PayNewOrderModel();   rm = JSON.parseObject(content, PayNewOrderModel.class);                   if (rm.getCode() != null    && "200".equalsIgnoreCase(rm.getCode())) {    tradeNo = rm.getResult().getTrade_no();    LogUtil.printPayLog("succeed to get order id:"     + tradeNo);                    orderStr = generateOrder();    PayStateMachine.getInstance().changeState(     PayState.PAY_APPLIED_ID);                   } else {    PayStateMachine.getInstance().reportError(     PayError.PAY_APPLY_ID_FAIL,     "code is not right");   }   }                   @Override   public void onFailure(Throwable error, String content) {   PayStateMachine.getInstance().reportError(    PayError.PAY_APPLY_ID_FAIL,    "failed to get order id");                   };                   @Override   public void onFinish() {   LogUtil.LogDebug("Payment", "on get order id finish",    null);                   };  }); }

第二步:組裝訂單數據,包括以下幾個子步驟:
創建訂單數據。

private String getOrderInfo(String partner, String seller) { String orderInfo;          // 合作者身份ID  orderInfo = "partner=" + "/"" + partner + "/"";                  // 賣家支付寶賬號  orderInfo += "&seller_id=" + "/"" + seller + "/"";                  // 商戶網站唯一訂單號  orderInfo += "&out_trade_no=" + "/"" + tradeNo + "/"";                  // 商品名稱  orderInfo += "&subject=" + "/"" + orderName + "/"";                  // 商品詳情  orderInfo += "&body=" + "/"" + orderDetail + "/"";                  // 商品金額  orderInfo += "&total_fee=" + "/"" + totalPrice + "/"";  // orderInfo += "&total_fee=" + "/"" + "0.01" + "/"";                  // 服務器異步通知頁面路徑  orderInfo += "¬ify_url=" + "/"" + Urls.ALI_PAY_NOTIFY + "/"";                  // 接口名稱, 固定值  orderInfo += "&service=/"mobile.securitypay.pay/"";                  // 支付類型, 固定值  orderInfo += "&payment_type=/"1/"";                  // 參數編碼, 固定值  orderInfo += "&_input_charset=/"utf-8/"";                  // 設置未付款交易的超時時間  // 默認30分鐘,一旦超時,該筆交易就會自動被關閉。  // 取值范圍:1m~15d。  // m-分鐘,h-小時,d-天,1c-當天(無論交易何時創建,都在0點關閉)。  // 該參數數值不接受小數點,如1.5h,可轉換為90m。  orderInfo += "&it_b_pay=/"30m/"";                  // 支付寶處理完請求后,當前頁面跳轉到商戶指定頁面的路徑.  // orderInfo += "&return_url=/"m.alipay.com/"";  // Bill: this item must not be empty! though the api demo said it  // can be.  orderInfo += "&return_url=/"m.alipay.com/"";                  // 調用銀行卡支付,需配置此參數,參與簽名, 固定值  // orderInfo += "&paymethod=/"expressGateway/""; }                 return orderInfo; }
  • 對訂單做RSA簽名:  demo代碼中提供SingUtils類實現該功能,即SignUtils.sign(content, RSA_PRIVATE);
  • 對簽名做 URL編碼:  調用java類庫接口,即URLEncoder.encode來實現。
  • 將訂單數據和簽名信息組合,生成符合支付寶參數規范的數據: 
final String payInfo = orderInfo + "&sign=/"" + sign + "/"&" + getSignType();

第三步:在子線程里調用PayTask的pay接口,將請求數據發送出去

PayTask alipay = new PayTask(PayDemoActivity.this);// 調用支付接口,獲取支付結果String result = alipay.pay(payInfo);

第四步:收到支付處理結果的消息。支付結果的狀態碼的意義如下:

  •     值為“9000”,代表支付成功;
  •     值為“8000”,代表等待支付結果確認,這可能由于系統原因或者渠道支付原因。支付的最終結果需要由服務器端的異步通知為準(支付寶將向)。
  •     值為其他,代表失敗。客戶端需要提示用戶。

注意事項:
1、本文特別需要指出的是,也就是最容易出問題的就是訂單數據的生成。在demo代碼的 PayDemoActivity類中,定義了getOrderInfo方法。 其中“orderInfo += "&return_url=/"m.alipay.com/"”;”在該demo代碼的注釋中,雖然說是可以為空,但實際情況,如果為空,將導致支付失敗。而且憑借失敗狀態碼,難以識別具體原因。
2、支付結果,除了支付寶服務器發通知到客戶端外,也會異步通知應用服務器。考慮到安全性,客戶端可以根據支付寶服務器的通知,進行商業邏輯的處理,比如訂單更新等,但是支付的數據入庫,需要由應用服務器端根據異步通知進行操作。
2、服務端實現
服務端基本操作包括:獲取支付寶賬號信息(為了安全,該信息放置在服務器,而不是客戶端),創建訂單,支付結果異步回調,申請退款等基本操作外。另外也可能包括:更新訂單(對于支持訂單可修改的應用),驗證消費碼,查詢訂單記錄,刪除訂單等操作。
本文介紹基于Java平臺的服務器方案。目前比較流行的框架組合是SpingMVC+Mybatis+Mysql。
訂單的創建。當用戶下訂單時,如果是新訂單(請求的數據沒有包括訂單編號信息),需要創建,并返回訂單號給客戶端。訂單類示例:

public class PayOrder {        public String tradeNo;   //隨機編號 public String amount;   //付款金額 public String status;   //操作狀態 public String statusCode;   //操作狀態代碼,0-未支付,10-已支付,4000-退款中,5000-已退款,6000-付款失敗,6001-取消付款,7000-已消費 public String orderNo;   //支付寶流水號 public String productDescription;  //商品名稱 public String payNo;   //消費碼 public String isRefund;   //是否申請退款 public String createTime;   //創建時間 public String modifyTime;   //修改時間 public String userId;   //用戶id public Integer id;    //主鍵 public String pId;    //商品id public int buyNumber;    //存儲購買數量 public int vendorId;    //商家ID}tradeNo代碼訂單編號。payNo代碼消費編號(消費碼)。orderNo是支付寶服務器端生成的訂單號。@RequestMapping(value = "/payorder")@ResponseBodypublic Map<String, Object> pay(HttpServletRequest request, HttpServletResponse response) { Map<String, Object> map = JsonPUtil.pToMap(request); Map<String, Object> msgMap = new HashMap<String, Object>(); if (!map.isEmpty()) { try {  log.info("執行購買前確認操作:" + map);  String now = String.valueOf(System.currentTimeMillis());  String trade_no = map.get("barId").toString() + "-" + map.get("barCoupon").toString() + "-" + map.get("count").toString() + "-" + now.substring(now.length() - 6);      PayOrder alipay = new PayOrder();  alipay.setAmount(map.get("amount").toString());  alipay.setTradeNo(trade_no);  alipay.setProductDescription(map.get("productDescription").toString());  alipay.setCreateTime(now);  alipay.setStatus("待支付");  alipay.setStatusCode("0");  alipay.setExtInt1(Integer.parseInt(map.get("count").toString()));  alipay.setUserId(map.get("userId").toString());  alipay.setpId(map.get("barCoupon").toString());  alipay.setExtInt2(Integer.parseInt(map.get("barId").toString()));      int flag = alipayServiceImpl.pay(alipay);  log.info("確認操作執行結果:" + flag);      Map<String, Object> m = new HashMap<String, Object>();  m.put("trade_no", trade_no);  m.put("seller", new String(Base64.encode(AlipayConfig.SELLER.getBytes())));  m.put("partner", new String(Base64.encode(AlipayConfig.partner.getBytes())));  m.put("privateKey", new String(Base64.encode(AlipayConfig.ios_private_key.getBytes())));      if (flag > 0)  msgMap = ResponseMessageUtil.respMsg(Constance.BASE_SUCCESS_CODE, "success", m);  else  msgMap = ResponseMessageUtil.respMsg(Constance.BASE_SERVER_WRONG_CODE, "fail"); } catch (Exception e) {  e.printStackTrace();  msgMap = ResponseMessageUtil.respMsg(Constance.BASE_SERVER_WRONG_CODE, "fail");  log.error("購買前確認失敗", e); } } else { log.info("請求參數不完整"); msgMap = ResponseMessageUtil.respMsg(Constance.ILLEGAL_OPERATE, "fail"); } return msgMap;}

支付寶服務器回調App服務器,通知支付結果。App服務器將相應的數據入庫后,通知支付寶服務器"success" or "fail"。

@RequestMapping(value = "/payOver") @ResponseBody public String payOver(HttpServletRequest request, HttpServletResponse response) { Map<String, String> map = JsonPUtil.buildMap(request); String result_str = "fail"; if (!map.isEmpty()) {  if (AlipayUtils.checkAlipay(map, false) > 0) {// 通過支付寶驗證  try {   log.info("執行付款的回調函數傳遞參數:" + map);   String now = String.valueOf(System.currentTimeMillis());   String status = map.get("trade_status").toString();   PayOrder alipay = new PayOrder();   alipay.setTradeNo(String.valueOf(map.get("out_trade_no")));   log.info("支付狀態:" + status);   if (Constance.ALIPAY_SUCCESS_CODE.equals(status) || Constance.ALIPAY_FINISHED_CODE.equals(status)) {// 支付成功   List<Alipay> ali = alipayServiceImpl.search(alipay);   if (ali.size() == 1 && (ali.get(0).getPayNo() == null || ali.get(0).getPayNo().equals(""))) {// 消息未處理    Alipay pay = new Alipay();    pay.setTradeNo(String.valueOf(map.get("out_trade_no")));    pay.setStatus("已支付");    pay.setStatusCode("10");    pay.setIsRefund("0");    pay.setModifyTime(String.valueOf(System.currentTimeMillis()));    pay.setPayNo(new String(Base64.encode(now.substring(now.length() - 10).getBytes())));    pay.setOrderNo(String.valueOf(map.get("trade_no")));    int flag = alipayServiceImpl.payOver(pay);    log.info("用戶付款成功" + map);    if (flag > 0)    result_str = "success";   }   } else {   return result_str;   }  } catch (Exception e) {   e.printStackTrace();   log.error("回調函數獲取參數失敗", e);   return result_str;  }  } } return result_str; }

以上就是基于Android支付寶支付設計和開發方案,希望對大家學習Android軟件編程有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 博野县| 长顺县| 天全县| 博爱县| 曲阳县| 新巴尔虎左旗| 沛县| 黎川县| 将乐县| 巴南区| 饶阳县| 保定市| 化隆| 志丹县| 普陀区| 达尔| 乃东县| 隆德县| 嘉义市| 美姑县| 南溪县| 新津县| 岚皋县| 兴和县| 安远县| 鄂州市| 独山县| 蒙山县| 五峰| 万宁市| 藁城市| 甘谷县| 收藏| 玛纳斯县| 上饶县| 扎囊县| 旬邑县| 乌什县| 绍兴县| 南城县| 吉木萨尔县|