Android支付寶支付對接

  • 支付寶出了新文檔 現(xiàn)在才知道
  • 記載一下新版與舊版區(qū)別

1 訂單信息生成

  • 舊版當(dāng)中訂單信息生成內(nèi)容較多 簽名在服務(wù)器 支付信息拼接樣式如下
final String orderInfo = getOrderInfo("測試", "測試支付", price);
String sign = sign(orderInfo);
final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();

getOrderInfo如下

private String getOrderInfo(String subject, String body, String price) {        
// 簽約合作者身份ID        
String orderInfo = "partner=" + "\"" + PARTNER + "\"";        
// 簽約賣家支付寶賬號        
orderInfo += "&seller_id=" + "\"" + SELLER + "\"";        
// 商戶網(wǎng)站唯一訂單號        
orderInfo += "&out_trade_no=" + "\"" + orderNum + "\"";        
// 商品名稱        
orderInfo += "&subject=" + "\"" + subject + "\"";        
// 商品詳情        
orderInfo += "&body=" + "\"" + body + "\"";        
// 商品金額        
orderInfo += "&total_fee=" + "\"" + price + "\"";        
// 服務(wù)器異步通知頁面路徑        
orderInfo += "&notify_url=" + "\"" + Constant.BASE_URL + "/zfbapp/notify_app.php"+ "\"";        
// 服務(wù)接口名稱缘琅, 固定值        
orderInfo += "&service=\"mobile.securitypay.pay\"";        
// 支付類型谴轮, 固定值        
orderInfo += "&payment_type=\"1\"";        
// 參數(shù)編碼, 固定值        
orderInfo += "&_input_charset=\"utf-8\"";        
// 設(shè)置未付款交易的超時時間        
// 默認(rèn)30分鐘,一旦超時晃痴,該筆交易就會自動被關(guān)閉。        
// 取值范圍:1m~15d。        
// m-分鐘,h-小時踱稍,d-天曲饱,1c-當(dāng)天(無論交易何時創(chuàng)建,都在0點關(guān)閉)珠月。        
// 該參數(shù)數(shù)值不接受小數(shù)點扩淀,如1.5h,可轉(zhuǎn)換為90m桥温。        
orderInfo += "&it_b_pay=\"30m\"";        
// extern_token為經(jīng)過快登授權(quán)獲取到的alipay_open_id,帶上此參數(shù)用戶將使用授權(quán)的賬戶進(jìn)行支付       
 // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";        
// 支付寶處理完請求后引矩,當(dāng)前頁面跳轉(zhuǎn)到商戶指定頁面的路徑梁丘,可空        
orderInfo += "&return_url=\"m.alipay.com\"";//        
// 調(diào)用銀行卡支付侵浸,需配置此參數(shù),參與簽名氛谜, 固定值 (需要簽約《無線銀行卡快捷支付》才能使用)
//         orderInfo += "&paymethod=\"expressGateway\"";        return orderInfo;    
}
  • 新版當(dāng)中訂單生成內(nèi)容較少 簽名 支付信息拼接樣式有所改變(看demo的意思應(yīng)該是這三部放到了服務(wù)器
Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APPID);
String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
String sign = OrderInfoUtil2_0.getSign(params, RSA_PRIVATE);
final String orderInfo = orderParam + "&" + sign;

OrderInfoUtil2_0

public static Map<String, String> buildOrderParamMap(String app_id) {
      Map<String, String> keyValues = new HashMap<String, String>();
      keyValues.put("app_id", app_id);
      keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\"0.01\",\"subject\":\"1\",\"body\":\"我是測試數(shù)據(jù)\",\"out_trade_no\":\"" + getOutTradeNo() +  "\"}");
      keyValues.put("charset", "utf-8");
      keyValues.put("method", "alipay.trade.app.pay");
      keyValues.put("sign_type", "RSA");
      keyValues.put("timestamp", "2016-07-29 16:55:53");
      keyValues.put("version", "1.0");
      return keyValues;   
} 
public static String buildOrderParam(Map<String, String> map) {
      List<String> keys = new ArrayList<String>(map.keySet());
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < keys.size() - 1; i++) {
         String key = keys.get(i);
         String value = map.get(key);
         sb.append(buildKeyValue(key, value, true));
         sb.append("&");
      }
      String tailKey = keys.get(keys.size() - 1);
      String tailValue = map.get(tailKey);
      sb.append(buildKeyValue(tailKey, tailValue, true));
      return sb.toString();
}
private static String buildKeyValue(String key, String value, boolean isEncode) {
      StringBuilder sb = new StringBuilder();
      sb.append(key);
      sb.append("=");
      if (isEncode) {
         try {
            sb.append(URLEncoder.encode(value, "UTF-8"));
         } catch (UnsupportedEncodingException e) {
            sb.append(value);
         }
      } else {
         sb.append(value);
      }
      return sb.toString();
}
public static String getSign(Map<String, String> map, String rsaKey) {
      List<String> keys = new ArrayList<String>(map.keySet());
      // key排序
      Collections.sort(keys);
      StringBuilder authInfo = new StringBuilder();
      for (int i = 0; i < keys.size() - 1; i++) {
         String key = keys.get(i);
         String value = map.get(key);
         authInfo.append(buildKeyValue(key, value, false));
         authInfo.append("&");
      }
      String tailKey = keys.get(keys.size() - 1);
      String tailValue = map.get(tailKey);
      authInfo.append(buildKeyValue(tailKey, tailValue, false));
      String oriSign = SignUtils.sign(authInfo.toString(), rsaKey);
      String encodedSign = "";
      try {
         encodedSign = URLEncoder.encode(oriSign, "UTF-8");
      } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
      }
      return "sign=" + encodedSign;
}
private static String getOutTradeNo() {
      SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());
      Date date = new Date();
      String key = format.format(date);
      Random r = new Random();
      key = key + r.nextInt();
      key = key.substring(0, 15);
      return key;
}

2 跳轉(zhuǎn)支付寶支付

  • 舊版(調(diào)取PayTask的pay方法)
Runnable payRunnable = new Runnable() {
    @Override    public void run() {
        // 構(gòu)造PayTask 對象
        PayTask alipay = new PayTask(ZhifubaoPayActivity.this);
        // 調(diào)用支付接口掏觉,獲取支付結(jié)果
        String result = alipay.pay(payInfo, true);
        Message msg = new Message();
        msg.what = SDK_PAY_FLAG;
        msg.obj = result;
        mHandler.sendMessage(msg);
    }
};
// 必須異步調(diào)用
Thread payThread = new Thread(payRunnable);
payThread.start();
  • 新版(調(diào)取PayTask的payV2方法)
Runnable payRunnable = new Runnable() {
    @Override    public void run() {
        // 構(gòu)造PayTask 對象
        PayTask alipay = new PayTask(ZhifubaoPayActivity.this);
        // 調(diào)用支付接口,獲取支付結(jié)果
        String result = alipay.payV2(payInfo, true);
        Message msg = new Message();
        msg.what = SDK_PAY_FLAG;
        msg.obj = result;
        mHandler.sendMessage(msg);
    }
};
// 必須異步調(diào)用
Thread payThread = new Thread(payRunnable);
payThread.start();

3 同步回調(diào)

  • 舊版
@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {
    @SuppressWarnings("unused")
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case SDK_PAY_FLAG: {
                PayResult payResult = new PayResult((String) msg.obj);
                String resultInfo = payResult.getResult();// 同步返回需要驗證的信息
                String resultStatus = payResult.getResultStatus();
                // 判斷resultStatus 為“9000”則代表支付成功值漫,具體狀態(tài)碼代表含義可參考接口文檔
                if (TextUtils.equals(resultStatus, "9000")) {
                    toast("支付成功");
                } else {
                    // 判斷resultStatus 為非"9000"則代表可能支付失敗
                    // "8000"代表支付結(jié)果因為支付渠道原因或者系統(tǒng)原因還在等待支付結(jié)果確認(rèn)澳腹,最終交易是否成功以服務(wù)端異步通知為準(zhǔn)(小概率狀態(tài))
                    if (TextUtils.equals(resultStatus, "8000")) {
                        toast("支付結(jié)果確認(rèn)中");
                    } else {
                        // 其他值就可以判斷為支付失敗,包括用戶主動取消支付杨何,或者系統(tǒng)返回的錯誤
                        toast("支付失敗");
                    }
                }
                break;
            }
            default:
                break;
        }
    }
};
  • 新版(修改了PayResult的構(gòu)造 還有就是Demo中取消了8000狀態(tài))
PayResult payResult = new PayResult((Map<String, String>) msg.obj);
/** 對于支付結(jié)果酱塔,請商戶依賴服務(wù)端的異步通知結(jié)果。同步通知結(jié)果危虱,僅作為支付結(jié)束的通知羊娃。 */
String resultInfo = payResult.getResult();
// 同步返回需要驗證的信息
String resultStatus = payResult.getResultStatus();
// 判斷resultStatus 為9000則代表支付成功
if (TextUtils.equals(resultStatus, "9000")) {
   // 該筆訂單是否真實支付成功,需要依賴服務(wù)端的異步通知埃跷。
   Toast.makeText(PayDemoActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
} else {
   // 該筆訂單真實的支付結(jié)果蕊玷,需要依賴服務(wù)端的異步通知。
   Toast.makeText(PayDemoActivity.this, "支付失敗", Toast.LENGTH_SHORT).show();
}

** 綜述:這是一次比較大的修改 主要修改了支付信息的拼接方式和8000狀態(tài)的取消 **

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弥雹,一起剝皮案震驚了整個濱河市垃帅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌剪勿,老刑警劉巖贸诚,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異厕吉,居然都是意外死亡赦颇,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門赴涵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來媒怯,“玉大人,你說我怎么就攤上這事髓窜∩劝” “怎么了欺殿?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳖敷。 經(jīng)常有香客問我脖苏,道長,這世上最難降的妖魔是什么定踱? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任棍潘,我火速辦了婚禮,結(jié)果婚禮上崖媚,老公的妹妹穿的比我還像新娘亦歉。我一直安慰自己,他們只是感情好畅哑,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布肴楷。 她就那樣靜靜地躺著,像睡著了一般荠呐。 火紅的嫁衣襯著肌膚如雪赛蔫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天泥张,我揣著相機與錄音呵恢,去河邊找鬼。 笑死媚创,一個胖子當(dāng)著我的面吹牛渗钉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播筝野,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼晌姚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了歇竟?” 一聲冷哼從身側(cè)響起挥唠,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎焕议,沒想到半個月后宝磨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡盅安,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年唤锉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片别瞭。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡窿祥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蝙寨,到底是詐尸還是另有隱情晒衩,我是刑警寧澤嗤瞎,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站听系,受9級特大地震影響贝奇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜靠胜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一掉瞳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧浪漠,春花似錦陕习、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘩欺。三九已至必盖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間俱饿,已是汗流浹背歌粥。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拍埠,地道東北人失驶。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像枣购,于是被迫代替她去往敵國和親嬉探。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 之前寫了一個關(guān)于微信支付的博文棉圈,后來有人問我為什么不寫上一個支付寶支付的呢涩堤。當(dāng)初想的是支付寶支付比較簡單,不像微信...
    2c2z0閱讀 2,092評論 0 0
  • 此項目已開源 趕快來圍觀 Start支持下吧 【客戶端開源地址-JPay】【服務(wù)端端開源地址-在com.javen...
    LucasAdam閱讀 1,954評論 0 3
  • 該文僅對于中間這種支付方式有參考價值喲 一分瘾、開發(fā)背景 在微信公眾號中胎围,需要進(jìn)行微信支付且為微信公眾號網(wǎng)頁支付。 二...
    英文名叫夏天閱讀 1,820評論 0 7
  • 9af0e05c6c75閱讀 360評論 0 0
  • 風(fēng)箏總是飛翔在人給它刻意安排的軌道上 它飛過的軌跡飄飄渺渺 可是留下了往事不堪回首 沒有人會在意它的感受 只是要滿...
    許你一世諾言閱讀 757評論 0 0