简介
这一系列讲述的是免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}\"¬ify_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不可能这么胖之支付宝支付
网友评论