使用微信js-sdk,请先详细阅读微信开发文档
先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
备注:登录后可在“开发者中心”查看对应的接口权限。
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js
备注:支持使用 AMD/CMD 标准模块加载方法加载
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});
签名算法见文末的附录1,所有JS接口列表见文末的附录2
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
所有接口通过wx对象(也可使用jWeixin对象)来调用,参数是一个对象,除了每个接口本身需要传的参数之外,还有以下通用参数:
1.success:接口调用成功时执行的回调函数。
2.fail:接口调用失败时执行的回调函数。
3.complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
4.cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
5.trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。
备注:不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回。
以上几个函数都带有一个参数,类型为对象,其中除了每个接口本身返回的数据之外,还有一个通用属性errMsg,其值格式如下:
调用成功时:"xxx:ok" ,其中xxx为调用的接口名
用户取消时:"xxx:cancel",其中xxx为调用的接口名
调用失败时:其值为具体错误信息
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
}
});
wx.previewImage({
current: '', // 当前显示图片的http链接
urls: [] // 需要预览的图片http链接列表
});
wx.uploadImage({
localId: '', // 需要上传的图片的本地ID,由chooseImage接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
var serverId = res.serverId; // 返回图片的服务器端ID
}
});
备注:上传图片有效期3天,可用微信多媒体接口下载图片到自己的服务器,此处获得的 serverId 即 media_id。
wx.downloadImage({
serverId: '', // 需要下载的图片的服务器端ID,由uploadImage接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: function (res) {
var localId = res.localId; // 返回图片下载后的本地ID
}
});
想了解更多接口请阅读微信开发者文档,下面开始码代码
1,所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用,
注入配置信息:
var URIstring=location.href.split('#')[0];//获取当前页面的全路径 |
---|
function updoadpic() { wx.chooseImage({ count : 3, // 最多能选择多少张图片,默认9 sizeType : [ 'original', 'compressed' ], // 可以指定是原图还是压缩图,默认二者都有 sourceType : [ 'album', 'camera' ], // 可以指定来源是相册还是相机,默认二者都有 success : function(res) { var localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 // 上传图片接口 syncUpload(localIds); } }); } var syncUpload = function(localIds) { }; function downloadImage(serverId) { server.splice(0, server.length);//删除,清空 //上传成功之后的操作 $.web.RemoveLoading();}, error : function(XMLHttpRequest, textStatus, errorThrown) { $.web.RemoveLoading(); mui.alert("不好意思,出了点小问题","提示","确定"); } }); } |
---|
ConfigParam.java
import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONObject; public class ConfigParam extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); String Rurl=java.net.URLDecoder.decode(request.getParameter("Rurl"),"utf-8"); //System.out.println(Rurl); Map JSONObject json=JSONObject.fromObject(ret); //System.out.println(json.toString()); out.print(json); } } |
---|
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 java.util.Date; import java.util.HashMap; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * 公众平台通用接口工具类 * * * */ public class WeixinUtil { private static Log log = LogFactory.getLog(WeixinUtil.class); // 获取access_token的接口地址(GET) 限200(次/天) public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token? grant_type=client_credential&appid=APPID&secret=APPSECRET"; private static Map /** * 获取access_token * * @param appid 凭证 * @param appsecret 密钥 * @param flag 是否重新获取 * @return */ public static AccessToken getAccessToken(String appid, String appsecret,boolean flag) { AccessToken accessToken = null; log.info("=================getAccessToken-start"); if(!flag){ accessToken = tokenMap.get(appid); } long now = System.currentTimeMillis(); if(accessToken != null && !flag){ long lastTime = accessToken.getCreateTime(); //当accessToken还在有效期内 if(now <= (lastTime + accessToken.getExpiresIn() * 1000) ){ log.info("读取缓存accessToken=="+accessToken); return accessToken; } } 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.setCreateTime(now); accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in") - 300); log.info("重新获取accessToken=="+accessToken); } catch (JSONException e) { accessToken = null; // 获取token失败 log.error("获取token失败 errcode:"+jsonObject.getInt("errcode")+" errmsg:{"+ jsonObject.getString("errmsg")+"}" ); } } log.info("=================getAccessToken-end"); tokenMap.put(appid, accessToken); return accessToken; } /** * 获取access_token * * @param appid 凭证 * @param appsecret 密钥 * @return */ public static AccessToken getAccessToken(String appid, String appsecret ) { log.info("getAccessToken:重新获取AccessToken"); return getAccessToken(appid, appsecret, true); } public static String JS_API_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; /** * * @param accessToken * @return */ public static String getJsapi_ticket(String accessToken){ log.info("=====================getJsapi_ticket:start"); String url = JS_API_URL.replace("ACCESS_TOKEN", accessToken); JSONObject json = httpRequest(url, "GET", null); log.info("getJsapi_ticket:"+json); String jsapi_ticket = ""; try { jsapi_ticket = json.getString("ticket"); } catch (Exception e) { log.error("=====================getJsapi_ticket:error"+json); e.printStackTrace(); } log.info("=====================getJsapi_ticket:end"); return jsapi_ticket; } //JS SDK 中需要的相关的数据 private static Map public static String getJsapi_ticket_cache(String accessToken ){ String jsapi = JsSDKMap.get(accessToken); if(jsapi != null){ log.info("读取jsapi_ticket缓存"+jsapi ); return jsapi; }else{ jsapi = getJsapi_ticket(accessToken); log.info("刷新Jsapi_ticket:"+jsapi+"===="+accessToken ); JsSDKMap.put(accessToken, jsapi); } return jsapi; } //获得jsapi_ticket,noncestr,timestamp public static Map log.info("=================getJSSDKData-start"); //1)获取access_token AccessToken accessToken = getAccessToken(appid, appsecret,false); String token = accessToken.getToken(); log.info("accessToken:"+accessToken); //2)获取jsapi_ticket(有效期7200秒 String jsapi_ticket = getJsapi_ticket_cache(token); log.info("jsapi_ticket:"+jsapi_ticket); //3)获取//随机字符串 String noncestr = Double.toString(Math.random()).substring(2, 15);//随机字符串 //4)获取 随机时间戳 String timeStamp =((int)(new Date().getTime()/1000))+"";//随机时间戳 //5)获取签名 String str = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr + "×tamp="+ timeStamp +"&url=" + requestUrl; log.info("str:" + str); String signature = SHA1Util.Sha1(str); Map map.put("ticket", jsapi_ticket); map.put("noncestr", noncestr); map.put("timestamp", timeStamp); map.put("signature", signature); map.put("url", requestUrl); map.put("appid", appid); log.info("=================getJSSDKData-end"); return map; } /** * 发起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(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) { log.error("Weixin server connection timed out."); } catch (Exception e) { log.error("https request error:{}", e); } return jsonObject; } } /** |
---|
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); //String mediaId=request.getParameter("mediaId"); Map String mediaId = request.getParameter("mediaId"); String folderName="/app/ss/"+new SimpleDateFormat("yyyy/MMdd/").format(new Date()); try { File dir = new File(folderName); if (!dir.exists()) dir.mkdirs(); } catch (Exception ex) { } String Str=""; String array[]=mediaId.split(",");//图片可能有多张,每次循环可以将每张上传的图片路径存起来(比如用StringBuilder加逗号),或者直接存入数据库 for (int i = 0; i < array.length; i++) { String randstr = UUID.randomUUID().toString().replaceAll("-", ""); String path=folderName+randstr;//绝对路径 String frontName = "" + randstr;//相对路径 String absFileName=path+".jpg";//"D:\\img\\a.jpg";// String str= DloadImgUtil.downloadMedia(array[i], absFileName,path+"_240.jpg","1");//调用下载接口 } map.put("status", "1"); map.put("msg",Str); map.put("path", ""); map.put("photoUrl",""); JSONObject json = JSONObject.fromObject(map); out.print(json); } |
---|
DloadImgUtil.java
public class DloadImgUtil { public static String downloadMedia(String mediaId, String savePath,String out,String type) { String filePath = null; AccessToken accessToken = WeixinUtil.getAccessToken(WechatUtil.appId, WechatUtil.appSecret, false); // 拼接请求地址 String requestUrl = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"; requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken.getToken()) .replace("MEDIA_ID", mediaId); String returnstr="0"; BufferedInputStream bis = null; FileOutputStream fos = null; HttpsURLConnection conn = 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(null,requestUrl,new // sun.net.www.protocol.https.Handler()); // URL url = new URL(requestUrl); URL url = new URL(requestUrl); conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(ssf); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); // 设置请求方式(GET/POST) conn.setRequestMethod("GET"); // 根据内容类型获取扩展名 // String fileExt = DloadImgUtil // .getFileexpandedName(conn.getHeaderField("Content-Type")); // 将mediaId作为文件名 filePath = savePath; bis = new BufferedInputStream(conn.getInputStream()); fos = new FileOutputStream(new File(filePath)); byte[] buf = new byte[8096]; int size = 0; while ((size = bis.read(buf)) != -1) fos.write(buf, 0, size); suof(savePath, out); } catch (Exception e) { returnstr="-1"; e.printStackTrace(); } finally { // 释放资源 conn.disconnect(); try { // 关闭流,释放资源 if (fos != null) { fos.close(); } if (bis != null) { bis.close(); } } catch (Exception e) { e.getStackTrace(); } } return returnstr; } /** } |
---|