首次接触微信开发,这里用来备份
上篇文章 微信JS-SDK 微信分享接口开发(介绍版) 初步介绍了微信分享的流程以及通过前端js快速的模拟出实际效果,但很遗憾以上介绍并不适用于实战,因此本文将重点介绍用Java开发的微信分享功能,并用于实战。
本次功能开发将介绍版中的js代码转为实际的java代码,分为两部分:
1.后台通过java代码请求微信接口获取access-token参数,以此access-token参数再次请求微信接口获取jsapi-ticket,并将获取的jsapi-ticket进行加密、校验与其他的参数封装成json格式的数据传送到前台JS页面
2.前台获取json数据后,并提供给参数给微信分享接口调用,具体接口为js.confige,js.ready;
获取微信分享页面的标题和描述,以及分享地址、缩略图地址
首先看看前台代码:
jq.wxShare.js 主要供微信分享接口调用:
- // 微信分享默认调用接口
- var $wx_account = wxdata.wx_account,
- $wx_share = wxdata.wx_share;
- //配置微信信息
- wx.config ({
- debug : false,
- appId : $wx_account[0],
- timestamp : $wx_account[1],
- nonceStr : $wx_account[2],
- signature : $wx_account[3],
- jsApiList : [
- // 所有要调用的 API 都要加到这个列表中
- 'onMenuShareTimeline',
- 'onMenuShareAppMessage',
- 'onMenuShareQQ',
- 'onMenuShareWeibo'
- ]
- });
- wx.ready (function () {
- // 微信分享的数据
- var shareData = {
- "imgUrl" : $wx_share[0],
- "link" : $wx_share[1],
- "desc" : $wx_share[2],
- "title" : $wx_share[3],
- success : function () {
- // 分享成功可以做相应的数据处理
- }
- };
- wx.onMenuShareTimeline (shareData);
- wx.onMenuShareAppMessage (shareData);
- wx.onMenuShareQQ (shareData);
- wx.onMenuShareWeibo (shareData);
- });
jq.wxShare_data.js 提供微信分享接口所用的参数数据
- // 提供微信分享接口所需的参数
- var wxdata = {
- wx_account : new Array(4),
- wx_share : new Array(4),
- get_wxshare_data : function(ctx){
- var url = ctx + "/weixinShareAction.do?method=getWxShareData";
- $.ajax({
- type : "GET",
- url : url,
- dataType : "json",
- cache : false,
- async : false,
- success : function(msg) {
- if(msg.errcode == 0){
- wxdata.wx_account[0] = msg.wxuser; // appid
- wxdata.wx_account[1] = msg.timestamp; // timestamp
- wxdata.wx_account[2] = msg.noncestr; // noncestr
- wxdata.wx_account[3] = msg.signature; // signature
- wxdata.wx_share[0] = msg.shareimg; // share_img 分享缩略图图片
- wxdata.wx_share[1] = msg.shareurl;// share_link 分享页面的url地址,如果地址无效,则分享失败
- var description = $("meta[name='description']").attr("content");
- if ($.trim(description) != "") {
- wxdata.wx_share[2] = $.trim(description); // share_desc
- }
- var title1 = document.title;
- if ($.trim(title1) != "") {
- wxdata.wx_share[3] = title1;// share_title
- }
- }
- },
- error : function(msg){
- }
- });
- }
- }
- var host = "http://" + window.location.host;
- wxdata.get_wxshare_data(host);
后台代码 WeiXinShareAction.java
- // 微信分享入口
- public void getWxShareData() throws Exception {
- JsonObject jsonObject = new JsonObject();
- String ticket = null;
- String[] wxInfo = new String[]{"appId","appsecret"};
- String ticketResString = this.getShareJsapiTicket(wxInfo);
- if (StringUtils.isNotEmpty(ticketResString)) {
- JSONObject ticketJSONObject = JSONObject.fromObject(ticketResString);
- if (ticketJSONObject.getInt("errcode") == 0) {
- ticket = JSONObject.fromObject(ticketResString).optString("ticket", "");
- }
- }
- if (StringUtils.isEmpty(ticket)) {
- jsonObject.addProperty("errcode", 10002);
- jsonObject.addProperty("errmsg", "ticket_error");
- this.responseWrite(jsonObject.toString());
- return;
- }
- String noncestr = this.createNonceStr();
- int timestamp = this.createTimestamp();
- String requestRefererURL = this.getRequest().getHeader("referer");
- logger.warn("requestRefererURL: " + requestRefererURL);
- String signature = this.createSignature(noncestr, ticket, timestamp, requestRefererURL);
- jsonObject.addProperty("errcode", 0);
- jsonObject.addProperty("errmsg", "");
- jsonObject.addProperty("wxuser", wxInfo[0]); // appId
- jsonObject.addProperty("timestamp", timestamp);
- jsonObject.addProperty("noncestr", noncestr);
- jsonObject.addProperty("signature", signature);
- jsonObject.addProperty("shareimg", "http://www.abc.com/123.jpg");
- jsonObject.addProperty("shareurl", "http://www.abc.com/123.html");
- this.responseWrite(jsonObject.toString());
- }
- /**
- * 微信分享,获取JsapiTicket
- */
- private String getShareJsapiTicket(String[] wxInfo) throws Exception {
- String siteId = "mywebSite";
- String jsapiTicket = remoteMemcachedClient.get(siteId + "_jsapiTicket");
- if (StringUtils.isNotEmpty(jsapiTicket)) {
- this.logger.warn(siteId + " from memcached jsapiTicket: " + jsapiTicket);
- return jsapiTicket;
- }
- String accessToken = this.getWeiXinAccessToken(wxInfo);
- if (StringUtils.isEmpty(accessToken)) { // 获取 accessToken 失败
- this.logger.warn(siteId + " accessToken is empty.");
- JsonObject jsonObject = new JsonObject();
- jsonObject.addProperty("errcode", "10000");
- jsonObject.addProperty("errmsg", "access_error");
- return jsonObject.toString();
- }
- String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="
- + accessToken + "&type=jsapi";
- jsapiTicket = this.httpReqExecute(url);
- this.logger.warn(siteId + " from weixin api jsapiTicket is: " + jsapiTicket);
- if(StringUtils.isNotEmpty(jsapiTicket)) {
- // 向memcached里写内容,第二个参数为过期时间,单位为:秒
- remoteMemcachedClient.set(siteId + "_jsapiTicket", 1 * 60 * 90, jsapiTicket);
- return jsapiTicket;
- }
- return null;
- }
- /**
- * 微信分享,获取access_token
- */
- private String getWeiXinAccessToken(String[] wxInfo) throws Exception {
- String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
- + wxInfo[0] + "&secret=" + wxInfo[1];
- String result = this.httpReqExecute(url);
- this.logger.warn("from weixin api accessToken: " + result);
- try {
- if(StringUtils.isNotEmpty(result)) {
- // 解析respContent,并获取其中的更新的key,
- String accessToken = JSONObject.fromObject(result).optString("access_token", "");
- return accessToken;
- }
- } catch (Exception e) {
- logger.error("getAccessToken error in WeiXinShareAction", e);
- }
- return null;
- }
组装数据方法
- // 数据签名
- private String createSignature(String nocestr, String ticket, int timestamp, String url) {
- // 这里参数的顺序要按照 key 值 ASCII 码升序排序
- String s = "jsapi_ticket=" + ticket + "&noncestr=" + nocestr
- + "×tamp=" + timestamp + "&url=" + url;
- return DigestUtils.shaHex(s);
- }
- // 创建随机串 自定义个数0 < ? < 32
- private String createNonceStr() {
- String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- String nonceStr = "";
- for (int i = 0; i < 16; i++) {
- int beginIndex = (int) Math.round(Math.random() * 10);
- nonceStr += str.substring(beginIndex, beginIndex + 1);
- }
- return nonceStr;
- }
- // 创建时间戳
- private int createTimestamp() {
- return Calendar.getInstance().get(Calendar.SECOND);
- }
http请求接口
- // HTTP远程调用
- private String httpReqExecute(String url) {
- String result = "";
- DefaultHttpClient httpclient = null ;
- try {
- httpclient = new DefaultHttpClient();
- HttpPost httppost = new HttpPost(url);
- // 执行
- org.apache.http.HttpResponse response = httpclient.execute(httppost);
- HttpEntity entity = response.getEntity();
- if(entity != null && response.getStatusLine().getStatusCode() == 200){
- result = EntityUtils.toString(entity, "UTF-8");
- }
- } catch (Exception e) {
- logger.error(" WeiXinShareAction 调用微信 API 失败!", e);
- } finally { // 关闭连接,释放资源
- httpclient.getConnectionManager().shutdown();
- }
- return result;
- }
- // 输出信息
- private void responseWrite(String content) {
- try {
- getResponse().setCharacterEncoding("utf-8");
- getResponse().getWriter().write(content);
- } catch (Exception e) {
- logger.error("responseWrite error in WeiXinShareAction", e);
- }
- }
详细代码见 实用版代码下载
注意:由于所有的js代码最后压缩为core.min.js文件,因此必须在分享页面中添加js文件 <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>,且该core.min.js文件必须在分享页面中加载,否则分享失败,