交互示例图

API接入规范流程图

通讯方式

通讯方式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
  • 步骤5:使用应用密钥,以SM3WithSM2算法签名上述字符串,得到的结果(Base64编码)即为签名值;
  • 步骤6:以KEYID_TIMESTAMP_NONCE作为用户名,5步中得到的签名值作为密码,在发送请求时,作为HTTP BASIC认证的username和password即可。

响应报文验签规则

本系统支持对响应报文进行签名,并将签名值随同响应报文返回,应用方系统验签规则如下:

  • 步骤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\"}";