免密冻结

签订支付协议(已安装招商银行APP)

1. 接口介绍

功能简述:

商户app唤起招行APP的方式来实现免密签约功能,或招行APP内场景商户直接进行APP免密签约。

应用场景:

1、 客户在招行侧未签订免密支付协议,商户需调用该接口为客户签约。
2、 调用该接口成功后,客户即在招行侧签订协议,并成功开通免密支付功能,商户侧收到“支付协议签订成功回调通知”。
3、 客户关闭支付协议的免密功能,可调用该接口重新开通,开通成功后,商户侧收到“支付协议签订成功回调通知”。

调用方式:

目前支持以下三种调用方式:
1、商户客户端集成招行SDK,通过SDK判断客户是否安装招行APP并发起签约。集成SDK方法请参考【SDK接口】,签约字段定义请参考本文档第3节jsonRequestData的参数定义。
2、商户客户端编写代码或采用其他方式,判断客户是否安装招行APP,未安装则参考本文档第2—3节内容进行调用。
3、商户不判断客户是否安装招行APP,仅对接APP免密签约流程,则参考本文档第2—3节内容进行调用。

约束条件:

1、秘钥,商户需通过配置管理,方便后续调整。
2、商户需要判断是否安装招行手机银行APP,已安装采用此方案。

正常流程:

1、商户APP唤起招行手机银行APP,或从招行APP内发起。
2、用户使用一网通登录后,信息校验通过后,正常签约成功。

异常流程:

1、用户信息校验不通过,界面报错,签约停止

2. 请求地址

1)招行App内的商户使用
var url = “http://cmbls/functionjump?action=gofuncid&funcid=0027013&clean=false&cmb_app_trans_parms_start=here&jsonRequestData=“ + encodeURIComponent($(“#jsonRequestData”).val());—-json组织同下方

2)在商户App内使用:
cmbmobilebank://CMBLS/FunctionJump?action=gofuncid&funcid=0027013&requesttype=post&cmb_app_trans_parms_start=here&jsonRequestData={“charset”:”UTF-8”,”sign”:”见签名处理章节”,”reqData”:{“agrNo”:”201606238888888”,”branchNo”:”0755”,”dateTime”:”20160623101430”,”lat”:”30.949505”,”lon”:”50.949506”,”merchantNo”:”123456”,”merchantSerialNo”:”2016062310143088”,”mobile”:”13888888888”,”noticePara”:””,”noticeUrl”:”http://www.xxx.com/xxx","userID":"2016062388888"}}

注意事项:jsonRequestData的值需要做urlEncode。

3. 请求报文

请求报文参数类型(长度)必填描述示例
jsonRequestDataStringMjson格式的请求参数,详见jsonRequestData定义

jsonRequestData参数定义

参数名类型(长度)必填描述示例
charsetString(8)M编码格式,固定为UTF-8(默认)UTF-8
versionString(3)M固定为1.01.0
signStringM使用商户支付密钥对reqData内的数据进行签名
signTypeStringM固定为SHA-256SHA-256
reqData请求数据


dateTimeString(14)M请求时间,商户发起该请求的时间,精确到秒。
格式:yyyyMMddHHmmss
20160623101430
merchantSerialNoString(32)M协议开通请求流水号,商户生成。
同一交易日期唯一,长度不超过32位,数字字母都可以,建议纯数字
2016062310143088
agrNoString(32)M客户协议号,不超过32位的数字字母组合。
未签约(首次支付)客户,填写新协议号,用于协议开通;已签约(再次支付)客户,填写该客户已有的协议号。商户必须对协议号进行管理,确保客户与协议号一一对应。
201606238888888
agrCodeStringO签约产品类型。
P 免密支付签约 
F 免密冻结签约
 该字段可“不送”或送“空”,视为“免密支付签约”
P 或 F
branchNoString(4)M商户分行号,4位数字0755
merchantNoString(6)M商户号,6位数字123456
mobileString(11)O商户用户的手机号13888888888
userIDString(20)O用于标识商户用户的唯一ID。
商户系统内用户唯一标识,不超过20位,数字字母都可以,建议纯数字
123abc
lonString(10)O经度,商户app获取的手机定位数据30.949505
latString(10)O纬度,商户app获取的手机定位数据50.949506
noticeUrlString(100)M商户接收成功签约结果通知的地址http://www.xxx.com/xxx
noticeParaString(256)O成功签约结果通知附加参数,该参数在发送成功签约结果通知时,将原样返回商户。注意:该参数可为空,商户如果需要不止一个参数,可以自行把参数组合、拼装,但组合后的结果不能带有&字符。
returnUrlString(256)O商户签约成功后,从招行APP返回商户APP或者招行站内url:
若返回的是招行小程序,且该页面显示招行APP的topbar,需要使用招行客户端的topbarUI方法设置返回,否则左上角返回存在部分情况下失效。
若返回的是商户APP,请填入商户APP的scheme值。
返回商户APP的例子:weixin:// ;站内url:https:// ;为空则关闭当前窗口
开通用户身份验证或银行卡校验功能时,需上送以下信息:
merchantUserIdTypeStringO商户上送用户的证件类型,若商户端用户未实名,不需要传该字段。
01 身份证 
02 护照 
03 其他
01
merchantUserIdNoStringO商户上送用户的证件编号,需要使用商户秘钥进行AES-256加密(秘钥需32位,不足则右侧补0),若商户端用户未实名,不需要传该字段。生成签名串时,是直接对密文进行签名
merchantUserNameStringO商户上送用户的姓名,需要使用商户秘钥进行AES-256加密(秘钥需32位,不足则右侧补0),若商户端用户未实名,不需要传该字段。生成签名串时,是直接对密文进行签名
merchantCardTypeStringO商户上送用户的银行卡类型,若商户端用户未实名,或不需要限制签约银行卡,则不需要传该字段。
02 本行借记卡
03 本行信用卡
08 他行借记卡
09 他行信用卡
02
merchantCardNoStringO商户上送用户的银行卡号,需要使用商户秘钥进行AES-256加密(秘钥需32位,不足则右侧补0),若商户端用户未实名,或不需要限制签约银行卡,不需要传该字段。(生成签名串时,是直接对密文进行签名)

请求示例:

json报文组织:

 {   
     "charset":"UTF-8",   
     "sign":"见签名处理章节",   
     "reqData":{        
         "agrNo":"201606238888888",        
         "branchNo":"0755",        
         "dateTime":"20160623101430",        
         "lat":"30.949505",        
         "lon":"50.949506",        
         "merchantNo":"123456",        
         "merchantSerialNo":"2016062310143088",        
         "mobile":"13888888888",        
         "noticePara":"",        
         "noticeUrl":"http://www.xxx.com/xxx",        
         "returnUrl":"http://www.xxx.com/yyy",        
         "userID":"2016062388888"        
         }   
 }

待签名字符串(未包含支付密钥):

首先组成待签名字符串。待签名字符串组成规则为:对reqData所有请求参数按从a到z的顺序排列,如果首字母相同,按第二个字母排列,以此类推。排序完成后按将所有键值对以&符号拼接:

param1=value1&param2=value2&……

样例报文:

agrNo=201606238888888&branchNo=0755&dateTime=20160623101430&lat=30.949505&lon=50.949506&merchantNo=123456&merchantSerialNo=2016062310143088&mobile=13888888888&noticePara=&noticeUrl=http://www.xxx.com/xxx&userID=2016062388888

注意:
1、所有reqData中请求参数,即便其值为空,也加入签名字符串
2、签名时,按指定的字符集将字符串转换为字节流
3、根据HTTP协议要求,如果请求参数值中有特殊字符,如&@等,需进行URLEncoding处理。待签名数据为原生值而非encoding后的值。

4. 响应报文

1、网页端直接展示签约成功或失败结果,无响应报文。
2、签约成功后有异步结果通知,失败无通知。详见【支付协议签订成功回调通知

5. 错误码


6. FAQ

参考【签订支付协议(未安装招商银行APP)】 FAQ

7. 商户APP调用招商银行APP签约功能样例

Android平台样例:

Private void callCMBApp() 
{     
    final String url = “cmbmobilebank://CMBLS/FunctionJump?
    action=gofuncid&funcid=0027013&requesttype=post&cmb_app_trans_parms_start=here &……”;     
    try     
    {         
        Intent intent = new Intent();         
        Uri data = Uri.parse(url);         
        intent.setData(data);         
        intent.setAction("android.intent.action.VIEW");         
        startActivity(intent);     
    }     
    catch(Exception e)     
    {         
        Log.d(TAG, "Exception", e);     
    } 
}

iOS平台样例:

(void)callCMBApp {    
    NSURL *url = [NSURL URLWithString: 
    @"cmbmobilebank://CMBLS/FunctionJump?
    action=gofuncid&funcid=0027013&requesttype=post&cmb_app_trans_parms_start=here&..."];    
    
    if (![[UIApplication sharedApplication] canOpenURL:url]) {        
        //没有安装手机银行或没有添加scheme"        
        return;     
    }   
    
    CGFloat systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];    
    if (systemVersion < 10.0f) {        
        BOOL success = [[UIApplication sharedApplication] openURL:url];        
        if (success) {            
            //跳转成功         
            }else {            
            //跳转失败         
            }     
    }else {         
        [[UIApplication sharedApplication] openURL:url                                            
                                           options:@{}                                  
                                 completionHandler:^(BOOL success) {              
             if (success) {                    
                 //跳转成功               
                 }else {                    
                 //跳转失败               
                 }         
         }];     
     } 
}