一、调用介绍
到家通过HTTP协议POST方式调用商家消息接收接口,实时为商家推送通知消息。推荐商家在接收到消息且进行基础校验后,后续逻辑采用异步方式处理。商家提供的消息接收接口性能要求: TP99 <200ms, TPS>1000, 最长响应时间超时阀值为3s。
由于网络原因、接口响应超时或要求业务重试(code返回-10000),平台会自动重新推送消息:重试最大有效期为4小时,每次重试间隔最大为5分钟,4小时内间隔性重试,要求接口具备消息排重能力。
到家通过HTTP协议POST方式调用商家消息接收接口,实时为商家推送通知消息。推荐商家在接收到消息且进行基础校验后,后续逻辑采用异步方式处理。商家提供的消息接收接口性能要求: TP99 <200ms, TPS>1000, 最长响应时间超时阀值为3s。
由于网络原因、接口响应超时或要求业务重试(code返回-10000),平台会自动重新推送消息:重试最大有效期为4小时,每次重试间隔最大为5分钟,4小时内间隔性重试,要求接口具备消息排重能力。
环境入口释义:推送消息时,需要调用商家侧开发的消息接收接口,接收相应订单状态下的数据,接口命名规则如下:
http调用入口地址:http://xxx.xxx.xxx/xxx/djsw/接口名,(其中红色部分商家自定义)。
商家侧开发消息接收接口,须严格按照开放平台签名规则开发,以下签名示例,仅供参考。
调用API时,必须传入系统级参数和对应的应用级参数。各个API的输入参数和返回结果详见API文档。
①系统级参数
字段 |
类型 |
是否必须 |
描述 |
token |
String |
是 |
采用OAuth授权方式为必填参数。 |
app_key |
String |
是 |
应用的app_key |
sign |
String |
是 |
签名 |
timestamp |
String |
是 |
时间戳,格式为yyyy-MM-dd HH:mm:ss,例如:2011-06-16 13:23:30。 |
format |
String |
是 |
暂时只支持json |
v |
String |
是 |
API协议版本,可选值:1.0. |
②如下为应用级参数拼装(拼装示例 ,仅供参考)
字段 |
描述 |
|
示例值 |
jd_param_json |
String |
标准json 类型 |
{ |
encrypt_jd_param_json |
String |
密文字符串 |
vADmYTpJtnUjzVWBTnGB9BubRu9CsgO41oBBFC3yhKWFOd5x1/lh5vpOtWHnO2JRoIr6pvFklvdGuAYwyo54Y |
调用API时需要对请求参数进行签名,服务器端会验证请求参数是否合法。
加密规则
①
所有请求参数按照字母先后顺序排列
例如:将token,app_key,timestamp,format,v
排序为app_key,format,timestamp,token,v
② 把所有参数名和参数值进行拼装
例如:app_keyxxxformatxxxxtimestampxxxxxxtokenxxxvx
③
把appSecret夹在字符串的两端
例如:appSecret+XXXX+appSecret
④ 使用MD5进行加密,再转化成大写
示例(以下示例只体现逻辑)
调用http://xxxx.xxx.xxx/xxx/djsw/接口名
,假设app_key=yourappkey、appSecret=yourappSecret、token=yourtoken
1) 输入参数
token=yourtoken
app_key=yourappkey
timestamp=2015-10-16
13:23:30
format=json
v=1.0
jd_param_json=
{
"billId":"10003129",
"statusId":"33060",
"timestamp":
"2015-10-16 13:23:30",
}
2) 把参数按照字母顺序排列
app_key=yourappkey
format=json
jd_param_json=
{
"billId":"10003129",
"statusId":"33060",
"timestamp":
"2015-10-16 13:23:30",
}
timestamp=2016-07-20 11:10:04
token=yourtoken
v=1.0
3) 连接参数名与参数值,并在首尾加上appSecret
3) 对于加密的消息,jd_param_json没有值的情况下,一定要将encrypt_jd_param_json字段中的值解密,然后赋到jd_param_json字段中,然后根据以上规则参与签名,encrypt_jd_param_json本身并不直接参与签名
授权接口:(示例)
yourappSecretapp_keyyourappkeyformatjsonjd_param_json{"billId":"10003129","statusId":"33060","timestamp":"2015-10-16 13:23:30"
}timestamp2016-07-20 11:10:04tokenyourtokenv1.0yourappSecret
注:
①以上字符串不允许有跨行,粘贴时请特别注意,除日期和时间中间的空格之外,不允许在其它位置出现空格。
4) MD5加密后转成大写:EDBE87FB9640EDD681FEBC79D858AAC0
注:
①以上字符串不允许有跨行,粘贴时请特别注意,除日期和时间中间的空格之外,不允许在其它位置出现空格。
②反向签名验证时,在接收到的jd_param_json值,当成普通字符串,不要解析成array,然后直接参与签名运算
1、加密算法采取AES(AES/CBC/NoPadding,即AES-128-CBC加密的NoPadding模式)算法。通知参数增加新字段encrypt_jd_param_json,此字段是对原字段jd_param_json的整体加密,加密的接口在API文档列表上会打上密标密
2、数据解析规则:
1)、对于无需加密的消息,数据内容不变
2)、对于需要加密的消息,明文密文并行期,两个字段jd_param_json(明文),encrypt_jd_param_json(密文)均有值
3)、并行期过后,仅encrypt_jd_param_json(密文)有值
4)、具体处理逻辑(参考):
所有消息,优先判断密文字段encrypt_jd_param_json内容是否为空,
如果为空,仍然解析明文字段jd_param_json中的业务数据
如果不为空的,获取密文字段encrypt_jd_param_json内容并解密,解密后获取业务数据(解密后的数据等效于明文字段jd_param_json中的数据)
一定不要将需要解密的消息限制到一个固定范围,只针对现有加密接口进行解密。请参考以上逻辑,一旦有非加密接口变成加密接口时,仍然能够正常解析
在消息仅发送密文的情况下,jd_param_json的值为空,此时请注意签名问题,签名规则不变,所以需要将解密后的内容放到jd_param_json下,来参与签名,encrypt_jd_param_json字段并不直接参与签名运算
5)、AES算法需要的key和偏移量采用appSecret的前16位和后16位
以java版SDK为例,使用方法
String key = appSecret.substring(0, 16);
String iv = appSecret.substring(16, 32);
String json = AESUtils.decryptAES(encrypt_jd_param_json, key, iv);
3、参考示例(可用于验证算法):
密文:8FvHJcQmVojAIU61SNaS1ermHN2UVWknueRHFSNf2q5EbxNNmznoTYpRu7ySc/8CuU+QGZ9UIBMCyTuFafY3PuszEokEKc8M1Qfv/+o15h5bIU8LXfwRKOCm3JYzZtTOvJVU0hk/USvtDgraToszFl2hQZjZN5gGH1af0X8vopo=
key:0bcbe9d6e6124cf2
iv:aef2856a540f1326
对应明文:{"billId":"232219501234567","outBillId":"12345678901","statusId":"150","storeId":"11912345","timestamp":"2022-08-14 17:24:44"}
4、具体示例代码(JAVA):
import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * @Classname AESUtils */ public class AESUtils { /** * @Description AES算法加密明文,加密用的Key 可以用26个字母和数字组成 使用AES-128-CBC加密模式,key需要为16位。 * key 密钥,长度16 * iv 偏移量,长度16 * @param data 明文 * @return 密文 */ public static String encryptAES(String data,String key,String iv) throws Exception { try { Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); int blockSize = cipher.getBlockSize(); byte[] dataBytes = data.getBytes(); int plaintextLength = dataBytes.length; if (plaintextLength % blockSize != 0) { plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize)); } byte[] plaintext = new byte[plaintextLength]; System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length); SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); // CBC模式,需要一个向量iv,可增加加密算法的强度 cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); byte[] encrypted = cipher.doFinal(plaintext); return AESUtils.encode(encrypted).trim(); // BASE64做转码。 } catch (Exception e) { e.printStackTrace(); return null; } } /** * @Description AES算法解密密文 * @param data 密文 * @return 明文 */ public static String decryptAES(String data,String key,String iv) throws Exception { try { byte[] encrypted1 = AESUtils.decode(data);//先用base64解密 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original); return originalString.trim(); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 编码 * @param byteArray * @return */ public static String encode(byte[] byteArray) { return new String(new Base64().encode(byteArray)); } /** * 解码 * @param base64EncodedString * @return */ public static byte[] decode(String base64EncodedString) { return new Base64().decode(base64EncodedString); } }
• 所有的API请求和响应数据编码皆为UTF-8格式(切勿转成unicode编码),仅支持Post表单请求(Content-Type是application/x-www-form-urlencoded),请求里的所有参数值在发送请求时会URLEncoder,接收请求时需做URLDecoder处理。
• API请求的应用级参数需要转换成json格式,例如:jd_param_json={"return_id":"20032","trade_no":"20032"}
• json格式应为标准的json
• 目前接口返回结果格式只支持json格式,具体格式示例:{"code":"0","msg":"success","data":""}
• 所有API请求和响应内的日期格式都为yyyy-MM-dd HH:mm:ss,注意小时格式是24小时制,例如:2011-07-21 20:23:30
• 签名方式为 md5(appsecret + key+ value .... key + value+appsecret)然后转大写字母,其中key、value对是除签名所有请求参数按key做的升序排列,value无需编码。
错误码 | 描述 |
0 | 操作成功 |
-1 | 操作失败 |
-10000 | 业务重试 |
10005 | 必填项参数未填 |
10013 | 无效Token令牌 |
10014 | 无效Sign签名 |
10015 | API参数异常 |
10018 | 不存在的方法名 |