微信JS-SDK Demo
var appId = '';
var timestamp = 0;//为了让后台传过来的timetamp是数字类型 否则字符串 估计又会报config fail错误
var nonceStr = '';
var signature = '';
$(document).ready(function(){
init({//用init.js去请求服务器获得相应的数据 这里是我自己封装的ajax请求 就不贴出来了
url:"/testSaoMa/getticket",//这是servlet 具体的请根据自己的servlert地址去填写
dataType:"json",
showType:"return",
Deferred:false,
Callback:function(dta){//获取数据
appId = dta.appId;
timestamp = dta.timestamp;
nonceStr = dta.nonceStr;
signature = dta.signature;
/*
* 注意:
* 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
* 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。
* 3. 常见问题及完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
*
* 开发中遇到问题详见文档“附录5-常见错误及解决办法”解决,如仍未能解决可通过以下渠道反馈:
* 邮箱地址:weixin-open@qq.com
* 邮件主题:【微信JS-SDK反馈】具体问题
* 邮件内容说明:用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。
*/
wx.config({//开始微信的配置 将获取的数据拿去请求
debug: false,
appId: appId,
timestamp: timestamp,
nonceStr: nonceStr,
signature: signature,
jsApiList: [//可以调用下面的接口 我们这里只是调用scanQRCode 也就是扫码接口
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone',
'hideMenuItems',
'showMenuItems',
'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem',
'translateVoice',
'startRecord',
'stopRecord',
'onVoiceRecordEnd',
'playVoice',
'onVoicePlayEnd',
'pauseVoice',
'stopVoice',
'uploadVoice',
'downloadVoice',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'getNetworkType',
'openLocation',
'getLocation',
'hideOptionMenu',
'showOptionMenu',
'closeWindow',
'scanQRCode',
'chooseWXPay',
'openProductSpecificView',
'addCard',
'chooseCard',
'openCard'
]
});
wx.ready(function () {
// 9.1.2 扫描二维码并返回结果
wx.scanQRCode({
needResult: 1,
desc: 'scanQRCode desc',
success: function (res) {
//alert(JSON.stringify(res));
//document.getElementById("result").innerHtml=JSON.stringify(res);
//$("#result").html(JSON.stringify(res));
$("#result").html(res.resultStr);
}
});
});
wx.error(function (res) {//错误时调用
alert(res.errMsg);
});
}
});
})
上面颜色不同的部分就是配置微信的过程那是固定不变的
微信JSSdk里面给出了一个方法 不需要导入任何的包 能获得 timestamp nonceStr
package com.weixin.util;
import java.util.UUID;
import com.alibaba.fastjson.JSONObject;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.UnsupportedEncodingException;
class Sign {
/**
* 获取nonce_str timestamp signature的方法
* @param jsapi_ticket 传入的ticket
* @param url 传入需要在微信中打开扫码的url
* @return map
*/
public static Map sign(String jsapi_ticket, String url) {
Map ret = new HashMap();
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 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 create_nonce_str() {
return UUID.randomUUID().toString();
}
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
三:写Servlet(spring里面的Controller也行)来控制
Servlet代码
package com.weixin.util;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.annotations.Since;
/**
* Servlet implementation class getticket
*/
@WebServlet("/getticket")
public class getticket extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public getticket() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// response.getWriter().append("Served at: ").append(request.getContextPath());
doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// doGet(request, response);
String jsapi_ticket = HttpUtil.getJsTicket();
String jsonstr = "{\"appId\":\""+WX_Token.APPID+"\",";
// 注意 URL 一定要动态获取
String url = " http://lg.kezir.com/testSaoMa/jsDemo.html";
Map ret = Sign.sign(jsapi_ticket, url);
for (Map.Entry entry : ret.entrySet()) {
jsonstr += "\""+entry.getKey() + "\":\"" + entry.getValue()+"\",";
}
jsonstr = jsonstr.substring(0,jsonstr.length()-1);
jsonstr +="}";
System.out.println(jsonstr);
response.getWriter().println(jsonstr);
}
}
图解
现在就只剩下方法Http.getJsTicket()没讲了(url直接设置分享的网址就行了)
这是用来获取ticket的
1先根据appId和appSecret获取access_token
2再根据access_token获取ticket
获取ticket 接口调用请求说明
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=wx_card
package com.weixin.util;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class HttpUtil {
private static String access_Token = "";
/**
* get请求获取网址
* @param url
* @param charset
* @return
*/
public static String sendGet(String url,String charset){
CloseableHttpClient httpClient=HttpClients.createDefault();
HttpGet get=new HttpGet(url);
CloseableHttpResponse response = null;
String result=null;
try {
response=httpClient.execute(get);
HttpEntity entity=response.getEntity();
//System.out.println(entity.getContentType().getValue());
result=EntityUtils.toString(entity,charset);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
//获取tickect
public static String getJsTicket(){
JSONObject jsonObject = new JSONObject();
String ticket = "";
if(access_Token ==""){//如果是第一次获取就直接去请求新的
ticket = getTicket();
}else{//否则就请求旧的
String result = sendGet(" https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_Token+"&type=jsapi","UTF-8");
jsonObject = JSON.parseObject(result);
String resultCode = jsonObject.getString("errcode");
if(resultCode !="0"){//请求旧的如果不行
ticket = getTicket();//再去请求新的
}
else{//如果请求的新的ok
ticket = jsonObject.getString("ticket");//直接获取
}
}
return ticket;
}
/**
* 获取最新的ticket
* @return
*/
public static String getTicket(){
JSONObject jsonObject = new JSONObject();
access_Token = WX_Token.getAccessTokenByNet().getAccess_token();//获取
Access_token 代码就不贴了
String result = sendGet(" https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+WX_Token.getAccessTokenByNet().getAccess_token()+"&type=jsapi","UTF-8");
jsonObject = JSON.parseObject(result);
return jsonObject.getString("ticket");
}
}