微信公众号扫一扫封装接口

一.微信准备功能

1.准备备案域名以及80端口服务器

本人准备是花生壳6元测试版

注册花生壳流程本人博客介绍花生壳IP配置流程

2.申请一个公众号

本人申请为个人订阅号(搜索公众号即可注册)

3.公众号配置appId和appsecret以及白名单

登录公众号——》选择左功能菜单开发——》基本配置(注意白名单里配置为服务器的外网IP)

 

4.公众号JS接口安全域名配置

填写域名,下载文件到tomcat/webapps/root下面

用域名加文件名,可以访问里面的内容即验证成功

 

二.代码实现功能(需加入公众号的appId和appsecret)

1.微信扫一扫功能封装接口wechatOpt.js

/**
 * 微信相关通用操作js
 */

var weChatObj = {
		
		//微信扫一扫配置
		wxScanConfig : function(url,callback){
			var sUrl = window.location.href;
			//mylayer.loading();
			$.ajax({
				url:url,
				type:"post",
				data:{"s_url":sUrl},
				dataType:"json",
				async: false,
				success:function(data){
					layer.closeAll();
					if(data.success){
						var retData = data.obj;
						wx.config({
						    debug:false , // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
						    appId: retData.appId, // 必填,公众号的唯一标识
						    timestamp:retData.timestamp, // 必填,生成签名的时间戳
						    nonceStr: retData.nonceStr, // 必填,生成签名的随机串
						    signature: retData.signature,// 必填,签名
						    jsApiList: [
										'checkJsApi',
										'scanQRCode'
						                ] // 必填,需要使用的JS接口列表
						}); 
						
						weChatObj.wxScanCheck(callback);
					}
				},
				error:function(){    
					layer.closeAll();   // 数据异常需要关闭弹出层
					//mylayer.msg("网络繁忙,请刷新页面重试",{icon:2,time:1500});
				}
			});
		},
		
		//微信扫一扫jsApi检查
		wxScanCheck : function(callback){
			wx.ready(function () {
				 wx.checkJsApi({
				      jsApiList: [
								'checkJsApi',
								'scanQRCode'
				      ],
				      success: function (res) {
				    	  weChatObj.wxScanCode(callback);
				      }
		        });
			});
		},
		
		//调用微信扫一扫接口
		wxScanCode : function(callback){
			wx.scanQRCode({
		        needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
		        scanType: ["qrCode"], // 可以指定扫二维码还是一维码,默认二者都有
		        success: function (res) {
		        	if(typeof callback == "function"){
						callback(res);
				  } 
		            
		        },
		        cancel : function(res){
		        	wx.closeWindow();
		        }
		    });
		},
		
		//微信定位配置
		wxLocateConfig : function(callback){
			var sUrl = window.location.href;
			//mylayer.loading();
			$.ajax({
				url:"/AisinoCDWL/wechat/page/shware/getWxScanSign.do",
				type:"post",
				data:{"s_url":sUrl},
				dataType:"json",
				async: false,
				success:function(data){
					if(data.success){
						var retData = data.obj;
						wx.config({
						    debug:false , // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
						    appId: retData.appId, // 必填,公众号的唯一标识
						    timestamp:retData.timestamp, // 必填,生成签名的时间戳
						    nonceStr: retData.nonceStr, // 必填,生成签名的随机串
						    signature: retData.signature,// 必填,签名
						    jsApiList: [
										'checkJsApi',
										'openLocation',
								        'getLocation'
						                ] // 必填,需要使用的JS接口列表
						}); 
						
						weChatObj.wxLocateCheck(callback);
					}else{
						//mylayer.msg("微信定位功能调用失败,请刷新重试",{icon:2,time:1500});
					}
				},
				error:function(){    
					layer.closeAll();   // 数据异常需要关闭弹出层
					//mylayer.msg("网络繁忙,请刷新页面重试",{icon:2,time:1500});
				}
			});
		},
		
		//微信jsApi检查
		wxLocateCheck : function(callback){
			wx.ready(function () {
				wx.checkJsApi({
				    jsApiList: [
				        'getLocation'
				    ],
				    success: function (res) {
				        if (res.checkResult.getLocation == false) {
				           // mylayer.msg('你的微信版本太低,不支持微信JS接口,请升级到最新的微信版本!',{icon:2,time:1500});
				            return;
				        }
				        if(typeof callback == "function"){
							callback(res);
				        } 
				    }
				});
			});
		},
		
		//微信上传图片
		wxUploadImg : function(callback){
			var sUrl = window.location.href;
			$.ajax({
				url:"/AisinoCDWL/wechat/page/shware/getWxScanSign.do",
				type:"post",
				data:{"s_url":sUrl},
				dataType:"json",
				async: false,
				success:function(data){
					if(data.success){
						var retData = data.obj;
						wx.config({
						    debug:false , // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
						    appId: retData.appId, // 必填,公众号的唯一标识
						    timestamp:retData.timestamp, // 必填,生成签名的时间戳
						    nonceStr: retData.nonceStr, // 必填,生成签名的随机串
						    signature: retData.signature,// 必填,签名
						    jsApiList: [
										'checkJsApi',
								        'chooseImage',
										'uploadImage',
								        'downloadImage',
								        'getLocalImgData'
						                ] // 必填,需要使用的JS接口列表
						}); 
						weChatObj.wxUploadImgCheck(callback);
					}else{
						//mylayer.msg("微信上传图片相关功能验证失败,请刷新重试",{icon:2,time:1500});
					}
				},
				error:function(){    
					layer.closeAll();   // 数据异常需要关闭弹出层
					//mylayer.msg("网络繁忙,请刷新页面重试",{icon:2,time:1500});
				}
			});
		},
		//验证上传图片相关微信接口
		wxUploadImgCheck : function(callback){
			wx.ready(function () {
				wx.checkJsApi({
				    jsApiList: [
						'chooseImage',
						'uploadImage',
						'downloadImage',
						'getLocalImgData'
				    ],
				    success: function (res) {
				        if (res.checkResult.getLocation == false) {
				            //mylayer.msg('你的微信版本太低,不支持微信JS接口,请升级到最新的微信版本!',{icon:2,time:1500});				           
				            return;
				        }
				        if(typeof callback == "function"){
							callback(res);
				        } 
				    }
				});
			});
		}
};

2.微信前端调用扫一扫方法wechatmbl.jsp

​
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>
<html>
<head>
    <title>
    </title>
     <!--引用微信JS库-->
    <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
    <!--引用jQuery库-->
    <script type="text/javascript" src="<%=basePath%>static/js/jquery-2.1.4.js"></script>
    <script type="text/javascript" src="<%=basePath%>static/js/wechatOpt.js"></script>
    <script type="text/javascript" src="<%=basePath%>static/js/layer.js"></script>
    <meta charset="utf-8">
<script type="text/javascript">
var basePath = '<%=basePath%>';
var url = basePath+ "wechat/page/shware/getWxScanSign.do";
weChatObj.wxScanConfig(url,callback);

//扫一扫的回调函数
function callback(res){
	var result = JSON.parse(res.resultStr);
	alert(result);
}
	
</script>
</head>
<body>
    <!-- <input type="button" value="扫一扫" id="scanQRCode"> -->
    <!-- <img src="static/Screenshot_20181031-104946.jpg"> -->
</body>
</html>

​

3.Https请求工具类HttpsUtil.java

package com.cooperation.weixin.util;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
 * 类名: MyX509TrustManager </br>
 * 描述:信任管理器 </br>
 * 开发人员: howin </br>
 * 创建时间: 2016-08-19 </br>
 * 发布版本:V1.0 </br>
 */
/*
 * 证书管理器的作用是让它新人我们指定的证书,
 * 此类中的代码意味着信任所有的证书,不管是不是权威机构颁发的。
 */
public class MyX509TrustManager implements X509TrustManager {
    // 检查客户端证书
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    // 检查服务器端证书
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    // 返回受信任的X509证书数组
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}
package com.taxsearch.util.KBUtil;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.json.JSONObject;
public class HttpsUtil {
	
	private static Logger log = LoggerFactory.getLogger(HttpsUtil.class);  
	
	/**
	 * @Title: httpsRequest
	 * @Description: (HTTP請求)
	 * @param: @param requestUrl
	 * @param: @param requestMethod
	 * @param: @param outputStr
	 * @param: @return  
	 * @return: JSONObject   
	 * @throws
	 */
	public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
	    JSONObject jsonObject = null;
	    try {
	      // 创建SSLContext对象,并使用我们指定的信任管理器初始化
	      TrustManager[] tm = { new MyX509TrustManager() };
	      SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
	      sslContext.init(null, tm, new java.security.SecureRandom());
	      // 从上述SSLContext对象中得到SSLSocketFactory对象
	      SSLSocketFactory ssf = sslContext.getSocketFactory();
	      URL url = new URL(requestUrl);
	      HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
	      conn.setSSLSocketFactory(ssf);
	      conn.setDoOutput(true);
	      conn.setDoInput(true);
	      conn.setUseCaches(false);
	      // 设置请求方式(GET/POST)
	      conn.setRequestMethod(requestMethod);
	      // 当outputStr不为null时向输出流写数据
	      if (null != outputStr) {
	        OutputStream outputStream = conn.getOutputStream();
	        // 注意编码格式
	        outputStream.write(outputStr.getBytes("UTF-8"));
	        outputStream.close();
	      }
	      // 从输入流读取返回内容
	      InputStream inputStream = conn.getInputStream();
	      InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
	      BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
	      String str = null;
	      StringBuffer buffer = new StringBuffer();
	      while ((str = bufferedReader.readLine()) != null) {
	        buffer.append(str);
	      }
	      // 释放资源
	      bufferedReader.close();
	      inputStreamReader.close();
	      inputStream.close();
	      inputStream = null;
	      conn.disconnect();
	      jsonObject = JSONObject.fromObject(buffer.toString());
	    } catch (ConnectException ce) {
	      log.error("连接超时:{}", ce);
	    } catch (Exception e) {
	      log.error("https请求异常:{}", e);
	    }
	    return jsonObject;
	  }
	
}

4.微信扫一扫后台接口,获取access_token,签名等WechatMblController.java

package com.taxsearch.controller.kp;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.taxsearch.commons.BaseController;
import com.taxsearch.commons.Logger;
import com.taxsearch.util.Json;
import com.taxsearch.util.KBUtil.HttpsUtil;

/**
 * 
 * <移动端-商品扫描Controller>
 * @author  swj
 * @version  [版本号, 2017年4月24日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@Controller("wechatMblController")
public class WechatMblController{
	
	private static final Logger log = Logger.getLogger(BaseController.class);
	
	/**
	 * 
	 * @file_name : WechatMblController.java
	 * @method : wechat
	 * @description : 进入扫描页面
	 * @author : linsa
	 * @return
	 * @date : 2018年11月2日
	 * @return : ModelAndView
	 */
	@RequestMapping(value="/wechat")
	public ModelAndView wechat(){
		ModelAndView mv=new ModelAndView();
		mv.setViewName("wl/wechatmbl");
		return mv;
	}
	
	/**
	 * 
	 * <获取微信扫一扫签名>
	 * @author  swj
	 * @date 2017年4月24日
	 * @param request
	 * @param response
	 * @param session
	 * @param model
	 * @see [类、类#方法、类#成员]
	 */
	@RequestMapping("wechat/page/shware/getWxScanSign")
	@ResponseBody
    public Json getWxScanSign(HttpServletRequest request,
			HttpServletResponse response, HttpSession session, Model model){
		Json retMap = new Json();
		
		String appId = "此为appID";
		String appsecret = "此为app密钥";
		//获取access_token
		String access_token = getToken(appId, appsecret);
		//获取JSTicket
		String sJsapiTicket = getJSTicket(access_token);
		
		Map<String,String> signResult = new HashMap<String,String>();
		
		String jsUrl = Str(request.getParameter("s_url"));
		log.info("获取调用页面: "+jsUrl);
		String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
		String nonceStr = getCharAndNumr(15);
		try {
			String signature = getSignature(sJsapiTicket, timestamp, nonceStr,jsUrl);
			signResult.put("appId", appId);
			signResult.put("timestamp", timestamp);
			signResult.put("nonceStr", nonceStr);
			signResult.put("signature", signature);
			
			retMap.setSuccess(true);
			retMap.setMsg("微信API签名获取成功!");
			retMap.setObj(signResult);
			log.info("获取微信签名完成:"+signResult+", jsUrl: "+jsUrl+",sJsapiTicket: "+sJsapiTicket);
		} catch (Exception e) {
			e.printStackTrace();
			retMap.setSuccess(false);
			retMap.setMsg("微信API签名获取失败!");
		}

		return retMap;
	}
	
	public String getSignature(String jsapi_ticket, String timestamp,
			String nonce, String jsurl) throws Exception {
		/****
		 * 对 jsapi_ticket、 timestamp 和 nonce 按字典排序 对所有待签名参数按照字段名的 ASCII
		 * 码从小到大排序(字典序)后,使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串
		 * string1。这里需要注意的是所有参数名均为小写字符。 接下来对 string1 作 sha1 加密,字段名和字段值都采用原始值,不进行
		 * URL 转义。即 signature=sha1(string1)。
		 * **如果没有按照生成的key1=value&key2=value拼接的话会报错
		 */
		String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
				"timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl };
		Arrays.sort(paramArr);
		// 将排序后的结果拼接成一个字符串
		String content = paramArr[0].concat("&" + paramArr[1])
				.concat("&" + paramArr[2]).concat("&" + paramArr[3]);
		// System.out.println("拼接之后的content为:"+content);
		String gensignature = null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			// 对拼接后的字符串进行 sha1 加密
			byte[] digest = md.digest(content.toString().getBytes());
			gensignature = byteToStr(digest);
		} catch (NoSuchAlgorithmException e) {
			// e.printStackTrace();
			log.error(e);
		}
		// 将 sha1 加密后的字符串与 signature 进行对比
		if (gensignature != null) {
			return gensignature;// 返回signature
		} else {
			return "false";
		}
	}
	
	/**
	 * 将字节数组转换为十六进制字符串
	 * 
	 * @param byteArray
	 * @return
	 */
	private String byteToStr(byte[] byteArray) {
		String strDigest = "";
		for (int i = 0; i < byteArray.length; i++) {
			strDigest += byteToHexStr(byteArray[i]);
		}
		return strDigest;
	}
	
	/**
	 * 将字节转换为十六进制字符串
	 * 
	 * @param mByte
	 * @return
	 */
	private String byteToHexStr(byte mByte) {
		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
				'B', 'C', 'D', 'E', 'F' };
		char[] tempArr = new char[2];
		tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
		tempArr[1] = Digit[mByte & 0X0F];
		String s = new String(tempArr);
		return s;
	}
	
	public String getCharAndNumr(int length) {
		String val = "";
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			// 输出字母还是数字
			String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
			// 字符串
			if ("char".equalsIgnoreCase(charOrNum)) {
				// 取得大写字母还是小写字母
				int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
				val += (char) (choice + random.nextInt(26));
			} else if ("num".equalsIgnoreCase(charOrNum)) { // 数字
				val += String.valueOf(random.nextInt(10));
			}
		}
		return val;
	}
	
	public String Str(Object obj){
		String str = "";
		if(obj!=null&&obj!=""){
			str = obj.toString();
		}
		return str;
	}
	
	/**
	 * 获取access_token
	 * @author gaomin
	 * @date 2018/11/2
	 *
	 */
	public String getToken(String appId, String appsecret){
		String infoUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
				+appId+"&secret="+appsecret;
		JSONObject result = HttpsUtil.httpsRequest(infoUrl, "GET", null);
		String access_token = "";
		if(result.containsKey("errcode")){
			access_token = "";
		}else{
			access_token = (String)result.get("access_token");
		}
		return access_token;
	}
	
	/**
	 * 获取JSTicket
	 * @author gaomin
	 * @date 2018/11/2
	 *
	 */
	public String getJSTicket(String access_token){
		String infoUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token="
				+ access_token;
		JSONObject result = HttpsUtil.httpsRequest(infoUrl, "GET", null);
		String jsTicket = (String)result.get("ticket");
		return jsTicket;
	}
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linsa_pursuer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值