小程序领取微信卡券

小程序领取微信卡券:(获取 access_token,api_ticket,singuare等完整版)转载自,感谢这位作者
https://www.cnblogs.com/w53064/p/9771232.html

返回主页
啊傑Plus
博客园首页新随笔联系订阅管理随笔 - 25 文章 - 0 评论 - 0
Spring+微信小程序 卡券打通
近期公司项目需要使用到微信卡券模块,主要做的是在小程序打通微信卡券,实现小程序领取卡券的功能效果。

简单说下涉及的东西:

Springboot—使用springboot做后端接口,非常便捷 并且根本是基于SSM

微信公众号—需要认证,并且开通卡券功能。

微信小程序--- 作为项目前端,接受后台接口返回的参数,并调用wx.addcard接口领取卡券。

开发准备:在公众号平台上开通卡券模块,并创建一张卡券,而且要让卡券进入投放的状态,记录下其card_id。

后台函数代码编写参考了网上其它人的程序:

创建一个OpenApi类,这里我把它加一个注解变成控制器

复制代码
1 private static String grantType = “client_credential”;
2 public static String appId = “wxc9e5635bb78789db”; //微信公众号appid
3 public static String secret = “1ee5c4ba6aca792196dbcfc73eabeed8”; //微信公众号密钥
4 public static AccessToken token = null; //微信公众号的accessToken对象,由于请求次数有限制,这里使用全局静态变量保存起来
5 public static ApiTicket ticket = null;//使用全局静态变量存储ApiTicket对象,当然如果使用缓存框架保存当然更好,这边只是做一个简单示例
6 //用于下面返回随机字符串的函数
7 private final static String string = “0123456789”;
8 final private static char[] chars = string.toCharArray();

这里注意 appid跟secret必须是公众号的,不然会有错误。

1 /**
2 * @param api_ticket:
3 * @param cardId:需要领取的卡券的cardId
4 * @return
5 * @Description: 生成卡券需要的签名并返回参数
6 */
7 public static Map<String, String> sign(String api_ticket, String cardId) {
8 Map<String, String> ret = new HashMap<String, String>();
9 String nonce_str = create_nonce_str();
10 String timestamp = create_timestamp();
11 String signature = “”;
12
13 String param[] = new String[4];
14
15 param[0] = nonce_str;
16 param[1] = timestamp;
17 param[2] = api_ticket;
18 param[3] = cardId;
19
20 Arrays.sort(param);//对参数的value值进行字符串的字典序排序
21
22 StringBuilder sb = new StringBuilder();
23 for (String b : param) {
24 sb.append(b);
25 }
26 System.out.println(sb);
27 //对上面拼接的字符串进行sha1加密,得到signature
28 try {
29 MessageDigest crypt = MessageDigest.getInstance(“SHA-1”);
30 crypt.reset();
31 crypt.update(sb.toString().getBytes(“UTF-8”));
32 signature = bytesToHexString(crypt.digest());
33 } catch (NoSuchAlgorithmException e) {
34 e.printStackTrace();
35 } catch (UnsupportedEncodingException e) {
36 e.printStackTrace();
37 }
38
39 //返回领取卡券需要的参数,其中nonceStr和timestamp必须和签名中的保持一致
40 ret.put(“card_id”, cardId);
41 ret.put(“api_ticket”, api_ticket);
42 ret.put(“nonceStr”, nonce_str);
43 ret.put(“timestamp”, timestamp);
44 ret.put(“signature”, signature);
45
46 return ret;
47 }

该函数是签名用的函数,注意这里有随机字符串参与签名。

/**
 * 返回时间戳(秒)
 * @return
 */
private static String create_timestamp() {
    return String.valueOf(new Date().getTime() / 1000);
}

/**
 * 返回随机字符串
 * @return
 */
private static String create_nonce_str() {
    String nonce = new String();
    for (int i = 0; i < 10; i++) {
        int rannum = (int) (Math.random() * 1000) % (chars.length);
        nonce += chars[rannum];
    }
    return nonce;
}

获取token的方式跟微信小程序获取token的方式一样

/**
 * 获取token
 * @return
 * @throws WeixinException
 * @throws JsonParseException
 * @throws JsonMappingException
 * @throws IOException
 * @throws org.weixin4j.WeixinException
 */
public static AccessToken getToken() throws WeixinException, JsonParseException, JsonMappingException, IOException, org.weixin4j.WeixinException {
    if (token == null || token.getExpires_in() < System.currentTimeMillis()) {
        //拼接参数
        String param = "?grant_type=" + grantType + "&appid=" + appId + "&secret=" + secret;
        //创建请求对象
        HttpsClient http = new HttpsClient();
        //调用获取access_token接口
        Response res = http.get("https://api.weixin.qq.com/cgi-bin/token" + param);
        System.out.println(res.asString());
        ObjectMapper mapper = new ObjectMapper();
        token = mapper.readValue(res.asString(), AccessToken.class);
    }
    return token;
}

/**
 * Convert byte[] to hex string
 * @param src byte[] data
 * @return hex string
 */
public static String bytesToHexString(byte[] src) {
    StringBuilder stringBuilder = new StringBuilder("");
    if (src == null || src.length <= 0) {
        return null;
    }
    for (int i = 0; i < src.length; i++) {
        int v = src[i] & 0xFF;
        String hv = Integer.toHexString(v);
        if (hv.length() < 2) {
            stringBuilder.append(0);
        }
        stringBuilder.append(hv);
    }
    return stringBuilder.toString();
}

}

/**
 * @param cardId:需要领取的卡券的cardId
 * @return
 * @throws WeixinException
 * @throws JsonParseException
 * @throws JsonMappingException
 * @throws IOException
 * @Description: 获取领取卡券获取签名等参数
 */
@RequestMapping("getCardSign")
@ResponseBody
public Map<String, String> getCardSign(String cardId) throws WeixinException, JsonParseException, JsonMappingException, IOException, org.weixin4j.WeixinException {
    Map<String, String> ret = new HashMap<String, String>();
    //先要获取api_ticket,由于请求api_ticket的接口访问有次数限制,所以最好将获得到的api_ticket保存到缓存中,这边做法比较简单,直接使用的静态变量
    if (ticket == null || ticket.getExpires_in() < System.currentTimeMillis()) {
        //创建请求对象
        HttpsClient http = new HttpsClient();

        ObjectMapper mapper = new ObjectMapper();

        AccessToken token = OpenApi.getToken();//这里获取的token就是最上方代码保存的微信公众号全局静态变量token

        //通过access_token调用获取api_ticket接口
        Response res = http.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + token.getAccess_token() + "&type=wx_card");
        System.out.println(res.asString());
        ticket = mapper.readValue(res.asString(), ApiTicket.class);
    }

    ret = sign(ticket.getTicket(), cardId);//生成领取卡券需要的签名,并返回相关的参数

    for (Map.Entry entry : ret.entrySet()) {
        System.out.println(entry.getKey() + ", " + entry.getValue());
    }
    return ret;
}

复制代码

@ResponseBody 注解的用处是让这个接口返回的是json数据。也可以在控制器定义的时候 将@Controller 直接写为@RestController。那这里就可以不用加

@ResponseBody注解。

接下来,小程序前端发起网络请求访问这个接口。返回签名所需要的数据

小程序调用wx.addCard函数

wx.addCard({

cardList: [{

cardId: cardId,

cardExt: ‘{“nonce_str”:"’ + res.data.nonceStr + ‘",“timestamp”:"’ + res.data.timestamp + ‘",“signature”:"’ + res.data.signature + ‘"}’

}],

success: function (res) {

console.log(“卡券添加结果”,res.cardList) // 卡券添加结果

}

})

很多人在这里会出现签名错误。我也是纠结了一天 才挑出问题,这里列一下有可能出现签名错误的原因。

后端签名的时候,appid跟secret没有用公众号的,而是用小程序的。一般后端出现问题的几率不高,这里可以用微信提供的接口自行验证签名是否
有问题。 签名校验地址: https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=cardsign

我的问题主要是出现在前端。cardExtc参数传值有误,或者拼接出错,都会出现签名错误的提示。这里需要注意的是,首先 官方文档中,cardExt有
openid跟code参数,但是实际上没有这两个值的话是不用填在cardExt里面的,比如我是通过公众平台直接创建的卡券,所以没有code和openid这两个参数,那么我上面的传值就干脆不写。

其实,我看了网上其它人的参数,有些人有这个nonce_str参数,一开始我是没传这个进入,结果一直显示签名错误,弄了我半天也不知道找不出原因。
后来我才知道,你在后台参与签名用的参数,在前端同样的得再cardExt中传过去,否则就会签名错误!这点希望注意下,确实坑。。但是也只能怪我自己

不够细心。

另外就是cardExt这个参数是要拼接成字符串json形式传值的,请不要直接传一个cardExt对象过去,或者直接构建一个cardExt对象,然后使用

JSON.stringify()函数转化一下,

排除掉签名错误的问题就大功告成了。。

微信卡券API源码是指微信官方提供的用于开发者集成在自己的应用或网站中使用的代码库。通过使用这些源码,开发者可以实现在微信平台上创建和管理卡券、发放和核销卡券、查询卡券信息等功能。 微信卡券API源码主要包含了与卡券相关的前后端代码和接口文档。前端代码负责展示卡券、用户领取和使用卡券的界面,以及与后端进行数据交互。后端代码则负责处理卡券相关的业务逻辑,包括创建和修改卡券、发放和核销卡券、查询卡券信息等。 通过使用微信卡券API源码,开发者可以根据自己的需求进行二次开发和定制,实现与自己应用或网站的业务逻辑相匹配的卡券功能。开发者可以根据微信提供的接口文档了解源码中提供的接口和参数,根据需求进行相应的调用和调试。 微信卡券API源码的使用需要开发者具备一定的编程基础和对微信开发相关知识的了解。同时,开发者还需要在微信公众平台上注册开发者账号,并进行相关的配置和认证。在实际使用中,开发者还需要结合自己的应用场景和需求,进行相应的接口调用和业务逻辑的实现。 总之,微信卡券API源码是一个帮助开发者实现卡券功能的代码库,通过使用源码可以实现在微信平台上创建、管理和使用卡券的功能。开发者可以根据自己的需求进行二次开发和定制,实现与自己应用或网站的业务逻辑相匹配的卡券功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值