当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS支付宝小程序与原生交互分析

iOS支付宝小程序与原生交互分析

2020年07月22日  | 移动技术网移动技术  | 我要评论

 

1.从 https://github.com/mpaas-demo/ios-tinyapp?spm=a2c4g.11186623.2.23.7e386fe0mar9s5 下载支付宝小程序demo,

按照说明执行

1).修改Podfile,设置基线号,支持设置为10.1.68-beta

2)、pod mpaas update --all

3)、pod update

根据提示再升级pod的mpaas版本,然后再pod update

demo能正常运行了

 

 

2.从官方文档可以看到FalconLooks库小程序需要

 

3.hook push方法先从进入页面的堆栈看,看不出啥

 

4.hook一下WKWebView的@selector(evaluateJavaScript:completionHandlerS:)

.h
#import <WebKit/WebKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface WKWebView (YYY)

@end

NS_ASSUME_NONNULL_END



.m

#import "WKWebView+YYY.h"
#import <objc/runtime.h>

typedef void (^BLOCKYYY)(id _Nullable  str7 , NSError * er7)   ;



@implementation WKWebView (YYY)



+(void)load{
    
 
    {
        Method originalMethod = class_getInstanceMethod([NSClassFromString(@"WKWebView") class], @selector(evaluateJavaScript:completionHandler:));
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(evaluateJavaScript:completionHandlerS:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
    
 
}
-(void)evaluateJavaScript:(NSString *)javaScriptString completionHandlerS:(void (^)(id _Nullable  str7 , NSError * er7))completionHandler{
    


    NSLog(@"小程序 %@ ",javaScriptString);
    
    [self evaluateJavaScript:javaScriptString completionHandlerS:^(id  _Nullable str, NSError *er) {
        NSLog(@"小程序返回 %@ ",str);
//        completionHandler(str,er);
    }];
    
    [self evaluateJavaScript:javaScriptString completionHandlerS:completionHandler];

        
    
    
}
@end

分类添加属性要使用关联,不能直接加

 

5.点击API->警告框

,看到的打印是:

2020-07-21 09:52:24.934694+0800 MPTinyAppDemo_pod[18373:5199176] 小程序 location.href 
2020-07-21 09:52:35.072146+0800 MPTinyAppDemo_pod[18373:5199176] 小程序 AlipayJSBridge._handleMessageFromObjC('{\"responseId\":\"postMessage_15952963380340.17604869608612228\",\"responseData\":{\"messageEventCanceled\":false}}'); 
2020-07-21 09:52:38.605279+0800 MPTinyAppDemo_pod[18373:5199176] 小程序 location.href 
2020-07-21 09:52:38.615518+0800 MPTinyAppDemo_pod[18373:5199176] 小程序 location.href 
2020-07-21 09:52:38.616711+0800 MPTinyAppDemo_pod[18373:5199176] 小程序返回 (null) 
2020-07-21 09:52:38.617399+0800 MPTinyAppDemo_pod[18373:5199176] 小程序返回 https://2020012000000001.h5app.com/#page/API/alert/alert?__appxPageId=102 
2020-07-21 09:52:38.620946+0800 MPTinyAppDemo_pod[18373:5199176] 小程序返回 https://2020012000000001.h5app.com/#page/API/alert/alert?__appxPageId=102 
2020-07-21 09:59:38.614236+0800 MPTinyAppDemo_pod[18373:5199176] 小程序 location.href 
2020-07-21 09:59:39.114819+0800 MPTinyAppDemo_pod[18373:5199176] 小程序 location.href 
2020-07-21 09:59:39.372248+0800 MPTinyAppDemo_pod[18373:5199176] 小程序返回 https://2020012000000001.h5app.com/#page/API/alert/alert?__appxPageId=102 
2020-07-21 09:59:40.035466+0800 MPTinyAppDemo_pod[18373:5199176] 小程序 AlipayJSBridge._handleMessageFromObjC('{\"callbackId\":\"objc_cb_3\",\"handlerName\":\"back\"}'); 

可以看到也没有什么有用信息

 

6.但是在上面方法打个断点,可以看到

H5JSCBridge的@selector(doCallWithItem:callBack:)这个方法

 

7.hook这个方法

- (void)doCallWithItem:(id)arg1 callBackS:(id)arg2;
{
    NSLog(@"doCallWithItem参数%@",arg1);
    [self doCallWithItem:arg1 callBackS:arg2 ];

}

并点击警告框 看其打印

2020-07-21 10:12:39.742773+0800 MPTinyAppDemo_pod[18410:5206087] doCallWithItem参数{
    callbackId = "pushWindow_15952975597410.2726862088613564";
    data = "{\"url\":\"#page/API/alert/alert?__appxPageId=101\",\"viewId\":3,\"launchParamsTag\":\"page/API/alert/alert\"}";
    handlerName = pushWindow;
}
2020-07-21 10:12:40.268824+0800 MPTinyAppDemo_pod[18410:5206087] doCallWithItem参数{
    callbackId = "postMessage_15952975602670.6360432434314175";
    data = "{\"data\":\"{\\\"data\\\":{\\\"c\\\":\\\"self\\\",\\\"m\\\":\\\"invokeCallback\\\",\\\"d\\\":101,\\\"a\\\":[1,{\\\"showOptionMenu\\\":false,\\\"app_startup_type\\\":\\\"inner\\\",\\\"url\\\":\\\"https://2020012000000001.h5app.com/#page/tabBar/component/index\\\",\\\"enableKeepAlive\\\":false,\\\"backgroundColor\\\":16119289,\\\"transparentTitle\\\":\\\"auto\\\",\\\"allowsBounceVertical\\\":\\\"NO\\\",\\\"version\\\":\\\"1.0.99.0\\\",\\\"enableTabBar\\\":true,\\\"backBehavior\\\":\\\"pop\\\",\\\"inPageRenderType\\\":\\\"map|video|camera|canvas|cdp|ai-camera|ad\\\",\\\"nboffline\\\":\\\"sync\\\",\\\"titleBarColor\\\":16777215,\\\"kPSDSceneInjectRequest\\\":true,\\\"sourceId\\\":\\\"\\\",\\\"enableDSL\\\":true,\\\"kPSDSessionH5Mode\\\":0,\\\"kPSDSessionPSDType\\\":0,\\\"appId\\\":\\\"2020012000000001\\\",\\\"tinyPubRes\\\":true,\\\"launchParamsTag\\\":\\\"page/tabBar/component/index\\\",\\\"defaultTitle\\

2020-07-21 10:12:41.427530+0800 MPTinyAppDemo_pod[18410:5206087] doCallWithItem参数{
    callbackId = "alert_15952975614230.9276469663708761";
    data = "{\"title\":\"\U4eb2\",\"message\":\"\U60a8\U672c\U6708\U7684\U8d26\U5355\U5df2\U51fa\",\"button\":\"\U6211\U77e5\U9053\U4e86\"}";
    handlerName = alert;
}

这样就能看到插件名字和参数了。

上面用到了跳页的pushWindow,弹框的alert。

到这里一般开发中遇到的问题及参数打印应该就没多大问题了。

 

 

 

 

 

8.按照惯例doFlushMessageQueue的功能是与h5交互,将返回的数据交给不同的插件去跳页或展示

用模拟器运行一下拖到hopper看一下,

void -[H5JSCBridge doFlushMessageQueue:](void * self, void * _cmd, void * arg2) {
    r14 = [arg2 retain];
    objc_initWeak(&var_-40, self);
    *(&var_-48 + 0xffffffffffffffd8) = __NSConcreteStackBlock;
    *(&var_-48 + 0xffffffffffffffe0) = 0xc2000000;
    *(&var_-48 + 0xffffffffffffffe8) = ___35-[H5JSCBridge doFlushMessageQueue:]_block_invoke;
    *(&var_-48 + 0xfffffffffffffff0) = ___block_descriptor_48_e8_32s40w_e5_v8?0l;
    objc_copyWeak(&var_-48, &var_-40);
    rax = [r14 retain];
    *(&var_-48 + 0xfffffffffffffff8) = rax;
    _ExMainCall_NebulaSDK("-[H5JSCBridge doFlushMessageQueue:]", 0x0, &var_-88);
    [var_-56 release];
    objc_destroyWeak(&var_-48);
    objc_destroyWeak(&var_-40);
    [rax release];
    return;
}

function ___35-[H5JSCBridge doFlushMessageQueue:]_block_invoke {
    r14 = rdi;
    rax = objc_loadWeakRetained(rdi + 0x28);
    rbx = rax;
    if (rax != 0x0) {
            rdx = [NSArray class];
            if ([*(r14 + 0x20) isKindOfClass:rdx] != 0x0) {
                    rax = [*(r14 + 0x20) copy];
                    var_-56 = rax;
                    rax = [rax count];
                    var_-48 = rbx;
                    if (rax > 0x0) {
                            r13 = rax;
                            r15 = _objc_msgSend;
                            r12 = 0x0;
                            do {
                                    rax = (r15)(var_-56, @selector(objectAtIndex:), r12, 0x0);
                                    rax = [rax retain];
                                    (r15)(var_-48, @selector(doCallWithItem:callBack:), rax, 0x0);
                                    [rax release];
                                    r12 = r12 + 0x1;
                            } while (r13 != r12);
                    }
                    [var_-56 release];
                    rbx = var_-48;
            }
    }
    rax = [rbx release];
    return rax;
}


void -[H5JSCBridge doFlushMessageQueue:callBack:](void * self, void * _cmd, void * arg2, void * arg3) {
    r15 = [arg2 retain];
    r12 = [arg3 retain];
    objc_initWeak(&var_-48, self);
    *(&var_-56 + 0xffffffffffffffd0) = __NSConcreteStackBlock;
    *(&var_-56 + 0xffffffffffffffd8) = 0xc2000000;
    *(&var_-56 + 0xffffffffffffffe0) = ___44-[H5JSCBridge doFlushMessageQueue:callBack:]_block_invoke;
    *(&var_-56 + 0xffffffffffffffe8) = ___block_descriptor_56_e8_32s40bs48w_e5_v8?0l;
    objc_copyWeak(&var_-56, &var_-48);
    rax = [r15 retain];
    r14 = rax;
    *(&var_-56 + 0xfffffffffffffff0) = rax;
    rax = [r12 retain];
    *(&var_-56 + 0xfffffffffffffff8) = rax;
    _ExMainCall_NebulaSDK("-[H5JSCBridge doFlushMessageQueue:callBack:]", 0x0, &var_-104);
    [var_-64 release];
    [var_-72 release];
    objc_destroyWeak(&var_-56);
    objc_destroyWeak(&var_-48);
    [rax release];
    [r14 release];
    return;
}


但这个不是

 

9.在void -[PSDJsBridge _doFlushMessageQueue:url:]打断点

看到了这个方法

MPTinyAppDemo_pod`-[PSDScriptMessageHandlerProxy userContentController:didReceiveScriptMessage:]:

这个应该就是h5直接调用原生的源方法

hook它,


#import "PSDScriptMessageHandlerProxy+YYY.h"
#import <objc/runtime.h>

@implementation PSDScriptMessageHandlerProxy (YYY)
+(void)load{
    Method originalMethod = class_getInstanceMethod([self class], @selector(userContentController:didReceiveScriptMessage:));
    Method swizzledMethod = class_getInstanceMethod([self class], @selector(userContentController:didReceiveScriptMessageS:));
    method_exchangeImplementations(originalMethod, swizzledMethod);
    
}
- (void)userContentController:(nonnull WKUserContentController *)arg1 didReceiveScriptMessageS:(nonnull WKScriptMessage *)arg2;{
    
    NSLog(@"userContentController %@ %@ %@",arg1,arg2.body,arg2.name);
    
    [self userContentController:arg1 didReceiveScriptMessageS:arg2];
    
}

@end

 

打印数据有下面这个,应该还有间接的取值过程

2020-07-21 11:08:40.929573+0800 MPTinyAppDemo_pod[64206:6239032] userContentController <WKUserContentController: 0x600000f13600> {
    msgKt = 41fa91654a13b6bca904cfcea7279bc1;
    queue = "[{\"responseId\":\"objc_cb_1\",\"responseData\":{\"messageEventCanceled\":false,\"syncJsApis\":[]}}]";
    type = api;
} PSDBRIDGEMESSAGEHANDLER

 

 

暂时先这样,后面遇到相关问题再完善

 

 

10.容器控制器打印创建参数

    PSDScene *delegate = (PSDScene *)self.delegate;
    PSDSceneParam *psdScene = [delegate createParam];
    NSDictionary *dic = psdScene.expandParams;

参数中包含tinyPubRes = 1;

猜想这个参数可以判断当前打开的是小程序还是离线包。

 

 

 

本文地址:https://blog.csdn.net/qq_15509071/article/details/107406227

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网