本文共 20926 字,大约阅读时间需要 69 分钟。
//2.获取getJsapiTicket的接口地址,有效期为7200秒 private static final String GET_JSAPITICKET_URL="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; /** * @desc :2.获取JsapiTicket * * @param accessToken 有效凭证 * @return * @throws Exception String */ public static String getJsapiTicket(String accessToken) throws Exception { //1.获取请求url String url=GET_JSAPITICKET_URL.replace("ACCESS_TOKEN", accessToken); //2.发起GET请求,获取返回结果 JSONObject jsonObject=HttpHelper.doGet(url); logger.info("jsonObject:"+jsonObject.toJSONString()); //3.解析结果,获取accessToken String jsapiTicket=""; if (null != jsonObject) { //4.错误消息处理 if (jsonObject.getInteger("errcode")!=null && 0 != jsonObject.getInteger("errcode")) { int errCode = jsonObject.getInteger("errcode"); String errMsg = jsonObject.getString("errmsg"); throw new Exception("error code:"+errCode+", error message:"+errMsg); //5.成功获取jsapiTicket }else { jsapiTicket=jsonObject.getString("ticket"); } } return jsapiTicket; }
/** * @desc :4.获取前端jsapi需要的配置参数 * * @param request * @return String */ public static String getJsapiConfig(HttpServletRequest request){ //1.准备好参与签名的字段 //1.1 url /* *以http://localhost/test.do?a=b&c=d为例 *request.getRequestURL的结果是http://localhost/test.do *request.getQueryString的返回值是a=b&c=d */ String urlString = request.getRequestURL().toString(); String queryString = request.getQueryString(); String queryStringEncode = null; String url; if (queryString != null) { queryStringEncode = URLDecoder.decode(queryString); url = urlString + "?" + queryStringEncode; } else { url = urlString; } //1.2 noncestr String nonceStr=UUID.randomUUID().toString(); //随机数 //1.3 timestamp long timeStamp = System.currentTimeMillis() / 1000; //时间戳参数 String signedUrl = url; String accessToken = null; String ticket = null; String signature = null; //签名 try { //1.4 jsapi_ticket accessToken=getAccessToken(Env.APP_ID, Env.APP_SECRET); ticket=getJsapiTicket(accessToken); //2.进行签名,获取signature signature=getSign(ticket,nonceStr,timeStamp,signedUrl); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } logger.info("accessToken:"+accessToken); logger.info("ticket:"+ticket); logger.info("nonceStr:"+nonceStr); logger.info("timeStamp:"+timeStamp); logger.info("signedUrl:"+signedUrl); logger.info("signature:"+signature); logger.info("appId:"+Env.APP_ID); String configValue = "{signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'" + timeStamp + "',appId:'" + Env.APP_ID + "'}"; logger.info("configValue:"+configValue); return configValue; } /** * @desc : 4.1 生成签名的函数 * * @param ticket jsticket * @param nonceStr 随机串,自己定义 * @param timeStamp 生成签名用的时间戳 * @param url 需要进行免登鉴权的页面地址,也就是执行dd.config的页面地址 * @return * @throws Exception String */ public static String getSign(String jsTicket, String nonceStr, Long timeStamp, String url) throws Exception { String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp + "&url=" + url; System.out.println(plainTex); try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(plainTex.getBytes("UTF-8")); return byteToHex(crypt.digest()); } catch (NoSuchAlgorithmException e) { throw new Exception(e.getMessage()); } catch (UnsupportedEncodingException e) { throw new Exception(e.getMessage()); } } /** * @desc :4.2 将bytes类型的数据转化为16进制类型 * * @param hash * @return * String */ private static String byteToHex(byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", new Object[] { Byte.valueOf(b) }); } String result = formatter.toString(); formatter.close(); return result; }
(1)参与签名的字段包括:
noncestr(随机字符串),
有效的jsapi_ticket,
timestamp(时间戳),
url(当前网页的URL,不包含#及其后面部分) 。
(2)对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
(3)对string1进行sha1签名,得到signature:
(1)待签名参数:
noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com
(2)字典序
string1=jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-
HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com
(3)sha1加密
signature=sha1(string1)
测试号:
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js
//1.jsapi签名校验wx.config({ beta: true,// 必须这么写,否则在微信插件有些jsapi会有问题 debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: _config.appId, // 必填,公众号的唯一标识 timestamp: _config.timeStamp, // 必填,生成签名的时间戳 nonceStr: _config.nonceStr, // 必填,生成签名的随机串 signature: _config.signature,// 必填,签名,见附录1 jsApiList: [ 'checkJsApi', 'onMenuShareAppMessage', 'onMenuShareWechat', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'previewFile', 'openEnterpriseChat', 'selectEnterpriseContact','chooseInvoice' ]// 必填,需要使用的JS接口列表,所有JS接口列表见附录2});
//2.jsapi签名校验失败后执行errorwx.error(function(err){ alert('wx error: ' + JSON.stringify(err)); // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。});
(1)使用 jssdk 上传图片到微信服务器,返回图片对应的mediaId( 即 serverId)
//2.2 上传图片 var images = { localId : [], serverId : [] }; $("#uploadImg").click(function(){ //2.2.1拍照或从手机相册中选图 wx.chooseImage({ success : function(res) { images.localId = res.localIds; alert('已选择 ' + res.localIds.length + ' 张图片'); //2.2.2 上传图片 uploadImg(); } }); }); // 2.2.2 上传图片 function uploadImg() { if (images.localId.length == 0) { alert('请先使用 chooseImage 接口选择图片'); return; } var i = 0, length = images.localId.length; images.serverId = []; function upload() { wx.uploadImage({ localId : images.localId[i], success : function(res) { i++; alert('已上传:' + i + '/' + length); images.serverId.push(res.serverId); //将serverId上传至服务器 alert("ajax请求即将执行--"); $.ajax({ type : "POST", url : "http://se9mxs.natappfree.cc/weixin_gz/uploadimg", data : { serverId : res.serverId }, dataType : "text", success : function(data) { alert(data); } }); if (i < length) { upload(); } }, fail : function(res) { alert(JSON.stringify(res)); } }); } upload(); };
(2)使用素材管理接口,根据 mediaId 从微信服务器将图片下载至服务器本地。参见:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String mediaId=request.getParameter("serverId"); System.out.println("serverId:"+mediaId); try { String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET); //String savePath=System.getProperty("user.dir").replaceAll("\\\\", "/")+"/WebContent/img/"+mediaId+".png"; String fileDir=request.getSession().getServletContext().getRealPath("").replaceAll("\\\\", "/")+"/img/"; System.out.println("fileDir:"+fileDir); //2.调用业务类,获取临时素材 TempMaterialService.getTempMaterial(accessToken, mediaId, fileDir); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } PrintWriter out = response.getWriter(); out.print("HHHHHHHHHH"); out.close(); out = null; }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>JSSDK之上传图片
UserName:UserId:是否验证成功测试按钮上传图片按钮拍照上传图片按钮扫码按钮
auth.js
//1.jsapi签名校验wx.config({ beta: true,// 必须这么写,否则在微信插件有些jsapi会有问题 debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: _config.appId, // 必填,公众号的唯一标识 timestamp: _config.timeStamp, // 必填,生成签名的时间戳 nonceStr: _config.nonceStr, // 必填,生成签名的随机串 signature: _config.signature,// 必填,签名,见附录1 jsApiList: [ 'checkJsApi', 'onMenuShareAppMessage', 'onMenuShareWechat', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'previewFile', 'openEnterpriseChat', 'selectEnterpriseContact','chooseInvoice' ]// 必填,需要使用的JS接口列表,所有JS接口列表见附录2});//2.jsapi签名校验成功后执行readywx.ready(function(){ // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 //2.1 提示jsapi签名验证成功 $("#yanzheng").html("验证成功"); $("#ceshi").click(function(){ alert("ceshiaaa"); }); $("#checkJsApi").click(function(){ wx.checkJsApi({ jsApiList: [ 'checkJsApi', 'onMenuShareAppMessage', 'onMenuShareWechat', 'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'getNetworkType', 'openLocation', 'getLocation', 'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem', 'closeWindow', 'scanQRCode', 'previewFile', 'openEnterpriseChat', 'selectEnterpriseContact','chooseInvoice' ], // 需要检测的JS接口列表,所有JS接口列表见附录2, success: function(res) { // 以键值对的形式返回,可用的api值true,不可用为false // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"} } }); }); //2.2 上传图片 var images = { localId : [], serverId : [] }; $("#uploadImg").click(function(){ //2.2.1拍照或从手机相册中选图 wx.chooseImage({ success : function(res) { images.localId = res.localIds; alert('已选择 ' + res.localIds.length + ' 张图片'); //2.2.2 上传图片 uploadImg(); } }); }); // 2.2.2 上传图片 function uploadImg() { if (images.localId.length == 0) { alert('请先使用 chooseImage 接口选择图片'); return; } var i = 0, length = images.localId.length; images.serverId = []; function upload() { wx.uploadImage({ localId : images.localId[i], success : function(res) { i++; alert('已上传:' + i + '/' + length); images.serverId.push(res.serverId); //将serverId上传至服务器 alert("ajax请求即将执行--"); $.ajax({ type : "POST", url : "http://se9mxs.natappfree.cc/weixin_gz/uploadimg", data : { serverId : res.serverId }, dataType : "text", success : function(data) { alert(data); } }); if (i < length) { upload(); } }, fail : function(res) { alert(JSON.stringify(res)); } }); } upload(); }; //2.3 扫一扫 $("#qrcode").click(function(){ wx.scanQRCode({ needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果, scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有 success: function (res) { var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果 alert(result); }, fail:function (res) { var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果 alert(result); } }); }); //2.4 拉起发票列表 //注意,调用此接口时,config接口必须传入beta参数。 $("#showInvoice").click(function(){ alert("timestamp:"+invoice_config.timestamp); alert("nonceStr:"+invoice_config.nonceStr); alert("signType:"+invoice_config.signType); alert("cardSign:"+invoice_config.cardSign); wx.invoke('chooseInvoice', { 'timestamp': invoice_config.timestamp, // 卡券签名时间戳 'nonceStr' : invoice_config.nonceStr, // 卡券签名随机串 'signType' : invoice_config.signType, // 签名方式,默认'SHA1' 'cardSign' : invoice_config.cardSign, // 卡券签名 }, function(res) { // 这里是回调函数 alert("aaaaaa"); alert(JSON.stringify(res)); // 返回的结果 }); });});//2.jsapi签名校验失败后执行errorwx.error(function(err){ alert('wx error: ' + JSON.stringify(err)); // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。});
weixin_gz index.html index.htm index.jsp default.html default.htm default.jsp weixin com.ray.weixin.gz.controller.WeiXinServlet weixin /weixin uploadimg uploadimg com.ray.weixin.gz.controller.UploadImgServlet uploadimg /uploadimg
package com.ray.weixin.gz.controller;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.ray.weixin.gz.config.Env;import com.ray.weixin.gz.service.tempmaterial.TempMaterialService;import com.ray.weixin.gz.util.AuthHelper;/** * Servlet implementation class UploadImgServlet */public class UploadImgServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public UploadImgServlet() { 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()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String mediaId=request.getParameter("serverId"); System.out.println("serverId:"+mediaId); try { String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET); //String savePath=System.getProperty("user.dir").replaceAll("\\\\", "/")+"/WebContent/img/"+mediaId+".png"; String fileDir=request.getSession().getServletContext().getRealPath("").replaceAll("\\\\", "/")+"/img/"; System.out.println("fileDir:"+fileDir); //2.调用业务类,获取临时素材 TempMaterialService.getTempMaterial(accessToken, mediaId, fileDir); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } PrintWriter out = response.getWriter(); out.print("HHHHHHHHHH"); out.close(); out = null; }}
package com.ray.weixin.gz.controller;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.ray.weixin.gz.config.Env;import com.ray.weixin.gz.service.tempmaterial.TempMaterialService;import com.ray.weixin.gz.util.AuthHelper;/** * Servlet implementation class UploadImgServlet */public class UploadImgServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public UploadImgServlet() { 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()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String mediaId=request.getParameter("serverId"); System.out.println("serverId:"+mediaId); try { String accessToken=AuthHelper.getAccessToken(Env.APP_ID, Env.APP_SECRET); //String savePath=System.getProperty("user.dir").replaceAll("\\\\", "/")+"/WebContent/img/"+mediaId+".png"; String fileDir=request.getSession().getServletContext().getRealPath("").replaceAll("\\\\", "/")+"/img/"; System.out.println("fileDir:"+fileDir); //2.调用业务类,获取临时素材 TempMaterialService.getTempMaterial(accessToken, mediaId, fileDir); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } PrintWriter out = response.getWriter(); out.print("HHHHHHHHHH"); out.close(); out = null; }}
其他的同上一节
转载地址:http://fcwql.baihongyu.com/