泉城通APP中H5与原生交互开发说明

[toc]

一、H5使用qct-jsdk

1.1、第一步:引入qct-jsdk

生产环境中“qct-jsdk-v1.0.0.js”文件引入url

https://qct.bolangit.cn/open/jsdk/qct-jsdk-v1.0.0.js
//或者
https://qct.bolangit.cn/omp/jsdk/qct-jsdk-v1.0.0.js

app开发测试环境中”h5页面引入地址“

http://110.88.209.214:8081/qct-jsdk-demo.html

1.2、第二部:引入js文件(5端使用qct-jsdk.js)

//引入qct-jsdk文件
<script type="text/javascript" src="https://gwc.bolangit.cn/jssdk/qct-jsdk-v1.0.0.js"></script>

1.3、第三步:通过config接口注入权限验证配置初始化qct-jsdk

//初始化
$(function(){

    //初始化参数,当前为预留,信息由后台返回
    config_param = {
        appid: "123456", //开放平台分配的用户唯一标识
        jsdk_access_token: "1234"
    }
    qct.config(config_param);//使用 config_param json参数初始化  

});

H5对应后端需要先向 “开放平台” 申请获取jsdk_access_token (该jsdk_access_token有效期2小时)
为了安全 jsdk_access_token 必须通过服务后端获取,不能在h5上直接去获取。
jsdk_access_token 的获取方式参见《泉城通开放平台第三方服务接入指南》相关章节。

1.4、第四步:通过ready接口统一处理业务接口

qct.ready(function () {
    //其他业务接口都要放到ready函数中进行处理
    //当前版本的业务接口清单如下:
    //qct.getLocation(param);//获取定位信息;
    //qct.getCode(param);//获取code;
});

1.5、第五步:H5获取回调参数

所有接口通过qct对象来调用,参数是一个json对象,除了每个接口本身需要传的参数之外,还有以下通用参数:
* success:接口调用成功时执行的回调函数。
* fail:接口调用失败时执行的回调函数。

H5可以通过上述回调函数获取“成功”和“失败”时,APP的返回信息。如果回调函数无响应,请通过查看console.log信息排查。

1.6、业务接口示例

1.6.1、获取code

1.6.1.1、 请求示例
 qct.ready(function () {
        qct.getCode({
            state: 'getCode发起的标题',
            success: function (res) {//成功回调函数
                //具体业务逻辑
            },
            fail: function (res) {//                                           
                //具体业务逻辑
            }
        })
  });

参数说明

参数名 是否必须 描述 类型
state app返回时会”原值“带上的参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 string
success 成功回调函数 function
fail 失败回调函数 function
1.6.1.2、成功时返回示例

成功时返回res json对象内容

    res={
        status: true,
        appid:"xxxxxxxxxxxxx"
        code:"xxxxxxxxxxxxxx"
    }

参数说明

参数名 是否必须 描述 类型
status 执行结果是否成功:true=成功、false=失败 boolean
appid 请求者的appid string
code 用来换取用户openid的CODE值 string
1.6.1.3、失败时返回示例

成功时返回res json对象内容

    res = {
        status: false,
        code:200,
        err:"错误信息,错误码200"
    }

参数说明

参数名 是否必须 描述 类型
status 执行结果是否成功:true=成功、false=失败 boolean
err 错误信息 string
code 失败状态码,请注意与成功返回时的code区别 string

1.6.2、获取定位信息

1.6.2.1、 请求示例
 qct.ready(function () {
        qct.getLocation({
            state: 'getLocation发起的标题',
            map: 'baidu',
            success: function (res) {//成功回调函数
                //具体业务逻辑
            },
            fail: function (res) {//失败回调函数
               //具体业务逻辑
            }
        })
 });

参数说明

参数名 是否必须 描述 类型
state app返回时会”原值“带上的参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 string
map 地图坐标类型,默认使用baidu地图默认坐标体系 取值范围 baidu=百度地图,amap=高德地图(暂不支持) string
success 成功回调函数 function
fail 失败回调函数 function
1.6.2.2、成功时返回示例

成功时返回res json对象内容

    res={
        status: true,
        map:"baidu",//地图类型:baidu,amap
        location: {
            lat: 188.000000,
            lng: 24.000000
        },
        formatted_address: "福建省泉州市丰泽区客运中心站",
        country: "中国",
        province: "福建省",
        city: "泉州市",
        district: "丰泽区",
        street: "泉秀街",
        number: "116号"
    }

参数说明

参数名 是否必须 描述 类型
status 执行结果是否成功:true=成功、false=失败 boolean
map 地图坐标类型,默认使用baidu地图默认坐标体系 取值范围 baidu=百度地图,amap=高德地图(暂不支持) string
location 经纬度坐标 object
formatted_address 格式化地址 string
country 国家 string
province 省份 string
city 城市 string
district 乡镇名 string
street 街道名称 string
number 门牌号 string
town 乡镇名 string
1.6.2.3、失败时返回示例

失败时返回res json对象内容

    res = {
            status: false,
            code:200,
            err:"错误信息,错误码200"
           }

参数说明

参数名 是否必须 描述 类型
status 执行结果是否成功:true=成功、false=失败 boolean
err 错误信息 string
code 失败状态码 string

二、原生app应答h5交互请求并携参回调

2.1、交互事件约定,根据需求,逐渐增加

actionType 描述 可取的反回参数
location 获取用户定位信息 lat:纬度,lng:经度,addres:详细地址,……
code 获取用户ID code:一次性code,……

2.2、callNativeWithData:h5获取原生请求,参数是个json对象,里面有必含的通用参数

{
"access_token":"xxxxx", //身份验证token
"action_type":"location"//请求交互事件类型s
}

其中
1. access_token 为前端身份验证token,每次执行需要验证一下用户请求是否合法。
2. action_type 参见2.1

2.3、回调函数格式约定

2.3.1、执行成功回调函数格式

app_call_h5.success(res); 

2.3.2、执行失败回调函数格式

app_call_h5.fail(_res);

原生APP处理交互业务的整体逻辑如下:
* 第一步:获取param参数对象;
* 第二步:判断param.action_type是否存在且被APP所支持;
* 第三步:验证access_token是否存在且合法;
* 第四步:根据param.action_type 参数的值,决定执行哪个交互逻辑
* 第五步:根据执行成功与否,判断调用哪一个回调函数

2.4、iOS实现示例关键代码

2.4.1、注册事件

 WKUserContentController  *userContentController =[[WKUserContentController alloc]init];
    //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
     WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
     [userContentController addScriptMessageHandler:weakScriptMessageDelegate  name:@"callNativeWithData"];];

2.4.2、监听事件

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
    //处理js传过来的参数
    id body = message.body;
    NSDictionary *parameter = nil;
    if ([body isKindOfClass:[NSString class]]) {
        NSData *jsonData = [body dataUsingEncoding:NSUTF8StringEncoding];
        NSError *err;
        parameter = [NSJSONSerialization JSONObjectWithData:jsonData
                                                            options:NSJSONReadingMutableContainers
                                                              error:&err];
    }else if ([body isKindOfClass:[NSDictionary class]]){
        parameter = body;
    }
    if([message.name isEqualToString:@"callNativeWithData"]){
        NSString *action_type = parameter[@"action_type"];
        NSString *access_token = parameter[@"access_token"];
        if ([action_type isEqualToString:@"location"]) {

            //TODO处理对应事件的逻辑

            BOOL state = NO;
            NSString *jsString = nil;
            if (state) {
                //执行成功回调js
                jsString = [NSString stringWithFormat:@"app_call_h5.success({'action_type':'%@','lat':'24','lng':'114','address':'泉州市'})",action_type];
            }else{
                //执行失败回调js
                jsString = [NSString stringWithFormat:@"app_call_h5.fail({'action_type':'%@','lat':'24','lng':'114','address':'泉州市'})",action_type];
            }
            [self.wkWebView evaluateJavaScript:jsString completionHandler:^(id _Nullable i, NSError * _Nullable error) {
                NSLog(@"error: %@ - %@",error,i);
            }];
        }else if ([action_type isEqualToString:@"code"]){
            NSString *jsString = [NSString stringWithFormat:@"app_call_h5.fail({'action_type':'%@','code':'%@'})",action_type,action_type];
            [self.wkWebView evaluateJavaScript:jsString completionHandler:^(id _Nullable i, NSError * _Nullable error) {
                NSLog(@"error: %@ - %@",error,i);
            }];
        }
    }
}

2.5、android实现示例代码

2.5.1、注册事件

    WebSettings mWebSettings = mWebView.getSettings();
    // 设置编码
    mWebSettings.setDefaultTextEncodingName("utf-8");
    //加上这句话才能使用javascript方法
    mWebSettings.setJavaScriptEnabled(true);
    mWebView.setWebChromeClient(new WebChromeClient());
    //添加js接口 有这个才能通信 activity统一标识 js与原生标识要一致,js调用Android
     mWebView.addJavascriptInterface(MainActivity.this,"activity");

2.5.2、监听事件

    /**
     *  @JavascriptInterface注解表面这个方法是给js调用的
     * Js调用原生方法看所在线程是不是在主线程 因为原生只能在主线程(ui线程)更新ui
     * jsonString:json字符串
     */
    @JavascriptInterface
    public void callNativeWithData(String jsonString){
        JSONObject object = JSONObject
                .parseObject(jsonString);
        String action_type = object.getString("action_type");
        String access_token = object.getString("access_token");
        boolean state = false;
        if (action_type.equals("location")){

            //To Do 处理对应事件的逻辑

            String jsString = "";
            if (state){
                //成功回调js
                jsString = "app_call_h5.success" +"({'actionType':'location','lat':'纬度','lng':'经度','address':'地址'})";
            }else {
                //失败回调
                jsString = "app_call_h5.fail" +"({'actionType':'code','code':'200'})";
            }
            final String finalJsString = jsString;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mWebView.evaluateJavascript(finalJsString, new ValueCallback<String>() {
                        @Override
                        public void onReceiveValue(String s) {
                            Log.i("main",s);
                        }
                    });
                }
            });
        }
    }

备注:
1、原生APP在接收参数时建议对参数进行”非空”判断。
2、原生APP回调时的参数格式请参见【1.6.1】和【1.6.2】。

三、开放平台对jsdk的支持

3.1、获取jsdk服务授权码jsdk_access_token

3.1.1、信息结构

https请求方式: GET
https://[SVR_URL]/v1/jsdk_access_token?appid=APPID&secret=APPSECRET&msgid=MSGID
请求参数
参数 类型 是否必须 描述
appid string appid
appsecret string 安全码
msgid string 请求的会话id,用于请求排重,32位随机码
返回参数
参数 类型 是否必须 描述
access_token string 获取到的凭证
expires_in string 凭证有效时间,单位:秒
status string 执行状态:0=执行成功 -1=执行失败

3.1.2、交互流程

3.2、验证jsdk服务授权码jsdk_access_token

3.2.1、信息结构

https请求方式: POST【泉城通后台服务向开放平台发起】
https://[SVR_URL]/v1/verify_jtk?appid=APPID&jsdk_access_token=JSDK_ACCESS_TOKEN&signature=SIGNATURE&nonce=NONCE×tamp=TIMESTAMP
请求参数
参数 类型 是否必须 描述
appid string 服务id
jsdk_access_token string 要验证的token
timestamp string 时间戳
nonce string 随机数
signature string 加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
返回参数
参数 类型 是否必须 描述
verify boolean 验证结果

3.2.2、交互流程

Leave A Reply

电子邮件地址不会被公开。 必填项已用*标注