微信公众号调用扫一扫_微信公众号调用微信扫一扫 - CSDN
精华内容
参与话题
  • 微信公众号,JS-SDK调用微信扫一扫

    千次阅读 2018-03-29 16:25:31
    微信公众号关联网页调用微信扫一扫功能,可以参照《微信公众平台技术文档》-> 微信JS-SDK说明文档,官方链接地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115步骤一:绑定...

    微信公众号关联网页调用微信扫一扫功能,可以参照《微信公众平台技术文档》-> 微信JS-SDK说明文档,官方链接地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

    步骤一:绑定域名

    先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。注:该域名不包括端口号,并且必须是备案过的域名。

    备注:登录后可在“开发者中心”查看对应的接口权限。

    步骤二:引入JS文件

    在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js

    备注:支持使用 AMD/CMD 标准模块加载方法加载

    步骤三:通过config接口注入权限验证配置

    所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。签名算法见文末的附录1,所有JS接口列表见文末的附录2

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名
        jsApiList: [] // 必填,需要使用的JS接口列表
    });

    步骤四:通过ready接口处理成功验证

    wx.ready(function(){
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
    });

    步骤五:通过error接口处理失败验证

    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    });

    调起微信扫一扫接口

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

    示例代码:

    tokenmanager管理类

    package com.wx.util;
    
    /**
     * AccessToken Manager
     * 
     * @author Administrator
     * 
     */
    public class TokenManager {
    	
    	// access_token
    	private static String accessToken = "";
    	// expires_in,有效时间
    	private static int expiresIn = 0;
    	// 获取access_token时的时间
    	private static long recordTime = 0;
    
    	/**
    	 * 获取token
    	 */
    	public static void init() throws Exception {
    		String appId = AppString.getAppid();
    		String appSecret = AppString.getAppsecret();
    		String url = "https://api.weixin.qq.com/cgi-bin/token";
    		String para = "grant_type=client_credential&appid=%s&secret=%s";
    		String param = String.format(Locale.ENGLISH, para, appId, appSecret);
    		String result = new HttpSender().sendGet(url, param);
    		Logger.getLogger(TokenManager.class.getName()).info(result);
    		JSONObject jResult = JSONObject.parseObject(result);
    		if (jResult.containsKey("errmsg")) {
    			String msg = jResult.getString("errmsg");
    			throw new Exception(msg);
    		} else {
    			accessToken = jResult.getString("access_token");
    			expiresIn = jResult.getIntValue("expires_in");
    			recordTime = System.currentTimeMillis();
    		}
    	}
    
    	/**
    	 * token是否过期,到期前10分钟内,更新token
    	 * 
    	 * @return
    	 */
    	public static boolean isTokenExpired() {
    		long currTime = System.currentTimeMillis();
    		if ((expiresIn - ((currTime - recordTime) / 1000)) < 600) {
    			return true;
    		} else {
    			return false;
    		}
    	}
    
    	public static String getAccessToken() {
    		return accessToken;
    	}
    
    	public static void setAccessToken(String accessToken) {
    		TokenManager.accessToken = accessToken;
    	}
    
    	public static int getExpiresIn() {
    		return expiresIn;
    	}
    
    	public static void setExpiresIn(int expiresIn) {
    		TokenManager.expiresIn = expiresIn;
    	}
    
    	public static long getRecordTime() {
    		return recordTime;
    	}
    
    	public static void setRecordTime(long recordTime) {
    		TokenManager.recordTime = recordTime;
    	}
    
    }
    

    TicketManager管理类

    package com.wx.util;
    
    /**
     * jsapi_ticket
     * 
     * @author Administrator
     * 
     */
    public class TicketManager {
    
    	// jsapi_ticket
    	private static String apiTicket = "";
    	// expires_in有效时间
    	private static int expiresIn = 0;
    
    	/**
    	 * 获取ticket
    	 * 
    	 * @throws Exception
    	 */
    	public static void init() throws Exception {
    		String token = TokenManager.getAccessToken();
    		String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
    		String para = "access_token=%s&type=jsapi";
    		String param = String.format(Locale.ENGLISH, para, token);
    		String result = new HttpSender().sendGet(url, param);
    		Logger.getLogger(TokenManager.class.getName()).info(result);
    		JSONObject jResult = JSONObject.parseObject(result);
    		if (jResult.containsKey("errcode")
    				&& (jResult.getIntValue("errcode") == 0)) {
    			apiTicket = jResult.getString("ticket");
    			expiresIn = jResult.getIntValue("expires_in");
    		} else {
    			throw new Exception(jResult.getString("errmsg"));
    		}
    	}
    
    	public static String getApiTicket() {
    		return apiTicket;
    	}
    
    	public static void setApiTicket(String apiTicket) {
    		TicketManager.apiTicket = apiTicket;
    	}
    
    	public static int getExpiresIn() {
    		return expiresIn;
    	}
    
    	public static void setExpiresIn(int expiresIn) {
    		TicketManager.expiresIn = expiresIn;
    	}
    
    }
    

    签名工具类JsSignUtil

    package com.wx.util
    /**
     * 签名工具类
     * 
     * @author Administrator
     * 
     */
    public class JsSignUtil {
    
    	/**
    	 * 签名工具
    	 * 
    	 * @param url
    	 * @return
    	 */
    	public static Map<String, String> sign(String url) {
    		Map<String, String> ret = new HashMap<String, String>();
    		if (TokenManager.getAccessToken().equals("")
    				|| TokenManager.isTokenExpired()) {
    			try {
    				TokenManager.init();
    				TicketManager.init();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    		String jsApiTicket = TicketManager.getApiTicket();
    		String nonceStr = create_nonce_str();
    		String timeStamp = create_timestamp();
    		String signature = "";
    		// 注意这里参数名必须全部小写,且必须有序
    		String str = "jsapi_ticket=" + jsApiTicket + "&noncestr=" + nonceStr
    				+ "×tamp=" + timeStamp + "&url=" + url;
    		Logger.getLogger(TokenManager.class.getName()).info(str);
    		try {
    			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    			crypt.reset();
    			crypt.update(str.getBytes("UTF-8"));
    			signature = byteToHex(crypt.digest());
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		ret.put("url", url);
    		ret.put("jsapi_ticket", jsApiTicket);
    		ret.put("nonceStr", nonceStr);
    		ret.put("timestamp", timeStamp);
    		ret.put("signature", signature);
    		ret.put("appId", AppString.getAppid());
    		Logger.getLogger(TokenManager.class.getName()).info(ret.toString());
    		return ret;
    	}
    
    	/**
    	 * 签名工具,二维码
    	 * 
    	 * @param url
    	 * @return
    	 */
    	public static Map<String, String> sign(HttpServletRequest req) {
    		Map<String, String> ret = new HashMap<String, String>();
    		if (TokenManager.getAccessToken().equals("")
    				|| TokenManager.isTokenExpired()) {
    			try {
    				TokenManager.init();
    				TicketManager.init();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    		String jsApiTicket = TicketManager.getApiTicket();
    		String nonceStr = create_nonce_str();
    		String timeStamp = create_timestamp();
    		String signature = "";
    		String url = req.getScheme() + "://" + req.getServerName() + "/main"; // 二维码扫描页
    		// 注意这里参数名必须全部小写,且必须有序
    		String str = "jsapi_ticket=" + jsApiTicket + "&noncestr=" + nonceStr
    				+ "×tamp=" + timeStamp + "&url=" + url;
    		Logger.getLogger(TokenManager.class.getName()).info(str);
    		try {
    			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    			crypt.reset();
    			crypt.update(str.getBytes("UTF-8"));
    			signature = byteToHex(crypt.digest());
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		ret.put("url", url);
    		ret.put("jsapi_ticket", jsApiTicket);
    		ret.put("nonceStr", nonceStr);
    		ret.put("timestamp", timeStamp);
    		ret.put("signature", signature);
    		ret.put("appId", AppString.getAppid());
    		Logger.getLogger(TokenManager.class.getName()).info(ret.toString());
    		return ret;
    	}
    
    	/**
    	 * 随机加密
    	 * 
    	 * @param hash
    	 * @return
    	 */
    	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;
    	}
    
    	/**
    	 * 产生随机串--由程序自己随机产生
    	 * 
    	 * @return
    	 */
    	private static String create_nonce_str() {
    		return UUID.randomUUID().toString();
    	}
    
    	/**
    	 * 由程序自己获取当前时间
    	 * 
    	 * @return
    	 */
    	private static String create_timestamp() {
    		return Long.toString(System.currentTimeMillis() / 1000);
    	}
    
    }

    调用二维码扫描jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*,com.wx.util.*"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
    <title>微信扫一扫</title>
    <link href="<%=request.getContextPath()%>/css/app_comm.css" rel="stylesheet" type="text/css" />
    <link href="<%=request.getContextPath()%>/css/app_style.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery.min.js"></script>
    <script type="text/javascript" src="<%=request.getContextPath()%>/js/app_comm.js"></script>
    <script type="text/javascript" src="<%=request.getContextPath()%>/js/common.js"></script>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    
    <%  
    //UserManager.init(request);
    Map<String, String> ret = new HashMap<String, String>();  
    //ret = JsSignUtil.sign(request.getRequestURL().toString());
    ret = JsSignUtil.sign(request); 
    %>
    
    <script type="text/javascript">  
        wx.config({  
            debug: false,  
            appId: '<%=ret.get("appId")%>',  
            timestamp:'<%=ret.get("timestamp")%>',  
            nonceStr:'<%=ret.get("nonceStr")%>',  
            signature:'<%=ret.get("signature")%>',  
            jsApiList : [ 'checkJsApi', 'scanQRCode' ]  
        });//end_config  
      
        wx.error(function(res) {  
            alert("出错了:" + res.errMsg);  
        });  
      
        wx.ready(function() {  
            wx.checkJsApi({  
                jsApiList : ['scanQRCode'],  
                success : function(res) {  
                }  
            });             
        });//end_ready  
        
        //扫描二维码  
        function qrscan(){      
            wx.scanQRCode({  
                    needResult : 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,  
                    scanType : [ "qrCode", "barCode" ], // 可以指定扫二维码还是一维码,默认二者都有  
                    success : function(res) {  
                        var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果  
                        document.getElementById("qrresult").value = result;//将扫描的结果赋予到jsp对应值上   
                        //将扫描结果放入input页
                        var url = "wx/handleQR?result=" + result;
                        window.location.href = url;                                        
                    }  
            });
        } 
        
        //扫码
        function scancd(){
    	  qrscan();   
        }
    
    </script>
    </head>
    
    <body>
    
    <div class="w_all app_main">
    	<div class="app_ch">
        	<ul>
            	<li><a href="javascript:void(0);" οnclick="scancd()"><b class="ico_app_c1"></b><i>扫码</i></a></li>
            </ul>
            <input type="hidden" id="qrresult" value=""/>
        </div>
    </div>
    </body>
    </html>

    完!!!

    展开全文
  • 该方法需引入微信js-sdk ,先npm安装 //在一个地方调用this.weixin()方法,比如说按钮 ...//写扫一扫方法 weixin() { var that = this; var url=''; var params = { ..... }; axios.post(url,param...

    该方法需引入微信js-sdk ,先npm安装

    //在一个地方调用this.weixin()方法,比如说按钮
    
    //写扫一扫方法
    weixin() {
            var that = this;
            var url='';
            var params = {
              .....
            };
            axios.post(url,params).then((res) => {
              var resulted = res.data.data;
              that.wxConfig = resulted;
              that.$wx.config({
                debug: false,
                appId: that.wxConfig.appid,
                timestamp: that.wxConfig.timestamp,
                nonceStr: that.wxConfig.noncestr,
                signature: that.wxConfig.signature,
                // 所有要调用的 API 都要加到这个列表中
                //要调用的微信接口
                jsApiList : [
                  'checkJsApi',
                  'startRecord',
                  'stopRecord',
                  'translateVoice',
                  'scanQRCode',
                  'openCard'
                ]
              });
              that.$wx.ready(function() {
                that.$wx.scanQRCode({
                  needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
                  scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
                  success: function(res) {
                    var objdata= res.resultStr; // 当needResult 为 1 时,扫码返回的结果             
                    that.text_search = objdata.assetqrcode
                    that.getAllTableData(that.text_search)//获取想要获取的数据,比如说table列表
                  }
                });
              });
    
            })
          },

     

    展开全文
  • 参考微信JS-SDK说明文档 尽管作用不是很大1.首先在JSP页面引入http://res.wx.qq.com/open/js/jweixin-1.1.0.js2.通过config接口注入权限验证配置

    参考微信JS-SDK说明文档 看到网上很多都说微信的说明文档很坑,在我看来,仔细阅读的话,介绍还是很全的。

    1.首先在JSP页面引入http://res.wx.qq.com/open/js/jweixin-1.1.0.js

    2.通过config接口注入权限验证配置

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,企业号的唯一标识,此处填写企业号corpid
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名,见附录1
        jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });

    3.通过ready接口处理成功验证

    wx.ready(function(){
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
    });

    4.通过error接口处理失败验证

    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    });

    5.调起微信扫一扫

    wx.scanQRCode({
        desc: 'scanQRCode desc',
        needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
        scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
        success: function (res) {
           // 回调
        }
        error: function(res){
              if(res.errMsg.indexOf('function_not_exist') > 0){
                   alert('版本过低请升级')
                }
         }
    });

    具体代码实现如下:

    scanBarcode.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html lang="zh-CN">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
    <head>
        <link rel="stylesheet" href="http://203.195.235.76/jssdk/css/style.css"/>
        <script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
        <link rel="stylesheet" href="../../../resources/css/example.css"/>
        <link rel="stylesheet" href="../../../resources/css/weui.min.css"/>
        <link rel="stylesheet" href="../../../resources/css/borrowScan.css"/>
    </head>
    <body>
    <div class="container" style="text-align: center;">
        <div class="body_bd body_fd">
            <a class="weui-btn weui-btn-primary weui-btn-zdy" id="scanQRCode1">
                <p>扫描条码</p>
            </a>
        </div>
    </div>
    <script type="text/javascript">
        $.ajax({
            url: "${pageContext.request.contextPath}/wechat/jsapisign",
            type: "post",
            data: {
                url: location.href.split('#')[0]
            },
            contentType: 'application/x-www-form-urlencoded;charset=utf-8',
            async: true,
            success: function (data) {
                wx.config({
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: data.appid, // 必填,公众号的唯一标识
                    timestamp: data.timestamp, // 必填,生成签名的时间戳
                    nonceStr: data.nonceStr, // 必填,生成签名的随机串
                    signature: data.signature,// 必填,签名,见附录1
                    jsApiList: ["scanQRCode"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
            }
        });
    
        wx.ready(function () {
            // 9.1.2 扫描二维码并返回结果
            document.querySelector('#scanQRCode1').onclick = function () {
                wx.scanQRCode({
                    needResult: 1,
                    desc: 'scanQRCode desc',
                    success: function (res) {
                        //扫码后获取结果参数赋值给Input
                        var url = res.resultStr;
                        //商品条形码,取","后面的
                        if (url.indexOf(",") >= 0) {
                            var tempArray = url.split(',');
                            var barCode = tempArray[1];
                            window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${basePath}/wechat/toBookDetail?barCode=" + barCode + "&response_type=code&scope=snsapi_base&state=BINDFACE#wechat_redirect";
                        } else {
                            alert("请对准条形码扫码!");
                        }
                    }
                });
            };
        });
    
        //初始化jsapi接口 状态
        wx.error(function (res) {
            alert("调用微信jsapi返回的状态:" + res.errMsg);
        });
    </script>
    </body>
    </html>

    微信验签代码 WxController.java

      /**
         * 微信验签
         * @param url
         * @return
         */
        @RequestMapping(value = "/jsapisign", method = {RequestMethod.GET, RequestMethod.POST}, produces = MEDIATYPE_CHARSET_JSON_UTF8)
        @ResponseBody
        public String jsApiSign(String url) {
            //添加微信js签名信息
            Map<String, String> signMap = WXJsapiticket.jsApiSign(url);
            return JSON.toJSONString(signMap);
        }

    用到的方法类

    WXJsapiticket.java

    public class WXJsapiticket {
        private static Logger logger = LoggerFactory.getLogger(WxController.class);
        /**
         * 微信jsapi验签
         * @param url
         * @return
         */
        public static Map<String, String> jsApiSign(String url) {
            Map<String, String> ret = new HashMap<String, String>();
            String nonce_str = CheckUtil.create_nonce_str();
            String timestamp = CheckUtil.create_timestamp();
            String jsapi_ticket = getJsApiTicket();
            String string1 = CheckUtil.getString1(nonce_str,timestamp,jsapi_ticket,url);
            String signature = CheckUtil.getSha1(string1);
            ret.put("appid", WXConstants.APPID);//取你自己的公众号appid
            ret.put("url", url);
            ret.put("jsapi_ticket", jsapi_ticket);
            ret.put("nonceStr", nonce_str);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            logger.info("jsApiSign------url=" + url + "-----jsapi_ticket=" + jsapi_ticket + "--------nonceStr=" + nonce_str + "--------timestamp=" + timestamp + "-------signature=" + signature);
            return ret;
        }
        public static String getJsApiTicket(){
            Map<String,Object> map = JsApiTicketCache.getInstance().getJsApiTicketAndExpiresIn();
            return (String) map.get("jsapi_ticket");
        }
    }

    CheckUtil.java

    public class CheckUtil {
        public static final String  token = "xiaodou"; //开发者自行定义Token
        /**
         * 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成字符串string1
         * @param nonce_str
         * @param timestamp
         * @param jsapi_ticket
         * @param url
         * @return
         */
        public static String getString1(String nonce_str,String timestamp,String jsapi_ticket,String url){
            //1.定义数组存放nonce_str,timestamp,jsapi_ticket,url
            String[] arr = {"noncestr="+nonce_str,"timestamp="+timestamp,"jsapi_ticket="+jsapi_ticket,"url="+url};
            //2.对数组进行排序
            Arrays.sort(arr);
            //3.生成字符串
            StringBuffer sb = new StringBuffer();
            for(String s : arr){
                sb.append(s);
                sb.append("&");
            }
            sb.deleteCharAt(sb.length()-1);
            return sb.toString();
        }
        public static String getSha1(String str){
            if(str==null||str.length()==0){
                return null;
            }
            char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9',
                    'a','b','c','d','e','f'};
            try {
                MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
                mdTemp.update(str.getBytes("UTF-8"));
                byte[] md = mdTemp.digest();
                int j = md.length;
                char buf[] = new char[j*2];
                int k = 0;
                for (int i = 0; i < j; i++) {
                    byte byte0 = md[i];
                    buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    buf[k++] = hexDigits[byte0 & 0xf];
                }
                return new String(buf);
            } catch (Exception e) {
                // TODO: handle exception
                return null;
            }
        }
        public static String create_nonce_str() {
            return UUID.randomUUID().toString();
        }
        public static String create_timestamp() {
            return Long.toString(System.currentTimeMillis() / 1000);
        }
    }

    JsApiTicketCatch.java(对jsapi_ticket的缓存可自行设置,redis或者存到数据库都是可行的)

    /**
     * 缓存ticket
     */
    public class JsApiTicketCache {
        //缓存jsapi_ticket的Map,map中包含jsapiTicket,expiresIn和缓存的时间戳time
        private Map<String, String> map = new HashMap<String,String>();
        private static JsApiTicketCache jsApiTicketCache = null;
        private JsApiTicketCache() { }
        // 静态工厂方法
        public static JsApiTicketCache getInstance() {
            if (jsApiTicketCache == null) {
                jsApiTicketCache = new JsApiTicketCache();
            }
            return jsApiTicketCache;
        }
        public Map<String, String> getMap() {
            return map;
        }
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
        /**
         * 获取 jsapi_ticket expires_in
         * @return
         */
        public Map<String,Object> getJsApiTicketAndExpiresIn() {
            Map<String,Object> result = new HashMap<String,Object>();
            JsApiTicketCache jsApiTicketCache = JsApiTicketCache.getInstance();
            Map<String, String> map = jsApiTicketCache.getMap();
            String time = map.get("time");
            String jsapiTicket = map.get("jsapi_ticket");
            String expiresIn = map.get("expires_in");
            Long nowDate = new Date().getTime();
            if (jsapiTicket != null && time != null && expiresIn!=null) {
                //这里设置过期时间为微信规定的过期时间减去5分钟
                int outTime = (Integer.parseInt(expiresIn)-300) * 1000;
                if (nowDate - Long.parseLong(time) < outTime) {
                    System.out.println("-----从缓存读取jsapi_ticket:" + jsapiTicket);
                    //从缓存中拿数据为返回结果赋值
                    result.put("jsapi_ticket", jsapiTicket);
                    result.put("expires_in", expiresIn);
                }
            } else {
                JsapiTicket info = WeiXinUtil.getjsapiTicket();//实际中这里要改为你自己调用微信接口去获取jsapi_ticket和expires_in
                System.out.println("-----通过调用微信接口获取jsapi_ticket:" + info.getJsapiTicket());
                //将信息放置缓存中
                map.put("time", nowDate + "");
                map.put("jsapi_ticket", info.getJsapiTicket());
                map.put("expires_in", info.getExpiresIn()+"");
                //为返回结果赋值
                result.put("jsapi_ticket", info.getJsapiTicket());
                result.put("expires_in", info.getExpiresIn());
            }
            return result;
        }
    
    }

    WeiXinUtil.java

    jsapi_ticket_url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";//GET方式请求获得jsapi_ticket
     /**
         * 获取jsapi_ticket
         * @return
         */
        public static JsapiTicket getjsapiTicket() {
            JsapiTicket jsapiTicket = null ;
            String accessToken = (String) AccessTokenCache.getInstance().getAcessTokenAndExpiresIn().get("access_token");
            String requestUrl = WXConstants.jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken);
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
            // 如果请求成功
            if (null != jsonObject) {
                try {
                    jsapiTicket = new JsapiTicket();
                    jsapiTicket.setJsapiTicket(jsonObject.getString("ticket"));
                    jsapiTicket.setExpiresIn(jsonObject.getInt("expires_in"));
                } catch (JSONException e) {
                    jsapiTicket = null;
                    // 获取token失败
                    log.error("获取ticket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return jsapiTicket;
        }

    accessToken的获取参照微信公众号开发之获取access_token,也可根据自己的定义获取。

    JsapiTicket.java

    public class JsapiTicket {
        private String id;
        private String jsapiTicket;
        private int expiresIn;
    
        public String getJsapiTicket() {
            return jsapiTicket;
        }
    
        public void setJsapiTicket(String jsapiTicket) {
            this.jsapiTicket = jsapiTicket;
        }
    
        public int getExpiresIn() {
            return expiresIn;
        }
    
        public void setExpiresIn(int expiresIn) {
            this.expiresIn = expiresIn;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    }

    在这里总结一下开发中需要注意的地方(我遇到的坑):

    1.确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。

    2.在生成string1时,拼接的参数均为小写,特别注意noncestr,而在jsp页面中为nonceStr(所有的参数一定要根据微信接口中的定义,否则会导致验签失败)。

    3.验证签名是否正确,可在 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign页面工具进行校验。

    展开全文
  • 最近其他项目组需要在微信公众号里面调用微信的扫一扫功能,于是就帮忙一起搞了搞,一开始以为挺简单,从网上搜一下教程弄一下就可以了,没成想还挺麻烦的,网上的教程呢好多都是会了不用看,不会的看了也没啥用的...

    目录

     

    前言:

    准备条件:

    用到的微信接口

    代码:

    效果:

    总结:


    前言:

        最近其他项目组需要在微信公众号里面调用微信的扫一扫功能,于是就帮忙一起搞了搞,一开始以为挺简单,从网上搜一下教程弄一下就可以了,没成想还挺麻烦的,网上的教程呢好多都是会了不用看,不会的看了也没啥用的。于是自己在弄完以后想着写一篇博客,造福一下大家。希望对大家能有所帮助。

    准备条件:

       1、ICP备案的域名,并且绑定对应的外网服务器。

           用处:你写的扫一扫功能的代码只有放到这个域名所对应的服务器中运行才能成功调起扫一扫功能。

          如果你准备好了域名,那么按照以下操作添加:

              (1)、打开微信公众号——设置——公众号设置——功能设置——JS接口安全域名中添加上你的域名。

       (2)、接下来的步骤是非常重要的,如下图,仔细阅读下图红框中的文字,明白它的意思。需要你下载红框中的文件,然后上传到域名绑定服务器的根目录下面,只有这样你的域名在此处才能添加成功。举个例子:通常访问域名会默认访问80端口,你可以在服务器上安装tomcat并设置端口号为80,然后将此处下载的文件放到tomcat中的webapp文件夹下面,也就和你的项目相同路径的文件夹下。如果你还不懂,博客下面会有我的微信,欢迎咨询。

    ps:由于微信开发中很多地方都用了域名,所以这里提供一个不用阿里云或者腾讯云备案的方法,利用natapp内网穿透,直接将本机设置为服务器并获得域名。填写域名时不要带着http://,例如http://www.baidu.com,只写www.baidu.com就行。

    https://natapp.cn/member/dashborad具体设置方法可以看里面的教程,不过这里需要购买VIP_1型隧道,免费的会被微信屏蔽。

    直接映射本地的80端口,然后用nginx做内部转发,就可以访问h5页面或者本地的后台服务。

    2、微信公众好的AppID和AppSecret,查看地方在:开发者——基本配置中,如下图。用于生成access_token使用

    3、IP白名单设置,查看地方在:开发者——基本配置中,如下图。在此处添加你的服务器IP,访问生成access_token的接口需要在添加了白名单的服务中访问,否则无法获取access_token

    以上条件准备好之后才能实现调用微信扫一扫功能,我用的是阿里云服务器,并且备案了对应的域名,然后使用自己的微信公众号。

    用到的微信接口:

    1、获取access_token接口:GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

    其中grant_type参数的固定值是:client_credential

    微信开发者文档地址:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

    2、获取ticket接口:http请求方式: GET https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=wx_card

    微信开发者文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#49

    PS:通过grant_type、appid、secret参数获取access_token;再根据access_token获取ticket。

          access_token和ticket的有效期是7200秒(两小时),后续代码中会提供解决它们时效性的方法。

    代码:

    1、JSSDK使用步骤,参考微信开发者文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#3

    对应我自己的代码:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=0">
        <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"> </script>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
    </head>
    <body>
    
    <div class="lbox_close wxapi_form">
        <h3>微信扫一扫</h3>
        <input id="codeValue">
        <button id="scanQRCode">扫码</button>
    
    </div>
    <script type="text/javascript">
        $(function() {
            //需要把当前页面的url地址传到后台,生成签名信息时需要使用到。下面的地址是controller层调用当前页面的路径
            var tokenUrl= "http://服务器域名/jsapi/ape/v1/qrcode";
            //获取签名的后台接口
            var _getWechatSignUrl = '/jsapi/getSign';
    
            $(document).ready(function(){
                //获取签名
                $.ajax({
                    url:_getWechatSignUrl,
                    data:{tokenUrl:tokenUrl},
                    dataType:"json",
                    success:function(res){
                        console.log(res);
                        //获得签名之后传入配置中进行配置
                        wxConfig(res.appId,res.timestamp,res.nonceStr,res.signature);
                    }
                })
            })
    
            function wxConfig(_appId,_timestamp, _nonceStr, _signature) {
                console.log('获取数据:' + _timestamp +'\n' + _nonceStr +'\n' + _signature);
                wx.config({
                    debug:true,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: _appId,// 必填,公众号的唯一标识
                    timestamp: _timestamp,// 必填,生成签名的时间戳
                    nonceStr: _nonceStr,// 必填,生成签名的随机串
                    signature: _signature,// 必填,签名,见附录1
                    jsApiList: ['checkJsApi','scanQRCode']
                    // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
            }
    
            $("#scanQRCode").click(function(event){
                wx.scanQRCode({
                    desc: 'scanQRCode desc',
                    needResult : 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
                    scanType : [ "qrCode", "barCode" ], // 可以指定扫二维码还是一维码,默认二者都有
                    success : function(res) {
                        console.log("调用扫描成功",res);
                        var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
                        $("#codeValue").val(result);//显示结果
                        alert("扫码结果为:" + result);
                    },
                    error:function(res){
                        console.log(res)
                    }
                });
            })
    
        });
    </script>
    
    </body>
    </html>

    代码解析:

    ps:调用微信扫一扫接口文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#49

    后台代码:

    1、QRCodeController.java。仔细看代码中的注释

    package com.lyd.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import com.lyd.pojo.JsonData;
    import com.lyd.service.JsApiService;
    import com.lyd.utils.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.data.repository.query.Param;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.Map;
    
    /**
     * @author Lyd
     * @date 2020/5/11 22:32
     */
    @Controller
    @RequestMapping("/jsapi")
    public class QRCodeController {
        private static final Logger log = LoggerFactory.getLogger(WechatUtil.class);
        @Autowired
        private RedisClient redisClient;
    
        @Autowired
        @Qualifier("wxJsService")
        private JsApiService jsApiService;
    
        /**
         * 用于返回        appId: _appId,// 必填,公众号的唯一标识
         *                 timestamp: _timestamp,// 必填,生成签名的时间戳
         *                 nonceStr: _nonceStr,// 必填,生成签名的随机串
         *                 signature: _signature,// 必填,签名,见附录1
         * 该方法会调用获取token、ticket两个方法,token和ticket需要从redis中获取
         * 该方法会调用redis并将生成的token、ticket保存到redis中同时设置失效时间
         * @param tokenUrl:微信扫一扫页面的路径
         * @param request
         * @return
         */
        @GetMapping(value = "/getSign")
        @ResponseBody
        public Map<String, String> scanJsApi(@Param("tokenUrl") String tokenUrl, HttpServletRequest request) {
            boolean redisAccess_token = redisClient.hasKey("access_token");
            boolean redisTicket = redisClient.hasKey("ticket");
            //判断从redis中获取的两个key值是否失效,如果没有则调用生成access_token和ticket的方法重新生成并保存到redis中
            if (redisAccess_token == false || redisTicket == false) {
                //调用生成access_token的方法
                JSONObject jsonObject=WechatUtil.getAccessToken();
                //如果access_token生成成功,则获取生成的access_token,并且保存到redis中,设置access_token的有效时间为7200秒
                if(jsonObject.containsKey("access_token")){
                    String access_token = jsonObject.getString("access_token");
                    log.info("=========获取access_token成功:"+access_token);
                    redisClient.setKeyValueAndTimeOut("access_token",access_token,7200);
                    log.info("=========access_token保存成功================");
                    //调用生成ticket的方法,获取ticket,并保存到redis中,设置ticket的有效时间为7200秒
                    JSONObject ticketJsonObject= WechatUtil.getJsApiTicket(redisClient.getRedis("access_token"));
                    if(ticketJsonObject.containsKey("ticket")){
                        String ticket = ticketJsonObject.getString("ticket");
                        log.info("=========获取ticket成功:"+ticket);
                        redisClient.setKeyValueAndTimeOut("ticket",ticket,7200);
                        log.info("=========ticket保存成功================");
                    }else {
                        log.info("=========ticket保存失败,失败信息:"+ticketJsonObject);
                    }
                }else{
                    log.info("=========获取token失败,失败信息:"+jsonObject);
                }
    
            }
            //调用获取签名的方法
            Map<String, String> res = jsApiService.sign(tokenUrl);
            return res;
        }
    
        /**
         * 微信扫一扫页面,访问路径
         * @return  微信扫一扫页面
         */
        @RequestMapping(value="/ape/v1/qrcode")
        public Object test(){
            return "user/qrcode";
        }
    }

    2、JsApiService.java:获取签名的实际实现类

    package com.lyd.service;
    
    import com.lyd.utils.*;
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    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.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    /**
     * @author Lyd
     * @date 2020/5/11 22:34
     */
    @Component("wxJsService")
    @Transactional
    public class JsApiService{
        private static final Logger log = LoggerFactory.getLogger(WechatUtil.class);
        @Autowired
        private RedisClient redisClient;
    
        /**
         * 获取签名
         * @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();
            String jsapiTicket =redisClient.getRedis("ticket");
            log.info("###########读取ticket:"+jsapiTicket);
            //这里签名中的nonceStr要与前端页面config中的nonceStr保持一致,所以这里获取并生成签名之后,还要将其原值传到前端
            String nonceStr = createNonceStr();
            //nonceStr
            String 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", Constants.GZH_APPID);
            log.info("###########打印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);
        }
    }
    

    3、Constants.java存放常量的类

    package com.lyd.utils;
    
    /**
     * @author Lyd
     * @date 2020/5/11 22:35
     */
    public class Constants {
        /**
         * 换取ticket的url
         */
        public static final String JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
        /**
         * 换取token的url
         */
        public static final String JSAPI_TOKEN = " https://api.weixin.qq.com/cgi-bin/token";
       
        public static final String GZH_APPID = "公众号的AppID";
        public static final String GZH_SECURET = "公众号的AppSecret";
    }
    

    4、HttpClientUtil .java用于访问获取access_token、ticket接口的工具类

    package com.lyd.utils;
    
    /**
     * @author Lyd
     * @date 2020/5/11 22:37
     */
    import java.io.IOException;
    import java.net.URI;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    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;
    
    public class HttpClientUtil {
    
        public static String doGet(String url, Map<String, String> param) {
    
            // 创建Httpclient对象
            CloseableHttpClient httpclient = HttpClients.createDefault();
    
            String resultString = "";
            CloseableHttpResponse response = null;
            try {
                // 创建uri
                URIBuilder 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);
                // 判断返回状态是否为200
                if (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;
        }
    }
    

    5、RedisClient.java用于操作redis的工具类,方便添加、修改、删除redis中的相关key-value

    package com.lyd.utils;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Component;
    
    import java.util.concurrent.TimeUnit;
    
    /**Redis工具类,用于存贮key-value和读取keyvalue
     * @Author:Lyd
     * @Date 2019/12/30 21:22
     */
    @Component
    public class RedisClient {
        @Autowired
        private StringRedisTemplate redisTemplate;
    
        /**
         * 设置key-value到redis中
         * @param key
         * @param value
         * @return
         */
        public  boolean setRedis(String key,String value){
            try{
                redisTemplate.opsForValue().set(key,value);
                return true;
            }catch (Exception e){
                return false;
            }
        }
        /**
         * 实现命令:SET key value EX seconds,设置key-value和超时时间(秒)
         *
         * @param key
         * @param value
         * @param timeout (以秒为单位)
         */
        public void setKeyValueAndTimeOut(String key, String value, long timeout) {
            redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
        }
        /**
         * 从Redis中获取key对应的value
         * @param key
         * @return
         */
        public String getRedis(String key){
            return redisTemplate.opsForValue().get(key);
        }
        /**
         * 从Redis中获取key对应的value
         * @param key
         * @return
         */
        public boolean hasKey(String key){
            return redisTemplate.hasKey(key);
        }
    
    }
    

    6、WechatUtil.java获取access_token、ticket的实现方法

    package com.lyd.utils;
    
    /**
     * @author Lyd
     * @date 2020/5/11 22:37
     */
    
    import com.alibaba.fastjson.JSONObject;
    import org.apache.commons.lang3.StringUtils;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**微信工具类
     * @author:Lyd
     * @Date 2020/5/13 10:02
     */
    public class WechatUtil {
        /**
         * 获得jsapi_ticket
         */
        public static JSONObject getJsApiTicket(String token) {
            String url = Constants.JSAPI_TICKET
                    + "?access_token=" + token
                    + "&type=jsapi";
            String msg = HttpClientUtil.doGet(url);
            if (StringUtils.isBlank(msg)) {
                return null;
            }
            JSONObject jsonObject = JSONObject.parseObject(msg);
            return jsonObject;
        }
    
        /**
         * 获取token
         * @return msg
         */
        public static JSONObject getAccessToken() {
            String url = Constants.JSAPI_TOKEN;
            Map<String, String> param = new HashMap<>(16);
            param.put("grant_type", "client_credential");
            param.put("appid", Constants.GZH_APPID);
            param.put("secret", Constants.GZH_SECURET);
            String msg = HttpClientUtil.doGet(url, param);
            if (StringUtils.isBlank(msg)) {
                return null;
            }
            JSONObject jsonObject = JSONObject.parseObject(msg);
            return jsonObject;
        }
    }
    
    

    配置文件:

    pom.xml中需要引入的相关jar

    <!--调用微信扫一扫所需要的jar包-->
    		<dependency>
    			<groupId>com.google.zxing</groupId>
    			<artifactId>core</artifactId>
    			<version>3.3.0</version>
    		</dependency>
    		<dependency>
    			<groupId>com.google.zxing</groupId>
    			<artifactId>javase</artifactId>
    			<version>3.3.0</version>
    		</dependency>
    
    		<dependency>
    			<groupId>com.alibaba</groupId>
    			<artifactId>fastjson</artifactId>
    			<version>1.2.44</version>
    		</dependency>
    		<dependency>
    			<groupId>com.vaadin.external.google</groupId>
    			<artifactId>android-json</artifactId>
    			<version>0.0.20131108.vaadin1</version>
    			<scope>compile</scope>
    		</dependency>

    application.properties

    #=========redis基础配置=========
    spring.redis.database=0
    
    #redis的安装地址
    spring.redis.host=localhost
    spring.redis.port=6379
    # 连接超时时间 单位 ms(毫秒)
    spring.redis.timeout=3000
    
    #=========redis线程池设置=========
    # 连接池最大连接数(使用负值表示没有限制)
    spring.redis.jedis.pool.max-active=200
    # 连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.jedis.pool.max-wait=-1
    # 连接池中的最大空闲连接
    spring.redis.jedis.pool.max-idle=200
    # 连接池中的最小空闲连接
    spring.redis.jedis.pool.min-idle=200

    ps:我遇到的一个问题,我的redis也装在域名对应的外网服务器上。在本地可以通过IP访问通,但是当我把项目放到服务器上的时候,用IP不行,用localhost就没有问题。

    redis的安装和集成到springboot可以参考我的博客:https://blog.csdn.net/m0_37027631/article/details/103766194

    效果:

                       

    总结:

      用了大概两天的时间将全流程弄通了,期间还是很有意义的,即使以后不再用到也写一个帖子记录以下吧。有不懂的小伙伴可以加我微信幺,欢迎咨询。

       相关源码在我的码云中:https://gitee.com/lydzyw/springbootLyd。该项目是我用来自己学习用的,里面还有其他的东西,大家有兴趣可以下载下来自己学习使用。

    我的微信号:

     

     

    展开全文
  • 1、安装、引用微信js-sdk #通过yarn安装 yarn add weixin-js-sdk #通过npm安装 npm i weixin-js-sdk 项目中的引用 import wx from 'weixin-js-sdk' ...wx.scanQRCode 调用微信扫一扫接口(官...
  • 微信公众号调用扫一扫

    千次阅读 2019-04-27 15:58:00
    文章目录微信公众号调用扫一扫1.申请测试账号2.通过AppID和AppSecret获取access_token3.通过access_token添加菜单4.通过access_token获取jsapi_ticket5.配置JS接口安全域名6.在js中添加以下代码7.调用扫码 微信...
  • 根据微信api,整理了一下调用微信扫一扫功能。如有问题请指正: 以下是具体步骤: 1、绑定域名(很关键)2、引入JS文件(很简单) script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js">script>3、通过...
  • 微信公众号调取扫一扫功能

    千次阅读 2019-10-19 16:41:45
    1、先获取扫一扫信息进行授权 // 扫一扫获取授权 author_WX() { let url=window.location.href.split("#")[0]; //正确 //调取后台接口 获取wx.config的配置信息 getWeix({ url: url, }).the...
  • JAVA微信公众号调用扫一扫功能开发

    千次阅读 2017-12-21 12:25:56
    微信扫一扫功能调用开发里面整个我开发的项目,直接下载导入eclipse中就可启动使用配置好自己的appid和screet即可
  • 微信企业号或微信公众号调用扫一扫功能JS-SDK安全域名配置配置设置好之后下面就上代码java代码 JS-SDK安全域名配置 企业微信号 —— 安全域名配置需要通过验证(如下图) 微信公众 ——— 安全域名配置 设置 ——&...
  • 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。 备注:登录后可在“开发者中心”查看对应的接口权限。 这里注意域名不要带http:// 等前缀。(顺便推荐做微信开发测试时,使用花生壳...
  • 1、前端页面: <!DOCTYPE html> <html> <head>...meta charset="utf-8">...扫一扫测试</title> <meta name="renderer" content="webkit"> <meta http-equiv=...
  • 求大神给个 微信开发 微信公众号sdk 调用扫一扫功能 java 项目 demo
  • ![图片说明]...!...段点看到wx.config获取的所需要的APPid签名等数据,后来用wx.ready也验证wx.config成功了。...手机上测试也没有出现扫一扫的拍照界面。求大佬帮忙看看具体是什么问题,在线等
  •  去微信公众号平台中设置js接口安全域名,要注意的是不填写http://, 只填写域名即可,如 www.baidu.com。 个月只能修改三次,要谨慎填写。 2.引入JS文件 在页面中引入微信js脚本文件。 <script src=...
  • 所以就需要使用微信公众平台提供的JSSDK来调用扫一扫功能。仅以此来记录自己的学习过程,也希望能帮助到有此需求的一些朋友。 过程中参考文章有:https://blog.csdn.net/u011327333/article/details/50439...
  • 微信公众号开发之微信扫一扫

    千次阅读 2019-05-27 22:32:59
    最近开发一个食堂项目,项目中用到使用微信扫一扫实现项目中的扫一扫的功能。 1、添加点击扫一扫的触发事件的按钮 <span id="scanQRCode">扫一扫</span> 2、添加微信扫一扫的js引用 <script ...
  • 微信公众号开发()服务器及接口的配置

    万次阅读 多人点赞 2019-05-22 09:21:41
    微信公众号开发()服务器及接口的配置 关于微信公众号中的订阅号和服务的区别这里不多加讨论,网上有很多资源可以搜到,这里直接进入正题,如果是个人开发者,这里建议使用测试号进行开发学习,测试号的权限要比...
  • 微信公众号中实现获取openid与调用扫一扫功能 环境:微信公众号,vue,脚手架,vuex(可以不用)。 问题:history模式下ios端要同时获取openid与调用微信扫一扫功能非常麻烦。建议将模式修改成hash。 需要提前...
  • npm install weixin-js-sdk --save <template> <div class="con"> <header class="tit">请扫描需要识别的设备二维码<...img id="scan" @click="onscan" :src="scan" style="margin:...
1 2 3 4 5 ... 20
收藏数 12,193
精华内容 4,877
关键字:

微信公众号调用扫一扫