Android開發中支付寶接入支付功能實現(詳細步驟)
今天做了一下支付寶的支付功能的實現,記錄一下。(注意:因為服務時常更新,所以主要記錄操作方法,而非依葫蘆畫瓢。另外,這次簡單實現了訂單提交—結果獲取,並沒有做那些進一步的驗證,後期會逐步完善)
步驟如下:
下載最新的sdk則點選上圖中下面的那個"SDK及DEMO下載",然後選擇相應的sdk下載即可。(這一步我們主要需要的是解壓包裡面的alipaySdk-20180403.jar)
2、匯入開發資源
這一步分為Eclipse和AndroidStudio兩個開發工具分別介紹。
2.1、Eclipse的匯入步驟:
(1)將demo裡面的alipaySdk-20180403.jar拷貝到我們工程的libs下,並新增到依賴中。
(2)在應用工程的AndroidManifest.xml裡配置使用者許可權,程式碼如下:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
並且,新增宣告:
<activity android:name="com.alipay.sdk.app.H5PayActivity" android:configChanges="orientation|keyboardHidden|navigation|screenSize" android:exported="false" android:screenOrientation="behind" android:windowSoftInputMode="adjustResize|stateHidden" > </activity> <activity android:name="com.alipay.sdk.app.H5AuthActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" android:windowSoftInputMode="adjustResize|stateHidden" > </activity>
(3)新增混淆規則
在專案的proguard-project.txt裡新增以下程式碼:
-libraryjars libs/alipaySdk-20180403.jar
-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}
2.2、androidstudio的匯入步驟和eclipse相似,並且官方開發文件中描述的也是Androidstudio開發工具的步驟,所以這裡不再贅言。
3、呼叫支付介面
需要在新執行緒中呼叫支付介面。
PayTask物件主要為商戶提供訂單支付、查詢功能,及獲取當前開發包版本號。
獲取PayTask支付物件呼叫支付(支付行為需要在獨立的非ui執行緒中執行),程式碼示例:
final String orderInfo = getOrderInfo("測試商品", "商品描述", "0.1"); // 訂單資訊
Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(MainActivity.this);
String result = alipay.pay(orderInfo,true);
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
msg.obj = result;
mHandler.sendMessage(msg);
}
};
// 必須非同步呼叫
Thread payThread = new Thread(payRunnable);
payThread.start();
其中的orderInfo儲存了訂單資訊,它是根據官方的“請求引數說明”得來的。(這個引數自己可以封裝成類,便於儲存到資料庫裡進行相應的操作)
我這裡暫時先用了一個方法來簡單建立訂單測試一下:
/**
* create the order info. 建立訂單資訊
*/
private String getOrderInfo(String subject, String body, String price) {
// 簽約合作者身份ID
String orderInfo = "partner=" + "\"" + PARTNER + "\"";
// 簽約賣家支付寶賬號
orderInfo += "&seller_id=" + "\"" + SELLER + "\"";
// 商戶網站唯一訂單號
orderInfo += "&out_trade_no=" + "\"" + getOutTradeNo() + "\"";
// 商品名稱
orderInfo += "&subject=" + "\"" + subject + "\"";
// 商品詳情
orderInfo += "&body=" + "\"" + body + "\"";
// 商品金額
orderInfo += "&total_fee=" + "\"" + price + "\"";
// 伺服器非同步通知頁面路徑
orderInfo += "¬ify_url=" + "\"" + "http://notify.msp.hk/notify.htm" + "\"";
// 服務介面名稱, 固定值
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\"";
// extern_token為經過快登授權獲取到的alipay_open_id,帶上此引數使用者將使用授權的賬戶進行支付
// orderInfo += "&extern_token=" + "\"" + extern_token + "\"";
// 支付寶處理完請求後,當前頁面跳轉到商戶指定頁面的路徑,可空
orderInfo += "&return_url=\"m.alipay.com\"";
// 呼叫銀行卡支付,需配置此引數,參與簽名, 固定值 (需要簽約《無線銀行卡快捷支付》才能使用)
// orderInfo += "&paymethod=\"expressGateway\"";
return orderInfo;
}
4、支付結果的獲取和處理
4.1、同步返回
商戶應用客戶端通過當前呼叫支付的Activity的Handler物件,通過它的回撥函式獲取支付結果。
程式碼示例:
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SDK_PAY_FLAG: {
PayResult payResult = new PayResult((String) msg.obj);
/**
* 同步返回的結果必須放置到服務端進行驗證(驗證的規則請看https://doc.open.alipay.com/doc2/
* detail.htm?spm=0.0.0.0.xdvAU6&treeId=59&articleId=103665&
* docType=1) 建議商戶依賴非同步通知
*/
String resultInfo = payResult.getResult();// 同步返回需要驗證的資訊
String resultStatus = payResult.getResultStatus();
// 判斷resultStatus 為“9000”則代表支付成功,具體狀態碼代表含義可參考介面文件
if (TextUtils.equals(resultStatus, "9000")) {
Toast.makeText(MainActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
} else {
// 判斷resultStatus 為非"9000"則代表可能支付失敗
// "8000"代表支付結果因為支付渠道原因或者系統原因還在等待支付結果確認,最終交易是否成功以服務端非同步通知為準(小概率狀態)
if (TextUtils.equals(resultStatus, "8000")) {
Toast.makeText(MainActivity.this, "支付結果確認中", Toast.LENGTH_SHORT).show();
} else {
// 其他值就可以判斷為支付失敗,包括使用者主動取消支付,或者系統返回的錯誤
Toast.makeText(MainActivity.this, "支付失敗", Toast.LENGTH_SHORT).show();
}
}
break;
}
default:
break;
}
};
};
其中,PayResult是根據“通知引數說明”自己封裝的一個類,用於方便操作。(通知引數返回的結果是一個map結構體)
4.2、非同步通知
商戶需要提供一個http協議的介面,包含在請求支付的入參中,其key對應notify_url。支付寶伺服器在支付完成後,會以POST方式呼叫notify_url傳輸資料。(官方例項程式碼)
另外,該Activity中應該宣告一些變數:(這些資訊是你申請的商戶支付寶的後臺裡可以查到的)
public static final String PARTNER = "";
// 商戶收款賬號
public static final String SELLER = "";
// 商戶私鑰,pkcs8格式
public static final String RSA_PRIVATE = "";
private static final int SDK_PAY_FLAG = 1;
備註:如果demo執行之後,出現支付寶的呼叫載入框,隨後立即出現"系統繁忙,請稍後重試(ALIN10129)"的提示,沒有關係,這說明你這邊除錯通了,只是因為你的支付寶還沒有開通移動支付的許可權,開通一下即可。