首先要說(shuō)明的是支付寶SDK的使用,官方建議,數(shù)據(jù)加密和下單等操作盡量由商戶后臺(tái)服務(wù)器完成,這樣才能保證財(cái)產(chǎn)和私密信息的安全性。因此本文介紹內(nèi)容,是APP和自己公司后臺(tái)服務(wù)器一起協(xié)作完成支付寶支付的方法。
一、首先需要介紹的是:支付寶的接入(可參考官方文檔)
還是簡(jiǎn)單給大家理一下流程,(1)在螞蟻金服后臺(tái)創(chuàng)建應(yīng)用,拿到APPID,給后臺(tái)開(kāi)發(fā)人員(2)添加APP支付功能(3)簽約商戶號(hào),簽約有一個(gè)審核時(shí)間,這中間可能會(huì)遇到各種問(wèn)題,(4)配置秘鑰,分別是公鑰和私鑰,這個(gè)讓后臺(tái)人員去弄
下載SDKhttps://docs.open.alipay.com/54/104509拖入工程里面。
手動(dòng)導(dǎo)入靜態(tài)庫(kù),然后command + B 編譯一下,看報(bào)不報(bào)錯(cuò)。
QQ20180204-143004.png
二、接下來(lái)給大家介紹項(xiàng)目里面的配置。
(1)第一步點(diǎn)擊工程名——>第二步點(diǎn)擊info——>第三步在URL Types里面添加一個(gè)支付寶返回URL type.如圖所示:
(2)在plist文件中確認(rèn)URL是否添加成功。
(3)在需要用到支付的ViewController里面添加以下代碼:
///支付寶sdk
#import <AlipaySDK/AlipaySDK.h>
#define AppScheme @"ShouNew"
注意上面三條的Scheme一定要保持一致,不然可能導(dǎo)致支付成功后不能返回原APP。
三、支付寶支付流程及代碼體現(xiàn)
(1)支付寶流程圖:
簡(jiǎn)單解釋一下:
第一步:APP向自己公司服務(wù)器發(fā)起下單請(qǐng)求(下單的時(shí)候要把商品的各項(xiàng)信息傳給服務(wù)器,比如價(jià)格,數(shù)量,商品名等),自己公司服務(wù)器向支付寶服務(wù)器統(tǒng)一下單,然后返回訂單號(hào)給用戶。
第二步:APP拿訂單號(hào)向服務(wù)器請(qǐng)求加密后的訂單信息,用于向支付寶服務(wù)器發(fā)起請(qǐng)求。
類似于這樣一串?dāng)?shù)據(jù)
"alipayInfo":"partner=2088321034383926&seller_id=717449318@qq.com&out_trade_no=r2017051922165642529&subject=首牛云控APP充值-¥10.0&body=首牛云控APP充值-¥10.0&total_fee=10.0¬ify_url=http://*******.cn/*********/alipayNotify.do&service=mobile.securitypay.pay&payment_type=1&_input_charset=utf-8&it_b_pay=30m&sign=hS%2BJNs3FT9Sx0U2CGIK58xs6Cdjx%2FsvBqw18Ah%2BwrtBUdNjQnqP99fjW4YK6JxjuRG5YocZmS5ZfcrtnXq7fmq9jf%2Fj%2Fz858CBBWPxtoGQZuEAPy91q8vbYYHkSgwO8qM8mtCTast9LjXyJ2un%2B6nPhNxHN0cX1%2FZxUMWwwmQQc%3D&sign_type=RSA",這是后臺(tái)用支付寶提供的RSA加密算法加密后的數(shù)據(jù)。
第三步:通過(guò)SDK向支付寶服務(wù)器發(fā)起支付請(qǐng)求。發(fā)起請(qǐng)求的時(shí)候要帶上APPScheme,用于返回APP支付結(jié)果回調(diào)。
第四步:完成支付后,支付寶會(huì)返回一個(gè)字典給APP,這個(gè)里面就有支付結(jié)果,但是這并不能作為支付成功與否的判斷結(jié)果,因?yàn)椋@個(gè)結(jié)果只是APP端成功,所以還要將這個(gè)字典內(nèi)容轉(zhuǎn)成json傳給服務(wù)器,查詢服務(wù)器支付結(jié)果,可能有朋友會(huì)問(wèn),服務(wù)器支付結(jié)果從何而來(lái),其實(shí)在APP端完成支付后,支付寶會(huì)根據(jù)這個(gè)訂單異步通知商戶服務(wù)器,讓服務(wù)器記錄這個(gè)訂單的支付結(jié)果。中間任何一環(huán)斷了,這個(gè)訂單都不算支付成功。
最后根據(jù)服務(wù)器查詢到的訂單支付結(jié)果來(lái)反應(yīng)給用戶。
接下來(lái)我們看代碼實(shí)現(xiàn):
首先是下單:
NSString *urlStr = @"orderz.do?method=submitOrderz";
//這兒需要包裝的參數(shù)由服務(wù)器來(lái)定
NSDictionary *dic = @{@"color":@"怪味胡豆60克",@"price":@"0.01",@"mallproductId":@"19",@"type" : @"1",@"num":@"1",@"jSessionId":@"這兒填寫(xiě)你們APP的唯一登錄標(biāo)示符,也可以說(shuō)是token",@"locationId": @"94"
};
[[SNNetWorkTools sharedTools]requestWithUrl:urlStr withRequestStyle:POST parameters:dic callback:^(id data, NSError *error) {
NSNumber *num = data[@"statusCode"];
if (codeNum) {
self.orderNum = data[@"data"][@"orderzNo"];
[self payWithAlipay];
}
}];
向服務(wù)器拿到加密信息,并向支付寶發(fā)起支付
-(void)payWithAlipay{
NSString *str = @"pay.do?method=getAlipayInfo";
NSDictionary *para = @{@"orderzNo":self.orderNum,@"jSessionId":@"這兒填寫(xiě)你們APP的唯一登錄標(biāo)示符,也可以說(shuō)是token"};
[[SNNetWorkTools sharedTools]requestWithUrl:str withRequestStyle:GET parameters:para callback:^(id data, NSError *error) {
NSNumber *num = data[@"statusCode"];
if (codeNum) {
NSString *orderStr = data[@"data"][@"alipayInfo"];
// 應(yīng)用注冊(cè)scheme,在AliPayDemo-Info.plist定義URL types
[[AlipaySDK defaultService]payOrder:orderStr fromScheme:AppScheme callback:^(NSDictionary *resultDic) {
}];
}
}];
}
在viewDidLoad方法中注冊(cè)監(jiān)聽(tīng)支付結(jié)果的通知
//注冊(cè)通知-支付寶
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(dealALiPayResult:) name:@"ALiPayresult" object:nil];
在APPDelegate中接受支付寶返回的支付結(jié)果轉(zhuǎn)化成Json傳給服務(wù)器查詢支付結(jié)果
#pragma mark -- 支付回調(diào)方法
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
//支付寶支付回調(diào)
if ([url.host isEqualToString:@"safepay"]) {
//跳轉(zhuǎn)支付寶錢(qián)包進(jìn)行支付,處理支付結(jié)果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
// NSLog(@"result = %@",resultDic);
NSString *jsonStr = [self DataTOjsonString:resultDic];
//將支付寶返回的dictionary轉(zhuǎn)成json再傳給服務(wù)器,查詢服務(wù)器支付狀態(tài)。
NSString *urlStr = @"pay.do?method=checkAlipayOrderz";
NSDictionary *para = @{@"data":jsonStr,@"jSessionId":@"這兒填寫(xiě)你們APP的唯一登錄標(biāo)示符,也可以說(shuō)是token"};
[[SNNetWorkTools sharedTools]requestWithUrl:urlStr withRequestStyle:POST parameters:para callback:^(id data, NSError *error) {
//發(fā)送通知,將支付結(jié)果傳給ViewController
[[NSNotificationCenter defaultCenter] postNotificationName:@"ALiPayresult" object:data[@"data"][@"trade_state"]];
}];
}];
}
return false;
}
//字典轉(zhuǎn)Json
-(NSString*)DataTOjsonString:(id)object
{
NSString *jsonString = nil;
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:object options:NSJSONWritingPrettyPrinted error:&error];
if (!jsonData) {
NSLog(@"字典轉(zhuǎn)json錯(cuò)誤: %@", error);
}else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return jsonString;
}
回到ViewController中實(shí)現(xiàn)通知監(jiān)聽(tīng)事件
#pragma mark --支付寶支付后查詢服務(wù)器訂單結(jié)果,展示給用戶
-(void)dealALiPayResult:(NSNotification*)notification{
NSString *result = notification.object;
NSLog(@"支付結(jié)果:%@",result);
if ([result isEqualToString:@"9000"]) {
NSLog(@"支付成功");
}else if([result isEqualToString:@"6001"]){
NSLog(@"支付失敗,中途取消");
}else{
NSLog(@"支付失敗,其他原因");
}
}