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

简介

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

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

一、获取支付参数

因涉及到敏感数据所以用参数名代替

实际使用时无需加{},添加{}主要是提醒这个是参数

----------open url: 0----------
weixin://app/{appId}/pay/?nonceStr=Ijs2foLuSi8sHEYS&package=Sign%3DWXPay&partnerId={partnerId}&prepayId={prepayId}&timeStamp=1499752264&sign={sign}&signType=SHA1

2、参数解释

以下为微信支付参数

//微信 URL Scheme
weixin

//固定写法
app

//微信app id
{appId}

//支付时使用 固定写法
pay

//随机串,防重发
nonceStr

//package iOS 只能是 Sign=WXPay 这里做了URL编码等号变成%3D
package

//商家向财付通申请的商家id
partnerId

//预支付订单
prepayId

//时间戳,防重发
timeStamp

商家根据微信开放平台文档对数据做的签名
sign

//签名类型
signType

二、构造支付参数

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

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

//服务器返回JSON形式数据,需要自己去拼接
+ (NSString *)payToWechatParameters:(NSDictionary *)parameters appid:(NSString *)appid onStateChanged:(TPayStateChangedHandler)stateChangedHandler {
    
    if (stateChangedHandler) {
        [TWeChatPlatform shareInstance].payStateChangedHandler = stateChangedHandler;
    }
    
    //生成URLscheme
    //    NSString *str = [NSString stringWithFormat:@"weixin://app/%@/pay/?nonceStr=%@&package=Sign%%3DWXPay&partnerId=%@&prepayId=%@&timeStamp=%@&sign=%@&signType=SHA1",appid,nonceStr,partnerId,prepayId,[NSString stringWithFormat:@"%d",[timeStamp intValue] ],sign];
    
    NSString * partnerId = parameters[@"partnerId"];
    NSString * prepayId = parameters[@"prepayId"];
    NSString * nonceStr = parameters[@"nonceStr"];
    NSString * timeStamp = parameters[@"timeStamp"];
//    NSString * package = parameters[@"package"];
    NSString * sign = parameters[@"sign"];
    
    NSString * wechatPayInfo = [NSString stringWithFormat:@"weixin://app/%@/pay/?nonceStr=%@&package=Sign%%3DWXPay&partnerId=%@&prepayId=%@&timeStamp=%@&sign=%@&signType=SHA1",appid,nonceStr,partnerId,prepayId,timeStamp,sign];
    
    return wechatPayInfo;
}

//服务器返回String 无需自己拼接
+ (NSString *)payToWechatOrderString:(NSString *)orderString appid:(NSString *)appid onStateChanged:(TPayStateChangedHandler)stateChangedHandler {
    
    if (stateChangedHandler) {
        [TWeChatPlatform shareInstance].payStateChangedHandler = stateChangedHandler;
    }
    
    NSString * wechatPayInfo = [NSString stringWithFormat:@"weixin://app/%@/pay/?%@&signType=SHA1",appid,orderString];
    return wechatPayInfo;
}

三、发起请求

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

//微信支付 需要手动拼接参数
+ (void)payToWechatParameters:(NSDictionary *)parameters onStateChanged:(TPayStateChangedHandler)stateChangedHandler {
    
    [Trochilus shareInstance].isPayment = YES;
    
    NSString * wechatPayInfo = [TWeChatPlatform payToWechatParameters:parameters
                                                                appid:[self platformForKey:weChat][@"appId"]
                                                       onStateChanged:^(TResponseState state, TUser *user, NSError *error) {
                                                           
                                                           if (stateChangedHandler) {
                                                               stateChangedHandler(state,user,error);
                                                           }
                                                           
                                                           
    }];
    
    [Trochilus sendToURL:wechatPayInfo];
}

//微信支付 服务器拼接好参数
+ (void)payToWechatorderString:(NSString *)orderString onStateChanged:(TPayStateChangedHandler)stateChangedHandler {
    
    [Trochilus shareInstance].isPayment = YES;
    
    NSString * wechatPayInfo = [TWeChatPlatform payToWechatOrderString:orderString
                                                                 appid:[self platformForKey:weChat][@"appId"]
                                                        onStateChanged:^(TResponseState state, TUser *user, NSError *error) {
                                                            
                                                            if (stateChangedHandler) {
                                                                stateChangedHandler(state,user,error);
                                                            }
    }];
    
    [Trochilus sendToURL:wechatPayInfo];
}

+ (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里的TWeChatPlatform类查看。

+ (BOOL)handleUrlWithWeChat:(NSURL *)url {
    
    if ([url.absoluteString rangeOfString:@"://pay/"].location != NSNotFound) {
            //微信支付
            NSDictionary * wechat = [NSMutableDictionary dictionaryWithUrl:url];
            if ([wechat[@"ret"] integerValue] == 0) {
                //支付成功
                if ([TWeChatPlatform shareInstance].payStateChangedHandler) {
                    [TWeChatPlatform shareInstance].payStateChangedHandler(TResponseStateSuccess, nil, nil);
                }
            }else if ([wechat[@"ret"] integerValue] == -2){
                //用户点击取消并返回
                if ([TWeChatPlatform shareInstance].payStateChangedHandler) {
                    [TWeChatPlatform shareInstance].payStateChangedHandler(TResponseStateCancel, nil, nil);
                }
            }
            else {
                //支付失败
                if ([TWeChatPlatform shareInstance].payStateChangedHandler) {
                    NSError * err = [NSError errorWithDomain:@"WechatDomain" code:[wechat[@"ret"] integerValue] userInfo:wechat];
                    [TWeChatPlatform shareInstance].payStateChangedHandler(TResponseStateFail, nil, err);
                }
                
            }
    }
    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不可能这么胖之微信支付)