交互示例图
通讯方式
通讯方式 | HTTPS协议 |
请求报文格式 | application/json或application/x-www-form-urlencoded |
响应报文格式 | application/json |
签名验签算法
本系统采用SM3WithSM2算法用于通讯间的签名、验签,以下为一个应用密钥(私钥)的示例:
Q0upIqUatcyfTt97BXLA7LoMOyE/yKb/z3NOksLMbmk=
注意事项:
- 应用密钥请勿与测试环境密钥一致。
- 建议定期更换应用密钥。
- 开发者需要严格保密自己的应用密钥,不能将应用密钥放置在可公开获取的地方,比如客户端中等。由于泄露应用密钥而导致的任何风险,需要开发者自行承担。
- 对于应用密钥,本系统服务器上没有保存副本,开发者若遗失,只能进行重置操作。
请求报文签名规则
开发者发起请求,都需要进行签名,以确保是应用方系统发出的交易指令,签名规则如下:
- 步骤1:将有效的GET或POST参数组成“参数键=参数值”的格式,如amount=100;
- 步骤2:将1步中所有的“参数键=参数值”按参数键以字典序进行排序;
- 步骤3:使用英文半角的&符号将2步中排序后的字符串连接起来,如key1=value1&key2=value2…,注意字符串最后没有符号&
- 步骤4:在字符串前部附加KEYID&TIMESTAMP&NONCE&METHOD&URI格式字符串,其中TIMESTAMP为当前时间,格式如 20160516120000;NONCE为请求随机数,需确保每次请求时不重复,最大长度为32,允许包含数字、大小写英文字母;METHOD为HTTP方法,使用大写,如GET、POST等;URI为当前请求的资源地址,如/api/test/queryOrder(域名之后,?之前)等。拼装后的报文格式类似如下:
KY0123456789012345678900&20160516120000&025e119557284840a52ec6a404123456&POST&/api/test/queryOrder&amount=100
响应报文验签规则
本系统支持对响应报文进行签名,并将签名值随同响应报文返回,应用方系统验签规则如下:
- 步骤1:签名内容为:时间戳+请求随机数+报文内容;
- 步骤2:签名值、时间戳及请求随机数在返回的HTTP Headers中,分别是Signature、Timestamp、Nonce;
- 步骤3:开发者使用应用的响应报文验签公钥,以SM3WithSM2算法对接收的签名值Signature进行验签操作。
待验签bytes内容为时间戳bytes+随机数bytes+响应报文bodyBytes
报文加解密算法
请求字段加密
本系统支持敏感字段数据加密功能:涉及敏感数据字段的接口,需要在应用方本地加密后,将密文传输给开放银行平台。
- 加密内容为敏感字段数据明文;
- 加密算法为:SM4,密码器类型为:SM4/CBC/PKCS5Padding(算法/模式/补码方式),初始向量全部为0。
完整参数示例(Java)
请求报文格式为application/x-www-form-urlencoded
开发者根据请求资源,准备不同的参数集合。根据接口不同,可能包括HEADER请求参数、GET请求参数、POST请求参数三种参数,具体请求参数示例如下图(嵌套类参数请按照示例中格式进行传输)。
Map urlParams = new HashMap();
urlParams .put("stringParam", "Hello World");
Map headParams = new HashMap();
headParams .put("stringParam", "Hello World");
Map bodyParams = new HashMap();
bodyParams.put("stringParam", "Hello World");
bodyParams.put("intParam", "111");
bodyParams.put("byteParam", "1");
bodyParams.put("shortParam", "1111");
bodyParams.put("longParam", "111111111");
bodyParams.put("floatParam", "111.111");
bodyParams.put("doubleParam", "111.111111");
bodyParams.put("boolParam", "false");
bodyParams.put("charParam", "A");
//嵌套实体
bodyParams.put("mockBean.intParam", "111");
//嵌套实体
bodyParams.put("mockBean.stringParam", "ascb");
//List类型(String)
bodyParams.put("stringList[0]", "stringList0");
//List类型(String)
bodyParams.put("stringList[1]", "stringList1");
//嵌套Map包含实体
bodyParams.put("mockBeanMap[0].intParam", "111");
//嵌套Map包含实体
bodyParams.put("mockBeanMap[0].doubleParam", "111.111");
//嵌套Map包含实体
bodyParams.put("mockBeanMap[0].stringParam", "AAAAA");
//嵌套Map包含实体
bodyParams.put("mockBeanMap[1].intParam", "222");
//嵌套Map包含实体
bodyParams.put("mockBeanMap[1].doubleParam", "222.222");
//嵌套Map包含实体
bodyParams.put("mockBeanMap[1].stringParam", "BBBBB");
//嵌套List包含实体
bodyParams.put("mockBeanList[0].intParam", "111");
//嵌套List包含实体
bodyParams.put("mockBeanList[0].doubleParam", "111.111");
//嵌套List包含实体
bodyParams.put("mockBeanList[0].stringParam", "group1/M00/97/68/CmAFGVpd3CGARE***O1Nr3I123.txt");
//嵌套List包含实体
bodyParams.put("mockBeanList[1].intParam", "222");
//嵌套List包含实体
bodyParams.put("mockBeanList[1].doubleParam", "222.222");
//嵌套List包含实体
bodyParams.put("mockBeanList[1].stringParam", "group2/M00/97/68/CmAFGVpd3CGAREP***O1Nr3I123.txt");
请求报文格式为application/json
String bodyjson = "{\"testString1\":\"test\",\"testString2\":\"test\"}";