准备环境

1.微信测试公众号申请:

微信公众平台http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

2.记录下申请的测试公众号的appid和appsecret

3.配置内网穿透:本篇使用的是natapp NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

设置本机的内网穿透代理,使用免费版。

4.配置js安全域名:其中js安全域名的设置不能携带http://。

5.扫码关注测试公众号:因为测试公众号,在手机端测试时要关注公众号。

开发环境

1.vue前端框架

2.jdk 1.8

3.springboot

后端代码

1.后端代码逻辑主要是:根据appid及appsecret获取token,再根据token获取jsapi_ticket,然后再根据jsapi_ticket,noncestr、timestamp、url拼接成字符串,然后加密生成签名,然后将url(调用扫一扫的页面地址)、jsapi_ticket、nonceStr、timestamp、signature、appId封装后传给前端进行微信验证。

首先微信获取token实体类

http工具类

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class HttpClient {public static String doGet(String url, Map<String, String> param) {// 创建Httpclient对象CloseableHttpClient httpclient = HttpClients.createDefault();String resultString = "";CloseableHttpResponse response = null;try {// 创建uriURIBuilder builder = new URIBuilder(url);if (param != null) {for (String key : param.keySet()) {builder.addParameter(key, param.get(key));}}URI uri = builder.build();// 创建http GET请求HttpGet httpGet = new HttpGet(uri);// 执行请求response = httpclient.execute(httpGet);// 判断返回状态是否为200if (response.getStatusLine().getStatusCode() == 200) {resultString = EntityUtils.toString(response.getEntity(), "UTF-8");}} catch (Exception e) {e.printStackTrace();} finally {try {if (response != null) {response.close();}httpclient.close();} catch (IOException e) {e.printStackTrace();}}return resultString;}public static String doGet(String url) {return doGet(url, null);}public static String doPost(String url, Map<String, String> param) {// 创建Httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = null;String resultString = "";try {// 创建Http Post请求HttpPost httpPost = new HttpPost(url);// 创建参数列表if (param != null) {List<NameValuePair> paramList = new ArrayList<>();for (String key : param.keySet()) {paramList.add(new BasicNameValuePair(key, param.get(key)));}// 模拟表单UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);httpPost.setEntity(entity);}// 执行http请求response = httpClient.execute(httpPost);resultString = EntityUtils.toString(response.getEntity(), "utf-8");} catch (Exception e) {e.printStackTrace();} finally {try {response.close();} catch (IOException e) {e.printStackTrace();}}return resultString;}public static String doPost(String url) {return doPost(url, null);}public static String doPostJson(String url, String json) {// 创建Httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();CloseableHttpResponse response = null;String resultString = "";try {// 创建Http Post请求HttpPost httpPost = new HttpPost(url);// 创建请求内容StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);httpPost.setEntity(entity);// 执行http请求response = httpClient.execute(httpPost);resultString = EntityUtils.toString(response.getEntity(), "utf-8");} catch (Exception e) {e.printStackTrace();} finally {try {response.close();} catch (IOException e) {e.printStackTrace();}}return resultString;}
}

此工具主要用于请求微信链接获取数据

微信工具类-获取accessToken及获取jsApiTicket

import cn.px.base.pojo.page.LayuiPageFactory;
import cn.px.blh.core.wx.WxTokenEntity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;@Component
public class WxUtil {//获取tokenprivate static final String TOKEN_URL  = "https://api.weixin.qq.com/cgi-bin/token";//微信APPIDpublic static String APP_ID;//微信秘钥private static String SECRET;//微信公众号token在redis中存储时的key值public static final String GZH_TOKEN = "wxgzh-access-token";//获取JSAPI_TICKETprivate static final  String JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";//微信公众号jsapi_ticket在redis中存储的key值public static final String JSAPI_KEY = "wxgzh-jsapi-ticket";//JSAPI_KEY在redis中的失效时间public static final Integer JSAPI_KEY_EXPIRED_TIME = 7000;@Value("${wx.appId}")public void setAppId(String appId) {WxUtil.APP_ID = appId;}@Value("${wx.secret}")public void setSecret(String secret) {WxUtil.SECRET = secret;}/*** 获取微信token* @return*/public static WxTokenEntity getAccessToken() {Map<String, String> param = new HashMap<>(16);param.put("grant_type", "client_credential");param.put("appid", APP_ID);param.put("secret", SECRET);String wxResult = HttpClient.doGet(TOKEN_URL,param);WxTokenEntity model = JSON.toJavaObject(JSONObject.parseObject(wxResult),WxTokenEntity.class);return model;}/*** 获得jsapi_ticket*/public static String getJsApiTicket(String token) {String url = JSAPI_TICKET+ "?access_token=" + token+ "&type=jsapi";String response = HttpClient.doGet(url);if (StringUtils.isBlank(response)) {return null;}JSONObject jsonObject = JSONObject.parseObject(response);String ticket = jsonObject.getString("ticket");return ticket;}}

根据url来获取js_api_ticket然后返回结果的实现类

import cn.px.base.util.CacheUtil;
import cn.px.blh.core.util.WxUtil;
import cn.px.blh.core.wx.WxTokenEntity;
import cn.stylefeng.roses.core.util.ToolUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;@Service
public class WxJsApiService {protected Logger logger = LogManager.getLogger();/*** 获取签名* @param url* @return*/public Map<String, String> sign(String url) {Map<String, String> resultMap = new HashMap<>(16);//这里的jsapi_ticket是获取的jsapi_ticket。String jsapiTicket = this.getJsApiTicket();//这里签名中的nonceStr要与前端页面config中的nonceStr保持一致,所以这里获取并生成签名之后,还要将其原值传到前端if(ToolUtil.isEmpty(jsapiTicket)){return resultMap;}String nonceStr = createNonceStr();//nonceStrString timestamp = createTimestamp();String string1;String signature = "";//注意这里参数名必须全部小写,且必须有序string1 = "jsapi_ticket=" + jsapiTicket +"&noncestr=" + nonceStr +"&timestamp=" + timestamp +"&url=" + url;System.out.println("string1:"+string1);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();}resultMap.put("url", url);resultMap.put("jsapi_ticket", jsapiTicket);resultMap.put("nonceStr", nonceStr);resultMap.put("timestamp", timestamp);resultMap.put("signature", signature);resultMap.put("appId", WxUtil.APP_ID);return resultMap;}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 createNonceStr() {return UUID.randomUUID().toString();}private static String createTimestamp() {return Long.toString(System.currentTimeMillis() / 1000);}public String getJsApiTicket(){String ticket = (String) CacheUtil.getCache().get(WxUtil.JSAPI_KEY);if(ToolUtil.isEmpty(ticket)){if(ToolUtil.isEmpty(getToken())){logger.error(String.format("获取token出错"));}else{ticket = WxUtil.getJsApiTicket(getToken());CacheUtil.getCache().set(WxUtil.JSAPI_KEY,ticket,WxUtil.JSAPI_KEY_EXPIRED_TIME);}}return ticket;}private String getToken(){//此处获取token先判断缓存中是否存在,如果没有则调取放入缓存String token = (String) CacheUtil.getCache().get(WxUtil.GZH_TOKEN);if(ToolUtil.isEmpty(token)){WxTokenEntity wxTokenEntity = WxUtil.getAccessToken();if(ToolUtil.isEmpty(wxTokenEntity.getAccess_token())){//获取token出错logger.error(String.format("获取token出错,错误编码:{%s};错误提示:{%s}",wxTokenEntity.getErrcode(),wxTokenEntity.getErrmsg()));}else{token = wxTokenEntity.getAccess_token();CacheUtil.getCache().set(WxUtil.GZH_TOKEN,token,Integer.parseInt(wxTokenEntity.getExpires_in()));}}return token;}}

其中token及jsApiTicket需放入缓存中,防止过多调用微信链接造成资源浪费,缓存工具类大家可以根据自己项目来实现,这里不再贴出。

Controller控制类

/*** 获取微信公众号信息*/@ApiOperation("获取微信公众号信息")@PostMapping(value = "/getSign")@ResponseBodypublic Object scanJsApi(@Param("tokenUrl") String tokenUrl) {Map<String, String> res = wxJsApiService.sign(tokenUrl);if(ToolUtil.isEmpty(res)){return setModelMap(HttpCode.BAD_REQUEST,"获取公众号信息失败");}else{return super.setSuccessModelMap(res);}}

vue前端代码

1.首先使用到微信的wexin-jsapi:

安装:npm install weixin-jsapi --save

页面引入:import wx from "weixin-jsapi";

2.初始化微信参数

 //初始化微信参数wxLoadConfig:function(){var vm = this;return new Promise((resolve, reject) => {// alert(window.location.href.split("#")[0]);vm.$root.api.getSign(window.location.href.split("#")[0]).then(res => {//获取数据if (res.httpCode == 200 || res.httpCode == '200') {var timestamp = res.data.timestamp;var noncestr = res.data.nonceStr;var signature = res.data.signature;var appId = res.data.appId;wx.config({debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。//                                debug : true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: appId, // 必填,公众号的唯一标识timestamp: timestamp, // 必填,生成签名的时间戳nonceStr: noncestr, // 必填,生成签名的随机串signature: signature, // 必填,签名jsApiList: ["scanQRCode"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});wx.checkJsApi({jsApiList:['scanQRCode'],success:function (res) {alert(res);}});} else {}resolve();}).catch(err => {reject(err);})})},

3.调取扫一扫

    //调取扫一扫takeScan:function(){wx.ready(function() {wx.scanQRCode({needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有success: function(res) {var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果alert(res);},error: function(res) {alert(res);}});});},

vue前端页面代码

/* eslint-disable no-undef */
<!--样式引入--><!--模版引入-->
<template><div><div><input type="button" value="调取扫一扫" @click="takeScan"/></div></div>
</template><script>import wx from "weixin-jsapi";// 在man.js中注册 weixin-jsapiexport default {name: 'index',data() {return {}},watch: {'$route'(to, from) {// 更新当前页面导航}},components: {},mounted: function() {this.wxLoadConfig();},methods: {//绑定证件,跳转绑定证件页面bindCertificate:function(){this.$router.push('/bind');},//初始化微信参数wxLoadConfig:function(){var vm = this;return new Promise((resolve, reject) => {// alert(window.location.href.split("#")[0]);vm.$root.api.getSign(window.location.href.split("#")[0]).then(res => {//获取数据if (res.httpCode == 200 || res.httpCode == '200') {var timestamp = res.data.timestamp;var noncestr = res.data.nonceStr;var signature = res.data.signature;var appId = res.data.appId;wx.config({debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。//                                debug : true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: appId, // 必填,公众号的唯一标识timestamp: timestamp, // 必填,生成签名的时间戳nonceStr: noncestr, // 必填,生成签名的随机串signature: signature, // 必填,签名jsApiList: ["scanQRCode"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});wx.checkJsApi({jsApiList:['scanQRCode'],success:function (res) {alert(res);}});} else {}resolve();}).catch(err => {reject(err);})})},//调取扫一扫takeScan:function(){wx.ready(function() {wx.scanQRCode({needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有success: function(res) {var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果alert(res);},error: function(res) {alert(res);}});});},}};
</script>

JAVA实现微信公众号扫一扫相关推荐

  1. Java实现微信公众号直接发送参数二维码给用户

    文章目录 前言 一.参数二维码的作用 二.功能实现 1. 生成带参数二维码 2. 上传二维码图片 3. 发送带参数二维码给用户 总结 前言 公众号开发近些年是一个比较热门的方向,今天为大家讲解的是用J ...

  2. Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理

    在前几节文章中我们讲述了微信公众号环境的搭建.如何接入微信公众平台.以及微信服务器请求消息,响应消息,事件消息以及工具处理类的封装:接下来我们重点说一下-微信服务器post消息体的接收及消息的处理,这 ...

  3. Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发

    接入微信公众平台开发,开发者需要按照如下步骤完成: 1.填写服务器配置 2.验证服务器地址的有效性 3.依据接口文档实现业务逻辑 资料准备: 1.一个可以访问的外网,即80的访问端口,因为微信公众号接 ...

  4. 微信公众号页面支付接口java,[Java教程]微信公众号支付(三):页面调用微信支付JS并完成支付...

    [Java教程]微信公众号支付(三):页面调用微信支付JS并完成支付 0 2015-09-15 15:00:30 一.调用微信的JS文件 1.首先要绑定[JS接口安全域名],"公众号设置&q ...

  5. Java实现微信公众号客服功能和本地联调

    Java实现微信公众号客服功能 微信公众平台设置 生产环境 公众号 设置 [开发]–> [基本配置]–> [服务器配置] 注: a.服务器地址(URL) 是开发者用来接收微信消息和事件的接 ...

  6. 利用Java实现微信公众号发送信息提醒通知

    项目场景: 项目场景:利用Java实现微信公众号发送信息提醒通知! Java实现方法: 1.首先创建实现公众号消息发送的方法: public ReturnDO<String> sendTe ...

  7. Java开发微信公众号之被动回复用户消息-回复图片消息

    一.前言 hello小伙伴们,大家好,做微信开发两年了,最近看到微信方面的文章阅读量和关注量上升的比较快速,激发了我满满的动力啊,所以就滋生了一个想法,从头开始整理一下微信公众号开发,写一个简易的教程 ...

  8. 手把手教程用Java实现微信公众号扫码登录功能

    文章目录 前言 一.环境准备 二.使用步骤 1. 使用微信工具包 2. 创建数据表 3. 登录页面代码逻辑 4. 验证微信公众号登录 总结 前言 微信现今是我们必不可少的社交工具了,围绕微信这个生态实 ...

  9. JAVA 实现微信公众号的生成带参数二维码和扫码后被动回复消息

    公司新需求实现生成微信公众号带参数二维码和对应扫码后回复相应信息的功能. 1.实现带参数二维码功能 public class QrTest {private static Logger logger ...

最新文章

  1. 在Ubuntu上编写一个开机自启动的Python脚本
  2. 计算机在中职教育中的运用论文,中职计算机教育的相关论文(2)
  3. 美团点评数据产品专家冷戈:如何利用数据提高用户体验
  4. 理解交通行业规律 用持续做“重”来重新定义共享出行
  5. ubuntu截图软件deepin scrot
  6. 网易云网络服务研发实践—第1代云网络服务|网易云
  7. 深度学习(三)转-可视化理解卷积神经网络 直接查看卷积神经网络的过程特征...
  8. 关于TCP粘包的拙见
  9. csharp:Compare two DataTables to rows in one but not the other
  10. BASE64Encoder
  11. 116 Python GIL全局解释器锁
  12. texmacs 源码安装
  13. Element-UI组件实现全局回到顶部功能
  14. java 获取list的泛型_获取java.util.List的泛型类型
  15. 【蓝桥杯单片机国赛 第九届】
  16. jquery input的value赋值
  17. 2. 转行学什么技术好?
  18. make: 放弃循环依赖 问题解决(3d 重建)
  19. 【三维重建】之 matlab读取 .wrl 三维图像文件
  20. 微信小程序国际化语言包实现方式(di18n-translate)

热门文章

  1. 关于笔记本触摸板的禁用
  2. 索引图像,RGB图像,灰度图像,.二值图像
  3. 华为设备初始用户名和密码
  4. 【常用代码06】CSS自定义滚动条样式 overflow-y开启滚动条
  5. Windows PE安装win7
  6. autojs文件上传服务器,autojs实现云端脚本(三)
  7. GreenDao使用
  8. 什么是智慧灯杆?城市智慧灯杆的无线通信解决方案
  9. 终端字体放大缩小快捷键
  10. 一台无线路由器通过网线连接台式计算机最多可以连几台计算机,如图所示,无线路由器是一种支持有线和无线连接的网络设备.可以通过后排接口同时连接多台电脑实现有线连接,则各接口之间是...