- 支付寶出了新文檔 現(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 += "¬ify_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)的取消 **