微信公众号开发——Java

  • 步骤一:需要先进入公众号平台进行JS接口安全域名的设置。
  • 步骤二:引入微信jssdk.js文件
    • 生成JS-SDK权限验证签名
  • 步骤三:通过config接口注入权限验证配置
  • 步骤四:通过ready接口处理成功验证
  • 步骤五:通过error接口处理失败验证
    • 重点:

步骤一:需要先进入公众号平台进行JS接口安全域名的设置。

​ 绑定域名一定要去掉 “http://”或者"https://",如下

JS接口安全域名  xxx.xxx.com

步骤二:引入微信jssdk.js文件

​ 示例文件 (x.x.x为版本号)

官方:https://res.wx.qq.com/open/js/jweixin-x.x.x.js

最重要是在java中获取jsapi_ticket,并且通过一系列操作得到一个签名;主要步骤是:

1、获取access_token(普通access_token),通过access_token获取到jsapi_ticket;access_token是公众号的全局唯一接口调用凭据,公众号调用各接口都需要access_token,access_token有效期只有2小时,最后用缓存存储,定时刷新
接口调用请求

https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

获取access_token代码:

private static String getAccessToken(String appid, String appSecret) {String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appSecret);// 发起GET请求获取凭证JSONObject jsonObject = getJsApiJSONObjectParam(requestUrl);String access_token = null;if (null != jsonObject) {access_token = jsonObject.getString("access_token");}return access_token;}public static JSONObject getJsApiJSONObjectParam(String url) {JSONObject jsonResult = new JSONObject();InputStream is = null;try {URL urlGet = new URL(url);HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();http.setRequestMethod("GET"); // 必须是get方式请求http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");http.setDoOutput(true);http.setDoInput(true);System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒http.connect();is = http.getInputStream();int size = is.available();byte[] jsonBytes = new byte[size];is.read(jsonBytes);String message = new String(jsonBytes, "UTF-8");jsonResult = JSONObject.parseObject(message);} catch (Exception e) {logger.error(e.getMessage(), e);} finally {IOUtils.closeQuietly(is);}return jsonResult;}

用拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

获取jsapi_ticket代码:

    private static String getJsApiTicket(String access_token) {String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";String requestUrl = url.replace("ACCESS_TOKEN", access_token);// 发起GET请求获取凭证JSONObject jsonObject = getJsApiJSONObjectParam(requestUrl);// 重试一次if ("40001".equals(jsonObject.getString("errcode"))) {access_token = getAccessToken(jsSdkConstants.getAppId(), jsSdkConstants.getAppSecret());cacheUtil.setCacheValue(Cache.WECHAT_ACCESS_TOKEN, access_token, 7200);requestUrl = url.replace("ACCESS_TOKEN", access_token);jsonObject = getJsApiJSONObjectParam(requestUrl);}String ticket = null;if (null != jsonObject) {ticket = jsonObject.getString("ticket");}return ticket;}public static JSONObject getJsApiJSONObjectParam(String url) {JSONObject jsonResult = new JSONObject();InputStream is = null;try {URL urlGet = new URL(url);HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();http.setRequestMethod("GET"); // 必须是get方式请求http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");http.setDoOutput(true);http.setDoInput(true);System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒http.connect();is = http.getInputStream();int size = is.available();byte[] jsonBytes = new byte[size];is.read(jsonBytes);String message = new String(jsonBytes, "UTF-8");jsonResult = JSONObject.parseObject(message);} catch (Exception e) {logger.error(e.getMessage(), e);} finally {IOUtils.closeQuietly(is);}return jsonResult;}

生成JS-SDK权限验证签名

签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

 private static Map<String, String> sign(String jsapi_ticket, String url) {Map<String, String> ret = new HashMap<String, String>();String nonce_str = create_nonce_str();String timestamp = create_timestamp();String string1;String signature = "";// 注意这里参数名必须全部小写,且必须有序string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;try {MessageDigest crypt = MessageDigest.getInstance("SHA-1");crypt.reset();crypt.update(string1.getBytes("UTF-8"));signature = byteToHex(crypt.digest());} catch (NoSuchAlgorithmException e) {logger.error(e.getMessage(), e);} catch (UnsupportedEncodingException e) {logger.error(e.getMessage(), e);}ret.put("url", url);ret.put("jsapi_ticket", jsapi_ticket);ret.put("nonceStr", nonce_str);ret.put("timestamp", timestamp);ret.put("signature", signature);return ret;}private 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;}

缓存工具类

@Component
public final class CacheUtil {@Resourceprivate RedisTemplate<String, String> redisTemplate;/*** 缓存取值* * @param key* @return*/public String getCacheValue(String key) {return this.redisTemplate.opsForValue().get(key);}/*** 缓存赋值* * @param key* @param value*/public void setCacheValue(String key, String value) {this.redisTemplate.opsForValue().set(key, value);}/*** 删除缓存* * @param key* @return*/public void delCacheValue(String key) {this.redisTemplate.delete(key);}/*** 缓存赋值并设置有效时间* * @param key* @param value* @param number 数据* @param unit   例如:TimeUnit.DAYS*/public void setCacheValue(String key, String value, long number, TimeUnit unit) {this.redisTemplate.opsForValue().set(key, value, number, unit);}/*** 获取有效期* * @param key*/public void getExpireTime(String key) {this.redisTemplate.getExpire(key);}/*** 通过 TimeUnit 获取有效期* * @param key* @param unit*/public void getExpireTime(String key, TimeUnit unit) {this.redisTemplate.getExpire(key, unit);}/*** 获取指定条件key值* * @param pattern *:所有* @return*/public Set<String> getCacheKeys(String pattern) {return this.redisTemplate.keys(pattern);}}

以上生成Map返回给前端

    /*** 获取微信签名* 通过url生成signature,noncestr,timestamp* @param* @return*/public static Map<String, String> getJsApiParam(String url) {Map<String, String> resultMap = new HashMap<String, String>();String access_token = (String) TokenCacheHelper.getInstance().get(Cache.WECHAT_ACCESS_TOKEN);if (StringUtils.isEmpty(access_token)) {access_token = getAccessToken(jsSdkConstants.getAppId(), jsSdkConstants.getAppSecret());TokenCacheHelper.getInstance().put(Cache.WECHAT_ACCESS_TOKEN, access_token, 7200);}String jsapi_ticket = (String) FbOmsSystemCacheUtil.get(Cache.WECHAT, "jsapi_ticket");// 从系统缓存中获取调用票据if (StringUtils.isEmpty(jsapi_ticket)) {jsapi_ticket = getJsApiTicket(access_token);FbOmsSystemCacheUtil.put(Cache.WECHAT, "jsapi_ticket", jsapi_ticket);access_token = (String) TokenCacheHelper.getInstance().get(Cache.WECHAT_ACCESS_TOKEN);}resultMap = sign(jsapi_ticket, url);resultMap.put("appId", jsSdkConstants.getAppId());resultMap.put("access_token", access_token);return resultMap;}

步骤三:通过config接口注入权限验证配置

在页面初始化的时候,调用上面方面,填充到wx.config里面

wx.config({debug: true, // 开启调试模式appId: '', // 必填,公众号的唯一标识timestamp: , // 必填,生成签名的时间戳nonceStr: '', // 必填,生成签名的随机串signature: '',// 必填,签名jsApiList: [] // 必填,需要使用的JS接口列表
});

返回示例:

"config", {appId: "XXXXXXXXXXXXXXXXXXXXX"beta: falsedebug: truejsApiList: (2) ["onMenuShareTimeline", "onMenuShareAppMessage"] nonceStr: "d28ed4e1-e88a-44c6-926e-de84d498dfa6"signature: "db117be7526d7443f33fd4a469977d38e74f1fa9"timestamp: "1627348841"}

步骤四:通过ready接口处理成功验证

wx.ready(function(){// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
})

步骤五:通过error接口处理失败验证

wx.error(function(res){  // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。});

然后就可以调用相关API接口,接口Demo链接

https://www.weixinsxy.com/jssdk/#menu-card

前端代码:**

import { getJsApiParam } from './services/wx';
async function config() {const index = window.location.href.indexOf('#');const url = window.location.href.substring(0, index);const res = await getJsApiParam({ url: url });if (!res) {return res;}const { appId, nonceStr, signature, timestamp } = res;window.wx.config({debug: true,appId,timestamp,nonceStr,signature,jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'], // 必填,需要使用的JS接口列表,所有JS接口列表见附录2beta: false,});
}
config();---------------------------------------------------------------------分割线--------------------------------------------------------------function share(pmCode: string, skuName: string) {const OnMenuShareAppMessageOptions: any = {title: 'XXXX',desc: `商品名【${skuName}】,请点击查看分享`,link: 'http://www.baidu.com/',type: 'link',imgUrl: `http://www.baidu.com/imges.png`,};window.wx.ready(function () {window.wx.onMenuShareAppMessage(OnMenuShareAppMessageOptions);});}

重点:

获取access_token需要新增Ip白名单,否则获取不了会报40164错误

可以通过微信公众号提供的在线测试接口测试是否能获取access_token

https://mp.weixin.qq.com/debug

微信公众号开发——Java相关推荐

  1. 微信公众号开发-Java版学习笔记

    微信公众号开发整体不难,主要是熟悉微信公众号常用的一些接口文档,然后会一门后端语言(比如java)即可. 罗召勇老师教程:微信公众号开发-Java版(蓝桥罗召勇) 微信公众号文档:微信公众号官方文档 ...

  2. 微信公众号开发-java版 腾讯课堂(开发接入)

    微信公众号开发-java版 腾讯课堂 微信测试号申请地址: 微信二维码直接扫描登录 1.新建web项目 2.内网穿透映射公网ip  (免费隧道需要支付宝实名认证) 3.微信接入验证签名 TOKEN自己 ...

  3. 微信公众号开发Java版

    源码地址: https://github.com/ishuaige/myWxMp https://gitee.com/niumazlb/myWxMp 一.申请微信开发者账号 注册账号 申请测试号 这里 ...

  4. 微信公众号开发java流程_微信公众号开发教程java 编程语言的特点及选择

    微信公众号开发教程java 编程语言的特点及选择 微信公众号为用户提供了相关的工具,来对微信公众号进行一个简单的开发.但是如果想实现一些复杂的功能,其实还是要借助于一些编程语言的使用.所以要了解,在微 ...

  5. 微信公众号开发java版-消息回复(普通文字消息和语音消息)

    本文介绍微信公众号消息自动回复功能的开发,开发语言 java话不多说,直接上代码 1.控制器代码 package webapp.controller;import org.springframewor ...

  6. 微信公众号开发(JAVA)-环境搭建与开发接入

    使用JAVA开发微信公众平台(一)--环境搭建与开发接入 一. 初始微信公众平台 微信公众平台,即我们平时所说的"公众号",曾用名"官方平台"."媒体 ...

  7. 微信公众号开发Java版的学习笔记和操作demo!

    基本原理: 会用到微信服务器,调用自己的服务器,自己服务器的访问可以基于spring boot的部署,当然也可以基于其他,其本质就是类似于远程的接口调用: 为社么需要:比如第三方,银行或者独立公司的服 ...

  8. 慕课网_《Java微信公众号开发进阶》学习总结

    时间:2017年08月12日星期六 说明:本文部分内容均来自慕课网.@慕课网:http://www.imooc.com 教学源码:http://img.mukewang.com/down/... 学习 ...

  9. java微信公众号开发token验证失败的问题及解决办法

    java微信公众号开发token验证失败的问题及解决办法 参考文章: (1)java微信公众号开发token验证失败的问题及解决办法 (2)https://www.cnblogs.com/beardu ...

最新文章

  1. Delphi Form Designer (窗体设计器)之四
  2. Quarkus:一个Kubernetes原生Java框架
  3. csdn新版博客初体验
  4. Java序列化和反序列化小记
  5. UA MATH566 统计理论1 充分统计量例题答案2
  6. shader 2: vertex, fragment, surf的区别
  7. FANUC常用CNC诊断数据表
  8. qt mysql数据库连接池_qt中使用数据库连接池
  9. SQL 2005 全文索引
  10. 统计单词个数(划分型)
  11. Mind+实时模式智能问答机器人
  12. C语言教程第六章:指针(1)
  13. Octopus系列之更新历史记录
  14. oracle11g远程命令执行漏洞,漏洞应急|Oracle Weblogic Server远程代码执行漏洞(CVE-2021-2109)...
  15. 如何在RedHat 5.4上使用免费的YUM源
  16. 机器学习面试笔试求职必背!八股文(1/5)
  17. 黑群DS3617xs 6.2.3套件中心无法添加第三方源/添加第三方源失败解决方案/群晖套件中心无效的位置解决
  18. Spring Data JPA 的动态查询和一对多及多对多查询
  19. blender导入png图片不透明 | png贴图在blender中有黑底
  20. 计算机实验原理word,完整word版计算机组成原理实验报告 微控制器

热门文章

  1. 如何利用日语翻译软件快速进行日语翻译
  2. Java基础进阶-评委打分系统
  3. python线程和进程
  4. pp助手服务器开小差,无法连接game center服务器通信的处理方法
  5. java数组游戏_基于java的挖地雷游戏
  6. 动态规划——1262:【例9.6】挖地雷
  7. Google maps API开发
  8. hnu 数字电路 实验4.4 RAM
  9. iwebshop index.php,【已完结】浅析iwebshop的登录过程
  10. 【应用回归分析】CH3 回归参数的估计1——最小二乘估计