iOS集積支付宝H 5支付ジャンプとコールバックを実現するソリューション



iOS集積支付宝H 5支付ジャンプとコールバックを実現するソリューション
 
 
前言
最近、iOSクライアント内に支付宝と微信を統合できないApp決済SDK(アップルの監査検出SDKを防ぐため)が必要なので、H 5決済を使う.微信と支付宝のH 5決済ドキュメントは、App内でH 5決済ではなくApp決済を使うと言っているが、方法はいつもある.
この記事では、アリペイH 5の支払い方法をAppからアリペイにジャンプする方法と、アリペイからAppにジャンプする方法について説明しています.
iOS統合H 5微信決済によるジャンプとコールバックのソリューション
実現する効果は、App→アリペイ→支払い(成功失敗またはキャンセル)→App
事前準備
本プロジェクトはWKWebViewを使用し、前置き動作はバックエンドの仲間がすでに支付宝H 5の支付下のリンクを処理し、クライアントが下のリンクを受信した後の操作である.
単一リンクは、支付宝H 5の支付文書-パラメータ説明-共通パラメータで構成されたhttps://openapi.alipay.com/gateway.doの先頭のリンクであり、構造リンクの操作はバックエンド処理に渡される.
操作手順
1.URL Schemeを追加してアリペイをホワイトリストに入れる
URL Schemeを追加します.xcodeprojファイルInfoタブの一番下のURL Typesに設定します.このURL Schemeは微信決済とは異なり、商戸のバックグラウンドに記入しなければならない1級ドメイン名を検証するため、支付宝のこれは任意に設定することができる.
支付宝のURL Scheme alipayalipaysを項目のホワイトリストに記入します.xcodeprojファイルInfoタブ内のCustom iOS Target PropertiesLSApplicationQueriesSchemesに上記2つの文字列を追加し、LSApplicationQueriesSchemesがなければ手動で追加を入力します.タイプは配列Arrayです.
2.WKWebViewロードリンク
プロトコルWKNavigationDelegateおよびWKUIDelegateを追加します.
WKWebViewを作成し、統合された単一リンクをロードします.
- (void)buildWKWebView {
    WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, NAV_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT - NAV_HEIGHT)];
    [self.view addSubview:webView];
    webView.navigationDelegate = self;
    webView.UIDelegate = self;
    NSURL *payURL = [NSURL URLWithString:self.payString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:payURL];
    [webView loadRequest:request];
}

ここでself.payStringはバックグラウンドから届いた支付宝5支付統一注文リンクで、フォーマットは:https://openapi.alipay.com/gateway.do?app_id=2015081808011180&biz_content={"body"%3A" "%2C"subject"%3A"10000 "%2C"out_trade_no"%3A"30677"%2C"total_amount"%3A"1.00"%2C"seller_id"%3A"2088721584425035"%2C"product_code"%3A"QUICK_WAP_PAY"%2C"goods_type"%3A"1"%2C"passback_params"%3A"20190322083556lkkzmwT2wi0bAaFL1W"%2C"store_id"%3A"company"%2C"timeout_express"%3A"3m"}&charset=UTF-8&format=JSON&method=alipay.trade.wap.pay&notify_url=https%3A%2F%2Fsttv3-api.company.com%2FaliNotify&return_url=https%3A%2F%2Fwww.company.com&sign_type=RSA2&timestamp=2019-03-22+20%3A35%3A56&version=1.0&sign=rmnKUOsZBYi%2BWzDELY%2B5ixnSFn0b0S38K0NR45SRZBAvmzr0qaXm7mnKaXm7OrvmnKUOsZRYiaJ2LNAaFL1K0hvJ3L3hZqH5HifNCIJ0hfTr1OkA5Lgyn1SCx74SrSWVfXdMXqiLurpN0Mj%2B2zs7vDee%2B8vxwzhRG3a5EaZbOHDQFN1%2OrvvVcdv%2F%2FBJCwISBhoXhBelvfZRYiaJ2LNAaFL1KdrJvjlo2lR%2BEzvda0ppMKFzjMLxRZBAvmzr0qNwxyTMfAuxjAT2%2BXAaF3hZqH5Hlo2lRiaJ2LNE
微信の支払いのように請求先を追加するのではなく、支付宝の簡単さが多く、直接アクセスすればいい.
3.代理方法でリンクをブロックし、アリペイをジャンプすることを実現する
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    if ([navigationAction.request.URL.scheme isEqualToString:@"alipay"]) {
        //  1. ?       
        NSArray *urlBaseArr = [navigationAction.request.URL.absoluteString componentsSeparatedByString:@"?"];
        NSString *urlBaseStr = urlBaseArr.firstObject;
        NSString *urlNeedDecode = urlBaseArr.lastObject;
        //  2.      Str,   URLDecode,        
        NSMutableString *afterDecodeStr = [NSMutableString stringWithString:[SmallTools decoderUrlEncodeStr:urlNeedDecode]];
        //  3.       Scheme    Scheme
        NSString *afterHandleStr = [afterDecodeStr stringByReplacingOccurrencesOfString:@"alipays" withString:@"alipayreturn.cutv.com"];
        //  4.       ,           ,          
        NSString *finalStr = [NSString stringWithFormat:@"%@?%@",urlBaseStr, [SmallTools urlEncodeStr:afterHandleStr]];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            //      ,        APP(            URL)
            if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:finalStr]]) {
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:finalStr]];
            } else {
                //      ,     
            }
        });
        
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

ついでにURLのEncodeとDecodeの方法を添付します.
//urlEncode  
+ (NSString *)urlEncodeStr:(NSString *)input {
    NSString *charactersToEscape = @"?!@#$^&%*+,:;='\"`<>()[]{}/\\| ";
    NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:charactersToEscape] invertedSet];
    NSString *upSign = [input stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
    return upSign;
}
//urlEncode  
+ (NSString *)decoderUrlEncodeStr: (NSString *) input {
    NSMutableString *outputStr = [NSMutableString stringWithString:input];
    [outputStr replaceOccurrencesOfString:@"+" withString:@"" options:NSLiteralSearch range:NSMakeRange(0,[outputStr length])];
    return [outputStr stringByRemovingPercentEncoding];
}

4.AppDelegateでのジャンプ動作の受信
もちろん、AppDelegateでリターンアクションを受信する必要はありません.直接支払いインタフェースに戻って、後続のロジックを自分で操作することもできます.
以下にAppDelegateがリターン動作を受信した例を示す.
このうちアリペイコールのhostは固定safepayであり、微信が支払うhostは勝手に定義されている.
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
    //safepay    H5     host, 
    if ([url.host isEqualToString:@"wxpaycallback"] || [url.host isEqualToString:@"safepay"]) {
        //         ,              ,popView      
        UITabBarController *tabBarVC = (UITabBarController *)topRootViewController;
        UINavigationController *navVC = tabBarVC.viewControllers[tabBarVC.selectedIndex];
        [navVC popViewControllerAnimated:YES];
        
        NSString *orderId = [[NSUserDefaults standardUserDefaults] objectForKey:@"PayOrderId"];
            NSString *payFee = [[NSUserDefaults standardUserDefaults] objectForKey:@"PayFee"];
            //      
        NSDictionary *resultDict = @{@"order_id":orderId, @"payFee":payFee};
        [[NSNotificationCenter defaultCenter] postNotificationName:@"htmlPaymentNotification" object:self userInfo:resultDict];
    }
}