iOS支付寶支付集成

概述

iOS支付寶支付集成

詳細

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

1、準備工做

一、向支付寶」簽約" 成爲支付寶的」商戶」, 簽約完成後, 支付寶會提供一些必要的數據給咱們(商戶ID-partner,賬號ID-支付寶賬號)算法

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

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

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

三、下載支付的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)微信

2、集成支付寶SDK步驟

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

576025-11a009c49e80a9d7.png.jpeg

 

二、app

點擊項目名稱,點擊「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

 

三、

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

也能夠不設置,我這個是我須要設置#import <UIKit/UIKit.h> #import <Foundation/Foundation.h>,也能夠不用使用,只在當前文件裏添加相對應的使用便可,可是這樣針對整個項目來講方便些

576025-ed9304eb37840edf.png

 

四、

修改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」

 

五、 爲URL Types 添加支付寶回調scheme

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

爲URL Types 添加支付寶回調scheme

576025-2698bcd1d3dde04a.png.jpeg

 

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

iOS 9之後的系統須要添加支付寶分享的scheme到白名單中,scheme名爲alipayshare

按以下形式添加便可:

576025-eb9a74995d62b951.png.jpeg

 

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

 

八、 在須要用的地方導入「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];
            }
        }];
    }
    
}

 

九、

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

 

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

 

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

1. 報錯 AL159

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

2. 報錯「建立交易異常,請從新建立後再付款」

返回的狀態碼是「6001」,取消支付

當是用公司註冊支付寶App時分配的商戶帳號登錄的支付寶,進行支付測試的。支付寶那邊檢測到是商戶而不是普通的支付帳號,商戶支付給商戶本身,因此支付失敗!

3、其餘補充

一、壓縮文件截圖

壓縮文件.png

二、Alipay 包截圖

alipay.png

 

目前是項目中直接操做, 在AlipayHeader.h文件裏補充上大家項目的aliPartnerID, aliSellerAccount, aliNotifyURL, 具體可參考代碼, 項目則可以直接運行!

 

 

注:本文著做權歸做者,由demo大師發表,拒絕轉載,轉載須要做者受權

相關文章
相關標籤/搜索