Android接入要点说明

基于Activity上下文调用CMBApi

商户APP应基于Activity上下文对CMBApi进行调用,相关要点如下:

1、实现与CMBApi进行交互的Activity,并在AndroidManifest中配置入口,以作为招行APP回调访问的入口

2、创建CMBApi接口对象

3、通过CMBApi接口对象向招行APP发送请求

4、转发招行APP发送的Intent给CMBApi接口对象

5、处理结果响应

在AndroidManifest.xml中配置与CMBApi进行交互的Activity

    <activity
        android:name=""
        android:label="@string/app_name"
        android:exported="true"
        android:launchMode="singleTop">

        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:scheme="sdksample"/>
        </intent-filter>
    </activity>
  

备注:1.android:scheme由招行业务系统与商户之间协商配置
          2.activity请配置为商户自己接受回调的activity

创建CMBApi接口对象

   @Override
    public void onCreate(Bundle savedInstanceState) {
	    …
	    CMBApiFactory.createCMBApi(this, APPID);
	    …
    }
                        

通过CMBApi接口对象向招行APP发送请求

   final CMBRequest request = new CMBRequest();

    request.mRequestData = requestData;
    request.mCMBJumpUrl = jumpUrl;
    request.mH5Url = h5Url;
    request.mMethod = method;

    cmbApi.sendReq(request);
                        

转发招行APP发送的Intent给CMBApi接口对象

商户APP需要在onCreate(), onNewIntent()以及onActivityResult方法里面显式调用handleIntent方法,否则将收不到最终的业务处理结果回调。

1、onCreate()

   @Override
    public void onCreate(Bundle savedInstanceState) {
	    …
	    api.createCMBApi(this, APPID);
	    api.handleIntent(getIntent, this);
	    …
    }
                        

2、onNewIntent()

   @Override
   protected void onNewIntent(Intent intent) {
      super.onNewIntent(intent);
   
      setIntent(intent);
      api.handleIntent(intent, this);
   }
                        

3、onActivityResult()

   @Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      api.handleIntent(data, this);
   }
                        

处理结果响应

商户APP入口Activity应实现CMBEventHandler接口以接收业务结果响应:

    public class CMBApiEntryActivity extends Activity implements
    CMBApi.CMBEventHandler {
        @Override
        public void onResp(CMBResponse resp) {
        if (0 == resp.mRespCode){
            //handle result in resp.mRespMsg
        }
        else {
           //handle errorCode in resp.mRespCode
           //handle error in resp.mRespMsg
        }
    }
                        

常见问题

Q1:scheme如何进行怎么设置?

A:scehme作为应用跳转的标识,推荐设置在当前商户应用的带有<category android:name="android.intent.category.LAUNCHER" />的activity中。商户可以选择配置在其他activity中,具体技术实现可参考网络教程。
参考链接:https://blog.csdn.net/xc765926174/article/details/51397847/

Q2:scheme是否可以设置多个?

A:可以,但不推荐商户这样做。影响:如果同一个应用设置多个相同scheme的话,支付成功返回时,安卓系统会弹框询问想要跳转去哪一个应用,进行一个选择。

Q3:测试招行SDK的app支付时,回调结果没有走回到onReps()方法如何处理?

A:请商户先确定所有机型皆是如此,还是只有特例机型。
特例机型建议查看:1、是否手机安全中心有所限制;2、确定是否是打包时混淆问题,使用非混淆的app进行测试。
所有机型都收不到回调:建议商户自己写一个scheme跳转应用进行测试,看看能否跳转到商户app中。如果自测能够跳转成功,建议联系招行技术支持小组,给出具体的请求报文。

Q4:测试招行SDK的H5支付时,回调结果没有走回到onReps()方法如何处理?

内置H5页面采用intent的方式进行数据回传。请检查onActivityResult中是否添加cmbapi.handleIntent方法,以及此方法中参数是否正确。尤其是data参数,此处传参不能采用getIntent()方法,直接传data即可。

Q5:集成招行支付SDK之后报冲突,报错内容如下,如何进行处理?

Error:Attribute application@allowBackup value=(true) from [:XXX:] AndroidManifest.xml:XXX is also present at [:cmbsdk-release-1.0:] AndroidManifest.xml:XXX value=(false).Suggestion: add 'tools:replace="android:allowBackup"'

A:商户应用manifest中设置allowBackup为false,并且加上tools:replace="android:allowBackup"

Q6:H5支付时如何定制导航栏?

A:考虑到各应用的导航栏会存在个性化需求,接口和页面不支持导航栏展示,如有显示需求,需应用自己开发访问H5页面。实现时需注意如下几点:

1、通过isCMBAPPInstalled判断是否已安装手机银行,已安装场景下通过sendRequest发送请求,未安装场景下才需访问H5页面。
2、需通过Post发送H5请求,body中包含信息见下图。
3、浏览器需注入CMBSDK.callback(respCode, respMessage)回调方法,用于支付结果知会。
4、HTTP请求头中需设置Content-Type为application/x-www-form-urlencoded,举例:[request setValue:@”application/x-www-form-urlencoded” forHTTPHeaderField:@”Content-Type”];

参数名 说明
cmbpbsdk_appid 商户在招商银行业务功能系统中的appid,这里是10位商户号
cmbpbsdk_method 业务功能类型
sdk_deviceType 设备类型(D/E),D: iPhone, E: Android
支付、协议、领券业务功能等请求参数,具体内容由业务功能码给出具体内容。与CMBRequest的requestData一致。

拼接示例如下:
"cmbpbsdk_appid=0025000017& cmbpbsdk_method=pay&sdk_deviceType=D&"+ jsonRequestData
•注:如果是商户自定义实现H5,在H5支付场景下无需通过SDK的回调来识别

1、如果是支付页返回告知,商户通过注入js,在js实现方法中即可获知反馈结果。
2、如果是用户通过导航栏或手势等方式返回,商户可自行侦听这些行为来识别用户取消支付。

iOS具体实现参看如下:(任一方案即可,接入方自行选择)

方案一:WKWebview实现

1、JS注入代码

1.      WKWebView *wkwb = WKWebView.new;
2.	NSString *js = @"window.CMBSDK = window.CMBSDK || {};window.CMBSDK.callback = function(respCode,respMessage){var tmpResult = {};tmpResult.respCode = respCode;tmpResult.respMessage = respMessage;window.webkit.messageHandlers.CMBSDK.postMessage(JSON.stringify(tmpResult));};";
3.	
4.	//document开始时注入
5.	WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
6.	[wkwb.configuration.userContentController addUserScript:wkUScript];
7.	
8.	//CustomerJSHandler是自己创建的类需要实现WKScriptMessageHandler协议
9.	CustomerJSHandler *handler = [[CustomerJSHandler alloc] init];
10.	handler.webView = wkwb;
11.	
12.	[wkwb.configuration.userContentController removeScriptMessageHandlerForName:@"CMBSDK"];
13.	[wkwb.configuration.userContentController addScriptMessageHandler:handler name:@"CMBSDK"];
                        

2、实现CustomerJSHandler,该类需要实现WKScriptMessageHandler协议,并实现以下方法接收JS调用事件

1.  - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
2.	//通过解析 message中的body等信息处理具体接口的转发调用,body为json字符串,格式为{"respCode":"xx","respMessage":"xxxx"}
3.	}
                        

方案二:UIWebview注入实现

1、 增加JS方法映射

1.	#import <JavaScriptCore/JavaScriptCore.h>
2.	
3.	@protocol CMBJSDelegate <JSExport>
4.	
5.	JSExportAs(callback,- (void)call:(NSString *)respCode back:(NSString *)respMessage);
6.	
7.	@end
                        

2、头文件实现CMBJSDelegate协议

   @interface xxxViewController:UIViewController<CMBJSDelegate>
                        

3、页面加载完成后注入JS方法

1.	- (void)webViewDidFinishLoad:(UIWebView *)webView {    
2.	    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
3.	    context[@"CMBSDK"] = self;
4.	    context.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
5.	        context.exception = exceptionValue;
6.	    };
7.	
8.	}
9.	
10.	- (void)call:(NSString *)respCode back:(NSString *)respMessage{
11.	    //根据响应码及内容进行后续逻辑处理
12.	}
                        

android具体实现参看如下:

1、webview注入JS

JS依赖注入,商户需自行定义。注入的交互方法固定为:public int callback(String respCode, String respString)。

以下为参考:

1.	CMBSDKExecutor mCmbSdkExecutor = new CMBSDKExecutor();
        注:CMBSDKExecutor仅供参考。 
2.	mWebView.addJavascriptInterface(mCmbSdkExecutor, "CMBSDK");
                        

2、接收页面回调

Native和JS交互的方法为public int callback(String respCode, String respString)。JS页面在有结果回调时,会回调此native方法,请商户自行在此方法中实现想要实现的功能。比如:关闭当前页面。

@JavascriptInterface

public int callback(String respCode, String respString) {

} 
                        

关于网站迁移公告


为提供更优质的开发技术支持,本网站已于2019年8月12日正式迁移至新域名http://openhome.cmbchina.com/paynew/pay/Home,敬请访问并收藏。原网站域名已停止更新维护,请以新网站提供的文档信息为准。

由此给您带来的不便,敬请谅解。


招商银行一网通支付技术支持小组

2019年8月12日