小程序领取微信卡券

2023-11-16

小程序领取微信卡券:(获取 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()函数转化一下,

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小程序领取微信卡券 的相关文章

  • Android 上的 setTimeOut() 相当于什么?

    我需要等效的代码setTimeOut call function milliseconds 对于安卓 setTimeOut call function milliseconds 您可能想查看定时任务 http developer andro
  • Hamcrest 泛型地狱 #2:iterable With Size 给出错误“不适用于参数”

    在 hamcrest 中 1 3 RC2 没有 JUnit 依赖项 我使用失败iterableWithSize 我有一个 扩展 Iterator参数化为Content像这样EndResult
  • 如何通过keytool命令删除已经导入的证书/别名?

    我正在尝试通过 keytool 命令删除已导入的证书 keytool delete noprompt alias initcert keystore keycloak jks 但低于异常 keytool 错误 java lang Excep
  • 在 Jenkins 内运行构建时,我收到“java/lang/OutOfMemoryError”

    2020 02 25 10 11 24 986 0000 id 79 信息hudson model AsyncPeriodicWork lambda doRun 0 开始maven repo cleanup 2020 02 25 10 11
  • lombok - 多个镜头中的 @Builder 模式

    I use Builder of 龙目岛项目 https github com rzwitserloot lombok 所以考虑我有这个例子 Builder public class Client private Getter Setter
  • JTable AutoCreateRowSorter 将数字排序为字符串

    我有一个 JTable JTable table new JTable String colNames c1 DefaultTableModel model new DefaultTableModel Integer x new Integ
  • C# 中的 Culture 相当于 Java 中的 Locale 吗?

    C 使用文化的概念 这在操作上与 Java 中的 Locale 类似吗 或者底层概念是否存在显着差异 从文化而不是语言环境的角度进行工作是一种寻找正确抽象层次的尝试 从以类似方式做事的人群的角度来考虑事物 而不是谈论地理区域和语言 并有点疯
  • 用户“root”@“localhost”的访问被拒绝

    我正在尝试从数据库中获取记录 但我面临这个访问被拒绝的问题 我尝试了 Stack Overflow 上提到的其他解决方案 例如向用户授予权限 但没有任何效果 访问数据库的代码 public void service HttpServletR
  • Java HttpURLConnection:内容长度计算

    我目前正在为 bitbucket issues RESTful API 开发一个库 我取得了很大的进步 现在我要解决这个部分更新问题 http confluence atlassian com display BBDEV Issues Is
  • 如何提高 Guice 启动时的性能

    好吧 我知道我的计算不客观等等 但无论如何 我讨厌在执行单元测试时等待这么多时间 我的 guice swing 应用程序需要大约 7 秒来初始化 这是一个简单的 IRC 客户端 在那一刻 没有打开连接 我什至还没有调用任何 java io
  • 从外部 clojar 导入/使用资源

    我想做的是将一个大文件 MIDI 声音字体 打包到一个独立的 Maven repo clojar 中 然后能够以编程方式将其拉下来并从单独的项目中使用它 事实证明 这个看似简单的任务比我想象的要复杂 理想的情况是 如果有一种方法可以直接访问
  • java3d 中的面部着色

    使用java3d 如何不在每个顶点基础上着色 而是在每个面基础上着色 我尝试学习 java3d 但我生成的 Shape3d 看起来并不符合预期 我想用不同的颜色给不同的三角形着色 但我不知道该怎么做 纹理看起来有点大材小用 而且我根本没有掌
  • Java反序列化中避免重复对象

    我有两个列表 list1 和 list2 其中包含对某些对象的引用 其中某些列表条目可能指向同一对象 然后 由于各种原因 我将这些列表序列化为两个单独的文件 最后 当我反序列化列表时 我想确保我不会重新创建超出需要的对象 换句话说 List
  • 如何在 Eclipse 中使用 Hibernate Tools 生成 DAO?

    我在用着 Eclipse Java EE IDE Web 开发人员 版本 Indigo 发布 使用 hibernate 工具 我对 Eclipse 中的 hibernate 很陌生 所以我学习如何配置 hibernate 并使用注释生成 P
  • Java 中 LINQ 的等价物是什么? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Java 中 LINQ 的等价物是什么 没有什么比 LINQ for Java 更好的了 Edit 现在
  • JFreeChart MeterPlot

    我目前正在用java做Agent项目 在某些时候 我需要显示一个仪表 例如 电池电量 我的程序中有 5 个代理 每个代理都会创建自己的带有名称的仪表图 但不知何故他们没有更新数据集 或者他们正在更新数据集 只是它没有显示在仪表图上 任何想法
  • 对于每个抛出异常的语句,try/catch 是否被视为反模式?

    我目前正在审查同事的 Java 代码 我看到很多情况下 每个可能抛出异常的语句都被封装在自己的 try catch 中 其中 catch 块都执行相同的操作 哪个操作与我的问题无关 对我来说 这似乎是一种代码味道 我记得读到过它是一种常见的
  • 无法运行简单的 doclet 程序:包 com.sun.javadoc 不存在

    我正在尝试运行一个简单的 doclet 程序 但无法编译它 javac cp cygdrive c Progra 2 Java jdk1 8 0 65 lib tools jar A java 但它抛出 A java 1 错误 包 com
  • 何时以及为何使用缓冲输入和输出流? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我读到这些是为了减少磁盘 网络调用开销而使用的 这在写操作的情况下似乎很好 但是进行缓冲读取有什么好处呢 如果您按字节读取文件 则每次都会进
  • 如何使用自定义转换器访问 jOOQ 生成的例程字段作为值?

    我在访问生成例程的字段时遇到问题PL pgSQL 用户定义函数 返回JSON 数据类型结果 已经提到this https stackoverflow com q 62535195 6805866问题 这是我的结果get all orders

随机推荐

  • npm install 、npm install --production 、npm install --save 、 npm install --save-dev

    首先四个都会下载js包到moudles里面 只是package json里面不同 npm install 安装所有依赖 npm install production 安装生产依赖 npm install xx save 安装XX到生产环境依
  • 01-Python的基本概念

    01 Python的基本概念 Python是一种直译式 Interpreted 面向对象 Object Oriented 的程序语言 它拥有完整的函数库 可以协助轻松地完成许多常见的工作 所谓的直译式语言是指 直译器 InteIpretor
  • oracle知识整理

    目录 语句1 建立表格语句 语句2 插入数据语句 语句3 查询表格表结构 语句4 查询表格的所有数据 语句5 表格插入多行新的数据 语句6 登陆oracle 语句7 删除整个表格语句 语句1 建立表格语句 create table CONT
  • 大数据之hbase_hbase的介绍及安装

    hbase简介 hbase是一个用以储存结构化和非结构化数据的分布式列式存储数据库 传统数据库mysql 单节点储存 储存容量小 且是行式储存 当我们需要查询某一个字段的所有数据时 需要将全表都加载一遍 而列式数据库则不需要 大大加快了查询
  • 大厂常见笔试题 滑动窗口内数的和

    大厂常见笔试题 我以为出一个很难的题 结果出了一个基础题 给你一个大小为n的整型数组和一个大小为k的滑动窗口 将滑动窗口从头移到尾 输出从开始到结束每一个时刻滑动窗口内的数的和 样例 对于数组 1 2 7 8 5 长度为n 滑动窗口大小k
  • TCP/IP编程之SO_REUSEADDR和SO_REUSEPORT套接字选项

    基本概念 SO REUSEADDR套接字选项能起到以下4个不同的功用 1 SO REUSEADDR允许启动一个监听服务器并捆绑众所周知端口 即使以前建立的该端口用作它们的本地端口的连接仍存在 这个条件通常是这样碰到的 a 启动一个监听服务器
  • 滤波电容的选择

    滤波电容的选择 理论部分 参考案例 一 参考案例 二 其他案例 理论部分 滤波电容主要看容值和耐压值 电容尺寸 容值x耐压值 电容价格 容值x耐压值 电解和钽电容耐压值要x2倍使用 陶瓷电容至少x1 5倍使用 电容选择的逻辑是频率越高 电容
  • 编译Linux内核的一些报错

    内核版本3 18 6 编译目标架构为x86 64 硬件实际架构为x86 64 1 error code model kernel does not support PIC mode 修改 kernel path arch x86 Makef
  • 微信小程序-获取用户手机号码

    1 在获取手机号码之前 要先进行登陆 使用wx login进行登录 登录成功会返回一个code 将code传给后台 获取登录密钥session key等信息 将这些信息存入data 2 使用type getPhoneNumber 的butt
  • 快速fcm matlab,Matlab中的FCM算法代码及中文详解

    Matlab中的FCM算法代码及中文详解 转自 http xiaozu renren com xiaozu 106512 336681453 function center U obj fcn FCMClust data cluster n
  • 【日积月累】后端刷题日志

    刷题日志 说说对Java的理解 JAVA中抽象类和接口之间的区别 Java中的泛型 和equals 的区别 八种基本数据类型与他们的包装类 在一个静态方法内调用一个非静态成员为什么是非法的 静态方法与实例方法有何不同 重载与重写 深拷贝浅拷
  • Sqli-labs 博客目录

    之前学习了一遍 sqli labs 这是巩固复习一遍 代码全部手敲 加深印象 Sqli labs 博客目录 Sqli labs Less01 04 基于错误的sql注入 GET Sqli labs Less05 06 报错型sql盲注 GE
  • 第12章 K8s进阶篇-细粒度权限控制

    12 1 什么是RBAC 负责k8s整个集群控制的 不同人员权限的管控 开发 测试 管理员等 12 2 RBAC配置解析 12 3 RBAC常用配置示例 参考官方文档 使用 RBAC 鉴权 Kubernetes 正常是通过yaml文件创建
  • 替代空格

    include
  • host文件的工作原理及应用

    host文件的工作原理及应用 Hosts文件是一个用于存储计算机网络中节点信息的文件 它可以将主机名映射到相应的IP地址 实现DNS的功能 它可以由计算机的用户进行控制 一 Hosts文件基本介绍 Hosts文件的存储位置在不同的操作系统中
  • java 16进制与字符串互相转

    字符串转换成为16进制 无需Unicode编码 param str return public static String str2HexStr String str char chars 0123456789ABCDEF toCharAr
  • 各种字符串Hash函数比较

    转自 beyond the void 常用的字符串Hash函数还有ELFHash APHash等等 都是十分简单有效的方法 这些函数使用位运算使得每一个字符都对最后的函数值产生影响 另外还有以MD5和SHA1为代表的杂凑函数 这些函数几乎不
  • get和post详解

    Get和post是表单提交数据的两种基本方式 get请求数据通过域名后缀url传送 用户可见 不安全 post请求数据通过在请求报文正文里传输 相对比较安全 get是通过url传递表单值 post通过url看不到表单域的值 get传递的数据
  • OceanBase 4.1解读:我们想给用户一个开箱即用的OceanBase部署运维工具

    欢迎访问 OceanBase 官网获取更多信息 https www oceanbase com 关于作者 肖磊 OceanBase 产品专家 负责 OceanBase 运维管控体系产品规划与设计 包括安装部署工具 OBD OAT 运维管控平
  • 小程序领取微信卡券

    小程序领取微信卡券 获取 access token api ticket singuare等完整版 转载自 感谢这位作者 https www cnblogs com w53064 p 9771232 html 返回主页 啊傑Plus 博客园