官方文档地址1、先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
【微信JSSDK|Vue微信公众号H5调用jssdk jsapi,例如(微信扫一扫)】2、H5或Web项目下:
调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js
3、Vue项目下:
3-1、安装
cnpm install weixin-jsapi --save
4、后台代码:
//以下为缓存使用的key值
/** 获取到的凭证 */
private static final String WX_ACCESS_TOKEN_KEY = "wxAccessTokenKey";
/** 凭证有效时间,单位:秒 */
private static final String WX_EXPIRES_IN_KEY = "wxExpiresInKey";
/** 获取凭证时的时间 */
private static final String WX_TOKEN_TIME_KEY = "wxTokenTimeKey";
/** 获取到的ticket */
private static final String WX_TICKET_KEY = "wxTicketKey";
/** ticket有效时间,单位:秒 */
private static final String WX_TICKET_EXPIRES_IN_KEY = "wxTicketExpiresInKey";
/** 获取ticket时的时间 */
private static final String WX_TICKET_TIME_KEY = "wxTicketTimeKey";
/**
* 获取对应的access_token
* @author lan
* @since 2020-5-6
* @url https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx10557a0b4df259ef&secret=fed31df017dc2b9db5b4530f9405ca60
* @return {"access_token":"ACCESS_TOKEN","expires_in":7200}
* @return {"errcode":40164,"errmsg":"invalid ip 192.168.0.1 ipv6
*:ffff:192.168.0.1, not in whitelist hint: [gtGupa07444814]"}
*/
private Map, Object> getAccessToken() {
String appId = "申请的APPID";
//平台配置的AppId
String appSecret = "申请的AppSecret";
//平台配置的AppSecret
Map, Object> result = new HashMap, Object>();
try {
// 从缓存中读取
if (null != redisService.getCodeVal(WX_ACCESS_TOKEN_KEY) && null != redisService.getCodeVal(WX_EXPIRES_IN_KEY) && !"".equals(redisService.getCodeVal(WX_ACCESS_TOKEN_KEY)) && !"".equals(redisService.getCodeVal(WX_EXPIRES_IN_KEY))) {
long expirsIn = Long.valueOf(redisService.getCodeVal(WX_EXPIRES_IN_KEY).toString());
long tokenTime = Long.valueOf(redisService.getCodeVal(WX_TOKEN_TIME_KEY).toString());
long currentTime = new Date().getTime() / 1000;
if ((currentTime - tokenTime) < expirsIn) {
String accessToken = redisService.getCodeVal(WX_ACCESS_TOKEN_KEY).toString();
if (!StringUtils.isBlank(accessToken)) {
System.out.println("access_token为缓存取值:" + accessToken);
result.put("success", true);
result.put("accessToken", accessToken);
return result;
} else {
System.out.println("access_token为缓存取值为空,立即接口取值");
}
}
}if (!StringUtils.isBlank(appId) && !StringUtils.isBlank(appSecret)
&& !StringUtils.isBlank(AccessTokenUrl)) {
System.out.println("access_token为接口取值");
long currentTime = new Date().getTime() / 1000;
redisService.saveCode(WX_TOKEN_TIME_KEY, currentTime + "", 7200L);
StringBuffer sb = new StringBuffer("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential");
sb.append("&appid=").append(appId).append("&secret=").append(appSecret);
String res = httpGet(sb.toString());
if (!StringUtils.isBlank(res)) {
JSONObject obj = JSONObject.parseObject(res);
if (obj != null) {
if (obj.get("access_token") != null) {
result.put("success", true);
result.put("accessToken", obj.get("access_token").toString());
// 加入缓存
redisService.saveCode(WX_ACCESS_TOKEN_KEY,obj.get("access_token").toString(), 7200L);
redisService.saveCode(WX_EXPIRES_IN_KEY, obj.get("expires_in").toString(), 7200L);
} else {
result.put("success", false);
result.put("accessToken", obj.get("errmsg"));
}
} else {
result.put("success", false);
result.put("accessToken", "操作失败");
}
} else {
result.put("success", false);
result.put("accessToken", "操作失败");
}
} else {
result.put("success", false);
result.put("accessToken", "操作失败");
}
return result;
} catch (Exception e) {
System.out.println("操作失败" + e);
result.put("success", false);
result.put("message", e.getMessage());
return result;
}
}/**
* 获取对应的jsapi_ticket
* @author lan
* @since 2020-5-6
* @url https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
* @return { "errcode":0, "errmsg":"ok","ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
*"expires_in":7200 }
* @return {"errcode":40164,"errmsg":"invalid ip 192.168.0.1 ipv6
*::ffff:192.168.0.1, not in whitelist hint: [gtGupa07444814]"}
*/
private String getJsapiTicket(String accessToken) {
System.out.println("执行getJsapiTicket");
try {
// 从缓存中读取
if (null != redisService.getCodeVal(WX_TICKET_KEY) && null != redisService.getCodeVal(WX_TICKET_EXPIRES_IN_KEY) && !"".equals(redisService.getCodeVal(WX_TICKET_KEY)) && !"".equals(redisService.getCodeVal(WX_TICKET_EXPIRES_IN_KEY))) {
long expirsIn = Long.valueOf(redisService.getCodeVal(WX_TICKET_EXPIRES_IN_KEY).toString());
long tokenTime = Long.valueOf(redisService.getCodeVal(WX_TICKET_TIME_KEY).toString());
long currentTime = new Date().getTime() / 1000;
if ((currentTime - tokenTime) < expirsIn) {
String ticket = redisService.getCodeVal(WX_TICKET_KEY).toString();
if (!StringUtils.isBlank(ticket)) {
System.out.println("ticket为缓存取值:" + ticket);
return ticket;
} else {
System.out.println("ticket为缓存取值为空,立即接口取值");
}
}
}if (!StringUtils.isBlank(accessToken)) {
System.out.println("ticket为接口取值");
long currentTime = new Date().getTime() / 1000;
redisService.saveCode(WX_TICKET_TIME_KEY, currentTime + "", 7200L);
StringBuffer sb = new StringBuffer("https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card");
sb.append("&access_token=").append(accessToken);
String res = httpGet(sb.toString());
if (!StringUtils.isBlank(res)) {
JSONObject obj = JSONObject.parseObject(res);
if (obj != null) {
if (obj.get("ticket") != null && "0".equals(obj.get("errcode").toString())) {
// 加入缓存
redisService.saveCode(WX_TICKET_KEY, obj.get("ticket").toString(), 7200L);
redisService.saveCode(WX_TICKET_EXPIRES_IN_KEY, obj.get("expires_in").toString(), 7200L);
return obj.get("ticket").toString();
} else {
return null;
}
} else {
return null;
}
} else {
return null;
}
} else {
return null;
}
} catch (Exception e) {
System.out.println("操作失败" + e);
return null;
}
}//提供一个供项目调用的接口
public ApiResult
工具类
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;
public class CreateWxSignUtil {
public static Map, String> getWxSign(String jsapi_ticket, String url) {
Map, String> ret = new HashMap, 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)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}ret.put("url", url);
ret.put("jsapiTicket", 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;
}private static String create_nonce_str() {
return UUID.randomUUID().toString();
}private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
5、前端
5-1、使用
import wx from "weixin-jsapi";
5-2、配置
//自定义一个POST请求
export function getJssdkSign(data) {
return request.post("http:127.0.0.1:8080/projectName/getJssdkSign", data);
}//微信扫一扫调用sdk核心配置
let url = location.href.split("#")[0];
//这里【url参数一定是去参的动态的当前页网址】
let params = {};
params.url = url;
getJssdkSign(params).then(res => {
wx.config({
// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
debug: false,
// 必填,公众号的唯一标识
appId: res.data.appId,
// 必填,生成签名的时间戳
timestamp: res.data.timestamp,
// 必填,生成签名的随机串
nonceStr: res.data.nonceStr,
// 必填,签名
signature: res.data.signature,
// 必填,需要使用的JS接口列表,所有JS接口列表
jsApiList: ["scanQRCode","checkJsApi", ......]
});
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
});
//调起微信扫一扫
openQRCode: function() {
let that = this;
wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
//scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
success: function(res) {
let result = res.resultStr;
// 当needResult 为 1 时,扫码返回的结果
if (result != null && result != "" && result != undefined) {
//扫码结果
//业务逻辑处理......
}
}
});
}
6、注意事项:
6-1、网上有说使用 “cnpm install weixin-js-sdk --save”,但我使用时出现-wx:undefined,后改用3-1即可,据了解微信提供了Vue环境下直接引用,未深究。
6-2、当出现 “config:invalid signature” 时,检查签名是否正确,可用官方提供的验签工具验证:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
6-3、签名时必须使用jsapi_ticket生成,生成签名时所需的URL必须为不包含#号的动态的本网页地址。
6-4、测试时需要使用服务器部署项目,使用nginx指向本地ip进行调试。
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- JavaScript|vue 基于axios封装request接口请求——request.js文件
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验