支付寶和微信都是業界的老大哥,相信你們都有所以爲文檔、SDK都是各類坑吧(純粹吐槽而已),本文先整理支付寶支付集成。html
一、向支付寶」簽約" 成爲支付寶的」商戶」, 簽約完成後, 支付寶會提供一些必要的數據給咱們(商戶ID-partner,賬號ID-支付寶賬號)算法
注意:簽約成爲支付寶商戶,須要提供公司營業執照[http://act.life.alipay.com/shopping/before/help/index.html](http://act.life.alipay.com/shopping/before/help/index.html)json
二、獲取支付相關的 '私鑰' 和 '密鑰'api
[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)安全
三、下載支付的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)微信
一、從官方Demo中把紅色標註的文件添加進入項目中,記得選copy;網絡
二、app
點擊項目名稱,點擊「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
三、
添加Pch文件新建pch成功後,在pch文件中添加#import而後按照下圖所示,進行修改pch的文件路徑
也能夠不設置,我這個是我須要設置#import <UIKit/UIKit.h> #import <Foundation/Foundation.h>,也能夠不用使用,只在當前文件裏添加相對應的使用便可,可是這樣針對整個項目來講方便些
四、
修改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」
五、 爲URL Types 添加支付寶回調scheme
點擊項目名稱,點擊「Info」選項卡,在URL types裏面添加一項,Identifier能夠不填,URL schemes必須和appScheme的值相同,用於支付寶處理回到應用的事件;
爲URL Types 添加支付寶回調scheme
六、在工程項目的plist文件中添加
iOS 9之後的系統須要添加支付寶分享的scheme到白名單中,scheme名爲alipayshare
按以下形式添加便可:
七、在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; }
八、 在須要用的地方導入「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]; } }]; } }
九、
在本頭文件中設置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];
十、建議除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); }]; }
十一、支付寶集成失敗相關問題
1. 報錯 AL159
查看金額是不是兩位小數,切不可拼接"元"
2. 報錯「建立交易異常,請從新建立後再付款」
返回的狀態碼是「6001」,取消支付
當是用公司註冊支付寶App時分配的商戶帳號登錄的支付寶,進行支付測試的。支付寶那邊檢測到是商戶而不是普通的支付帳號,商戶支付給商戶本身,因此支付失敗!
一、壓縮文件截圖
二、Alipay 包截圖
目前是項目中直接操做, 在AlipayHeader.h文件裏補充上大家項目的aliPartnerID, aliSellerAccount, aliNotifyURL, 具體可參考代碼, 項目則可以直接運行!