### 1.筛选
将所有请求参数组合为一个集合,包括公共请求参数(消息通知无此项)和业务参数,但***不包括sign参数和值为NUll参数***
### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#2%E5%BA%8F%E5%88%97%E5%8C%96%E5%8F%82%E6%95%B0%E5%B9%B6%E6%8B%BC%E6%8E%A5)2.序列化参数并拼接
将筛选后的集合序列化为JSON格式,并保证***所有层级的Key***按照ASCII码递增排序(字母升序排序),将序列化后参数使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串,在字符串最后拼接`&appSecret=`应用的秘钥
### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#3%E7%AD%BE%E5%90%8D)3.签名
使用MD5算法对拼接后的字符串采用"UTF-8"格式生成文件摘要,并转为16进制字符串,把生成的字符串转为大写赋值给公共的请求参数`sign`
### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#4%E7%A4%BA%E4%BE%8B)4.示例
#### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#41-%E6%8F%90%E4%BA%A4%E8%AE%A2%E5%8D%95%E9%A2%84%E4%B8%8B%E5%8D%95)4.1 提交订单(预下单)
* 接口名:dby.scm.order.submit
* 版本号:v1
* 请求方式:POST
* 请求数据类型: application/json
* 业务请求参数:
~~~json
{
"orderRemark":"测试下单",
"consigneeAddress":"安腾国际",
"consigneeMobile":"15900000000",
"consigneeName":"张三",
"consigneeProvinceCode":"42",
"consigneeTownCode":"420106010",
"consigneeCountyCode":"420106",
"consigneeCityCode":"4201",
"skuInfos":[
//嵌套的key也需要排序
{
"unitPrice":8000,
"skuNum":1,
"skuCode":"50180878441"
}],
"tradeNo":"1598510632214159360"
}
~~~
#### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#42-%E5%85%AC%E5%85%B1query%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0)4.2 公共Query请求参数
~~~
method=dby.scm.order.submit
appKey=7knzxd30ob
version=v1
timestamp=1669949608466
sign=
~~~
#### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#43-%E6%8E%92%E5%BA%8F%E5%90%8E%E7%9A%84%E5%8F%82%E6%95%B0)4.3 排序后的参数
~~~json
{
"appKey":"7knzxd30ob",
"consigneeAddress":"安腾国际",
"consigneeCityCode":"4201",
"consigneeCountyCode":"420106",
"consigneeMobile":"15900000000",
"consigneeName":"张三",
"consigneeProvinceCode":"42",
"consigneeTownCode":"420106010",
"method":"dby.scm.order.submit",
"orderRemark":"测试下单",
"skuInfos":[
{
"skuCode":"50180878441",
"skuNum":1,
"unitPrice":8000
}
],
"timestamp":1669949608466,
"tradeNo":"1598510632214159360",
"version":"v1"
}
~~~
#### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#44-%E6%8B%BC%E6%8E%A5%E4%B8%BA%E5%BE%85%E7%AD%BE%E5%90%8D%E5%AD%97%E7%AC%A6%E4%B8%B2)4.4 拼接为待签名字符串
~~~
appKey=7knzxd30ob&consigneeAddress=安腾国际&consigneeCityCode=4201&consigneeCountyCode=420106&consigneeMobile=15900000000&consigneeName=张三&consigneeProvinceCode=42&consigneeTownCode=420106010&method=dby.scm.order.submit&orderRemark=测试下单&skuInfos=[{"skuCode":"50180878441","skuNum":1,"unitPrice":8000}]×tamp=1669949608466&tradeNo=1598510632214159360&version=v1&appSecret=2077wuuyh88gfzf2vpv2s2gf1cqkkuro
~~~
#### 4.5 对待签名字符串进行md5签名后转换为16进制字符串并转为大写,赋值给公共Query参数`sign`,最终的请求为
~~~
curl -XPOST -H "Content-type: application/json" -d '{
"consigneeAddress":"安腾国际",
"consigneeCityCode":"4201",
"consigneeCountyCode":"420106",
"consigneeMobile":"15900000000",
"consigneeName":"张三",
"consigneeProvinceCode":"42",
"consigneeTownCode":"420106010",
"orderRemark":"测试下单",
"skuInfos":[
{
"skuCode":"50180878441",
"skuNum":1,
"unitPrice":8000
}
],
"tradeNo":"1598523628516773888"
}' 'http://127.0.0.1/open/api?method=dby.scm.order.submit&appKey=7knzxd30ob&version=v1×tamp=1669952706993&sign=7D2F11F449D7160D1684968A029583A6'
~~~
### [](https://duobaoyu.com.cn/documentcenter?onlyFlag=414ce68bebb334fe46d941321863e22b#5-%E7%AD%BE%E5%90%8D%E5%8F%82%E8%80%83)5\. 签名参考
Java
~~~json
public class SignUtil {
/**
* 签名参考
*
* @param appKey 商户应用appKey
* @param method 接口方法名称
* @param timestamp 13位格式时间戳,5分钟误差内
* @param version 版本号,现在固定为v1
* @param appSecret 商户应用appSecret
* @param bizParam 业务参数,具体参数请查看接口对接文档
* @return 签名字符串
*/
public static String sign(String appKey, String method, Long timestamp, String version, String appSecret, Object bizParam) {
//参数排序
SortedMap signParam = new TreeMap<>();
//添加通用参数
signParam.put("appKey", appKey);
signParam.put("method", method);
signParam.put("timestamp", timestamp);
signParam.put("version", version);
//添加业务参数
if (ObjectUtil.isNotNull(bizParam)) {
//对参数进行排序(a-z)
//所有的层级都需要排序
String jsonStr = JSONObject.toJSONString(bizParam, SerializerFeature.MapSortField);
JSONObject bizJson = JSONObject.parseObject(jsonStr, Feature.OrderedField);
signParam.putAll(bizJson);
}
StringBuilder strBuilder = new StringBuilder();
boolean isFirst = true;
for (Map.Entry entry : signParam.entrySet()) {
//排除值为NULL的参数
if (entry.getKey() != null && entry.getValue() != null) {
if (isFirst) {
isFirst = false;
} else {
strBuilder.append("&");
}
//拼接字符串
strBuilder.append(Convert.toStr(entry.getKey())).append("=").append(Convert.toStr(entry.getValue()));
}
}
//末尾拼接appSecret
strBuilder.append("&appSecret=" + appSecret);
//生成待签名字符串
String signStr = strBuilder.toString();
//使用Md5算法生成摘要并转为16进制字符串
return new Digester(DigestAlgorithm.MD5).digestHex(signStr, CharsetUtil.UTF_8).toUpperCase();
}
}
~~~
PHP
~~~json
<?php
/**
* 签名参考
*
* @param string appKey 商户应用appKey
* @param string method 接口方法名称
* @param string timestamp 13位格式时间戳,5分钟误差内
* @param string version 版本号,现在固定为v1
* @param string appSecret 商户应用appSecret
* @param array bizParam 业务参数,具体参数请查看接口对接文档
* @return 签名字符串
*/
function sign($appKey, $method, $timestamp, $version, $appSecret, array $bizParam)
{
//添加通用参数
$commonParam = array();
$commonParam[‘appKey’] = $appKey;
$commonParam[‘method’] = $method;
$commonParam[‘timestamp’] = $timestamp;
$commonParam[‘version’] = $version;
//合并通用参数和业务参数数组
$paramArr = array_merge($commonParam, bizParam);
//对所有层级参数递归排序(a-z)
recursion_ksort(paramArr);
//将参数按序拼接成字符串
$spliceStr = ‘&’;
foreach ($paramArr as $key => $value) {
if (!is_null($value)) {
$spliceStr .= ‘&’ . $key . ‘=’ . (is_array($value) ? json_encode($value, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : $value);
}
}
$spliceStr = trim($spliceStr, ‘&’) . ‘&appSecret=’ . $appSecret;
//生成待签名字符串,md5签名并转大写
$sign = strtoupper(md5($spliceStr));
return $sign;
}
/**
* 关联数组递归排序
* @param array $arr
* @param bool $removeNull
* @return void
*/
function recursion_ksort(array &$arr,$removeNull = true)
{
$kstring = true;
foreach ($arr as $k => &$v) {
if (!is_string($k)) {
$kstring = false;
}
if(is_null($v) && $removeNull){
unset($arr[$k]);
}
if (is_array($v)) {
recursion_ksort($v,$removeNull);
}
}
if ($kstring) {
ksort($arr);
}
}
~~~
- 产品介绍
- 开发指南
- 实物商品对接流程
- 签名规则
- JAVA SDK使用
- PHP SDK使用
- 商品消息对接流程
- 虚拟商品对接流程
- 电影H5对接流程
- 卡密信息解密规范
- 错误码查询
- 商品API文档
- 商品
- 查询商品SPU详情
- 查询商品SPU深度分页
- 查询商品可售性
- 手机号所属运营商查询
- 查询商品详情
- 查询商户商品上下架状态
- 查询商品最小起订量
- 查询商品价格
- 根据SKU查询商品SPU详情
- 查询商品分类逐级获取
- 查询商品分类分页获取
- 订单
- 运费评估
- 确认收货
- 查询订单物流信息
- 查询订单详情
- 取消订单
- 确认下单
- 实物商品预下单
- 虚拟商品预下单
- 售后
- 查询售后退款详情
- 查询售后订单详情
- 取消售后申请
- 确认售后完成
- 提交运单信息
- 查询售后支持的物流
- 查询客户寄回地址
- 创建退款退货申请
- 上传商品售后凭证
- 批量查询商品售后权益
- 地址
- 详细地址转换成供应链地址编码
- 省市区街道4级地址查询
- 消息
- 消息通知
- 账户
- 查询商户账户信息
- 电影API文档
- 电影H5
- 电影H5首页免登录
- 设置商户价格策略
- 设置商户货币兑换比例
- H5电影订单详情
- H5电影订单确认
- H5电影订单列表
- 电影消息
- 电影消息通知