本文檔展示了如何從零開始,使用螞蟻金服開放平台服務端SDK快速接入手機網站支付產品,完成與支付寶對接的部分。
注意: 文檔中的代碼示例和Demo是用來闡述API基本使用方法的,僅針對大眾場景。供ISV參考,特殊情況還請ISV自行擴展,確保符合自身業務需求。
支付產品全面升級,若您使用的是老接口,請移步老版本手機網站支付文檔。
第一步:創建應用並獲取APPID
要在您的應用中使用支付寶開放產品的接口能力,您需要先去螞蟻金服開放平台(open.alipay.com),在管理中心中創建登記您的應用,並提交審核,審核通過后會為您生成應用唯一標識(APPID),並且可以申請開通開放產品使用權限,通過APPID您的應用才能調用開放產品的接口能力。需要詳細了解開放平台創建應用步驟請參考《開放平台應用創建指南》。
第二步:配置密鑰
開發者調用接口前需要先生成RSA密鑰,RSA密鑰包含應用私鑰(APP_PRIVATE_KEY)、應用公鑰(APP_PUBLIC_KEY)。生成密鑰后在開放平台管理中心進行密鑰配置,配置完成后可以獲取支付寶公鑰(ALIPAY_PUBLIC_KEY)。詳細步驟請參考《配置應用環境》。
第三步:搭建和配置開發環境
1. 下載服務端SDK
為了幫助開發者調用開放接口,我們提供了開放平台服務端SDK,包含JAVA、PHP和.NET三語言版本,封裝了簽名&驗簽、HTTP接口請求等基礎功能。請先下載對應語言版本的SDK並引入您的開發工程。
2. 接口調用配置
各語言版本服務端SDK詳細使用說明,請參考《服務端SDK使用說明》
在使用SDK調用具體API前,進行初始化,代碼如下:
1
|
AlipayClient alipayClient =
new
DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);
|
配置參數 | 示例值解釋 | 獲取方式/示例值 |
---|---|---|
URL | 支付寶網關(固定) | https://openapi.alipay.com/gateway.do |
APP_ID | APPID即創建應用后生成 | 獲取見上面創建應用並獲取APPID |
APP_PRIVATE_KEY | 開發者應用私鑰,由開發者自己生成 | 獲取見上面配置密鑰 |
FORMAT | 參數返回格式,只支持json | json(固定) |
CHARSET | 請求和簽名使用的字符編碼格式,支持GBK和UTF-8 | 開發者根據實際工程編碼配置 |
ALIPAY_PUBLIC_KEY | 支付寶公鑰,由支付寶生成 | 獲取詳見上面配置密鑰 |
SIGN_TYPE | 商戶生成簽名字符串所使用的簽名算法類型,目前支持RSA2和RSA,推薦使用RSA2 | RSA2 |
接下來,就可以用alipayClient來調用具體的API了。alipayClient只需要初始化一次,后續調用不同的API都可以使用同一個alipayClient對象。
第四步:調用接口
手機網站支付產品包含兩類API:
- 頁面跳轉類:需要從前端頁面以Form表單的形式發起請求,瀏覽器會自動跳轉至支付寶的相關頁面(一般是收銀台或簽約頁面),用戶在該頁面完成相關業務操作后再回跳到商戶指定頁面。例如本產品中的手機網站支付接口alipay.trade.wap.pay。
- 系統調用類:直接從服務端發起HTTP請求,支付寶會同步返回請求結果。例如本產品中的交易查詢等配套API。
調用流程
如上圖所示,用戶在商戶的H5網站下單支付后,商戶系統按照手機網站支付接口alipay.trade.wap.payAPI的參數規范生成訂單數據,然后在前端頁面通過Form表單的形式請求到支付寶。此時支付寶會自動將頁面跳轉至支付寶H5收銀台頁面,如果用戶手機上安裝了支付寶APP,則自動喚起支付寶APP。開發者需要關注安裝了支付寶和未安裝支付寶的兩種測試場景,對於在手機瀏覽器喚起H5頁面的模式下,如果安裝了支付寶卻沒有喚起,大部分原因是當前瀏覽器不在支付寶配置的白名單內,對於商戶app內嵌webview中的支付場景,建議集成支付寶App支付產品。
用戶在支付寶APP或H5收銀台完成支付后,會根據商戶在手機網站支付API中傳入的前台回跳地址return_url自動跳轉回商戶頁面,同時在URL請求中以Query String的形式附帶上支付結果參數,詳細回跳參數見“手機網站支付接口alipay.trade.wap.pay”前台回跳參數。
同時,支付寶還會根據原始支付API中傳入的異步通知地址notify_url,通過POST請求的形式將支付結果作為參數通知到商戶系統,詳情見支付結果異步通知。
除了正向支付流程外,支付寶也提供交易查詢、關閉、退款、退款查詢以及對賬等配套API。
特別注意:
- 由於前台回跳的不可靠性,前台回跳只能作為商戶支付結果頁的入口,最終支付結果必須以異步通知或查詢接口返回為准,不能依賴前台回跳。
- 商戶系統接收到異步通知以后,必須通過驗簽(驗證通知中的sign參數)來確保支付通知是由支付寶發送的。詳細驗簽規則參考異步通知驗簽。
- 接受到異步通知並驗簽通過后,一定要檢查通知內容,包括通知中的app_id, out_trade_no, total_amount是否與請求中的一致,並根據trade_status進行后續業務處理。
使用SDK快速接入
手機網站支付alipay.trade.wap.pay:
對於頁面跳轉類API,SDK不會也無法像系統調用類API一樣自動請求支付寶並獲得結果,而是在接受request請求對象后,為開發者生成前台頁面請求需要的完整form表單的html(包含自動提交腳本),商戶直接將這個表單的String輸出到http response中即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
void
doPost(HttpServletRequest httpRequest,
HttpServletResponse httpResponse)
throws
ServletException, IOException {
AlipayClient alipayClient =
new
DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do"
, APP_ID, APP_PRIVATE_KEY,
"json"
, CHARSET, ALIPAY_PUBLIC_KEY,
"RSA2"
); //獲得初始化的AlipayClient
AlipayTradeWapPayRequest alipayRequest =
new
AlipayTradeWapPayRequest();
//創建API對應的request
alipayRequest.setBizContent(
"{"
+
" \"out_trade_no\":\"20150320010101002\","
+
" \"total_amount\":\"88.88\","
+
" \"subject\":\"Iphone6 16G\","
+
" \"seller_id\":\"2088123456789012\","
+
" \"product_code\":\"QUICK_WAP_PAY\""
+
" }"
);
//填充業務參數
String form = alipayClient.pageExecute(alipayRequest).getBody();
//調用SDK生成表單
httpResponse.setContentType(
"text/html;charset="
+ AlipayServiceEnvConstants.CHARSET);
httpResponse.getWriter().write(form);
//直接將完整的表單html輸出到頁面
httpResponse.getWriter().flush();
}
|
關鍵入參:
參數名稱 | 參數說明 |
---|---|
out_trade_no | 商戶訂單號,需要保證不重復 |
subject | 訂單標題 |
seller_id | 實際收款賬號,一般填寫商戶PID即可 |
total_amount | 訂單金額 |
異步通知驗簽:
1
2
3
4
5
6
7
|
Map<String, String> paramsMap = ...
//將異步通知中收到的所有參數都存放到map中
boolean
signVerified = AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET, SIGN_TYPE)
//調用SDK驗證簽名
if
(signVerfied){
// TODO 驗簽成功后,按照支付結果異步通知中的描述,對支付結果中的業務內容進行二次校驗,校驗成功后在response中返回success並繼續商戶自身業務處理,校驗失敗返回failure
}
else
{
// TODO 驗簽失敗則記錄異常日志,並在response中返回failure.
}
|
關鍵通知參數:
參數名稱 | 參數說明 |
---|---|
trade_no | 支付寶28位交易號 |
trade_status | 交易狀態 |
total_amount | 訂單金額 |
交易查詢接口alipay.trade.query:
1
2
3
4
5
6
7
8
9
|
AlipayClient alipayClient =
new
DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do"
, APP_ID, APP_PRIVATE_KEY,
"json"
, CHARSET, ALIPAY_PUBLIC_KEY,
"RSA2"
); //獲得初始化的AlipayClient
AlipayTradeQueryRequest request =
new
AlipayTradeQueryRequest();
//創建API對應的request類
request.setBizContent(
"{"
+
" \"out_trade_no\":\"20150320010101001\","
+
" \"trade_no\":\"2014112611001004680073956707\""
+
" }"
);
//設置業務參數
AlipayTradeQueryResponse response = alipayClient.execute(request);
//通過alipayClient調用API,獲得對應的response類
System.out.print(response.getBody());
//根據response中的結果繼續業務邏輯處理
|
關鍵入參:
參數名稱 | 參數說明 |
---|---|
out_trade_no | 支付時傳入的商戶訂單號,與trade_no必填一個 |
trade_no | 支付時返回的支付寶交易號,與out_trade_no必填一個 |
關鍵出參:
參數名稱 | 參數說明 |
---|---|
trade_no | 支付寶28位交易號 |
out_trade_no | 支付時傳入的商戶訂單號 |
trade_status | 交易當前狀態 |
交易退款接口alipay.trade.refund:
1
2
3
4
5
6
7
8
9
10
11
|
AlipayClient alipayClient =
new
DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do"
, APP_ID, APP_PRIVATE_KEY,
"json"
, CHARSET, ALIPAY_PUBLIC_KEY,
"RSA2"
); //獲得初始化的AlipayClient
AlipayTradeRefundRequest request =
new
AlipayTradeRefundRequest();
//創建API對應的request類
request.setBizContent(
"{"
+
" \"out_trade_no\":\"20150320010101001\","
+
" \"trade_no\":\"2014112611001004680073956707\","
+
" \"out_request_no\":\"1000001\","
+
" \"refund_amount\":\"2014112611001004680073956707\""
+
" }"
);
//設置業務參數
AlipayTradeRefundResponse response = alipayClient.execute(request);
//通過alipayClient調用API,獲得對應的response類
System.out.print(response.getBody());
//根據response中的結果繼續業務邏輯處理
|
關鍵入參:
參數名稱 | 參數說明 |
---|---|
out_trade_no | 支付時傳入的商戶訂單號,與trade_no必填一個 |
trade_no | 支付時返回的支付寶交易號,與out_trade_no必填一個 |
out_request_no | 本次退款請求流水號,部分退款時必傳 |
refund_amount | 本次退款金額 |
關鍵出參:
參數名稱 | 參數說明 |
---|---|
refund_fee | 該筆交易已退款的總金額 |
查詢對賬單下載地址接口alipay.data.dataservice.bill.downloadurl.query:
1
2
3
4
5
6
7
8
9
|
AlipayClient alipayClient =
new
DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do"
, APP_ID, APP_PRIVATE_KEY,
"json"
, CHARSET, ALIPAY_PUBLIC_KEY,
"RSA2"
); //獲得初始化的AlipayClient
AlipayDataDataserviceBillDownloadurlQueryRequest request =
new
AlipayDataDataserviceBillDownloadurlQueryRequest();
//創建API對應的request類
request.setBizContent(
"{"
+
" \"bill_type\":\"trade\","
+
" \"bill_date\":\"2016-04-05\""
" }"
);
//設置業務參數
AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);
System.out.print(response.getBody());
//根據response中的結果繼續業務邏輯處理
|
關鍵入參:
參數名稱 | 參數說明 |
---|---|
bill_type | 固定傳入trade |
bill_date | 需要下載的賬單日期,最晚是當期日期的前一天 |
關鍵出參:
參數名稱 | 參數說明 |
---|---|
bill_download_url | 賬單文件下載地址,30秒有效 |
下載賬單文件:
1
2
3
4
5
6
7
8
9
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
38
39
|
//將接口返回的對賬單下載地址傳入urlStr
String urlStr =
"http://dwbillcenter.alipay.com/downloadBillFile.resource?bizType=X&userId=X&fileType=X&bizDates=X&downloadFileName=X&fileId=X"
;
//指定希望保存的文件路徑
String filePath =
"/Users/fund_bill_20160405.csv"
;
URL url =
null
;
HttpURLConnection httpUrlConnection =
null
;
InputStream fis =
null
;
FileOutputStream fos =
null
;
try
{
url =
new
URL(urlStr);
httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setConnectTimeout(
5
*
1000
);
httpUrlConnection.setDoInput(
true
);
httpUrlConnection.setDoOutput(
true
);
httpUrlConnection.setUseCaches(
false
);
httpUrlConnection.setRequestMethod(
"GET"
);
httpUrlConnection.setRequestProperty(
"Charsert"
,
"UTF-8"
);
httpUrlConnection.connect();
fis = httpUrlConnection.getInputStream();
byte
[] temp =
new
byte
[
1024
];
int
b;
fos =
new
FileOutputStream(
new
File(filePath));
while
((b = fis.read(temp)) != -
1
) {
fos.write(temp,
0
, b);
fos.flush();
}
}
catch
(MalformedURLException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
finally
{
try
{
if
(fis!=
null
) fis.close();
if
(fos!=
null
) fos.close();
if
(httpUrlConnection!=
null
) httpUrlConnection.disconnect();
}
catch
(IOException e) {
e.printStackTrace();
}
}
|
關於沙箱
如何接入沙箱
沙箱環境是開放平台提供給開發者調試接口的環境,具體操作步驟見 沙箱接入指南。
手機網站支付沙箱接入注意點
1、手機網站支付支持沙箱接入;在沙箱調通接口后,必須在線上進行測試與驗收,所有返回碼及業務邏輯以線上為准;
2、手機網站支付只支持余額支付,不支持銀行卡、余額寶等其他支付方式;
3、支付時,請使用沙箱買家賬號支付,在登錄支付寶,輸入手機號的頁面,點擊右下角 支付寶賬戶登錄;