序
本文源于今天早上@清望同学遇到的一个问题。
需求
项目需求需要使用两个不同的微信appid授权,进行不同的操作。
appid1: 用于微信授权进行账号登录。
appid2: 用于微信授权进行微信取现。
问题
获取appid2授权时,可能跳转到appid1的授权页。
分析
微信授权
// 1. 注册
[WXApi registerApp:WEIXIN_APP_ID];
// 2. 请求授权
SendAuthReq *auth = [[SendAuthReq alloc] init];
auth.scope = @"snsapi_userinfo";
auth.state = @"UUID";
[WXApi sendAuthReq:auth viewController:nil delegate:self];
// 3. 处理请求结果
[WXApi handleOpenURL:url delegate:self];
以上是微信的授权流程。由于两次请求授权使用不同的key。所以每次请求之前都重新初始化。但是没有跳转到相应appid的授权。
猜测
由于是授权页没有调转到相应appid的授权页。
所以猜测[WXApi registerApp:WEIXIN_APP_ID];
接口重新初始化,appid没有改变
验证猜测
由于请求授权[WXApi sendAuthReq:auth viewController:nil delegate:self];
内部最终会调用UIApplication
的
- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion
接口。
我们可以注入钩子代码查看这里的url
值是否使用正确的appid。
[[UIApplication sharedApplication] aspect_hookSelector:@selector(openURL:options:completionHandler:) withOptions:AspectPositionBefore usingBlock:^(id aspectInfo) {
// 打印微信URL参数
NSLog(@"%@: %@", aspectInfo.instance, aspectInfo.arguments);
} error:NULL];
注入方法
- 使用runtime。这种方法需要额外手工写代码注入方法。
- 使用Aspects。使用比较简单。源码地址 https://github.com/steipete/Aspects
解决问题
确认是由于[WXApi registerApp:WEIXIN_APP_ID];
接口重新初始化后,并没有修改相应的appid。
那么我们做相应的修改来确保重新初始化appid。
方法一:使用runtime直接修改微信内部属性值。
我没有采用这种方法。如果你做了,可以告诉我怎么做 :)
方法二:修改UIApplication
的openURL函数调用时的url值,修改为正确的appid。
#define WEIXIN_APP_ID_1 @"微信appid1"
#define WEIXIN_APP_ID_2 @"微信appid2"
[[UIApplication sharedApplication] aspect_hookSelector:@selector(openURL:options:completionHandler:) withOptions:AspectPositionInstead usingBlock:^(id<AspectInfo> aspectInfo) {
NSLog(@"%@: %@", aspectInfo.instance, aspectInfo.arguments);
// 修改url中相应的appid参数。
NSInvocation *invocation = info.originalInvocation;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"weixin://app/%@/auth/?scope=snsapi_userinfo&state=%@", WEIXIN_APP_ID_2,weakSelf.reqKey]];
[invocation setArgument:&url atIndex:2];
[invocation retainArguments];
[invocation invoke];
} error:NULL];
总结
- 微信sdk初始化,再次初始化不会改变相应的appid值。也没有提供反初始化接口。
- 采用钩子的方法,验证猜想。
- 使用runtime修复问题。
后续
微信SDK内部还可能存储上一次的授权信息。也需要清除。看看下午调试结果再补充吧……