概述
詳細
支付寶和微信都是業界的老大哥,相信大家都有所覺得文檔、SDK都是各種坑吧(純粹吐槽而已),本文先整理支付寶支付集成。
一、准備工作
1、向支付寶”簽約" 成為支付寶的”商戶”, 簽約完成后, 支付寶會提供一些必要的數據給我們(商戶ID-partner,帳號ID-支付寶帳號)
注意:簽約成為支付寶商戶,需要提供公司營業執照[http://act.life.alipay.com/shopping/before/help/index.html](http://act.life.alipay.com/shopping/before/help/index.html)
2、獲取支付相關的 '私鑰' 和 '密鑰'
[https://doc.open.alipay.com/doc2/detail?treeId=44&articleId=103242&docType=1](https://doc.open.alipay.com/doc2/detail?treeId=44&articleId=103242&docType=1)
3、下載支付的SDK
[https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1](https://doc.open.alipay.com/doc2/detail?treeId=54&articleId=103419&docType=1)
二、集成支付寶SDK步驟
1、從官方Demo中把紅色標注的文件添加進入項目中,記得選copy;

2、
點擊項目名稱,點擊“Build Phases”選項卡,在“Link Binary with Librarles” 選項中,新增“AlipaySDK.framework”和“SystemConfiguration.framework” 兩個系統庫文件。如果項目中已有這兩個庫文件,可不必再增加;
添加下圖中的庫:

localhost:alipay mac$ ls APAuthV2Info.h Order.h libssl.a APAuthV2Info.m Order.m openssl AlipaySDK.bundle Util AlipaySDK.framework libcrypto.a 導入系統庫 SystemConfiguration.framework
3、
添加Pch文件新建pch成功后,在pch文件中添加#import然后按照下圖所示,進行修改pch的文件路徑
也可以不設置,我這個是我需要設置#import <UIKit/UIKit.h> #import <Foundation/Foundation.h>,也可以不用使用,只在當前文件里添加相對應的使用即可,但是這樣針對整個項目來說方便些

4、
修改SDK路徑完成以上兩步之后,會發現出現了一個經典的錯誤,找不到:#include解決這個問題,需要在Header Search Path中配置SDK中的點a(libssl.a/libcrypto.a)文件所在的路徑,找到之后設置好正確的路徑

點擊項目名稱,點擊“Build Settings”選項卡,在搜索框中,以關鍵字“search” 搜索,對“Header Search Paths”增加頭文件路徑:“$(SRCROOT)/項目名稱/IntegratedAlipay/AlipayFiles”(注意:不包括引號,如果不是放到項目根目錄下,請在項目名稱后面加上相應的目錄名);

根據你文件位置,我的是:
“$(SRCROOT)/QTXStudent/Classes/Alipay/AlipayFiles”
5、 為URL Types 添加支付寶回調scheme
點擊項目名稱,點擊“Info”選項卡,在URL types里面添加一項,Identifier可以不填,URL schemes必須和appScheme的值相同,用於支付寶處理回到應用的事件;
為URL Types 添加支付寶回調scheme

6、在工程項目的plist文件中添加
iOS 9以后的系統需要添加支付寶分享的scheme到白名單中,scheme名為alipayshare
按如下形式添加即可:

7、在AppDelegate中處理事件回調:
/**
這里處理微信/支付寶支付完成之后跳轉回來
*/
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
//如果極簡 SDK 不可用,會跳轉支付寶錢包進行支付,需要將支付寶錢包的支付結果回傳給 SDK
if ([url.host isEqualToString:@"safepay"]) {
//跳轉支付寶錢包進行支付,處理支付結果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"支付寶客戶端支付結果result = %@",resultDic);
if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
// 發通知帶出支付成功結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
} else {
// 發通知帶出支付失敗結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
}
}];
}
if ([url.host isEqualToString:@"platformapi"]){//支付寶錢包快登授權返回 authCode
[[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"支付寶網頁版result = %@",resultDic);
if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
// 發通知帶出支付成功結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
} else {
// 發通知帶出支付失敗結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
}
}];
}
return YES;
}
// NOTE: 9.0以后使用新API接口
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
//如果極簡 SDK 不可用,會跳轉支付寶錢包進行支付,需要將支付寶錢包的支付結果回傳給 SDK
if ([url.host isEqualToString:@"safepay"]) {
//跳轉支付寶錢包進行支付,處理支付結果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"支付寶客戶端支付結果result = %@",resultDic);
if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
// 發通知帶出支付成功結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
} else {
// 發通知帶出支付失敗結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
}
}];
}
if ([url.host isEqualToString:@"platformapi"]){//支付寶錢包快登授權返回 authCode
[[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"支付寶網頁版result = %@",resultDic);
if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
// 發通知帶出支付成功結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnSucceedPayNotification object:resultDic];
} else {
// 發通知帶出支付失敗結果
[[NSNotificationCenter defaultCenter] postNotificationName:ZLAliReturnFailedPayNotification object:resultDic];
}
}];
}
return YES;
}
8、 在需要用的地方導入“AlipayHeader.h”,並使用“[AlipayRequestConfig alipayWithPartner:...”方法進行支付;
/**
* 配置請求信息,僅有變化且必要的參數
*
* @param partner 合作者身份ID 以 2088 開頭由 16 位純數字組成的字符串。
* @param sellerID 賣家支付寶賬號 以 2088 開頭由 16 位純數字組成的字符串。
* @param outTradeNO 商戶網站唯一訂單號
* @param subject 商品名稱
* @param body 商品詳情
* @param totalFee 總金額
* @param notifyURL 服務器異步通知頁面路徑
* @param itBPay 未付款交易的超時時間
*/
+ (void)alipayWithPartner:(NSString *)partner
sellerID:(NSString *)sellerID
outTradeNO:(NSString *)outTradeNO
subject:(NSString *)subject
body:(NSString *)body
totalFee:(NSString *)totalFee
notifyURL:(NSString *)notifyURL;
僅含有變化的參數:
+ (void)alipayWithPartner:(NSString *)partner
sellerID:(NSString *)sellerID
outTradeNO:(NSString *)outTradeNO
subject:(NSString *)subject
body:(NSString *)body
totalFee:(NSString *)totalFee
notifyURL:(NSString *)notifyURL {
[self alipayWithPartner:partner sellerID:sellerID outTradeNO:outTradeNO subject:subject body:body totalFee:totalFee notifyURL:aliNotifyURL service:@"mobile.securitypay.pay" paymentType:@"1" inputCharset:@"utf-8" itBPay:@"30m" privateKey:aliPrivateKey appScheme:aliAppScheme];
}
包含所有必要的參數:
+ (void)alipayWithPartner:(NSString *)partner
sellerID:(NSString *)sellerID
outTradeNO:(NSString *)outTradeNO
subject:(NSString *)subject
body:(NSString *)body
totalFee:(NSString *)totalFee
notifyURL:(NSString *)notifyURL
service:(NSString *)service
paymentType:(NSString *)paymentType
inputCharset:(NSString *)inputCharset
itBPay:(NSString *)itBPay
privateKey:(NSString *)privateKey
appScheme:(NSString *)appScheme {
Order *order = [Order order];
order.partner = partner;
order.sellerID = sellerID;
order.outTradeNO = outTradeNO;
order.subject = subject;
order.body = body;
order.totalFee = totalFee;
order.notifyURL = notifyURL;
order.service = service;
order.paymentType = paymentType;
order.inputCharset = inputCharset;
order.itBPay = itBPay;
// 將商品信息拼接成字符串
NSString *orderSpec = [order description];
// 獲取私鑰並將商戶信息簽名,外部商戶可以根據情況存放私鑰和簽名,只需要遵循 RSA 簽名規范, 並將簽名字符串 base64 編碼和 UrlEncode
NSString *signedString = [self genSignedStringWithPrivateKey:aliPrivateKey OrderSpec:orderSpec];
// 調用支付接口
[self payWithAppScheme:appScheme orderSpec:orderSpec signedString:signedString];
}
生成signedString:
+ (NSString *)genSignedStringWithPrivateKey:(NSString *)privateKey OrderSpec:(NSString *)orderSpec {
// 獲取私鑰並將商戶信息簽名,外部商戶可以根據情況存放私鑰和簽名,只需要遵循 RSA 簽名規范, 並將簽名字符串 base64 編碼和 UrlEncode
id<DataSigner> signer = CreateRSADataSigner(privateKey);
return [signer signString:orderSpec];
}
支付:
+ (void)payWithAppScheme:(NSString *)appScheme orderSpec:(NSString *)orderSpec signedString:(NSString *)signedString {
// 將簽名成功字符串格式化為訂單字符串,請嚴格按照該格式
NSString *orderString = nil;
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"", orderSpec, signedString, @"RSA"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) { // 網頁版
NSLog(@"支付寶支付結果 reslut = %@", resultDic);
// 返回結果需要通過 resultStatus 以及 result 字段的值來綜合判斷並確定支付結果。 在 resultStatus=9000,並且 success="true"以及 sign="xxx"校驗通過的情況下,證明支付成功。其它情況歸為失敗。較低安全級別的場合,也可以只通過檢查 resultStatus 以及 success="true"來判定支付結果
if (resultDic && [resultDic objectForKey:@"resultStatus"] && ([[resultDic objectForKey:@"resultStatus"] intValue] == 9000)) {
// 發通知帶出支付成功結果
[ZLNotificationCenter postNotificationName:QTXAliReturnSucceedPayNotification object:resultDic];
} else {
// 發通知帶出支付失敗結果
[ZLNotificationCenter postNotificationName:QTXAliReturnFailedPayNotification object:resultDic];
}
}];
}
}
9、
在本頭文件中設置aliPartnerID、aliSellerAccount、aliNotifyURL、aliAppScheme和aliPrivateKey的值(所有的值在支付寶回復的郵件里面:注意,建議除appScheme以外的字段都從服務器請求);
這時候,我們支付就直接一句話搞定:
// 支付寶支付
[AlipayRequestConfig alipayWithPartner:aliPartnerID sellerID:aliSellerAccount outTradeNO:[self generateTradeNO] subject:@"測試" body:@"支付寶支付" totalFee:@"0.01" notifyURL:aliNotifyURL]; // notifyURL: 回調url@"http://www.xxx.com"
[ZLNotificationCenter addObserver:self selector:@selector(paySucceed) name:ZLAliReturnSucceedPayNotification object:nil];
[ZLNotificationCenter addObserver:self selector:@selector(payFailed) name:ZLAliReturnFailedPayNotification object:nil];
10、建議除appScheme以外的字段都從服務器請求!
建議除appScheme以外的字段都從服務器請求!建議除appScheme以外的字段都從服務器請求!
PS:重要的事情說三遍!!!
上面的第七步和第八步建議不要使用,直接用第九步去替代!建議除appScheme以外的字段都從服務器請求!
如果后台給你一個接口返回那些參數了,你就不用客戶端去加密算法,只負責請求后台拿到這些參數再去請求支付寶即可.
下面例子是支付寶的拼接方式,請按照當前版本的相對應的拼接方式來.
// 支付寶支付
- (void)alipayPay {
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"orderNo"] = self.orderNo; // 訂單號
params[@"realAmt"] = [NSString stringWithFormat:@"%.2lf", self.realAmt]; // 金額
__weak __typeof(self) weakSelf = self;
[QTXHttpTool post:QTX_aliPay_url params:params success:^(id json) {
QTXLog(@"支付寶支付返回參數接口 請求成功-%@", json);
if ([json[@"success"] isEqual:@(YES)]) {
// 返回生成訂單信息及簽名
NSString *signedString = json[@"data"][@"sign"];
NSString *orderInfoEncoded = json[@"data"][@"orderInfo"];
// NOTE: 如果加簽成功,則繼續執行支付
if (signedString != nil) {
// NOTE: 將簽名成功字符串格式化為訂單字符串,請嚴格按照該格式
// NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@&sign_type=RSA", orderInfoEncoded, signedString];
NSString *orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderInfoEncoded, signedString, @"RSA"];
// NOTE: 調用支付結果開始支付
[[AlipaySDK defaultService] payOrder:orderString fromScheme:XHHAppScheme callback:^(NSDictionary *resultDic) {
QTXLog(@"reslut = %@",resultDic);
if ([resultDic[@"resultStatus"] intValue] == 9000) {
[QTXNotificationCenter addObserver:self selector:@selector(paySucceed) name:QTXWXReturnSucceedPayNotification object:nil];
} else {
[QTXNotificationCenter addObserver:self selector:@selector(payFailed) name:QTXWXReturnFailedPayNotification object:nil];
}
}];
}
} else {
[MBProgressHUD showError:[NSString stringWithFormat:@"%@", json[@"errorMessage"]]];
}
} failure:^(NSError *error) {
[MBProgressHUD showError:@"暫無網絡,稍后再試"];
QTXLog(@"支付寶支付返回參數接口 請求失敗-%@", error);
}];
}
11、支付寶集成失敗相關問題
1. 報錯 AL159
查看金額是否是兩位小數,切不可拼接"元"
2. 報錯“創建交易異常,請重新創建后再付款”
返回的狀態碼是“6001”,取消支付
當是用公司注冊支付寶App時分配的商戶賬號登陸的支付寶,進行支付測試的。支付寶那邊檢測到是商戶而不是普通的支付賬號,商戶支付給商戶自己,所以支付失敗!
三、其他補充
1、壓縮文件截圖

2、Alipay 包截圖

目前是項目中直接操作, 在AlipayHeader.h文件里補充上你們項目的aliPartnerID, aliSellerAccount, aliNotifyURL, 具體可參考代碼, 項目則能夠直接運行!
注:本文著作權歸作者,由demo大師發表,拒絕轉載,轉載需要作者授權
