[微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/card/wx.addCard.html)
小程序端添加卡券时需要提供签名进行校验,需要提供signature参数,建议从后端获取该参数
生成签名需要四个参数:nonceStr-随机字符串,timestamp以秒为单位的时间戳(记住一定是以秒为单位,否则会签名失败),ticket(生成方法见下面),cardId(微信端提供)
1.生成ticket
private String getTicketFromWx() {
String accessToken = getAccessToken();
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<ApiTicket> forEntity = restTemplate.getForEntity("https://api.weixin.qq" +
".com/cgi-bin/ticket/getticket?type=wx_card&access_token=" + accessToken,
ApiTicket.class);
logger.info("getTicketFromWx_ApiTicket:{}", JSON.toJSONString(forEntity));
ApiTicket apiTicket = forEntity.getBody();
if (apiTicket == null || StringUtils.isBlank(apiTicket.getTicket())) {
logger.info("getTicketFromWx_error:获取ApiTicket出错");
return null;
}
String key = "wxTicketForWxCard_";
stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(apiTicket));
return apiTicket.getTicket();
}
url的type一定是wx_card,否则生成的ticket无效
2.生成随机字符串nonceStr
static String createNonceStr() {
return UUID.randomUUID().toString();
}
3.生成时间戳timestamp
static String createTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
核心代码
public Map<String, String> getCardSign(String cardId) {
//获取ticket
String apiTicket = getTicketForCard();
if (StringUtils.isBlank(apiTicket)) {
logger.info("getCardSign_error:获取到的ticket为空");
return new HashMap<>(1);
}
//生成领取卡券需要的签名,并返回相关的参数
Map<String, String> ret = new HashMap<>(6);
String nonceStr = createNonceStr();
String timestamp = createTimestamp();
String signature;
String[] param = new String[4];
param[0] = nonceStr;
param[1] = timestamp;
param[2] = apiTicket;
param[3] = cardId;
//对参数的value值进行字符串的字典序排序
Arrays.sort(param);
StringBuilder sb = new StringBuilder();
Arrays.stream(param).forEach(sb::append);
//对上面拼接的字符串进行sha1加密,得到signature
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(sb.toString().getBytes(StandardCharsets.UTF_8));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
logger.info("getCardSign_error:", e);
return ret;
}
//返回领取卡券需要的参数,其中nonceStr和timestamp必须和签名中的保持一致
ret.put("card_id", cardId);
ret.put("apiTicket", apiTicket);
ret.put("nonceStr", nonceStr);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
return ret;
}
字节转换方法
static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
[源码地址](https://github.com/shengshengshengsheng/wx_card_demo.git)