前一久做了支付寶支付,分享一下接入的詳細步驟吧,移動端和服務端demo源碼已上傳至GitHub,要下載的移步至文章末尾。
先給出支付寶官方文檔:https://docs.open.alipay.com/204/105051/
適用場景
在App內集成支付寶支付。APP調用支付寶提供的SDK,SDK再調用支付寶APP內的支付模塊。如果用戶已安裝支付寶APP,商家APP會跳轉到支付寶中完成支付,支付完后跳回到商家APP內。如果用戶沒有安裝支付寶APP,商家APP內會調起支付寶網頁支付收銀台,用戶登錄支付寶賬戶,支付完后展示支付結果。
接入
1. 創建應用並獲取APPID
地址:https://open.alipay.com/platform/appManage.htm#/apps
創建應用后即生成應用的標識APPID
創建指南:https://docs.open.alipay.com/200/105310/
2. 添加App支付功能
從我的應用列表點擊應用對應的查看詳情按鈕進入

添加完成后,若應用狀態為開發中狀態,只能在沙箱環境下進行調試。應用申請上線后,會同時申請此列表的功能,接口即生效。
注:手機端支付可以添加 APP支付 和手機網站支付。APP支付使用原生開發,調用支付寶支付SDK。手機網站支付是在網頁中調用支付寶,所以使用h5+mui方式開發APP可使用此功能,無需跳轉至原生。這里根據需要酌情選擇。
3. 簽約
在功能列表中點擊簽約,簽約后才能正常使用,簽約前可使用沙箱模式進行調試。
以上的步驟可以交給公司相關人員進行申請,開發人員請看下面
密鑰配置
1. 支付寶密鑰處理體系

所以需要獲取到應用公鑰、應用私鑰以及支付寶公鑰:
①應用公鑰
由商戶自己生成的RSA公鑰(與應用私鑰必須匹配),商戶需上傳應用公鑰到支付寶開放平台,以便支付寶使用該公鑰驗證該交易是否是商戶發起的。
②應用私鑰
由商戶自己生成的RSA私鑰(與應用公鑰必須匹配),商戶開發者使用應用私鑰對請求字符串進行加簽。
③支付寶公鑰
支付寶的RSA公鑰,商戶使用該公鑰驗證該結果是否是支付寶返回的。
2. 獲取密鑰和密鑰配置
步驟:https://docs.open.alipay.com/200/105310#s2
簽名專區:https://docs.open.alipay.com/291/106103/
密鑰生成工具:https://docs.open.alipay.com/291/106097/
注:使用密鑰生成工具生成密鑰時,要注意密鑰格式,如果服務端使用.Net或其他非java語言,一定要選PKCS1(非JAVA適用),否則后面要涼涼。密鑰長度建議選擇2048。

集成開發
使用App支付功能需要在原生中實現,這里以Android為例。接入移動支付需要集成兩個SDK,分別是客戶端的SDK和服務端的SDK。
SDK下載地址:
客戶端https://docs.open.alipay.com/54/104509
服務端https://docs.open.alipay.com/54/106370/
注:為何需要兩個SDK?因為客戶端不能含有敏感信息,包括密鑰、APPID等,這些東西都必須從服務端獲取,包括加簽驗簽過程,所以還需要集成一個服務端給APP調用。
客戶端(Android)SDK集成
集成方法:https://docs.open.alipay.com/204/105296/
(1)發起支付請求
支付寶SDK中提供了一個PayTask類,使用其payV2方法即可發起支付請求。
/**
* 支付(加簽過程不允許在客戶端進行,必須在服務端,否則有極大的安全隱患)
*
* @param orderInfo 加簽后的支付請求參數字符串(主要包含商戶的訂單信息,key=value形式,以&連接)。
*/
private void pay(final String orderInfo) {
final Runnable payRunnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(MainActivity.this);
//第二個參數設置為true,將會在調用pay接口的時候直接喚起一個loading
Map<String, String> result = alipay.payV2(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: app支付請求參數字符串,主要包含商戶的訂單信息,key=value形式,以&連接。由眾多請求參數加簽以及非對稱加密后生成。
具體參數說明請看文檔:https://docs.open.alipay.com/204/105465/
所以發起支付請求的重點在於獲取orderInfo,也就是從服務端獲取加簽結果,加簽過程不允許在客戶端進行,否則可能被反編譯,造成嚴重的后果。所以加簽過程請看下面服務端(.Net)SDK集成的第(1)條。
(2)支付回調
調用支付寶支付后,將會收到同步通知和異步通知。如果過程中取消支付則只會收到同步通知。
同步通知:支付寶sdk對商戶的請求支付數據處理完成后,會將結果同步反饋給app端。在支付回調中即可獲取支付結果信息。
異步通知: 對於App支付產生的交易,支付寶會根據原始支付API中傳入的異步通知地址notify_url,通過POST請求的形式將支付結果作為參數通知到商戶系統。
注: 手機端同步通知有可能存在獲取不到的情況,如手機關機,應用crash等情況,所以手機端同步回調只作為支付結果提示。真正的支付成功邏輯將在支付寶異步通知(服務端)中做處理,請看下面服務端(.Net)SDK集成的第(2)條。
so,手機端只做同步通知處理,如下:
Map<String, String> result = alipay.payV2(orderInfo, true);
result就是返回的同步回調結果,里面的resultStatus是支付狀態碼,如果是9000則支付成功。
if (TextUtils.equals(resultStatus, "9000")) {
// 該筆訂單是否真實支付成功,需要依賴服務端的異步通知。
showAlert(MainActivity.this, "支付成功" + payResult);
} else {
// 該筆訂單真實的支付結果,需要依賴服務端的異步通知。
showAlert(MainActivity.this, "支付失敗" + payResult);
}
如果使用混合開發(h5+mui+原生),還需跳轉至mui頁面,則可使用js回調函數將同步通知傳入mui端進行后續處理,如:
// 調用方法將原生代碼的執行結果返回給js層並觸發相應的JS層回調函數
JSUtil.execCallback(mWebview, CallBackID, resultStatus, JSUtil.OK, false);
服務端(.Net)SDK集成
集成方法:https://docs.open.alipay.com/54/106370/
為了便於支付寶異步接口調用,這里服務端將使用webApi,服務端主要工作為加簽、驗簽(異步通知驗證)以及更改訂單支付狀態。
(1)加簽
核心步驟:
//從pem文件中讀取
APP_PRIVATE_KEY = GetCurrentPathByAbs() + "rsa_private_key.pem";
ALIPAY_PUBLIC_KEY = GetCurrentPathByAbs() + "rsa_alipay_public_key.pem";
//最后一個參數為false直接將私鑰內容寫入代碼,true從pem文件中讀取
IAopClient client = new DefaultAopClient(gateway, APPID, APP_PRIVATE_KEY, format, version, sign_type, ALIPAY_PUBLIC_KEY, CHARSET, true);
//實例化具體API對應的request類,類名稱和接口名稱對應,當前調用接口名稱如:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已經封裝掉了公共參數,這里只需要傳入業務參數。以下方法為sdk的model入參方式(model和biz_content同時存在的情況下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.Body = body;
model.Subject = subject;
model.TotalAmount = total_amount;
model.ProductCode = product_code;
model.OutTradeNo = out_trade_no;
model.TimeoutExpress = timeout_express;
request.SetBizModel(model);
request.SetNotifyUrl(notify_url);
//這里和普通的接口調用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = client.SdkExecute(request);
string resp = response.Body;
return resp;
支付寶服務端SDK中提供了一個SdkExcute方法,需要傳入對應的request類AlipayTradeAppPayRequest。實例化IAopClient對象時需要傳入請求網關(gateway)、APPID、應用私鑰、支付寶公鑰、調用的接口版本、編碼方式、簽名算法類型以及是否從文件中讀取密鑰的一個bool類型值。
其中,簽名算法類型應和配置密鑰時選擇的類型一致,另外2018年1月5號之后創建的應用都需要使用RSA2,也就是sign_type=RSA2,否則會加簽失敗。最后一個bool型參數,為false直接從代碼中讀取密鑰,為true則從pem文件中讀取。
如果覺得密鑰放在代碼中不夠安全的話,建議將密鑰存儲為pem文件,執行加簽過程時從文件中讀出,做法如下:
##### ① 生成pem文件 pem文件是有格式的,就像這樣 ```csharp -----BEGIN RSA PRIVATE KEY----- MIIEogIBAjayyr4gU38hr/EYnXdbEfbaGkdVnvf6Y+9zWkkiPcNq-----這里是密鑰內容 -----END RSA PRIVATE KEY----- ``` 生成pem文件需要使用openssl.exe這個可執行文件,當然也可以copy個pem文件替換下里面的密鑰內容,不過這樣有可能會導致格式亂了。openssl.exe在密鑰生成工具的openssl的bin目錄下,雙擊即可打開。 
生成應用私鑰pem文件,輸入命令:genrsa -out rsa_private_key.pem 2048
生成應用公鑰pem文件,輸入命令:rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
支付寶公鑰需要上傳應用公鑰獲取,如果不使用pem文件,代碼中直接放上支付寶公鑰就行,如果要使用pem文件,可以將應用公鑰的pem文件復制一份,將密鑰內容換成支付寶公鑰的,格式如下。
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAADCBi----------這里是支付寶公鑰
-----END PUBLIC KEY-----
注:上面密鑰的格式默認為PKCS1的,如果使用PKCS8(Java適用)別忘記執行轉碼命令,否則也要涼涼的。如果使用沙箱模式請將密鑰換成沙箱版進行測試。
② 從pem文件中讀取密鑰
首先獲取存放密鑰文件的路徑,為了防止出現意外,可獲取文件的絕對路徑,如下:
/// <summary>
/// 獲取私鑰公鑰的路徑(絕對路徑)
/// </summary>
/// <returns></returns>
private static string GetCurrentPathByAbs()
{
return HttpRuntime.AppDomainAppPath.ToString() + "rsa/";
}
獲取到文件路徑后傳入IAopClient的構造函數中,並將最后一個參數置為true即可。
IAopClient client = new DefaultAopClient(gateway, APPID, APP_PRIVATE_KEY, format, version, sign_type, ALIPAY_PUBLIC_KEY, CHARSET, true);
(2) 驗簽
當支付寶發送異步通知時,會將支付結果的信息異步返回至服務端,服務端需要進行驗簽操作,驗證請求是否是支付寶發送,並利用支付寶公鑰進行比對,保證交易的安全性和正確性。主要步驟如下:
①提供異步調用接口
支付寶異步通知將以post的方式發起請求,所以我們需要編寫一個webapi接口,並保證接口的正確性,如下:
/// <summary>
/// 異步驗簽(客戶端支付后,支付寶服務器將異步調用此方法)
/// 實際支付邏輯在此操作,支付寶服務端將保證調用到此接口
/// </summary>
/// <returns></returns>
[HttpPost]
public string GetAsynchronousYanQian()
{
return AlipayUtil.AsynchronousYanQian(GetRequestPost());
}
這個接口地址便是加簽過程中傳入的異步通知地址notify_url
②獲取異步通知結果並驗簽
官方文檔地址:https://docs.open.alipay.com/54/106370/
上面這個鏈接支付寶介紹了如何獲取通知參數並驗簽。但是部分代碼是錯的,請看我寫的。
獲取支付寶異步通知結果如下:
/// <summary>
/// 獲取支付寶POST過來通知消息,並以“參數名=參數值”的形式組成數組
/// request回來的信息組成的數組
/// </summary>
/// <returns></returns>
public Dictionary<string, string> GetRequestPost()
{
int i = 0;
IDictionary<string, string> sArray = new Dictionary<string, string>();
NameValueCollection coll;
coll = Request.Form;
String[] requestItem = coll.AllKeys;
for (i = 0; i < requestItem.Length; i++)
{
sArray.Add(requestItem[i], Request.Form[requestItem[i]]);
}
return (Dictionary<string, string>)sArray;
}
驗簽:
驗簽過程支付寶AlipaySignature類提供了驗簽方法RSACheckV1和RSACheckV2,區別就不細說,這里使用RSACheckV1方法,第一個參數便是支付寶返回的異步通知結果,第二個參數傳入支付寶公鑰,同樣最后一個參數傳false從代碼讀取支付寶公鑰,傳true從pem 文件中讀取。
bool flag = AlipaySignature.RSACheckV1(result, ALIPAY_PUBLIC_KEY, CHARSET, sign_type, true);
驗簽結果返回一個bool值,如果驗簽成功返回true,否則false。
③通知支付寶
支付寶異步通知調用接口后,如果未收到成功反饋,將會在一段時間內重復發送異步通知,以保證服務端接收到異步通知。所以當驗簽成功並真正的改變訂單支付狀態后,需要給支付寶返回success。如果反饋給支付寶的字符不是success這7個字符,支付寶服務器會不斷重發通知,直到超過24小時22分鍾。一般情況下,25小時以內完成8次通知(通知的間隔頻率一般是:4m,10m,10m,1h,2h,6h,15h)。
if (flag)
{
//驗簽成功,將數據庫中訂單的支付狀態改變
if (ChangePayState())
{
//如果數據庫插入成功,通知支付寶已收到通知
return "success";
}
else
{
return "fail";
}
}
else
{
return "fail";
}
注:如果在改變訂單支付狀態時需要的某些參數無法獲取,可以將其拼接在加簽過程中某些不是很必要的參數里,支付寶將在異步通知中返回。
效果圖

以上便是支付寶支付的實現步驟,包括了移動端(原生)和服務端(.Net)。Demo已上傳至GitHub,有興趣的可以下載:
移動端:https://github.com/yangxch/AlipayDemo
服務端:https://github.com/yangxch/AlipayServerAPIDemo
原創不易,轉載請注明:https://www.cnblogs.com/xch-yang/p/10336922.html