開發(fā)準備
1.首先新建項目,然后去官網(wǎng)下載最新的開發(fā)包:
http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1,
當然也可以用CocoaPods
來下載不過用這個下載的話只會下載到單純的客戶端與網(wǎng)絡服務請求的SDK不包含加密的那些代碼,而有些公司是要把加密做到本地的所以選擇哪種方式看開發(fā)者的習慣于公司需求.
2.下載后打開點擊開發(fā)包可以打開更新日志
來比對當前版本不要去一些非官網(wǎng)的地方下載SDK有可能不是最新版本會出現(xiàn)BUG
3.打開客戶端開發(fā)包找到IOS對應的包文件解壓得到開發(fā)包,包含1個framework
文件一個bundle
文件一個Demo
文件夾
一般情況下支付功能的交互流程
比如我們?nèi)ツ硞€APP去支付一個產(chǎn)品,流程為:
1.用戶點擊支付->
2.客戶端請求服務器用戶支付->
3.服務器接收請求生成金額訂單等要給第三方支付的一切信息,并生成回調(diào)參數(shù)傳給客戶端->
4.客戶端接收信息(一般會再讓用戶確認支付或者干脆購買后是生成訂單,然后才是付款)并將服務器給的信息分別傳入SDK需要的參數(shù)中,調(diào)用SDK的支付方法->
5.由SDK向SDK自己的服務器發(fā)出支付請求,SDK自己的服務器接收支付請求處理成功后,給客戶端本身與公司的后臺都發(fā)送一條支付成功的消息,客戶端與后臺根據(jù)這條消息再做處理.
針對開發(fā)環(huán)境的一些設置
支付又分為2種情況本地簽名,和服務器簽名,我用到正好都是公司要求本地簽,服務器的我就稍微說1點.
服務器簽名:
/**
* 支付接口
*
* @param orderStr 訂單信息
* @param schemeStr 調(diào)用支付的app注冊在info.plist中的scheme
* @param compltionBlock 支付結(jié)果回調(diào)Block
*/
- (void)payOrder:(NSString *)orderStr
fromScheme:(NSString *)schemeStr
callback:(CompletionBlock)completionBlock;
服務器簽名注意的是在callback:回調(diào)中要進行驗簽,就是把服務器給的訂單簽名信息在用公鑰解密,比對訂單細節(jié),檢查是否被他人篡改,并且如果是wap支付,不會反回在appDelegate
的application:openURL
方法.
本地簽名:
先拖入實現(xiàn)加密的文件與模型:
這時候會報錯(補充一點: 有些朋友找不到NSString或者一些數(shù)據(jù)類型報錯都是因為缺少Foundation頭文件,可能我寫的不太明白,有些朋友還是不太懂)大部分錯誤都是因為一些文件中在支付寶的Demo的Pch
文件中統(tǒng)一添加的#import <Foundation/Foundation.h>
,如果我們的項目中沒有這一步,那么要么也建立pch
要么單獨添加上.
這時還會有一個錯誤:
注意這里的Header Search Paths
路徑為空:
打開電腦這個文件的所在地 雙擊Header Search Paths
將電腦的文件拖入Header Search Paths
會生成一個路徑:
導入一來框架: 這個最好跟著Demo一個一個往里添加,也不要光看網(wǎng)上資料主要還是看Demo:
添加SDK和靜態(tài)庫:
報錯:這個錯誤與另外一種說SDK不支持64位比較常見,都是把靜態(tài)庫或者SDK都刪了重新導入就行了
到這里應該已經(jīng)可以運行程序了.
如果還是出現(xiàn)了編譯錯誤等問題,導入框架不全與SDK靜態(tài)庫的路徑錯誤比例比較大.
建議等能夠運行程序后在進行開發(fā).
正式開發(fā)
首先我們介紹一段代碼:
NSString *orderSpec = [order description];
將商品的信息添加為字符串order
是一個對象,而description]
是將這個對象的屬性進行拼接返回一個字符串.
在介紹3個屬性:
//合作商戶ID。用簽約支付寶賬號登錄ms.alipay.com后,在賬戶信息頁面獲取。
NSString *partner = @"";
//賬戶ID。用簽約支付寶賬號登錄ms.alipay.com后,在賬戶信息頁面獲取。
NSString *seller = @"";
//商戶私鑰,自助生成
NSString *privateKey = @"";
這3個屬性必須是個人或公司申請后才能得到的..我用的公司的就不寫上了請自行填寫.
//將商品信息賦予AlixPayOrder的成員變量
Order *order = [[Order alloc] init];
order.partner = partner;
order.seller = seller;
order.tradeNO = @"G111111111111"; //訂單ID(由商家自行制定)
order.productName = @"我的測試"; //商品標題
order.productDescription = @"我的商品描述"; //商品描述
order.amount = @"0.01"; //商品價格
order.notifyURL = @"http://www.xxx.com"; //回調(diào)URL
order.service = @"mobile.securitypay.pay";
order.paymentType = @"1";
order.inputCharset = @"utf-8";
order.itBPay = @"30m";
order.showUrl = @"m.alipay.com";
//應用注冊scheme,在AlixPayDemo-Info.plist定義URL types
NSString *appScheme = @"alisdkdemo";
//將商品信息拼接成字符串
NSString *orderSpec = [order description];
NSLog(@"orderSpec = %@",orderSpec);
//獲取私鑰并將商戶信息簽名,外部商戶可以根據(jù)情況存放私鑰和簽名,只需要遵循RSA簽名規(guī)范,并將簽名字符串base64編碼和UrlEncode
id<DataSigner> signer = CreateRSADataSigner(privateKey);
NSString *signedString = [signer signString:orderSpec];
NSString *orderString = nil;
生成加密后的字符串 注意的是NSString *appScheme = @"alisdkdemo";
這個值是從支付寶的商戶地址中填寫的,請保持一致.
最后處理結(jié)果:
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString, @"RSA"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
//結(jié)果處理,其實就是取字典里面的內(nèi)容,這個取字符串然后變個模型就好了 或者直接取不便模型,方法很多.
NSLog(@"開始確認支付狀態(tài) %@",resultDic[@"resultStatus"]);
AlixPayResult* resultModel = [AlixPayResult itemWithDictory:resultDic];
if (resultModel)
{
//狀態(tài)返回9000為成功
if (resultModel.statusCode == 9000)
{
/*
*用公鑰驗證簽名 嚴格驗證請使用result.resultString與result.signString驗簽
*/
NSLog(@"支付寶交易成功");
/*
*用公鑰驗證簽名 嚴格驗證請使用result.resultString與result.signString驗簽
*/
//交易成功
NSString* key = AlipayPubKey;//簽約帳戶后獲取到的支付寶公鑰
id<DataVerifier> verifier;
verifier = CreateRSADataVerifier(key);
// 驗證簽名
if ([verifier verifyString:resultModel.resultString withSign:resultModel.signString])
{
//驗證簽名成功,交易結(jié)果無篡改
NSLog(@"驗證成功");
}
}
}
else if([resultDic[@"resultStatus"]isEqualToString:@"6001"])
{
//用戶取消
NSLog(@"用戶主動取消支付");
}else
{
}
}];
}
這里注意:if([resultDic[@"resultStatus"]isEqualToString:@"6001"])
支付寶有BUG 這個6001 不要信,可以和公司商量下,是加個確認接口還是一定時間內(nèi)檢查后臺,總之很有可能用戶付錢成功,SDK通知你用戶手動取消,這個BUG是在弱網(wǎng)狀態(tài)下比較多.
然后記得在 AppDelegate
里面加上如下代碼:
//只要是調(diào)用手機上的支付寶客戶端,在支付寶客戶端操作完成返回自己的app時,都會調(diào)用這個方法,
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
//跳轉(zhuǎn)支付寶錢包進行支付,需要將支付寶錢包的支付結(jié)果回傳給SDK(這個是將支付寶客戶端的支付結(jié)果傳回給SDK)
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService]
processOrderWithPaymentResult:url
standbyCallback:^(NSDictionary *resultDic)
{
NSLog(@" ------result = %@",resultDic);//返回的支付結(jié)果
}];
}
return YES;
}
最后記得把這里寫了:
NSString *appScheme = @"alisdkdemo"
代碼 網(wǎng)頁上申請的 圖片上那里填寫的保持一致.
補充: 如果要用swift
來調(diào)用支付寶SDK 最好把支付的與回調(diào)的邏輯單獨建立工具類傳遞數(shù)據(jù)便好,從流程上本身無太大區(qū)別稍微注意的是在swift
中 AlipaySDK.h
有可能因為語言環(huán)境問題出現(xiàn)缺少引入類的情況,少什么補什么就好,其他也一樣.
如有問題歡迎留言...