1. scan.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="js/jquery-1.9.1.js"></script>
<!--依赖文件:微信的JS-SDK源文件-->
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<title>扫一扫</title>
</head>
<body>
<div style="width:200px; background-color: gray;" id="scanQRCode">
<img src="<c:url value='/image/scan.png'/>" style="width:200px"></img>
</div>
<script type="text/javascript">
$(function(){
var targetUrl = location.href.split('#')[0];
//alert('targetUrl : '+targetUrl)
//配置调用手机微信功能
$.ajax({
type: "post",
url: '<%=basePath%>sample.do',
dataType:"json",
data:{"targetUrl":targetUrl},
success: function(ret){
//通过config接口注入权限验证配置
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: ret.appId, // 必填,企业号的唯一标识,此处填写企业号corpid
timestamp: ret.timestamp, // 必填,生成签名的时间戳
nonceStr: ret.nonceStr, // 必填,生成签名的随机串
signature: ret.signature,// 必填,签名,见附录1
jsApiList: ['scanQRCode','chooseImage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 ,配置多个时用英文逗号“,”隔开。
});
}
});
});
$("#scanQRCode").click(function(){
wx.scanQRCode({
desc: 'scanQRCode desc',
//本人测试发现0适用于二维码,1适用于一维码;
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
success: function (res) {
//alert(res);
var url = res.resultStr; // 商品条形码,取","后面的
//alert(res.resultStr)
if (url.indexOf(",") >= 0) {
var tempArray = url.split(',');
var tempNum = tempArray[1];
alert("条形码 : "+tempNum);
} else {
alert("url.indexOf(',') < 0");
}
},
error: function(res) {
if (res.errMsg.indexOf('function_not_exist') > 0) {
alert('版本过低请升级')
}
}
});
});
</script>
</body>
</html>
2. Wx_JS_SDK_Controller.java
package com.want.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.want.util.ServerEnvUtil;
import com.want.util.WeixinUtil;
import com.want.pojo.AccessToken;
import net.sf.json.JSONObject;
@Controller
public class Wx_JS_SDK_Controller {
private static final Logger logger = Logger.getLogger(Wx_JS_SDK_Controller.class);
/**
* 程序入口
*
* 例如:
* https://open.weixin.qq.com/connect/oauth2/authorize?appid=第三方用户唯一凭证
* &redirect_uri=http://第三方用户域名/项目名/main.do
* &response_type=code&scope=snsapi_base&state=sunlight#wechat_redirect
*
* @param request
* @param response
* @return
* @throws IOException
*/
@RequestMapping(value = "/main.do")
public ModelAndView main(HttpServletRequest request, HttpServletResponse response) throws IOException {
ModelAndView mv = new ModelAndView("/scan");
return mv;
}
/**
* js-sdk
*
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value = "/sample.do")
public void Sample(HttpServletRequest request, HttpServletResponse response) throws IOException {
JSONObject jsApiTicket = new JSONObject();
// 第三方用户唯一凭证
String appId = 第三方用户唯一凭证;
// 第三方用户唯一凭证密钥
String appSecret = 第三方用户唯一凭证密钥;
// 调用接口获取access_token
AccessToken accessToken = WeixinUtil.getAccessToken(appId, appSecret);
if (null != accessToken) {
jsApiTicket = WeixinUtil.getJsApiTicket(accessToken.getToken());
}
// 注意 URL 一定要动态获取,不能 hardcode
String url = request.getParameter("targetUrl");
Map<String, String> ret = sign(jsApiTicket.get("ticket").toString(), url);
ret.put("appId", appId);
JSONObject oj = JSONObject.fromObject(ret);
PrintWriter out = response.getWriter();
out.print(oj);
out.flush();
out.close();
};
public Map<String, String> sign(String jsapi_ticket, String url) {
Map<String, String> ret = new HashMap<String, String>();
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsapi_ticket +
"&noncestr=" + nonce_str +
"×tamp=" + timestamp +
"&url=" + url;
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();
}
ret.put("url", url);
ret.put("jsapi_ticket", jsapi_ticket);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
return ret;
}
private 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 String create_nonce_str() {
return UUID.randomUUID().toString();
}
private String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
3. WerxinUtil.java
package com.want.util;
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.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.want.pojo.AccessToken;
import net.sf.json.JSONObject;
@Component
public class WeixinUtil {
private static final Logger logger = Logger.getLogger(WeixinUtil.class);
/**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
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(null, requestUrl, new sun.net.www.protocol.https.Handler());
// URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
}
catch (ConnectException ce) {
ce.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
return jsonObject;
}
/**
* 获取access_token
*
* @param appid
* 凭证
* @param appsecret
* 密钥
* @return AccessToken
*/
public static AccessToken getAccessToken(String appid, String appsecret) {
AccessToken accessToken = null;
String ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=APPID&corpsecret=APPSECRET";
String requestUrl = ACCESS_TOKEN_URL
.replace("APPID", appid)
.replace("APPSECRET", appsecret);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
try {
accessToken = new AccessToken();
accessToken.setToken(jsonObject.getString("access_token"));
accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
}
catch (Exception e) {
accessToken = null;
}
}
return accessToken;
}
public static String js_api_url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN";
/**
* 获取jsApiTicket
*
* @param accessToken 有效的access_token
*/
public static JSONObject getJsApiTicket(String accessToken) {
// 拼装url
String url = js_api_url.replace("ACCESS_TOKEN", accessToken);
return httpRequest(url, "POST", null);
}
4. MyX509TrustManager.java
package com.want.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* 证书信任管理器(用于https请求)
*
*/
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;
}
}
5. AccessToken.java
package com.want.pojo;
/**
* 微信通用接口凭证
*
*/
public class AccessToken {
// 获取到的凭证
private String token;
// 凭证有效时间,单位:秒
private int expiresIn;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
}