Web端调用微信sdk扫一扫功能
常见问题
- 没有调用成功摄像头?
准备工作
- 微信公众号订阅号即可 绑定自己的域名(JS接口安全域名),添加IP白名单、获取AppSecret
- 在Java后端写一些Utils去向微信发送请求,以达到鉴权获取 ticket
后端代码
1 2
| public static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token"; public static final String TICKET_URL = " https://api.weixin.qq.com/cgi-bin/ticket/getticket";
|
获取签名的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| package com.ruoyi.system.service.impl;
import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.Constants; import com.ruoyi.common.utils.SendToWxUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional;
import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.concurrent.TimeUnit;
@Component("JsApiService") @Transactional public class JsApiService {
@Autowired private RedisCache redisCache;
public Map<String, String> sign(String url) { Map<String, String> resultMap = new HashMap<>(16);
String ticket = null; Object object = redisCache.getCacheObject("ticket"); if (object != null) { ticket = object.toString(); } else { HashMap<String, String> resMap = SendToWxUtils.getTicket(); ticket = resMap.get("ticket"); redisCache.setCacheObject("ticket", ticket); redisCache.expire("ticket", 2, TimeUnit.HOURS); }
System.err.println("###########读取ticket:" + ticket); String nonceStr = createNonceStr(); String timestamp = createTimestamp(); String string1; String signature = "";
string1 = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + 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", ticket); resultMap.put("nonceStr", nonceStr); resultMap.put("timestamp", timestamp); resultMap.put("signature", signature); resultMap.put("appId", Constants.APPID); System.err.println("###########打印resultMap:" + resultMap.get("jsapi_ticket") + "," + resultMap.get("url")); 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); } }
|
后端向微信发送请求获取Token、等参数的Utils
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| package com.ruoyi.common.utils;
import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.core.redis.RedisCache;
import javax.annotation.Resource; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ConnectException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLConnection; import java.util.HashMap;
public class SendToWxUtils { @Resource RedisCache redisCache;
public static String getAccessToken() { String param = String.format("appid=%s&secret=%s&grant_type=%s", Constants.APPID, Constants.SECRET, Constants.GRANT_TYPE); String res = sendGet(Constants.TOKEN_URL, param); JSONObject obj = JSONObject.parseObject(res); String accessToken = obj.getString("access_token"); System.err.println("accessToken-->" + accessToken); return obj.getString("access_token"); }
public static HashMap<String, String> getTicket() { String accessToken = getAccessToken(); String param = String.format("access_token=%s&type=jsapi", accessToken); String res = sendGet(Constants.TICKET_URL, param); JSONObject parsed = JSONObject.parseObject(res); String ticket = parsed.getString("ticket"); HashMap<String, String> resMap = new HashMap<>(); resMap.put("ticket", ticket); return resMap; }
public static String sendGet(String url, String param) { StringBuilder result = new StringBuilder(); BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); URLConnection connection = realUrl.openConnection(); connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); connection.connect(); in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); String line; while ((line = in.readLine()) != null) { result.append(line); } } catch (ConnectException e) { System.err.println("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param + e); } catch (SocketTimeoutException e) { System.err.println("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param + e); } catch (IOException e) { System.err.println("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param + e); } catch (Exception e) { System.err.println("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param + e); } finally { try { if (in != null) { in.close(); } } catch (Exception ex) { System.err.println("调用in.close Exception, url=" + url + ",param=" + param + ex); } } return result.toString(); }
public static void main(String[] args) { String param = String.format("appid=%s&secret=%s&grant_type=%s", Constants.APPID, Constants.SECRET, Constants.GRANT_TYPE); String res = sendGet(Constants.TOKEN_URL, param); JSONObject obj = JSONObject.parseObject(res); String accessToken = obj.getString("access_token");
String param2 = String.format("access_token=%s&type=jsapi", accessToken); String res2 = sendGet(Constants.TICKET_URL, param2); JSONObject parsed = JSONObject.parseObject(res2); String ticket = parsed.getString("ticket"); System.err.println(accessToken); System.err.println(ticket); } }
|
一些静态常量
1 2 3 4 5 6 7 8 9 10
| package com.ruoyi.common.utils;
public class Constants { public static final String GRANT_TYPE = "client_credential"; public static final String APPID = "你自己的APPID "; public static final String SECRET = "你自己的SECRET ";
public static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token"; public static final String TICKET_URL = " https://api.weixin.qq.com/cgi-bin/ticket/getticket"; }
|
前端调用接口
1 2 3 4 5
| @PostMapping("/getSign") public AjaxResult getSign(@RequestBody String url) { Map<String, String> sign = jsApiService.sign(url); return AjaxResult.success(sign); }
|
前端代码
这里我使用的是Vue,先安装 weixin-js-sdk,pip install即可。
考虑到Android和IOS适配我们需要写一个Config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
import wx from "weixin-js-sdk"; import { getSign } from '@/api/system/tab' export function isIOS() { let isIphone = navigator.userAgent.includes("iPhone"); let isIpad = navigator.userAgent.includes("iPad"); return isIphone || isIpad; }
export function requestWxStr() { getSign({ url: window.location.href.split('#')[0] }).then(res => { console.log('获取签名信息成功', res) wx.config({ debug: false, appId: res.data.appId, timestamp: res.data.timestamp, nonceStr: res.data.nonceStr, signature: res.data.signature, jsApiList: ['checkJsApi', 'scanQRCode'] }) }).catch(error => { console.log('获取签名信息失败', error) }) wx.ready(() => { wx.checkJsApi({ jsApiList: ['scanQRCode'], success: function(res) { alert("扫一扫准备就绪") } }) }) }
|
在Vue组件中使用,这里我用到的是微信扫一扫功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import wx from 'weixin-js-sdk' methods: { init() { if (!isIOS()) { requestWxStr() } }, scanBarCode(row, col) { var that = this this.scanData.rowNumber = row this.scanData.columnNumber = col wx.scanQRCode({ needResult: 1, scanType: ['barCode'], success: function(res) { const parts = res.resultStr.split(',') that.scanData.content = parts[1] that.isOpen = true }, error: function(res) { alert('识别error') } } ) },
|
然后就没有然后了,就搞定了。注意需要发布到线上才能测试,可以打印一些log测试。alert(xxx);