生成下单参数与签名
收藏
我的收藏

接口说明​

该文档对tt.requestOrder接口中,服务端如何生成data和byteAuthorization参数进行说明​

使用说明​

    开发者按照文档说明构造data,其结果为string类型,且必须符合json格式​
    开发者基于data生成签名,并按文档说明构造byteAuthorization,其结果为string类型​

data​

属性名
类型
默认值
必填
说明
skuList​
SkuList[]​
SkuList说明见下文​
无​
是​
下单商品信息​
注意:目前只支持传入一项​
outOrderNo​
string​
无​
是​
外部订单号​
totalAmount​
number​
无​
是​
订单总金额​
单位:分​
payExpireSeconds​
number​
无​
否​
支付超时时间,单位秒,例如 300 表示 300 秒后过期;不传或传 0 会使用默认值 300,不能超过48小时。
payNotifyUrl​
string​
无​
否​
支付结果通知地址,必须是 HTTPS 类型,传入后该笔订单将通知到此地址。​
注:开发者需先按照接入前准备,配置并发布一个默认回调地址。​
merchantUid​
string​
无​
否​
开发者自定义收款商户号​
orderEntrySchema​
Schema​
Schema说明见下文​
无​
是​
订单详情页​
limitPayWayList​
number[]​
无​
否​
屏蔽的支付方式,当开发者没有进件某个支付渠道,可在下单时屏蔽对应的支付方式。如:[1, 2]表示屏蔽微信和支付宝​
枚举说明:​
1-微信​
2-支付宝​

SkuList​

属性名
类型
默认值
必填
说明
skuId​
string​
无​
是​
外部商品id,如:号卡商品id、会员充值套餐id、某类服务id、付费工具id等​
price​
number​
无​
是​
价格​
单位:分​
quantity​
number​
无​
是​
购买数量​
0 < quantity <= 100 ​
title​
string​
无​
是​
商品标题,长度 <= 256字节​
imageList​
string[]​
无​
是​
商品图片链接,长度 <= 512 字节​
注意:目前只支持传入一项​
type​
number​
无​
是​
商品类型,详见此处的商品类型枚举值
示例:​
    号卡商品:传101​
    剧集: 传404​
tagGroupId​
string​
无​
是​
交易规则标签组​
点此查看对应商品类型的标签组ID​
注意:根据接入规范,选择适合的标签组ID传入,该标签组对应标签将会在用户收银台展示。​
entrySchema​
Schema​
Schema说明见下文​
无​
否​
商品详情页链接​
skuAttr​
Json Object​
无​
否​
号卡类商品必填,即当前商品类型 type in [101、102、103、104、105、106、107]的商品必填,内部结构请详见下文 ”skuAttr“ 小节说明。​
示例:​
JSON
复制
{
"package_cost": //14.50元/2月
{
"amount": 1450,//总价14.50元
"time_len": 2, //时长2
"unit": "month" //时长单位:月
},
"call_duration": 1000, //通话时长:1000分钟
"traffic_bundle": 50,//流量包大小50G
"telecom_operator_type": "official"
}

skuAttr​

号卡类​

属性名
类型
默认值
必填
示例值
说明
package_cost​
Json Object​
无​
是​
JSON
复制
{
"amount": 1450,
"time_len": 2,
"unit": "month"
}
号卡商品套餐详情,具体字段说明详见下文”package_cost字段说明“小结​
call_duration​
number​
无​
否,call_duration与traffic_bundle至少需要填一个​
1000​
套餐包含的通话时长,单位:分钟,​
traffic_bundle​
number​
无​
否​
50​
套餐包含的流量包大小,单位:G​
telecom_operator_type​
string​
无​
是​
official​
提供套餐的运营方性质,枚举值​
official:官方​
private:私营​

package_cost字段说明​

属性名
类型
默认值
必填
示例值
说明
amount​
number​
无​
是​
1450​
套餐售价,单位:分​
time_len​
number​
无​
是​
2​
套餐时长​
unit​
string​
无​
是​
month​
时长单位,枚举值​
year:年​
month:月​
day:天​

Schema:​

名称
类型
是否必传
描述
正确示例
错误示例
path​
string​
是​
小程序xxx详情页跳转路径,没有前导的“/”路径后不可携带query参数,路径中不可携带『?: & *』等特殊字符,路径只可以是『英文字符、数字、_、/ 』等组成,长度<=512byte
page/path/index​
page/path/index?id=1234page/path:hello/index​
params​
string​
否​
xx情页路径参数,自定义的json结构,内部为k-v结构,序列化成字符串存入该字段,平台不限制,但是写入的内容需要能够保证生成访问xx详情的schema能正确跳转到小程序内部的xx详情页,长度须<=512byteparams内key不可重复。​
'{"id":1234, "name":"hello"}'​
{"id":1234,"id":2334,"name":hello}​

结果示例:​

JSON
复制
{"skuList":[{"skuId":"657","price":1,"quantity":1,"title":"test_title","imageList":["https://xxxx.com/xxxxx.jpg"],"type":401,"tagGroupId":"tag_group_7272625659888041996"}],"outOrderNo":"test_out_order_no","totalAmount":1,"payExpireSeconds":300,"orderEntrySchema":{"path":"","params":""},"payNotifyUrl":"https://xxxxx/xxx"}

byteAuthorization​

推荐开发者基于代码示例进行开发​
第一步:构造待签名串
待签名串一共有五行(且必须严格按照以下顺序),每一行必须以 \n(换行符,ASCII 编码值为 0x0A)结束​
Plain Text
复制
POST\n/requestOrder\n请求时间戳\n请求随机串\ndata\n
第二步:计算签名值
使用「应用私钥」对待签名串进行SHA256-RSA2048签名,并对签名结果进行Base64编码得到签名值。​
第三步:生成 byteAuthorization
以下为具体格式:​
Plain Text
复制
SHA256-RSA2048 应用appid,请求随机串nonce_str,请求时间戳timestamp,公钥版本key_version,签名值signature
示例:​
Plain Text
复制
SHA256-RSA2048 appid=tt8629f0941xxxxxxxx,nonce_str=7CC7D26A52F05BA5CFD,timestamp=1698916641,key_version=1,signature=jz1+pplJX2IRcS24lsdsFFOF7+Wky3KiQhOMUz58u7n5VEDNr/axPLzm8+i232Aw4vxjoxavI77n8iUSaGcjHOXS1e4pkdJEHE1qQkQ1bNGsT1X2yXOMB5t8gceGiBJimwQkTSeq+KK/OzYTlCRaNuE784Mx7wtUdXCnBDKZDMxWBxu6R7L2eZ8mC5v67lV+oJcu7tRD10PePRXH1z+9zaX1CSwEg3K0IkLFxHqgrpsER7OeVBE8w9glsxjvuc2Gg==

代码示例

JAVA
GO
PHP
Java
复制
import java.security.PrivateKey;
import java.security.Signature;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.UUID;
public class DYSign {
public static void main(String []args) {
// 请求时间戳
long timestamp = System.currentTimeMillis()/1000L;
// 开发者填入自己的小程序app_id
String appId = "testAppId";
// 随机字符串
String nonceStr = UUID.randomUUID().toString();
// 应用公钥版本,每次重新上传公钥后需要更新,可通过「开发管理-开发设置-密钥设置」处获取
String keyVersion = "1";
// 应用私钥,用于加签 重要:1.测试时请修改为开发者自行生成的私钥;2.请勿将示例密钥用于生产环境;3.建议开发者不要将私钥文本写在代码中
String privateKeyStr = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCZSHNcFfthd/bV\nYexEJWOBVEjjDcXjfr1fYevuraNFfMmLPKV836BbvCiUSWHzJYEpkJ934e/j28NB\nEcEbPDLiGlLTd6AVwR22TkUwpLr41oQprz0HKFwhVPZ0HQCGIv0pVMA53TFSitIq\niqbNLmgm5yzSNqNy1t/0X/RfqEtA6Eoxw9u/Sx57i+pBFuLlZYanlm57+b7t1khg\n9JHvF0ulo7DScyJ4qgrD7oQf0RIQB0rqCFIeYuYO1cfvnxb9x4DPodEyVoAM4i9Y\ndFop9ZHt73W/icuLku/P8/G1+arzB5b7S1S3ky5/KdS8AEA9Ww5czZcdf9Jgm2S6\nRymjFGjzAgMBAAECggEBAIryGNgdePyWcSJmHHR9a+CdFWD0aDBa/7CJpAN8VKc1\ngcB8Xgp+7+6X9jTM/EQa+CVEWrmiDgF/gVPnkyNsAzff4rqcEnoFzzglZSS9/lp4\nod7jYa+uTy1LxgflDkeJSfEASStqrT4EZpR3kNInQfQZ1BBNxQXhb6smm+9mL6kK\nQJjAqBgEqtUAmNv0GnH89ZPPgZuIZeeL4cb4BhMEoa5MBnI+HDf07cN1nECQXRJl\nHU/iyhAPfP7RpO8O9KGDEDE36qebu0Cu4yUjWANXiqECFv93sQzONotkl3VPealv\nXM+jzGT7YdgHo/t3QKE8flMBo/XUzGTqi8j5AOXiaBkCgYEAylKVtjQMYgg4qMwd\n9Je+KZ9qL6QVHCsB2NPUt8N99oj70efsG4aGaEAadr8meNhIJ5lpoK+FXqSBIbbD\nS/xeOVI3XoMx/EdKLw/ZNi87G/EHYK9z7Fr3W7q8DFXe2hZ/ojFXC/aaBanjVVBK\n/6RfPzXfnx+vGX/t1FhcLC+yQD8CgYEAwfMtrXfH+3dW77dxXT/CTFJVs/o1K2qb\nepnQ6A33KMHPLBtPZZ6z5rzIO7OMSNItOTXTEoRXHmOKc5FtXGtbCvGSRByb6FgD\nWG3p2Bp2sZLuJBzXmLbSnEbHTNHM6uTgxNgWAh8pYpjPY8xF7BqYz2rGT47OPBmc\ntRzDjnzjak0CgYAqkM1mk/S2+zvQZ4E14GblouBYPZEjZ/jvgUGTl9F8eL1iIAUQ\nlXDZpgLrULPrYLVtf101rTfF/Z4dVbIo3mOEc8OqYre1d9onpJHyUGWDL2Z59O/S\nniDEb7j4b2h/QZSArxi9L5if8GofnNDqj85qIg92Dthr6PpEXoKl2TMLSQKBgFzQ\nBHHYukiqSV4ZyRQ4qMBhPkYMXFlUgObgqMoDtN06MewHfa1BjxHCEYgQWfeXLLEO\nAt3/mrkeJWk8lLr/XOgVxkr17d34EFHG93rE3zwG9hMuAjZAdvT2IfWvCIL32GAa\nkB2fz+ww+D3nySY9bBcGH7R+wE6eaxF4nFSZizKZAoGBAJzuaWCnVK0djfgvUsjm\nGUtyDvgyREcpAsXvES1pB2NLVeEUxm0uRtj6k4DhCv3rJfUwfMr0+sa9NUnXuaSR\nVqLYvAD8bNPKXwn7ymzQ7WioCqmZuUhLnQRppkjhfQGKLH0MnMw9Xh9FwJ9kzGNE\nUnTEhaaHsoaHMlLlRET32gyG".replace("\n","");
// 生成好的data
String data = "{\"skuList\":[{\"skuId\":\"1\",\"price\":9999,\"quantity\":1,\"title\":\"标题\",\"imageList\":[\"https://dummyimage.com/234x60\"],\"type\":401,\"tagGroupId\":\"idxxx\"}],\"outOrderNo\":\"1213\",\"totalAmount\":9999,\"limitPayWayList\":[],\"payExpireSeconds\":3000,\"orderEntrySchema\":{\"path\":\"page/index/index\",\"params\":\"{\\\"poi\\\":\\\"6601248937917548558\\\",\\\"aweme_useTemplate\\\":1}\"}}";
String byteAuthorization = getByteAuthorization(privateKeyStr, data, appId, nonceStr, timestamp, keyVersion);
System.out.println(byteAuthorization);
}
public static String getByteAuthorization(String privateKeyStr, String data, String appId, String nonceStr, long timestamp, String keyVersion) {
String byteAuthorization = "";
try {
// 生成签名
String signature = getSignature(privateKeyStr, "POST", "/requestOrder", timestamp, nonceStr, data);
// 构造byteAuthorization
StringBuilder sb = new StringBuilder();
sb.append("SHA256-RSA2048 ").
append("appid=").append(appId).append(",").
append("nonce_str=").append(nonceStr).append(",").
append("timestamp=").append(timestamp).append(",").
append("key_version=").append(keyVersion).append(",").
append("signature=").append(signature);
byteAuthorization = sb.toString();
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
return byteAuthorization;
}
public static String getSignature(String privateKeyStr, String method, String uri, long timestamp, String nonce, String data) throws Exception {
String rawStr = method + "\n" +
uri + "\n" +
timestamp + "\n" +
nonce + "\n" +
data + "\n";
System.out.println(rawStr);
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(string2PrivateKey(privateKeyStr));
sign.update(rawStr.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(sign.sign());
}
public static PrivateKey string2PrivateKey(String privateKeyStr) {
PrivateKey prvKey = null;
try {
byte[] privateBytes = Base64.getDecoder().decode(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
prvKey = keyFactory.generatePrivate(keySpec);
} catch (Exception ex) {
ex.printStackTrace();
}
return prvKey;
}
}

密钥生成​

推荐使用签名调试工具
适用于JAVA(PKCS8格式)
非JAVA适用(PKCS1格式)
PowerShell
复制
openssl
genrsa -out private_key.pem 2048
rsa -in private_key.pem -pubout -out public_key.pem
pkcs8 -topk8 -inform PEM -in private_key.pem -outform PEM -nocrypt -out rsa_private_key.pem
rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
exit
// 注:生成出来的私钥文件为rsa_private_key.pem, 公钥文件为rsa_public_key.pem
// PKCS8格式,私钥以-----BEGIN PRIVATE KEY-----开头,-----END PRIVATE KEY-----结尾

应用公钥上传方式

登录「抖音开放平台」,进入小程序的「开发管理-开发设置」页,在「密钥设置」处点击“更新”​