Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 108 additions & 24 deletions ios/Classes/WechatKitPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ @implementation WechatKitPlugin {
BOOL _isRunning;
BOOL _handleInitialWXReqFlag;
WechatKitWXReqRunnable _initialWXReqRunnable;
NSURL *_pendingOpenURL;
NSUserActivity *_pendingUserActivity;
NSString *_cachedLaunchReqType;
NSDictionary *_cachedLaunchReqData;
}

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
Expand All @@ -34,7 +38,6 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
- (instancetype)init {
self = [super init];
if (self) {
// _channel = channel;
_qrauth = [[WechatAuthSDK alloc] init];
_qrauth.delegate = self;
_isRunning = NO;
Expand All @@ -54,7 +57,19 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
NSString *universalLink = call.arguments[@"universalLink"];
[WXApi registerApp:appId universalLink:universalLink];
_isRunning = YES;
[self handlePendingWXOpenIfNeeded];
result(nil);
} else if ([@"getLaunchReq" isEqualToString:call.method]) {
if (_cachedLaunchReqType != nil && _cachedLaunchReqData != nil) {
result(@{
@"type": _cachedLaunchReqType,
@"data": _cachedLaunchReqData,
});
_cachedLaunchReqType = nil;
_cachedLaunchReqData = nil;
} else {
result(nil);
}
} else if ([@"handleInitialWXReq" isEqualToString:call.method]) {
if (!_handleInitialWXReqFlag) {
_handleInitialWXReqFlag = YES;
Expand Down Expand Up @@ -114,25 +129,61 @@ - (void)handleMethodCall:(FlutterMethodCall *)call
}
}

- (void)handlePendingWXOpenIfNeeded {
if (_initialWXReqRunnable != nil) {
return;
}
if (_pendingOpenURL != nil) {
BOOL ok = [WXApi handleOpenURL:_pendingOpenURL delegate:self];
if (!ok && _channel != nil) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setValue:_pendingOpenURL.absoluteString forKey:@"messageExt"];
[self cacheLaunchReq:@"launch" data:dictionary];
[_channel invokeMethod:@"onLaunchFromWXReq" arguments:dictionary];
}
_pendingOpenURL = nil;
}
if (_pendingUserActivity != nil) {
BOOL ok = [WXApi handleOpenUniversalLink:_pendingUserActivity delegate:self];
if (!ok && _channel != nil) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
if ([_pendingUserActivity.webpageURL absoluteString] != nil) {
[dictionary setValue:_pendingUserActivity.webpageURL.absoluteString forKey:@"messageExt"];
}
[self cacheLaunchReq:@"launch" data:dictionary];
[_channel invokeMethod:@"onLaunchFromWXReq" arguments:dictionary];
}
_pendingUserActivity = nil;
}
}

- (void)cacheLaunchReq:(NSString *)type data:(NSDictionary *)data {
if (type == nil || data == nil) {
return;
}
_cachedLaunchReqType = [type copy];
_cachedLaunchReqData = [data copy];
}

- (void)handleAuthCall:(FlutterMethodCall *)call result:(FlutterResult)result {
SendAuthReq *req = [[SendAuthReq alloc] init];
req.scope = call.arguments[@"scope"];
req.state = call.arguments[@"state"];
NSNumber *type = call.arguments[@"type"];

if ([type intValue] == 0) {
[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
} else if ([type intValue] == 1) {
UIViewController *viewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
[WXApi sendAuthReq:req
viewController:viewController
delegate:self
completion:^(BOOL success){
// do nothing
}];
}

result(nil);
}

Expand All @@ -144,6 +195,7 @@ - (void)handleQRAuthCall:(FlutterMethodCall *)call
NSString *noncestr = call.arguments[@"noncestr"];
NSString *timestamp = call.arguments[@"timestamp"];
NSString *signature = call.arguments[@"signature"];

[_qrauth Auth:appId
nonceStr:noncestr
timeStamp:timestamp
Expand All @@ -153,16 +205,17 @@ - (void)handleQRAuthCall:(FlutterMethodCall *)call
} else if ([@"stopQrauth" isEqualToString:call.method]) {
[_qrauth StopAuth];
}

result(nil);
}

- (void)handleOpenUrlCall:(FlutterMethodCall *)call
result:(FlutterResult)result {
OpenWebviewReq *req = [[OpenWebviewReq alloc] init];
req.url = call.arguments[@"url"];

[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -172,7 +225,6 @@ - (void)handleOpenRankListCall:(FlutterMethodCall *)call
OpenRankListReq *req = [[OpenRankListReq alloc] init];
[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -184,9 +236,9 @@ - (void)handleShareTextCall:(FlutterMethodCall *)call
req.scene = [scene intValue];
req.bText = YES;
req.text = call.arguments[@"text"];

[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -204,10 +256,10 @@ - (void)handleShareMediaCall:(FlutterMethodCall *)call
if (thumbData != nil) {
message.thumbData = thumbData.data;
}

if ([@"shareImage" isEqualToString:call.method]) {
WXImageObject *mediaObject = [WXImageObject object];
FlutterStandardTypedData *imageData =
call.arguments[@"imageData"];
FlutterStandardTypedData *imageData = call.arguments[@"imageData"];
if (imageData != nil) {
mediaObject.imageData = imageData.data;
} else {
Expand All @@ -230,8 +282,7 @@ - (void)handleShareMediaCall:(FlutterMethodCall *)call
message.mediaObject = mediaObject;
} else if ([@"shareEmoji" isEqualToString:call.method]) {
WXEmoticonObject *mediaObject = [WXEmoticonObject object];
FlutterStandardTypedData *emojiData =
call.arguments[@"emojiData"];
FlutterStandardTypedData *emojiData = call.arguments[@"emojiData"];
if (emojiData != nil) {
mediaObject.emoticonData = emojiData.data;
} else {
Expand All @@ -245,8 +296,7 @@ - (void)handleShareMediaCall:(FlutterMethodCall *)call
mediaObject.musicUrl = call.arguments[@"musicUrl"];
mediaObject.musicDataUrl = call.arguments[@"musicDataUrl"];
mediaObject.musicLowBandUrl = call.arguments[@"musicLowBandUrl"];
mediaObject.musicLowBandDataUrl =
call.arguments[@"musicLowBandDataUrl"];
mediaObject.musicLowBandDataUrl = call.arguments[@"musicLowBandDataUrl"];
message.mediaObject = mediaObject;
} else if ([@"shareVideo" isEqualToString:call.method]) {
WXVideoObject *mediaObject = [WXVideoObject object];
Expand All @@ -262,8 +312,7 @@ - (void)handleShareMediaCall:(FlutterMethodCall *)call
mediaObject.webpageUrl = call.arguments[@"webpageUrl"];
mediaObject.userName = call.arguments[@"username"];
mediaObject.path = call.arguments[@"path"];
FlutterStandardTypedData *hdImageData =
call.arguments[@"hdImageData"];
FlutterStandardTypedData *hdImageData = call.arguments[@"hdImageData"];
if (hdImageData != nil) {
mediaObject.hdImageData = hdImageData.data;
}
Expand All @@ -275,10 +324,10 @@ - (void)handleShareMediaCall:(FlutterMethodCall *)call
mediaObject.disableForward = disableForward.boolValue;
message.mediaObject = mediaObject;
}

req.message = message;
[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -294,9 +343,9 @@ - (void)handleSubscribeMsgCall:(FlutterMethodCall *)call
#endif
req.templateId = call.arguments[@"templateId"];
req.reserved = call.arguments[@"reserved"];

[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -308,9 +357,9 @@ - (void)handleLaunchMiniProgramCall:(FlutterMethodCall *)call
req.path = call.arguments[@"path"];
NSNumber *miniProgramType = call.arguments[@"type"];
req.miniProgramType = miniProgramType.unsignedIntegerValue;

[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -320,9 +369,9 @@ - (void)handleOpenCustomerServiceChatCall:(FlutterMethodCall *)call
WXOpenCustomerServiceReq *req = [[WXOpenCustomerServiceReq alloc] init];
req.corpid = call.arguments[@"corpId"];
req.url = call.arguments[@"url"];

[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -333,9 +382,9 @@ - (void)handleOpenBusinessViewCall:(FlutterMethodCall *)call
req.businessType = call.arguments[@"businessType"];
req.query = call.arguments[@"query"];
req.extInfo = call.arguments[@"extInfo"];

[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -350,6 +399,7 @@ - (void)handleOpenBusinessWebviewCall:(FlutterMethodCall *)call
req.businessType = [businessType unsignedLongValue];
#endif
req.queryInfoDic = call.arguments[@"queryInfo"];

result(nil);
}

Expand All @@ -363,9 +413,9 @@ - (void)handlePayCall:(FlutterMethodCall *)call result:(FlutterResult)result {
req.timeStamp = [timeStamp intValue];
req.package = call.arguments[@"package"];
req.sign = call.arguments[@"sign"];

[WXApi sendReq:req
completion:^(BOOL success){
// do nothing
}];
result(nil);
}
Expand All @@ -374,27 +424,57 @@ - (void)handlePayCall:(FlutterMethodCall *)call result:(FlutterResult)result {
#pragma mark - AppDelegate

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [WXApi handleOpenURL:url delegate:self];
if (!_isRunning) {
_pendingOpenURL = url;
}
BOOL ret = [WXApi handleOpenURL:url delegate:self];
return ret;
}

- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
return [WXApi handleOpenURL:url delegate:self];
if (!_isRunning) {
_pendingOpenURL = url;
}
BOOL ret = [WXApi handleOpenURL:url delegate:self];
return ret;
}

- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:
(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
return [WXApi handleOpenURL:url delegate:self];
if (!_isRunning) {
_pendingOpenURL = url;
}
BOOL ret = [WXApi handleOpenURL:url delegate:self];
if (!ret && _isRunning && _channel != nil) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setValue:url.absoluteString forKey:@"messageExt"];
[self cacheLaunchReq:@"launch" data:dictionary];
[_channel invokeMethod:@"onLaunchFromWXReq" arguments:dictionary];
}
return ret;
}

- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *_Nonnull))restorationHandler {
return [WXApi handleOpenUniversalLink:userActivity delegate:self];
if (!_isRunning) {
_pendingUserActivity = userActivity;
}
BOOL ret = [WXApi handleOpenUniversalLink:userActivity delegate:self];
if (!ret && _isRunning && _channel != nil) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
if ([userActivity.webpageURL absoluteString] != nil) {
[dictionary setValue:userActivity.webpageURL.absoluteString forKey:@"messageExt"];
}
[self cacheLaunchReq:@"launch" data:dictionary];
[_channel invokeMethod:@"onLaunchFromWXReq" arguments:dictionary];
}
return ret;
}

#pragma mark - WXApiDelegate
Expand All @@ -407,6 +487,7 @@ - (void)onReq:(BaseReq *)req {
[dictionary setValue:launchFromWXReq.message.messageExt forKey:@"messageExt"];
[dictionary setValue:launchFromWXReq.lang forKey:@"lang"];
[dictionary setValue:launchFromWXReq.country forKey:@"country"];
[self cacheLaunchReq:@"launch" data:dictionary];
if (_isRunning) {
[_channel invokeMethod:@"onLaunchFromWXReq" arguments:dictionary];
} else {
Expand All @@ -422,6 +503,7 @@ - (void)onReq:(BaseReq *)req {
[dictionary setValue:showMessageFromWXReq.message.messageExt forKey:@"messageExt"];
[dictionary setValue:showMessageFromWXReq.lang forKey:@"lang"];
[dictionary setValue:showMessageFromWXReq.country forKey:@"country"];
[self cacheLaunchReq:@"showMessage" data:dictionary];
if (_isRunning) {
[_channel invokeMethod:@"onShowMessageFromWXReq" arguments:dictionary];
} else {
Expand All @@ -441,6 +523,7 @@ - (void)onResp:(BaseResp *)resp {
if (resp.errStr != nil) {
[dictionary setValue:resp.errStr forKey:@"errorMsg"];
}

if ([resp isKindOfClass:[SendAuthResp class]]) {
// 授权
if (resp.errCode == WXSuccess) {
Expand Down Expand Up @@ -519,6 +602,7 @@ - (void)onAuthGotQrcode:(UIImage *)image {
if (imageData == nil) {
imageData = UIImageJPEGRepresentation(image, 1);
}

NSDictionary *dictionary = @{
@"imageData" : imageData,
};
Expand Down
18 changes: 18 additions & 0 deletions lib/src/wechat_kit_method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@ class MethodChannelWechatKit extends WechatKitPlatform {
return methodChannel.invokeMethod<void>('handleInitialWXReq');
}

@override
Future<WechatReq?> getLaunchReq() async {
final raw = await methodChannel.invokeMethod<Map>('getLaunchReq');
if (raw == null) return null;
final type = raw['type'];
final data = raw['data'];
if (type is String && data is Map) {
final payload = data.cast<String, dynamic>();
if (type == 'launch') {
return WechatLaunchFromWXReq.fromJson(payload);
}
if (type == 'showMessage') {
return WechatShowMessageFromWXReq.fromJson(payload);
}
}
return null;
}

@override
Future<bool> isInstalled() async {
return await methodChannel.invokeMethod<bool>('isInstalled') ?? false;
Expand Down
4 changes: 4 additions & 0 deletions lib/src/wechat_kit_platform_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ abstract class WechatKitPlatform extends PlatformInterface {
throw UnimplementedError('qrauthRespStream() has not been implemented.');
}

Future<WechatReq?> getLaunchReq() {
throw UnimplementedError('getLaunchReq() has not been implemented.');
}

/// 微信回调 - 冷启
Future<void> handleInitialWXReq() {
throw UnimplementedError('handleInitialWXReq() has not been implemented.');
Expand Down