欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-06-24 12:38:01
先从进入页面的堆栈看后面看demo的小程序 pop 插件调用 交互...

 

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库小程序需要

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

 

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

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

 

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->警告框

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

,看到的打印是:

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/index.html#page/API/alert/alert?__appxPageId=102 
2020-07-21 09:52:38.620946+0800 MPTinyAppDemo_pod[18373:5199176] 小程序返回 https://2020012000000001.h5app.com/index.html#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/index.html#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.但是在上面方法打个断点,可以看到

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

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/index.html#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:]打断点

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

看到了这个方法

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