iOS支付寶支付集成


概述

iOS支付寶支付集成

詳細

支付寶和微信都是業界的老大哥,相信大家都有所覺得文檔、SDK都是各種坑吧(純粹吐槽而已),本文先整理支付寶支付集成。

一、准備工作

1、向支付寶”簽約" 成為支付寶的”商戶”, 簽約完成后, 支付寶會提供一些必要的數據給我們(商戶ID-partner,帳號ID-支付寶帳號)

注意:簽約成為支付寶商戶,需要提供公司營業執照[http://act.life.alipay.com/shopping/before/help/index.html](http://act.life.alipay.com/shopping/before/help/index.html)

2、獲取支付相關的 '私鑰' 和 '密鑰'

[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)

3、下載支付的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)

二、集成支付寶SDK步驟

1、從官方Demo中把紅色標注的文件添加進入項目中,記得選copy;

576025-11a009c49e80a9d7.png.jpeg

 

2、

點擊項目名稱,點擊“Build Phases”選項卡,在“Link Binary with Librarles” 選項中,新增“AlipaySDK.framework”和“SystemConfiguration.framework” 兩個系統庫文件。如果項目中已有這兩個庫文件,可不必再增加;

添加下圖中的庫:

576025-96e1a7c6a53aecb6.png.jpeg

localhost:alipay mac$ ls
APAuthV2Info.h        Order.h            libssl.a
APAuthV2Info.m        Order.m            openssl
AlipaySDK.bundle    Util
AlipaySDK.framework    libcrypto.a
導入系統庫
SystemConfiguration.framework

 

3、

添加Pch文件新建pch成功后,在pch文件中添加#import然后按照下圖所示,進行修改pch的文件路徑

也可以不設置,我這個是我需要設置#import <UIKit/UIKit.h> #import <Foundation/Foundation.h>,也可以不用使用,只在當前文件里添加相對應的使用即可,但是這樣針對整個項目來說方便些

576025-ed9304eb37840edf.png

 

4、

修改SDK路徑完成以上兩步之后,會發現出現了一個經典的錯誤,找不到:#include解決這個問題,需要在Header Search Path中配置SDK中的點a(libssl.a/libcrypto.a)文件所在的路徑,找到之后設置好正確的路徑

576025-405b7b528143bbed.png

點擊項目名稱,點擊“Build Settings”選項卡,在搜索框中,以關鍵字“search” 搜索,對“Header Search Paths”增加頭文件路徑:“$(SRCROOT)/項目名稱/IntegratedAlipay/AlipayFiles”(注意:不包括引號,如果不是放到項目根目錄下,請在項目名稱后面加上相應的目錄名);

576025-d672c7034c31c881.png.jpeg

根據你文件位置,我的是:

“$(SRCROOT)/QTXStudent/Classes/Alipay/AlipayFiles”

 

5、 為URL Types 添加支付寶回調scheme

點擊項目名稱,點擊“Info”選項卡,在URL types里面添加一項,Identifier可以不填,URL schemes必須和appScheme的值相同,用於支付寶處理回到應用的事件;

為URL Types 添加支付寶回調scheme

576025-2698bcd1d3dde04a.png.jpeg

 

6、在工程項目的plist文件中添加

iOS 9以后的系統需要添加支付寶分享的scheme到白名單中,scheme名為alipayshare

按如下形式添加即可:

576025-eb9a74995d62b951.png.jpeg

 

7、在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;
}

 

8、 在需要用的地方導入“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];
            }
        }];
    }
    
}

 

9、

在本頭文件中設置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];

 

10、建議除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);
    }];
    
}

 

11、支付寶集成失敗相關問題

1. 報錯 AL159

查看金額是否是兩位小數,切不可拼接"元"

2. 報錯“創建交易異常,請重新創建后再付款”

返回的狀態碼是“6001”,取消支付

當是用公司注冊支付寶App時分配的商戶賬號登陸的支付寶,進行支付測試的。支付寶那邊檢測到是商戶而不是普通的支付賬號,商戶支付給商戶自己,所以支付失敗!

三、其他補充

1、壓縮文件截圖

壓縮文件.png

2、Alipay 包截圖

alipay.png

 

目前是項目中直接操作, 在AlipayHeader.h文件里補充上你們項目的aliPartnerID, aliSellerAccount, aliNotifyURL, 具體可參考代碼, 項目則能夠直接運行!

 

 

注:本文著作權歸作者,由demo大師發表,拒絕轉載,轉載需要作者授權

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM