近期客戶提出要開發一個IOS上的app做爲訪問他們站點的途徑之中的一個。爲何說之中的一個呢。由於眼下PC和Mobile這兩個站眼下都已經上線了。css
因此問題就簡單了,咱們僅僅需要把mobile站UI改動一下,而後在依據客戶的新需求改動下程序,以後把這個站套個IOS的殼子就可以了。c++
那麼問題來了,咱們的mobile支付的時候調用的是支付寶的網頁支付,這個頁面是支付寶的,咱們沒辦法改動,因此假設套在殼子裏繼續使用這樣的支付方式會有點不三不四的感受。因此咱們就決定調用支付寶錢包,也就是支付寶client。api
下面是我參考支付寶移動支付文檔整理出來的一些資料:數組
這是demo的下載地址,包含IOS和Android兩個版本號
http://aopsdkdownload.cn-hangzhou.alipay-pub.aliyun-inc.com/demo/WS_MOBILE_PAY_SDK_BASE.zip?安全
spm=0.0.0.0.LJBZ4o&file=WS_MOBILE_PAY_SDK_BASE.zipbash
首先要調用支付寶錢包你必須你登陸商戶的支付寶帳戶的「簽約管理」裏面去申請簽約開通「移動支付」markdown
PID和密鑰管理app
支付寶提供商戶接口產品時,會自主提供一個保障商戶接入安全的一組信息及其相應的配置平臺。這組信息就是密鑰。由商戶密鑰與支付寶密鑰交換後與支付寶商戶標識(如partnerID、APPID等)綁定。dom
合做夥伴密鑰異步
在服務市場簽約得到的大部分接口,簽約主體是商戶,接口權限屬於詳細的商戶。這部分接口需要使用PID和密鑰來調用,此類接口網關通常爲mapi(https://mapi.alipay.com/gateway.do)。PID相應的密鑰一共同擁有三種簽名方式,各自是MD五、RSA、DSA。由於產品的特殊性,每個產品支持哪些簽名方式不盡一樣,詳細需參考各個產品的接口技術文檔。
使用合做夥伴密鑰的典型功能包含:快捷登陸、移動支付、即時到帳收款、手機站點支付等。
查看PID和密鑰
查看PID
查看MD5(Key)
查看RSA商戶公鑰與支付寶公鑰
查看DSA商戶公鑰與支付寶公鑰
上傳公鑰
上傳RSA公鑰
上傳DSA公鑰
密鑰生成
RSA私鑰及公鑰生成
DSA私鑰及公鑰生成
這塊流程可以讓你上層領導來處理。這裏的相關操做都要在商戶支付寶帳戶中操做。
咱們來看一下咱們開發人員需要care的點
①交互流程:
功能流程
流程說明(以Android平臺爲例):
第2步:調用支付接口:此消息就是本接口所描寫敘述的開發包提供的支付對象PayTask,將商戶訂單信息傳進pay方法喚起支付寶收銀臺,訂單格式詳細參見「請求參數說明」。
第3步:手機支付寶支付開發包將會依照商戶App提供的參數發送支付請求。
第5步:異步發送支付通知:手機支付寶支付server端發送異步通知消息給商戶server端,參見「server異步通知參數說明」。
第7步:接口返回支付結果:商戶應用client經過當前調用支付的Activity的Handler對象,經過它的回調函數獲取支付結果,參見「同步通知參數說明」。
數據交互
1.構造訂單數據並簽名
商戶client依據手機支付寶支付開發包的接口規則,經過程序生成獲得簽名結果及要傳輸給手機支付寶支付開發包的數據集合。簽名相關的公私鑰生成及配置規則,見PID和密鑰管理。
2.發送請求數據
把構造完畢的數據集合傳遞給手機支付寶支付開發包。
手機支付寶支付開發包對請求數據進行處理
手機支付寶支付開發包將請求數據依據業務規則包裝後傳遞給支付寶服務端,服務端獲得這些集合後,會先進行安全校驗等驗證,一系列驗證經過後便會處理完畢此次發送過來的數據請求。
3.返回處理的結果數據
對於處理完畢的交易,支付寶會以兩種方式把數據分別反饋給商戶應用和商戶server。
在手機client上,開發包client直接把處理的數據結果反饋給商戶client;
支付寶server主動發起通知,調用商戶在請求時設定好的頁面路徑(參數notify_url,假設商戶沒設定。則不會進行該操做)。
4.對獲取的返回結果數據進行處理
商戶在client同步通知接收模塊或服務端異步通知接收模塊獲取支付寶返回的結果數據後,可以結合商戶自身業務邏輯進行數據處理(如:訂單更新、本身主動充值到會員帳號中等)。同步通知結果僅用於結果展現,入庫數據需以異步通知爲準。
②client調用
iOS
Alipay接口主要爲商戶提供訂單支付功能。接口所提供的方法,例如如下表所看到的:
方法名稱 | 方法描寫敘述 |
---|---|
+(Alipay *)defaultService; |
獲取服務實例。
|
-(BOOL)isLogined; |
檢測本地是否曾登陸使用過。 |
-(void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock; |
支付並經過回調返回結果。 |
快捷訂單支付iOS
方法名稱:pay方法
方法原型:(void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;
方法功能:提供給商戶快捷訂單支付功能。
參數名稱 | 參數描寫敘述 |
---|---|
NSString* scheme | 商戶程序註冊的URL protocol,供支付完畢後回調商戶程序使用。 |
(CompletionBlock)completionBlock | 快捷支付開發包回調函數,返回免登、支付結果。相應的結果參考「同步通知參數說明」。 |
NSString* orderStr | 主要包含商戶的訂單信息,key=「value」形式。以&鏈接。 |
支付參數示比例如如下,參數說明見「請求參數說明」:
partner="2088101568358171"&seller_id="xxx@alipay.com"&out_trade_no="0819145412-6177"&subject="測試"&body="測試測試"&total_fee="0.01"¬ify_url="http://notify.msp.hk/notify.htm"&service="mobile.securitypay.pay"&payment_type="1"&_input_charset="utf-8"&it_b_pay="30m"&sign="lBBK%2F0w5LOajrMrji7DUgEqNjIhQbidR13GovA5r3TgIbNqv231yC1NksLdw%2Ba3JnfHXoXuet6XNNHtn7VE%2BeCoRO1O%2BR1KugLrQEZMtG5jmJIe2pbjm%2F3kb%2FuGkpG%2BwYQYI51%2BhA3YBbvZHVQBYveBqK%2Bh8mUyb7GM1HxWs9k4%3D"&sign_type="RSA"
處理client返回url
方法名稱:處理client方法
方法原型:-(void)processOrderWithPaymentResult:(NSURL*)resultUrl standbyCallback:(CompletionBlock)completionBlock;
方法功能:設備已安裝支付寶client狀況下。處理支付寶client返回的url。
注意:該方法必須實現,不然將會致使在安裝手機支付寶的狀況下,支付結果沒法正常同步返回。
參數名稱 | 參數描寫敘述 |
---|---|
NSURL *resultUrl | 支付寶client回傳的url |
CompletionBlock completionBlock | 當支付寶client在操做時,商戶app進程在後臺被結束,僅僅能經過這個block輸出支付結果。
|
備註:請在APPDelegate的- (BOOL)application:(UIApplication )application openURL:(NSURL )url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation中調用該方法,詳細可參見Demo。
回調接口
在支付過程結束後,會經過callbackBlock同步返回支付結果。
返回結果需要經過resultStatus以及result字段的值來綜合推斷並肯定支付結果。在resultStatus=9000,並且success=「true」以及sign=「xxx」校驗經過的狀況下,證實支付成功。
其餘狀況歸爲失敗。
較低安全級別的場合。也可以僅僅經過檢查resultStatus以及success=「true」來斷定支付結果。
下面爲訂單支付成功的完畢信息演示樣例:
ResultStatus={9000};memo={};result={partner="2088101568358171"&seller_id="xxx@alipay.com"&out_trade_no="0819145412-6177"&subject="測試"&body="測試測試"&total_fee="0.01"¬ify_url="http://notify.msp.hk/notify.htm"&service="mobile.securitypay.pay"&payment_type="1"&_input_charset="utf-8"&it_b_pay="30m"&success="true"&sign_type="RSA"&sign="hkFZr+zE9499nuqDNLZEF7W75RFFPsly876QuRSeN8WMaUgcdR00IKy5ZyBJ4eldhoJ/2zghqrD4E2G2mNjs3aE+HCLiBXrPDNdLKCZgSOIqmv46TfPTEqopYfhs+o5fZzXxt34fwdrzN4mX6S13cr3UwmEV4L3Ffir/02RBVtU="}
注意:
支付結果的提取。必須經過CompletionBlock獲取,禁止開發人員私自解析支付結果返回的URL。獲取值的Key相應resultStatus、memo與result(result中的值,開發人員可以自行解析);
爲了保障已有商戶的正常使用。返回參數ResultStatus首字母爲大寫。
在新的SDK中已經用統一的工具類實現了ResultStatus到resultStatus的轉換。商戶從CompletionBlock中獲取resultStatus就能夠。
③導入代碼:
步驟1:啓動IDE(如Xcode)。把iOS包中的壓縮文件裏下面文件複製到項目目錄下,並導入到項目project中。
AlipaySDK.bundle
AlipaySDK.framework
在Build Phases選項卡的Link Binary With Libraries中,添加下面依賴:
當中。需要注意的是:
假設是Xcode 7.0以後的版本號,需要加入libc++.tbd、libz.tbd;
假設是Xcode 7.0以前的版本號,需要加入libc++.dylib、libz.dylib(例如如下圖)。
步驟2:在需要調用AlipaySDK的文件裏,添加頭文件引用。
#import <AlipaySDK/AlipaySDK.h>
步驟3:假設你的app基於9.0編譯。那麼爲了適配iOS9.0中的App Transport Security(ATS)對http的限制。這裏需要對支付寶的請求地址alipay.com、alipayobjects.com作例外,在app相應的info.list中加入例如如下配置(文中以XML格式描寫敘述)。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>alipay.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSTemporaryExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>alipayobjects.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSTemporaryExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>
說明:
假設商戶配置了例如如下的配置:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
則上述的NSAppTransportSecurity可以不配置。
步驟4:配置請求信息。
Order *order = [[Order alloc] init];
order.partner = partner;
order.seller = seller;
order.tradeNO = [self generateTradeNO]; //訂單ID(由商家?自?行制定)
order.productName = product.subject; //商品標題
order.productDescription = product.body; //商品描寫敘述
order.amount = [NSString stringWithFormat:@"%.2f",product.price]; //商
品價格
order.notifyURL = @"http://www.xxx.com"; //回調URL
order.service = @"mobile.securitypay.pay";
order.paymentType = @"1";
order.inputCharset = @"utf-8";
order.itBPay = @"30m";
//應用註冊scheme,在AlixPayDemo-Info.plist定義URL types
NSString *appScheme = @"alisdkdemo";
//將商品信息拼接成字符串
NSString *orderSpec = [order description];
NSLog(@"orderSpec = %@",orderSpec);
//獲取私鑰並將商戶信息簽名,外部商戶可以依據狀況存放私鑰和簽名,僅僅需要遵循RSA簽名規範,並將簽名字符串base64編碼和UrlEncode
id<DataSigner> signer = CreateRSADataSigner(privateKey);
NSString *signedString = [signer signString:orderSpec];
//將簽名成功字符串格式化爲訂單字符串,請嚴格依照該格式
NSString *orderString = nil;
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString, @"RSA"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
//【callback處理支付結果】
NSLog(@"reslut = %@",resultDic);
}];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
詳細可參見Demo中演示樣例文件
AliSDKDemo\APViewController.h
AliSDKDemo\APViewController.m
AliSDKDemo\Order.h
AliSDKDemo\Order.m
步驟5:配置支付寶client返回url處理方法。
(外部存在支付包錢包。支付寶錢包將處理結果經過url返回。)
如演示樣例AliSDKDemo\APAppDelegate.m文件裏,添加引用代碼:
#import <AlipaySDK/AlipaySDK.h>
在@implementation AppDelegate中添加例如如下代碼:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
//假設極簡開發包不可用,會跳轉支付寶錢包進行支付,需要將支付寶錢包的支付結果回傳給開發包
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
//【由於在跳轉支付寶client支付的過程當中,商戶app在後臺很是可能被系統kill了,因此pay接口的callback就會失效,請商戶對standbyCallback返回的回調結果進行處理,就是在這種方法裏面處理跟callback同樣的邏輯】
NSLog(@"result = %@",resultDic);
}];
}
if ([url.host isEqualToString:@"platformapi"]){//支付寶錢包快登受權返回authCode
[[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
//【由於在跳轉支付寶client支付的過程當中,商戶app在後臺很是可能被系統kill了。因此pay接口的callback就會失效。請商戶對standbyCallback返回的回調結果進行處理,就是在這種方法裏面處理跟callback同樣的邏輯】
NSLog(@"result = %@",resultDic);
}];
}
return YES;
}
④針對demo的執行注意:
一、關於簽名代碼問題
AliSDKDemo\Util及下面所有文件
AliSDKDemo\openssl及下面所有文件
libcrypto.a
libssl.a
這些文件是爲演示樣例簽名所在client本地使用。出於安全考慮。請商戶儘可能把私鑰保存在服務端,在服務端進行簽名驗籤。
二、假設遇到執行後報錯。類似於下面提示信息:
Cannot find interface declaration for 'NSObject', superclass of 'Base64'
那麼需要打開報錯了的文件,添加頭文件。
#import <Foundation/Foundation.h>
三、假設商戶要在某個文件裏使用支付寶的開發包類庫。需添加引用頭文件。
#import <AlipaySDK/AlipaySDK.h>
四、點擊項目名稱,點擊「Build Settings」選項卡,在搜索框中,以關鍵字「search」搜索,對「Header Search Paths」添加頭文件路徑:$(SRCROOT)/項目名稱。
假設頭文件信息已添加,可沒必要再添加。
五、點擊項目名稱。點擊「Build Phases」選項卡,在「Link Binary with Librarles」選項中。新增「AlipaySDK.framework」和「SystemConfiguration.framework」兩個系統庫文件。
假設商戶項目中已有這兩個庫文件,可沒必要再添加。
六、點擊項目名稱。點擊「Info」選項卡。在「URL Types」選項中。點擊「+」。在「URL Schemes」中輸入「alisdkdemo」。「alisdkdemo」來自於文件「APViewController.m」的NSString *appScheme = @「alisdkdemo」;。
注意:這裏的URL Schemes中輸入的alisdkdemo,爲測試demo,實際商戶的app中要填寫獨立的scheme。建議跟商戶的app有必定的標示度,要作到和其餘的商戶app不反覆。不然可能會致使支付寶返回的結果沒法正確跳回商戶app。
⑤基本配置信息:
打開「APViewController.m」文件,對下面三個參數進行編輯。
NSString *partner = @"";
NSString *seller = @"";
NSString *privateKey = @"";
IOS基本信息配置表:
參數 | 含義 |
---|---|
partner | 合做身份者ID,以2088開頭由16位純數字組成的字符串。請參考查看PID。 |
seller | 支付寶收款帳號。手機號碼或郵箱格式。 |
private_key | 商戶方的私鑰。pkcs8格式。請參考RSA私鑰及公鑰生成。 |
注意:這些參數配置是爲client簽名功能服務的。僅做爲演示樣例使用。
商戶在接入支付寶產品時,請把這些信息經過商戶項目本身的服務端傳遞。
⑥代碼演示樣例執行邏輯:
步驟1:調用order.m裏的函數description將商品信息拼接成字符串做爲待簽名字符串,如:
"partner=\"2088101568353491\"&seller_id=\"2088101568353491\"&out_trade_no=\"YR2VGG3G1I31XDZ\"&subject=\"1\"&body=\"我是測試數據\"&total_fee=\"0.02\"¬ify_url=\"http://www.xxx.com\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\""
步驟2:使用類CreateRSADataSigner,調用signString簽名函數作簽名,如:
"GsSZgPloF1vn52XAItRAldwQAbzIgkDyByCxMfTZG%2FMapRoyrNIJo4U1LUGjHp6gdBZ7U8jA1kljLPqkeGv8MZigd3kH25V0UK3Jc3C94Ngxm5S%2Fz5QsNr6wnqNY9sx%2Bw6DqNdEQnnks7PKvvU0zgsynip50lAhJmflmfHvp%2Bgk%3D"
步驟3:把簽名結果賦值給參數sign,並把sign加入以前的待簽名數組中,此時獲得的即是要請求給支付寶的所有數據。
"partner=\"2088101568353491\"&seller_id=\"2088101568353491\"&out_trade_no=\"YR2VGG3G1I31XDZ\"&subject=\"1\"&body=\"我是測試數據\"&total_fee=\"0.02\"¬ify_url=\"http://www.xxx.com\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\"&sign=\"GsSZgPloF1vn52XAItRAldwQAbzIgkDyByCxMfTZG%2FMapRoyrNIJo4U1LUGjHp6gdBZ7U8jA1kljLPqkeGv8MZigd3kH25V0UK3Jc3C94Ngxm5S%2Fz5QsNr6wnqNY9sx%2Bw6DqNdEQnnks7PKvvU0zgsynip50lAhJmflmfHvp%2Bgk%3D\"&sign_type=\"RSA\""
步驟4:調用(AlipaySDK *)defaultService類下面的支付接口函數。喚起支付寶支付頁面。
(void)payOrder:(NSString *)orderStr
fromScheme:(NSString *)schemeStr
callback:(CompletionBlock)completionBlock
appScheme爲app在info.plist註冊的scheme。
支付寶支付頁面:
後面的動做全由買家在支付寶收銀臺中操做完畢。假設設備中有支付寶client,會優先調用支付寶client進行支付,支付完畢後會又一次喚起商戶app。
步驟5:當這筆交易被買家支付成功後支付寶收銀臺上顯示該筆交易成功,並提示用戶「返回」。此時在APAppDelegate.m的 - (BOOL)application:(UIApplication )application openURL:(NSURL )url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 中調用獲取返回數據的代碼:
[[AlipaySDK defaultService]
processOrderWithPaymentResult:url
standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);//返回的支付結果
//【由於在跳轉支付寶client支付的過程當中,商戶app在後臺很是可能被系統kill了。因此pay接口的callback就會失效,請商戶對standbyCallback返回的回調結果進行處理,就是在這種方法裏面處理跟callback同樣的邏輯】
}];
拿到返回數據:
點取消後返回
"alisdkdemo://safepay/?%7B%22memo%22:%7B%22result%22:%22%22,%22memo%22:%22%E7%94%A8%E6%88%B7%E4%B8%AD%E9%80%94%E5%8F%96%E6%B6%88%22,%22ResultStatus%22:%226001%22%7D,%22requestType%22:%22safepay%22%7D"
對其作URLDecode
"alisdkdemo://safepay/?{"memo":{"result":"","memo":"用戶中途取消","ResultStatus":"6001"},"requestType":"safepay"}"
點確認後返回
"alisdkdemo://safepay/?%7B%22memo%22:%7B%22result%22:%22partner=%5C%222088101568353491%5C%22&seller_id=%5C%222088101568353491%5C%22&out_trade_no=%5C%22QU6ZOD85K4HVQFN%5C%22&subject=%5C%221%5C%22&body=%5C%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%5C%22&total_fee=%5C%220.02%5C%22¬ify_url=%5C%22http:%5C/%5C/www.xxx.com%5C%22&service=%5C%22mobile.securitypay.pay%5C%22&payment_type=%5C%221%5C%22&_input_charset=%5C%22utf-8%5C%22&it_b_pay=%5C%2230m%5C%22&success=%5C%22true%5C%22&sign_type=%5C%22RSA%5C%22&sign=%5C%22pg16DPA%5C/cIRg1iUFCl8lYZG54de+kfw+vCj32hGWye97isZ1A4bW6RNaDXHhZXVaI5Vk2YDxhNUl85EHRd+EL7%5C/+ogQTnsaEHl+D13PuZExIXRKGBnkYqaNV6kH6hDygnf5IOtoojHWLQyem7oRBVzB0vlF%5C/+YGFpzFHZyTVpM8=%5C%22%22,%22memo%22:%22%22,%22ResultStatus%22:%229000%22%7D,%22requestType%22:%22safepay%22%7D"
對其作URLDecode
"alisdkdemo://safepay/?{"memo":{"result":"partner=\"2088101568353491\"&seller_id=\"2088101568353491\"&out_trade_no=\"QU6ZOD85K4HVQFN\"&subject=\"1\"&body=\"我是測試數據\"&total_fee=\"0.02\"¬ify_url=\"http:\/\/www.xxx.com\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\"&success=\"true\"&sign_type=\"RSA\"&sign=\"pg16DPA\/cIRg1iUFCl8lYZG54de+kfw+vCj32hGWye97isZ1A4bW6RNaDXHhZXVaI5Vk2YDxhNUl85EHRd+EL7\/+ogQTnsaEHl+D13PuZExIXRKGBnkYqaNV6kH6hDygnf5IOtoojHWLQyem7oRBVzB0vlF\/+YGFpzFHZyTVpM8=\"","memo":"","ResultStatus":"9000"},"requestType":"safepay"}"
以後,對這些數據作處理。
注意:
由於在跳轉支付寶client支付的過程當中,商戶app在後臺很是可能被系統kill了。因此pay接口的callback就會失效。請商戶對standbyCallback返回的回調結果進行處理;
同步返回數據時,建議經過服務端的驗籤功能代碼作驗籤處理,以後再對返回的數據作業務邏輯處理;
須以server異步通知的結果數據爲準,並對其作業務邏輯處理;
SDK付款有兩種模式:假設外部存在支付寶錢包。則直接跳轉到支付寶錢包付款;不存在的場景下。在SDK內部進行H5支付。測試同窗需要關注這兩類測試場景。
至此文檔結束,由於我本人對於IOS開發並不精通,因此以上絕大部分借鑑支付寶相關文檔,但都是我以爲比較重要的地方,僅供參考。