iOS 接入支付寶SDK封裝的工具類(lèi)HHAliPaySDK(服務(wù)端簽名和驗(yàn)簽)

開(kāi)篇吐槽,文檔看不懂,文檔看不懂,文檔看不懂.重要的事說(shuō)三遍.
對(duì)于沒(méi)集成過(guò)支付寶SDK的人來(lái)說(shuō),官方文檔看完也是一臉懵逼,在網(wǎng)上搜完別人寫(xiě)的什么文檔流程,看完也是一臉懵逼.
官方demo運(yùn)行不了,還有各種什么order類(lèi)生成簽名,返回結(jié)果驗(yàn)簽巴拉巴拉,反正說(shuō)的我心累.


看一下支付寶給的流程圖

圖中的“商戶(hù)客戶(hù)端”其實(shí)就是我們的iOS客戶(hù)端需要做的事情:
1.用后臺(tái)給的簽名后訂單信息調(diào)用支付寶支付接口
2.處理支付寶返回的支付結(jié)果
完了,這就完事了,很簡(jiǎn)單的事情,只需要這兩步,官方文檔給的那么亂七八糟的復(fù)雜東西,什么order類(lèi)啥的,都是把后臺(tái)做的事情,放在了客戶(hù)端來(lái)做,所以才那么復(fù)雜.


{7D03662F-CC3F-AE65-ECAB-8DA5F7FF92F9}.png

那么為什么官方demo中能放在客戶(hù)端做的事情(簽名,驗(yàn)簽)要給后臺(tái)來(lái)做.

看下面官方給的提示:

{ABDC1148-DE4D-8D69-61BD-E3B6741D5818}.png

第一條:私鑰要保存在服務(wù)端,那么決定了調(diào)用支付寶接口需要的簽名后的訂單信息(也就是參數(shù)payOrder)需要后臺(tái)來(lái)生成,傳給我們.
第二條:到底付款成沒(méi)成功,需要依賴(lài)服務(wù)端收到的異步通知結(jié)果來(lái)進(jìn)行判斷,我們客戶(hù)端這邊收到成功的提示也沒(méi)用,必須后臺(tái)告訴我們,他們也成功了,才算成功
第三條:說(shuō)到了難住大多數(shù)人的驗(yàn)簽,官方建議驗(yàn)簽規(guī)則參考異步通知驗(yàn)簽,而異步通知驗(yàn)簽,是在服務(wù)端來(lái)完成的,官方在服務(wù)端的SDK中提供了一個(gè)工具類(lèi)用來(lái)驗(yàn)簽,所以我們也是在服務(wù)端完成的.


了解以上就可以集成支付寶SDK了

這里是官方支付寶SDK集成流程
這里是創(chuàng)建應(yīng)用獲取APPID和配置秘鑰的方法

設(shè)置URL Scheme(要記住這個(gè)標(biāo)識(shí),調(diào)用支付寶方法時(shí)會(huì)用到這個(gè)參數(shù))

修改 info.plist 文件 URL types 項(xiàng)中后面的URL Schemes內(nèi)容,官方建議跟商戶(hù)的app有一定的標(biāo)示度,要做到和其他的商戶(hù)app不重復(fù)泄鹏,否則可能會(huì)導(dǎo)致支付寶返回的結(jié)果無(wú)法正確跳回商戶(hù)app秧耗。(比如你們項(xiàng)目名稱(chēng)+AliPay,我這里設(shè)置了支付寶,qq,微信,微博,只用到支付寶的話(huà),就添加支付寶的就ok)


2EA80578-7343-433E-8803-73E4E826BE11.png

添加依賴(lài)庫(kù)

把下載的SDK中AlipaySDK.bundle和AlipaySDK.framework拖入工程,然后按官方給的圖添加依賴(lài)庫(kù).官方文檔看到這張圖這里就夠了,其余以下的不用管,都是教你demo怎么運(yùn)行,簽名和驗(yàn)簽也沒(méi)我們客戶(hù)端的事,看他demo干嘛.


{6F9683DA-F3FC-EB1C-9F34-C2D3EA014542}.png

設(shè)置頭文件路徑

點(diǎn)擊“Build Settings”選項(xiàng)卡,在搜索框中车猬,以關(guān)鍵字“search”搜索,對(duì)“Header Search Paths”增加頭文件路徑:$(SRCROOT)/項(xiàng)目名稱(chēng)惜浅。如果頭文件信息已增加伏嗜,可不必再增加.

添加URL Schemes白名單

在“Info.plist”中增加一個(gè)LSApplicationQueriesSchemes值,設(shè)置為array, 添加支付寶需要的item:
alipay
也就是圖中的最后一項(xiàng),其他的都是微信微博和QQ的.

4ECDABF8-640E-4CF9-BBB8-C93037F155D9.png

設(shè)置https訪(fǎng)問(wèn)

在“Info.plist”中增加一個(gè)App Transport Security Settings值, 其中有一個(gè)Allow Arbitrary Loads對(duì)應(yīng)的值要設(shè)置為YES


39DD2532-0055-4AC0-AC11-920D6A18E179.png

然后就就可以愉快的寫(xiě)代碼了

創(chuàng)建了一個(gè)繼承于NSObject的 HHAliPaySDK工具類(lèi),我在其中封裝了一下向后臺(tái)請(qǐng)求簽名后的訂單信息(也就是payOrder)的方法和處理回調(diào)結(jié)果用到的方法.

ps:這個(gè)類(lèi)中有網(wǎng)絡(luò)請(qǐng)求,HHttpManager是我自己對(duì)AFNetworking3.0的二次封裝,感興趣的可以看一看,不感興趣的同學(xué)可以用AFN或者自己的網(wǎng)絡(luò)框架.

.h文件

#import <Foundation/Foundation.h>

@interface HHAliPaySDK : NSObject

/**
 根據(jù)訂單信息向后臺(tái)申請(qǐng)prepayId以調(diào)用支付寶支付接口

 @param amount  金額
 @param orderId  訂單信息(支付前請(qǐng)求后臺(tái)給的沒(méi)有簽名過(guò)的訂單號(hào))
 */
+ (void)sendAliPayRequestWithAmount:(NSString *)amount
                            orderId:(NSString *)orderId;

/**
 openURL
 */
+(BOOL)handleOpenURL:(NSURL *)url;


@end

.m文件


#import "HHAliPaySDK.h"
#import <AlipaySDK/AlipaySDK.h>
@implementation HHAliPaySDK

//post請(qǐng)求后臺(tái),獲取簽名后的訂單信息(也就是payOrder)
+ (void)sendAliPayRequestWithAmount:(NSString *)amount
                            orderId:(NSString *)orderId{
    NSDictionary *paramDict = @{
                                @"totalAmount":amount,
                                @"orderId":orderId,
                                };
//getAliPayOrder:后臺(tái)提供的接口,用來(lái)請(qǐng)求簽名后的訂單信息(也就是payOrder)
    [HHttpManager POST:getAliPayOrder parameters:paramDict success:^(id responseObject) {
        NSNumber *state = responseObject[@"state"];
        if (state.integerValue == 0) {
            NSString *orderStr = responseObject[@"data"][0][@"AlipaySign"];
            [self sendPayRequstWithPayOrder:orderStr];
        }else{
            NSLog(@"請(qǐng)求失敗--%@",responseObject[@"msg"]);
        }
    } failure:^(NSError * error) {
        NSLog(@"請(qǐng)求失敗--%@",error);
 
    }];
}


//調(diào)用支付寶支付(無(wú)支付寶客戶(hù)端時(shí)的結(jié)果回調(diào)也在此方法中)
+ (void)sendPayRequstWithPayOrder:(NSString *)payOrder{
    NSLog(@"%@", payOrder);
//AliPay_Scheme:設(shè)置URL Scheme時(shí)讓你記住的參數(shù).
    [[AlipaySDK defaultService] payOrder:payOrder fromScheme:AliPay_Scheme callback:^(NSDictionary *resultDic) {
        NSLog(@"%@", resultDic);
        [self handleAliPayCallBackResultWithDictionary:resultDic];
        
    }];
}

/**
 openURL(有支付寶客戶(hù)端時(shí)返回的結(jié)果)
 */
+(BOOL)handleOpenURL:(NSURL *)url{
    if ([url.host isEqualToString:@"safepay"] ) {
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            [self handleAliPayCallBackResultWithDictionary:resultDic];
        }];
    }
    
    if ([url.host isEqualToString:@"platformapi"]){
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
            [self handleAliPayCallBackResultWithDictionary:resultDic];
        }];
    }
    return YES;
}


+ (void)handleAliPayCallBackResultWithDictionary:(NSDictionary *)resultDic{
    if ([resultDic[@"resultStatus"] isEqual:@"9000"])
    {
        //客戶(hù)端支付成功,然后向后臺(tái)請(qǐng)求,看他是否驗(yàn)簽成功,他也成功了,才證明支付成功,
    }
    
    if ([resultDic[@"resultStatus"] isEqual:@"4000"])
    {
        //支付失敗
    }
    
    if ([resultDic[@"resultStatus"] isEqual:@"6001"])
    {
        //取消支付
    }
    
    if ([resultDic[@"resultStatus"] isEqual:@"6002"])
    {
        //網(wǎng)絡(luò)連接失敗
    }
    
}
@end

設(shè)置(個(gè)人喜歡類(lèi)方法,調(diào)用方便,可自己修改)

在AppDelegate.m文件中
openURL方法中設(shè)置回調(diào),支付寶不用初始化,是不是很開(kāi)森0.0(這里一個(gè)是iOS9以下的系統(tǒng)調(diào)用的系統(tǒng)方法和一個(gè)是iOS9以上的系統(tǒng)調(diào)用的系統(tǒng)方法,都要設(shè)置)

#pragma mark - OpenURL回調(diào)結(jié)果
//iOS9-
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    [self handleOpenURLWithURLHost:url];
    return YES;
}
//iOS9和9+
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options{
    [self handleOpenURLWithURLHost:url];
    return YES;
}

- (void)handleOpenURLWithURLHost:(NSURL *)url{
 NSLog(@"url.host:%@", url.host);
    //支付寶
   if ([url.host isEqualToString:@"safepay"]||[url.host isEqualToString:@"platformapi"]) {
        [HHAliPaySDK handleOpenURL:url];
    }

}


調(diào)用

類(lèi)方法直接調(diào)用封裝好的接口就行,orderId是需要向后臺(tái)請(qǐng)求的訂單號(hào)(比如:D123457890)

/**
 根據(jù)訂單信息向后臺(tái)申請(qǐng)prepayId以調(diào)用支付寶支付接口

 @param amount  金額
 @param orderId  訂單信息(支付前請(qǐng)求后臺(tái)給的沒(méi)有簽名過(guò)的訂單號(hào))
 */
+ (void)sendAliPayRequestWithAmount:(NSString *)amount
                            orderId:(NSString *)orderId;

客戶(hù)端題外話(huà),關(guān)于RSA

(上面引入的是阮一峰寫(xiě)的一篇RSA算法原理,都是專(zhuān)業(yè)數(shù)學(xué)知識(shí),看的我一愣一愣的,感謝大大的講解)

簽名和驗(yàn)簽都交給后臺(tái)的來(lái)做,對(duì)我們客戶(hù)端來(lái)說(shuō),既安全有方便(真不是我們客戶(hù)端不做,是官方建議的,上面我有說(shuō)明過(guò),涉及錢(qián)的問(wèn)題,一切為了安全),客戶(hù)端這邊是不需要了解RSA加密解密的(沒(méi)錯(cuò),反正我是不會(huì)),但是需要后臺(tái)了解,最簡(jiǎn)單來(lái)說(shuō),在生產(chǎn)訂單時(shí),需要使用私鑰生成簽名,在處理返回的支付結(jié)果時(shí),需要使用公鑰驗(yàn)證返回結(jié)果是否被篡改.驗(yàn)證通過(guò)才算支付成功.具體后臺(tái)怎么驗(yàn)簽,支付寶提供了方法,他給服務(wù)端的SDK提供了一個(gè)工具類(lèi)用來(lái)驗(yàn)簽,官方舉的例子是Java

Map<String, String> paramsMap = ... //將異步通知中收到的待驗(yàn)證所有參數(shù)都存放到map中
boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET) //調(diào)用SDK驗(yàn)證簽名
if(signVerfied){
   // TODO 驗(yàn)簽成功后
   //按照支付結(jié)果異步通知中的描述八酒,對(duì)支付結(jié)果中的業(yè)務(wù)內(nèi)容進(jìn)行1\2\3\4二次校驗(yàn),校驗(yàn)成功后在response中返回success羞迷,校驗(yàn)失敗返回failure
}else{
    // TODO 驗(yàn)簽失敗則記錄異常日志,并在response中返回failure.
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末浊猾,一起剝皮案震驚了整個(gè)濱河市热鞍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌薇宠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件椒涯,死亡現(xiàn)場(chǎng)離奇詭異回梧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)湖苞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)详囤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事滑肉≌觯” “怎么了问畅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)矾端。 經(jīng)常有香客問(wèn)我卵皂,道長(zhǎng),這世上最難降的妖魔是什么灯变? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮滚粟,結(jié)果婚禮上刃泌,老公的妹妹穿的比我還像新娘。我一直安慰自己耙替,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布硝烂。 她就那樣靜靜地躺著狐援,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啥酱。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天禾酱,我揣著相機(jī)與錄音,去河邊找鬼颤陶。 笑死,一個(gè)胖子當(dāng)著我的面吹牛垦江,可吹牛的內(nèi)容都是我干的搅方。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼衩藤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼涛漂!你這毒婦竟也來(lái)了赏表?” 一聲冷哼從身側(cè)響起匈仗,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锚沸,失蹤者是張志新(化名)和其女友劉穎跋选,沒(méi)想到半個(gè)月后哗蜈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炼列,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年音比,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片稽犁。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骚亿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出来屠,到底是詐尸還是另有隱情震鹉,我是刑警寧澤捆姜,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站浆兰,受9級(jí)特大地震影響珊豹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜平夜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一卸亮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧段直,春花似錦溶诞、人聲如沸鸯檬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)功茴。三九已至孽亲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間返劲,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工孵延, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留搔耕,地道東北人隙袁。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓菩收,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親娜饵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容