100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > JAVA实现微信公众号扫一扫

JAVA实现微信公众号扫一扫

时间:2023-01-20 16:02:54

相关推荐

JAVA实现微信公众号扫一扫

准备环境

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

微信公众平台http://mp./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 .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.ponent;import java.util.HashMap;import java.util.Map;@Componentpublic class WxUtil {//获取tokenprivate static final String TOKEN_URL = "https://api./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./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;@Servicepublic 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>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。