微信公众号开发——Java
微信公众号开发——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 + "×tamp=" + 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相关推荐
- 微信公众号开发-Java版学习笔记
微信公众号开发整体不难,主要是熟悉微信公众号常用的一些接口文档,然后会一门后端语言(比如java)即可. 罗召勇老师教程:微信公众号开发-Java版(蓝桥罗召勇) 微信公众号文档:微信公众号官方文档 ...
- 微信公众号开发-java版 腾讯课堂(开发接入)
微信公众号开发-java版 腾讯课堂 微信测试号申请地址: 微信二维码直接扫描登录 1.新建web项目 2.内网穿透映射公网ip (免费隧道需要支付宝实名认证) 3.微信接入验证签名 TOKEN自己 ...
- 微信公众号开发Java版
源码地址: https://github.com/ishuaige/myWxMp https://gitee.com/niumazlb/myWxMp 一.申请微信开发者账号 注册账号 申请测试号 这里 ...
- 微信公众号开发java流程_微信公众号开发教程java 编程语言的特点及选择
微信公众号开发教程java 编程语言的特点及选择 微信公众号为用户提供了相关的工具,来对微信公众号进行一个简单的开发.但是如果想实现一些复杂的功能,其实还是要借助于一些编程语言的使用.所以要了解,在微 ...
- 微信公众号开发java版-消息回复(普通文字消息和语音消息)
本文介绍微信公众号消息自动回复功能的开发,开发语言 java话不多说,直接上代码 1.控制器代码 package webapp.controller;import org.springframewor ...
- 微信公众号开发(JAVA)-环境搭建与开发接入
使用JAVA开发微信公众平台(一)--环境搭建与开发接入 一. 初始微信公众平台 微信公众平台,即我们平时所说的"公众号",曾用名"官方平台"."媒体 ...
- 微信公众号开发Java版的学习笔记和操作demo!
基本原理: 会用到微信服务器,调用自己的服务器,自己服务器的访问可以基于spring boot的部署,当然也可以基于其他,其本质就是类似于远程的接口调用: 为社么需要:比如第三方,银行或者独立公司的服 ...
- 慕课网_《Java微信公众号开发进阶》学习总结
时间:2017年08月12日星期六 说明:本文部分内容均来自慕课网.@慕课网:http://www.imooc.com 教学源码:http://img.mukewang.com/down/... 学习 ...
- java微信公众号开发token验证失败的问题及解决办法
java微信公众号开发token验证失败的问题及解决办法 参考文章: (1)java微信公众号开发token验证失败的问题及解决办法 (2)https://www.cnblogs.com/beardu ...
最新文章
- Delphi Form Designer (窗体设计器)之四
- Quarkus:一个Kubernetes原生Java框架
- csdn新版博客初体验
- Java序列化和反序列化小记
- UA MATH566 统计理论1 充分统计量例题答案2
- shader 2: vertex, fragment, surf的区别
- FANUC常用CNC诊断数据表
- qt mysql数据库连接池_qt中使用数据库连接池
- SQL 2005 全文索引
- 统计单词个数(划分型)
- Mind+实时模式智能问答机器人
- C语言教程第六章:指针(1)
- Octopus系列之更新历史记录
- oracle11g远程命令执行漏洞,漏洞应急|Oracle Weblogic Server远程代码执行漏洞(CVE-2021-2109)...
- 如何在RedHat 5.4上使用免费的YUM源
- 机器学习面试笔试求职必背!八股文(1/5)
- 黑群DS3617xs 6.2.3套件中心无法添加第三方源/添加第三方源失败解决方案/群晖套件中心无效的位置解决
- Spring Data JPA 的动态查询和一对多及多对多查询
- blender导入png图片不透明 | png贴图在blender中有黑底
- 计算机实验原理word,完整word版计算机组成原理实验报告 微控制器