HomeDocs
跳到主要内容

动态素材更新

简单来说:将需要更新的内容表单,和需要的入参,推送到小程序开放平台的指定接口。我们会在负一屏请求开放平台的时候,提供相应的更新内容。

一、环境选择

环境选择访问前缀备注
生产环境https://api.dlight-app.com/miniapp/launchplatformdeveloper/openapi
印度环境https://api-ind.dlight-app.com/miniapp/launchplatformdeveloper/openapi如果需要推送给印度服务,需要调用该域名

二、接入方案

1. 接入前准备

第三方线下申请接入小程序卡片后,小程序会注册卡片更新表单,然后第三方获取卡片对应的更新表单 id(bizId),密钥,以及可以更新的 keys
第三方可以选择同步或者异步获取返回信息,
同步:直接调用写入接口等到返回
异步:第三方提供回调接口,详情见 3.6 章

2. OpenApi 接口

2.1 写入接口

请求 URL:/cardform/cmd/sendCardForm
请求方式:post
请求 Header 参数

参数名称参数类型是否必要参数描述
Accept-TimezoneString时区

OpenApi 字段

参数数据类型说明必须参数来源示例
dataCardFormInfoRequestDTO素材更新参数true开发者见 CardFormInfoRequestDTO 参数
bizIdString卡片表单 idtrue咨询小程序产运团队1000675095676309504
miniappIdString卡片对应的小程序 idtrue咨询小程序产运团队3000317415459377152
operatorIdString操作人 idfalse咨询小程序产运团队qewrqewrq-qweqwrqw
signString签名字段true开发者FA8762C9BB9BE1B162D0386F1AB3
timeStampString时间戳false开发者1690180572312
requestIdString请求 idtrue开发者qqrea

CardFormInfoRequestDTO 参数

参数数据类型说明必须参数来源示例
textString(json)表单信息(注:如果是 deeplink 参数,需要按照 clickUrl 规则 强校验,否则不予通过)true开发者{\"title\":\"logo\",
\"name\":\name\"}
cardFormReceiverInfoCardFormReceiverInfoDTO表单信息得接收人true开发者见 CardFormReceiverInfoDTO 参数

CardFormReceiverInfoDTO 参数

参数数据类型说明必须参数来源示例
uniqueIdsList<String>uniqueId 数组,(一次性最多传 50 个),且该字段不为空时,不处理标签信息false获取方式dlt.getUniqueId["003c92f3245bddbe736eefd66a7b
55c3b9cb04f446c4d3a13b1ec0dc4ae99"]
keywordString关键字:如果卡片时全搜场景,不能为空false咨询小程序产运团队phone
labelsList<LabelDTO>接收人得标签数组false咨询小程序产运团队见 LabelDTO 参数

LabelDTO 参数

参数数据类型说明必须参数来源示例
labelNameString标签名称false咨询小程序产运团队country
labelValueString标签值false咨询小程序产运团队406

2.2 查询接口

2.2.1 与客户端接口区别

涉及标签时
客户端:若素材的某个标签为空,客户端该标签传入任何值都匹配
该接口:查询传入的标签值必须与素材的标签值完全匹配
请求 URL:/cardform/cmd/getCardForm
请求方式:post
请求 Header 参数:

参数名称参数类型是否必要参数描述
Accept-TimezoneString时区

2.3 OpenApi 字段

参数数据类型说明必须参数来源示例
dataGetCardFormReceiverInfoDTO素材查询参数false开发者见 GetCardFormReceiverInfoDTO 参数
bizIdString卡片表单 idtrue咨询小程序产运团队1000675095676309504
miniappIdString卡片对应的小程序 idtrue咨询小程序产运团队3000317415459377152
operatorIdString操作人 id,第三方自行定义false开发者11
signString签名字段true开发者FA8762C9BB9BE1B162D0386F1AB3BFE
D72A6255E985379B017D68DB4080D5
timeStampString时间戳false开发者1690180572312
requestIdString请求 idtrue开发者qqrea

GetCardFormReceiverInfoDTO 参数

参数数据类型说明必须参数来源示例
uniqueIdStringuniqueIdfalse开发者更新时传入003c92f3245bddbe736eefd66a7b
55c3b9cb04f446c4d3a13b1ec0dc4ae99
keywordString关键字false开发者更新时传入Phone
labelsLabelDTO标签false开发者更新时传入见 LabelDTO 参数

LabelDTO 参数

参数数据类型说明必须参数来源示例
labelNameString标签名称false咨询小程序产运团队country
labelValueString标签值false咨询小程序产运团队406

3. OpenApi 签名

3.1 报文签名说明

使用 RSA 来验证数据传输过程中的数据真实性和完整性,需要对数据进行数字签名,在接收签名数据之后进行签名校验。 要求对整段报文做签名值,然后赋值给 sign(签名值)字段,签名时只对 data 一个字段进行签名

3.2 签名方式

使用的签名算法为 SHA256withRSA,返回报文先验签再反序列化为对象

3.3 签名报文组装

将请求报文中 data 字段值按照名称的 ASCII 码从小到大进行排序以&连接,如果名称的首字母相同,则比较第二个字母,以此类推拼接成 key=value&key=value 的字符串,然后进行签名,并且赋值给 sign。

3.4 签名数据示例


@Slf4j
public class EncryptSha256Util {
private EncryptSha256Util() {
throw new IllegalStateException("EncryptSha256Util class");
}

/**
* sha256加密
*
* @param str 要加密的字符串
* @return 加密后的字符串
*/
public static String getSha256Str(String str) {
MessageDigest messageDigest;
String encodeStr = "";
try {
messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
encodeStr = byte2Hex(messageDigest.digest());
} catch (NoSuchAlgorithmException e) {
log.error("进行sha256加密失败!massage:{}", e.getMessage());
}
return encodeStr;
}

/**
* sha256加密 将byte转为16进制
*
* @param bytes 字节码
* @return 加密后的字符串
*/
private static String byte2Hex(byte[] bytes) {
StringBuilder stringBuilder = new StringBuilder();
String tempStr;
for (byte aByte : bytes) {
tempStr = Integer.toHexString(aByte & 0xFF);
if (tempStr.length() == 1) {
//得到第一位的进行补0操作
stringBuilder.append("0");
}
stringBuilder.append(tempStr);
}
return stringBuilder.toString();
}

public static void main(String[] args) {
getCardFormParm();
SetCardFormParm();
}

//查询接口参数
private static void getCardFormParm() {
CardRequestDTO<GetCardFormReceiverInfoDTO>res = new CardRequestDTO<>();
String timeStamp = System.currentTimeMillis()+"";
String secretAccessKey = "你的 AccessKeySecret";
String miniappId = "1000083312531542016";
String bizId = "101691407379048";
String requestId = "fdsagfsdgfsdagsdg";
String operatorId = "11";
GetCardFormReceiverInfoDTO dto = new GetCardFormReceiverInfoDTO();
dto.setUniqueId("04820f410572fee703273addc166a41aeead24de447d8abd8e08eacd44e3d901");
dto.setKeyword("iphone");
List<LabelDTO> labels = new ArrayList<>();
LabelDTO dto1 = new LabelDTO();
dto1.setLabelName("country");
dto1.setLabelValue("406");
LabelDTO dto2 = new LabelDTO();
dto2.setLabelName("brand");
dto2.setLabelValue("cy");
LabelDTO dto3 = new LabelDTO();
dto3.setLabelName("model");
dto3.setLabelValue("acth");

LabelDTO dto4 = new LabelDTO();
dto4.setLabelName("model111");
dto4.setLabelValue("mode");
labels.add(dto1);
labels.add(dto2);
labels.add(dto3);
labels.add(dto4);
dto.setLabels(labels);
String requestStr = "requestId=" + requestId + "&bizId=" + bizId +"&miniappId=" + miniappId + "&operatorId=" + operatorId + "&data=" + JSONObject.toJSONString(dto) + "&timeStamp=" + timeStamp;

String secretAccessKeySign = "&secretAccessKey=" + secretAccessKey;
requestStr = requestStr + secretAccessKeySign;
String sign = EncryptSha256Util.getSha256Str(requestStr).toUpperCase();
res.setData(dto);
res.setBizId(bizId);
res.setRequestId(requestId);
res.setMiniappId(miniappId);
res.setOperatorId(operatorId);
res.setTimeStamp(timeStamp);
res.setSign(sign);
System.out.println(JSONObject.toJSONString(res));
}

//更新接口参数
private static void SetCardFormParm() {
CardRequestDTO<CardFormInfoRequestDTO>res = new CardRequestDTO<>();

String timeStamp = System.currentTimeMillis()+"";
String secretAccessKey = "你的 AccessKeySecret";
String miniappId = "1000083312531542016";
String bizId = "101691407379048";
String requestId = "fdsagfsdgfsdagsdg";
String operatorId = "11";
CardFormInfoRequestDTO dto = new CardFormInfoRequestDTO();
JSONObject textJson = new JSONObject();
textJson.put("imageUrl", "title_uniqueid_555_gaid");
textJson.put("ClickUrl", "https://app-oss.byte-app.com/demoapp/Sryb8HnKqK.jpg");
dto.setText(textJson.toJSONString());
CardFormReceiverInfoDTO info = new CardFormReceiverInfoDTO();
List<String> uniqueIds = new ArrayList<>();
uniqueIds.add("4dc737855eb61401d6e426f61799a0156831356b0fc51848557034b20a7c3546");
uniqueIds.add("85e267220b86c309a85b4e86142366af813304e581014258dd9a0585cd898069");
uniqueIds.add("c81962159ee8417b8e113abb4ce4670f98c3941c97d86c13f1e521def2c62af0");
uniqueIds.add("04820f410572fee703273addc166a41aeead24de447d8abd8e08eacd44e3d901");
info.setUniqueIds(uniqueIds);
info.setKeyword("iphone");
List<LabelDTO> labels = new ArrayList<>();
LabelDTO dto1 = new LabelDTO();
dto1.setLabelName("country");
dto1.setLabelValue("406");
LabelDTO dto2 = new LabelDTO();
dto2.setLabelName("brand");
dto2.setLabelValue("cy");
LabelDTO dto3 = new LabelDTO();
dto3.setLabelName("model");
dto3.setLabelValue("acth");

labels.add(dto1);
labels.add(dto2);
labels.add(dto3);
info.setLabels(labels);
dto.setCardFormReceiverInfo(info);
String requestStr = "requestId=" + requestId + "&bizId=" + bizId +"&miniappId=" + miniappId + "&operatorId=" + operatorId + "&data=" + JSONObject.toJSONString(dto) + "&timeStamp=" + timeStamp;

String secretAccessKeySign = "&secretAccessKey=" + secretAccessKey;
requestStr = requestStr + secretAccessKeySign;
String sign = EncryptSha256Util.getSha256Str(requestStr).toUpperCase();

res.setData(dto);
res.setBizId(bizId);
res.setRequestId(requestId);
res.setMiniappId(miniappId);
res.setOperatorId(operatorId);
res.setTimeStamp(timeStamp);
res.setSign(sign);
System.out.println(JSONObject.toJSONString(res));

}

}


4. 数据规范

4.1 请求报文规范

应答报文分为两层:

  • 外层 公共参数
  • 内层 【data】 业务参数

内容体 data 在 code 等于 0 时返回

{
"data": {
"cardFormReceiverInfo": {
"labels": [
{ "labelName": "country", "labelValue": "ch" },
{ "labelName": "brand", "labelValue": "brand1" },
{ "labelName": "model", "labelValue": "model2" },
{ "labelName": "model111", "labelValue": "model1" },
{ "labelName": "serviceProvider", "labelValue": "serviceProvider1" }
],
"uniqueIds": [
"003c92f3245bddbe736eefd66a7b55c3b9cb04f446c4d3a13b1ec0dc4ae99a01"
]
},
"text": "{\"titleName\":\"logo222\",\"backLogo\":\"name222\",\"checkurl\":\"title222\",\"titleValue\":\"http://hhh.html\"}"
},
"formId": "101690449368932",
"miniappId": "1000083312531542016",
"operatorId": "11",
"sign": "F87E21E1ECDB776001134AA94C89A6F13D70DFF6F687B5749AE845B6A476E229",
"timeStamp": "1690458554576"
}

返回结果

返回参数返回参数类型描述
codeInteger错误状态码
messageString返回消息
dataCardFormInfoVo见 CardFormInfoVo 参数

CardFormInfoVo 参数

返回参数返回参数类型描述
successUniqueIdlist<String>当一次更新多个 uniqueid 的信息时,返回成功的 uniqueid
errorUniqueIdlist<String>当一次更新多个 uniqueid 的信息时,返回失败的 uniqueid

示例:

{
"code": 0,
"message": null,
"data": {
"successUniqueId": ["gsdgsdfgsdfss"],
"errorUniqueId": ["gsdgsdfgsdf"]
},
"sign": "CDD73496515A7F9B66E620CB39470F560A93730E5B4F4C24474E342C4F1B7945"
}

状态码:

状态码描述
10004Data JSON 解析异常
10005签名异常
10007权限异常
20001该表单 id 不存在
20002该表单 id 和小程序 id 不匹配
20006更新表单失败
20007DATA 表单数据不能为空且不能缺失
20008一次发送用户 id 超过限制
20009传入的 key 对应的 value 不能为空
30001用户 uniqueId 不存在
00002请求过快限流了

4.2 回调接口

请求 URL:开发者提供
请求方式:post
输入参数:

参数数据类型备注
requestIdstring写入时的请求 id
returInforeturInfo详见 3.5 返回结果

素材传入的 DeepLink 链接是否正确,格式如下:

  • 包壳小程序形式:launcherdlt://miniapp?appId={小程序 id}&h5Path=xxx&query=yyy

    1. 跳首页,不带额外参数:h5Path=&query=
    2. 跳具体 path,不带额外参数: h5Path=xxx&query=;xxx 代表页面路径
    3. 跳具体 path,需要携带额外参数:h5Path=xxx&query=yyy;xxx 代表页面路径,yyy 是携带的参数,xxx,yyy 需要 encode
    4. 示例:https://www.xxx.com/example?param=1
      1. 对 /example 做 encode 得 %2Fexample
      2. 对 param=1 做 encode param%3D1xxx
      3. 更新素材接口传值 h5Path=%2Fexample&query=param%3D1
  • 常规小程序形式:launcherdlt://miniapp?appId={小程序 id}&page=xxx&query=yyy

    1. 跳首页,不带额外参数:page=&query=
    2. 跳具体 path,不带额外参数: page=xxx&query=;xxx 代表页面路径
    3. 跳具体 path,需要携带额外参数:page=xxx&query=yyy;xxx 代表页面路径,yyy 是携带的参数,yyy 需要 encode
    4. 示例:launcherdlt://miniapp?appId={小程序 id}&page=pages/index/index, 参数为 param=1
      1. 对 param=1 做 encode param%3D1
      2. 更新素材接口传值 page=pages/index/index&query=param%3D1
  • 多小程序类型卡片:该卡片绑定一个默认小程序 defaultMiniappId,但是该卡片还可以跳转至其他小程序

    1. 若跳转到默认小程序,根据 a,b 规则进行链接参数生成
    2. 若跳转到非默认小程序 jumpMiniappId,在 a,b 规则的基础上生成链接后,在链接前面拼接参数 appId={jumpMiniappId}&,示例如下
      1. 跳转小程序 :300000(h5 小程序)
      2. 跳转链接:https://www.xxx.com/example?param=1
      3. 因为是 h5 小程序,按照 a 规则 生成 :h5Path=%2Fexample&query=param%3D1
      4. 最终链接参数 appId=300000&h5Path=%2Fexample&query=param%3D1
Privacy agreementDeveloper agreementcontact us: developer_service.mi@transsion.com © 2024 MiniApp. All Rights Reserved.