美文网首页程序员
我的APP不可能这么胖之支付宝支付

我的APP不可能这么胖之支付宝支付

作者: 萌恬丶 | 来源:发表于2017-07-18 13:54 被阅读82次

    简介

    这一系列讲述的是免SDK实现分享、登录、支付等业务。

    将会使用ShareSDK Demo进行部分试验。

    一、获取支付参数

    因涉及到敏感数据所以后面参数全部省略

    ----------open url: 0----------
    alipay://alipayclient/?一大串参数(URL编码的)
    

    2、参数解释

    以下为支付宝支付参数

    //支付宝 URL Scheme
    alipay
    
    //固定写法
    alipayclient
    
    //一大串参数(URL编码的)看下文
    
    

    二、构造支付参数

    代码仅供参考,部分代码做了封装,需要到demo里的TAliPayPlatform类查看。

    支付参数全部通过服务端获取,本地不做任何处理

    + (NSString *)payToAliPayUrlScheme:(NSString *)urlScheme orderString:(NSString *)orderString onStateChanged:(TPayStateChangedHandler)stateChangedHandler {
        
        if (stateChangedHandler) {
            [TAliPayPlatform shareInstance].payStateChangedHandler = stateChangedHandler;
        }
        
        //对敏感数据进行处理
        //alipay://alipayclient/?{
        //    "fromAppUrlScheme" : "{URL scheme}",
        //    "requestType" : "SafePay",
        //    "dataString" : "payment_type=\"1\"&out_trade_no=\"{订单编号}\"&partner=\"{partner}\"&subject=\"{subject}\"&service=\"mobile.securitypay.pay\"&_input_charset=\"UTF-8\"&total_fee=\"5.0\"&body=\"{body}\"&notify_url=\"{回调地址}\"&seller_id=\"{seller_id}\"&sign=\"{sign}\"&sign_type=\"RSA\"&bizcontext=\"{\"appkey\":\"{appkey}\"}\""
        //}
        
        NSDictionary * aliPayDic = @{@"fromAppUrlScheme" : urlScheme,
                                     @"requestType" : @"SafePay",
                                     @"dataString" : orderString};
        NSError * error;
        NSData * aliPayJsonData = [NSJSONSerialization dataWithJSONObject:aliPayDic
                                                                 options:NSJSONWritingPrettyPrinted
                                                                   error:&error];
        NSString * aliPayJsonString = [[NSString alloc] initWithData:aliPayJsonData encoding:NSUTF8StringEncoding];
        NSString * aliPayInfo = [NSString stringWithFormat:@"alipay://alipayclient/?%@",aliPayJsonString];
        NSString * aliPayUrl = [aliPayInfo stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        return aliPayUrl;
    }
    

    三、发起请求

    代码仅供参考,部分代码做了封装,需要到demo里的Trochilus类查看。

    //支付宝支付
    + (void)payToAliPayUrlScheme:(NSString *)urlScheme orderString:(NSString *)orderString onStateChanged:(TPayStateChangedHandler)stateChangedHandler {
        
        [Trochilus shareInstance].isPayment = YES;
        
        NSString * aliPayInfo = [TAliPayPlatform payToAliPayUrlScheme:urlScheme
                                                          orderString:orderString
                                                       onStateChanged:^(TResponseState state, TUser *user, NSError *error) {
                                                           if (stateChangedHandler) {
                                                               stateChangedHandler(state,user,error);
                                                           }
        }];
        
        [Trochilus sendToURL:aliPayInfo];
    }
    
    + (void)sendToURL:(NSString *)url {
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
        });
        
    }
    

    四、支付宝户端回调

    代码仅供参考,部分代码做了封装,需要到demo里的TAliPayPlatform类查看。

    + (BOOL)handleUrlWithAliPay:(NSURL *)url {
        
        if ([url.absoluteString rangeOfString:@"//safepay/"].location != NSNotFound) {
            NSError *err;
            NSDictionary *ret=[NSJSONSerialization JSONObjectWithData:[[NSString urlDecode:url.query]dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&err];
            if (err||ret[@"memo"]==[NSNull null]||[ret[@"memo"][@"ResultStatus"] intValue]!=9000) {
                //支付失败
                NSError * err = [NSError errorWithDomain:@"alipay_pay" code:ret[@"memo"]!=[NSNull null]?[ret[@"memo"][@"ResultStatus"] intValue]:-1 userInfo:ret];
                
                if ([TAliPayPlatform shareInstance].payStateChangedHandler) {
                    [TAliPayPlatform shareInstance].payStateChangedHandler(TResponseStateFail,nil,err);
                }
            }
            else if (err||ret[@"memo"]==[NSNull null]||[ret[@"memo"][@"ResultStatus"] intValue] == 6001) {
                //用户取消
                NSError * err = [NSError errorWithDomain:@"alipay_pay" code:ret[@"memo"]!=[NSNull null]?[ret[@"memo"][@"ResultStatus"] intValue]:-1 userInfo:ret];
                if ([TAliPayPlatform shareInstance].payStateChangedHandler) {
                    [TAliPayPlatform shareInstance].payStateChangedHandler(TResponseStateCancel,nil,err);
                }
            }
            else{
                //支付成功
                if ([TAliPayPlatform shareInstance].payStateChangedHandler) {
                    [TAliPayPlatform shareInstance].payStateChangedHandler(TResponseStateSuccess,nil,nil);
                }
            }
            return YES;
        }
        
        return NO;
    }
    
    

    五、iOS9起状态栏返回回调处理

    iOS9起在状态栏左右两侧增加了返回APP的功能,通过这个功能微信客户端是不会发信息给我们APP的,因此需要做特殊处理。

    我们看看微信返回我们APP时,我们APP的appDelegate方法执行顺序是什么

    applicationWillEnterForeground:-> application:openURL:options: || application:openURL:sourceApplication:annotation:

    因此我们在applicationWillEnterForeground做文章,代码如下:

    - (void)t_applicationWillEnterForeground:(UIApplication *)application {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
        
        [self t_applicationWillEnterForeground:application];
        
        dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5/*延迟执行时间*/ * NSEC_PER_SEC));
        dispatch_after(delayTime, dispatch_get_main_queue(), ^{
            //延迟0.5s执行
            if ([Trochilus isURLResponse] == NO && [Trochilus isPay] == YES) {
                [[NSNotificationCenter defaultCenter] postNotificationName:kTrochilusPayment object:self userInfo:nil];
            }
        });
    }
    
    

    这里做了 method swizzle 具体看UIApplication+Trochilus类,实现了ShareSDK那个效果

    同时做了延迟处理 判断客户端是否有返回信息,没有就去自己服务器请求结果吧

    [Trochilus isURLResponse] == YES 说明微信有返回信息 反之 微信没返回信息,那么我们需要去自己服务器查支付结果

    [Trochilus isPay] == YES 说明是支付类型,因为我这还有分享、授权,为了避免发送不必要的通知

    六、参考资料

    https://github.com/100apps/openshare

    http://www.jianshu.com/p/8930b4496023

    七、Demo

    https://github.com/quanweiwang/Trochilus

    目录

    分享篇
    1、我的APP不可能这么胖之QQ好友分享
    2、我的APP不可能这么胖之QQ空间分享
    3、我的APP不可能这么胖之微信好友分享
    4、我的APP不可能这么胖之微信朋友圈分享
    5、我的APP不可能这么胖之新浪微博分享
    登录篇
    6、我的APP不可能这么胖之QQ登录
    7、我的APP不可能这么胖之微信登录
    8、我的APP不可能这么胖之新浪微博登录
    支付篇
    9、我的APP不可能这么胖之微信支付
    10、我的APP不可能这么胖之支付宝支付

    相关文章

      网友评论

        本文标题:我的APP不可能这么胖之支付宝支付

        本文链接:https://www.haomeiwen.com/subject/hgfhkxtx.html