# 账号说明

字段 释义 描述
merchantId 商户id 商户 id 是您的小程序在数据接入的唯一标识,不区分环境
appId appId 与微信 appId 不同,这是您的品牌在腾讯数据接入的 appId ,也是前端 SDK 的token,区分环境
appSecret appSecret 这是您的品牌在腾讯数据接入的 appsecret ,区分环境;后端 API 需要使用 appId + appSercet 生成 signature ,具体方式见下文

测试环境

  • 后端 API 测试环境 url:https://test.zhls.qq.com/

  • 前端 SDK 测试环境 url:https://zhls.qq.com/

前端SDK url 不区分环境,均为 https://zhls.qq.com/


生产环境

  • 后端 API 生产环境 url:https://zhls.qq.com/

  • 前端 SDK 生产环境 url:https://zhls.qq.com/



# 签名生成方式

# 前端 SDK 上报

使用腾讯数据接入 appId 即可,区分测试和生产环境。

腾讯数据接入 appId 与微信小程序 appId 不同。腾讯数据接入 appId 通常以 bi 开头,微信小程序 appId 通常以 wx 开头。


# 接口上报

以下是签名过程会涉及的参数。

参数 说明
app_id 腾讯数据接入分配的应用ID
app_secret 腾讯数据接入分配的签名密钥,需要绝对保密
timestamp 当前时间戳,单位为秒
nonce 随机字符串标识,不超过32个字符
sign 签名算法,目前只支持 sha256
signature 最终的签名参数

# 计算签名

  1. 随机生成 timestampnonce
  2. 拼接字符串:app_id=&nonce=&sign=×tamp=(key已经按字符串顺序顺次排列,不需要对value进行url encode)
  3. 使用sign算法和app_secret对拼接的字符串进行加密,然后使用hex进行编码,获得签名signature

# 示例

  1. 随机生成:timestamp = "1542951251", nonce = "407313d23c3f7"

  2. 拼接字符串:conStr = "app_id=abc&nonce=407313d23c3f7&sign=sha256&timestamp=1542951251"

  3. 使用秘钥加密生成签名 app_secret="123",

    signature = hex(sha256(conStr)) = "25d5806d0aadc93129879874227c348c33f8e29d70cdcb3094c6909fadb3007b"


# 请求

POST https://zhls.qq.com/api/v1/safe-report?app_id=<app_id>&nonce=<nonce>&timestamp=<timestamp>&sign=<sign>&signature=<signature> 
body <数据内容: JSON Object or JSON Array>

# 请求示例

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Random;

public class ZhlsApiSignature {
    String app_id = "abc";
    String app_secret = "xyz";
    StringBuilder hexStringBuilder = new StringBuilder();

    private ZhlsApiSignature() {}

    /**
     * Init with your key pair.
     * @param app_id
     * @param app_secret
     */
    public ZhlsApiSignature(String app_id, String app_secret) {
        this.app_id = app_id;
        this.app_secret = app_secret;
    }

    /**
     * app_id=${app_id}&nonce=${nonce}&sign=sha256&timestamp=${timestamp}&signature=${signature}
     * @return
     * @throws Exception
     */
    public String sign() throws Exception {
        Random random = new Random(System.currentTimeMillis());
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonce = String.valueOf(Math.abs(random.nextLong()));
        // try the doc example
        // timestamp="1542951251";
        // nonce="407313d23c3f7";
        // ----
        String str = String.format("app_id=%s&nonce=%s&sign=sha256&timestamp=%s", app_id, nonce, timestamp);
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(app_secret.getBytes("UTF-8"), mac.getAlgorithm());
        mac.init(secretKey);
        byte[] bytes = mac.doFinal(str.getBytes("UTF-8"));
        hexStringBuilder.setLength(0);
        for (int i = 0; i < bytes.length; ++i) {
            String hex = Integer.toHexString(0xff & bytes[i]);
            if (hex.length() == 1) {
                hexStringBuilder.append('0');
            }
            hexStringBuilder.append(hex);
        }
        String signature = hexStringBuilder.toString();
        return str + "&signature=" + signature;
    }

//    public static void main(String[] args) throws Exception {
//        System.out.println(new ZhlsApiSignature().sign());
//    }
}
<?php
$app_id = "xyz";
$app_secret = "abc";
$date = strtotime(date('YmdHis'));
$nonce = rand(1000000, 100000000);
$str = "app_id=" . $app_id . "&nonce=" . $nonce . "&sign=sha256&timestamp=" . $date;
$sign = hash_hmac('sha256', $str, $app_secret, false);
echo $sign;
?>
import hmac
import base64
from hashlib import sha256
import random,time

# python3 
# refer doc here: https://mp.zhls.qq.com/youshu-docs/develop/dev_account/dev_account_access.html

#参数赋值方法
app_id='abc'
appsecret='123'
nonce=random.randint(0,90000000)
sign="sha256"
timestamp=(int)(time.time())

# 页面demo的参数计算值过程
conStr = "app_id=abc&nonce=407313d23c3f7&sign=sha256&timestamp=1542951251"
private_key = "123".encode('utf-8')  #  秘钥
data = conStr.encode('utf-8')  #  加密数据
signature  = hmac.new(private_key, data, digestmod=sha256).hexdigest()
print (signature )
# 25d5806d0aadc93129879874227c348c33f8e29d70cdcb3094c6909fadb3007b
const crypto = require('crypto');
const qs = require('qs');

module.exports = {
  sign(appID, appSecret, sign, timestamp, nonce) {
    const conStr = qs.stringify({
      app_id: appID,
      timestamp,
      nonce,
      sign,
    }, {
      sort: (a, b) => a.localeCompare(b),
      encode: false,
    });
    // console.log(conStr)
    const hmac = crypto.createHmac('sha256', appSecret);
    const signature = hmac.update(Buffer.from(conStr, 'utf8')).digest('hex').toLowerCase();
    // console.log(appID, appSecret, sign, timestamp, nonce, signature)
    return signature;
  },
};

如接口使用除 JAVA, PHP,PYTHON 外的开发语言,想获得签名代码样例时,请联系 youshu_helper,我们将尽快为您解决问题。



# 常见FAQ

接口调用时的签名机制,是否需要把请求 body 内容加入到签名串中?

答:不需要,只需文档中的 6 个参数。