上篇文章写到了公众号开发的基本配置(不明白的可以参考https://blog.csdn.net/TOP__ONE/article/details/78183209),这里继续写微信分享接口功能代码实现。

如果以下代码涉及到微信工具类方法,而我没有提到的,请到链接下载:https://download.csdn.net/download/top__one/10875681

实现微信页面的分享自定义接口功能,需要先配置js-sdk以下数据项,所以需要先获取这些数据项。

wx.config({debug : false,appId : appId,timestamp : timestamp,nonceStr : nonceStr,signature : signature,jsApiList : [ 'chooseWXPay', 'checkJsApi', 'closeWindow','onMenuShareTimeline', 'onMenuShareAppMessage' ]});

1、后台接口程序开发

先对跳转分享页面action的基本编写,进行必要数据的封装

    /*** 分享页初始化* * @param map* @return*/@RequestMapping(value = "/toshare")public String index(Model model, @RequestParam Map<String, String> map) {logger.info("进入分享主页");// 为了获取调取微信的jsdk的方法,进行配置数据项的封装Map<String, String> sign = getSingture(request);model.addAttribute("sign", sign);//此host为访问域名,即项目域名,要和js安全域名一致String host = PropertieSingle.getInstance().getProperty("host");model.addAttribute("host", host);return "shareIndex";}/*** 获取singture的公共方法* * @param request* @return*/private static Map<String, String> getSingture(HttpServletRequest request) {// response.setContentType("text/javascript;charset=utf-8");// FiXME 通过接口获取access_token,再通过access_token获取jsapi_ticketString wechatTicket = WechatServiceUtil.getWechatTicket();String strBackUrl = "http://" + request.getServerName() // 服务器地址
//               + ":"
//               + request.getServerPort() //端口号+ request.getContextPath() // 项目名称+ request.getServletPath(); // 请求页面或其他地址if (!StringUtils.isEmpty(request.getQueryString()))strBackUrl += "?" + (request.getQueryString()); // 参数Map<String, String> sign = Sign.sign(wechatTicket, strBackUrl);sign.put("appId", PropertieSingle.getInstance().getProperty("APPID"));return sign;}

其中里面的Sign工具类代码

package com.chinatsp.wechat.util;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.UUID;public class Sign {public static void main(String[] args) {String jsapi_ticket = "jsapi_ticket";// 注意 URL 一定要动态获取,不能 hardcodeString url = "http://example.com";Map<String, String> ret = sign(jsapi_ticket, url);for (Map.Entry entry : ret.entrySet()) {System.out.println(entry.getKey() + ", " + entry.getValue());}};/*** 这是jssdk中需要的那个singture签名* @param jsapi_ticket* @param url* @return*/public static 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 = "";System.out.println(nonce_str);System.out.println(timestamp);System.out.println(jsapi_ticket);System.out.println(url);//注意这里参数名必须全部小写,且必须有序string1 = "jsapi_ticket=" + jsapi_ticket +"&noncestr=" + nonce_str +"&timestamp=" + timestamp +"&url=" + url;System.out.println(string1);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;}public static String create_nonce_str() {return UUID.randomUUID().toString().replaceAll("-", "");}public static String create_timestamp() {return Long.toString(System.currentTimeMillis() / 1000);}
}

其中wechatTicket的获取代码如下,另附TicketAPI.

/**
*这里是用到了redis缓存,tiket的有效期为7200s,我设置redis过期时间为7000s
*tiket每天获取次数有限,所以尽量做一个缓存处理
*/
public static String  getWechatTicket(){//获取TICKET,从redis中String ticket= RedisUtils.getCachRedisData(WechatBean.TICKET);if(ticket==null){//获取tokenTicket t= TicketAPI.ticketGetticket(getWechatToken());RedisUtils.setCachRedisDataTimeLong(WechatBean.TICKET,Integer.parseInt(WechatBean.WECHAT_TOKEN_TIME+""),t.getTicket());return t.getTicket();}else{return ticket;}}

另附TicketAPI.ticketGetticket方法代码

package weixin.popular.api;import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;import weixin.popular.bean.Ticket;
import weixin.popular.client.LocalHttpClient;/*** JSAPI ticket* @author LiYi**/
public class TicketAPI extends BaseAPI{/*** 获取 jsapi_ticket* @param access_token* @return*/public static Ticket ticketGetticket(String access_token){HttpUriRequest httpUriRequest = RequestBuilder.post().setUri(BASE_URI + "/cgi-bin/ticket/getticket").addParameter("access_token",access_token).addParameter("type", "jsapi").build();return LocalHttpClient.executeJsonResult(httpUriRequest,Ticket.class);}
}

至此,后台获取token、ticket、sign等参数,然后跳转前台页面,进行页面数据配置

2、进行页面js-sdk数据配置,通过config接口注入权限验证配置

首先需要引用js: <script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

注:请注意,原有的 wx.onMenuShareTimeline、wx.onMenuShareAppMessage、wx.onMenuShareQQ、wx.onMenuShareQZone 接口,即将废弃。请尽快迁移使用客户端6.7.2及JSSDK 1.4.0以上版本支持的 wx.updateAppMessageShareData、updateTimelineShareData 接口。

我此处引用的是1.2.0版本js,此博文也是在1.2.0版本基础上进行的。后面后附上我试用1.4版本js的问题。

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.4.0.js

如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.4.0.js (支持https)。

备注:支持使用 AMD/CMD 标准模块加载方法加载

页面代码:

<script type="text/javascript">$(document).ready(function() {var appId = $("#appId").val();var timestamp = $("#timestamp").val();var nonceStr = $("#nonceStr").val();var signature = $("#signature").val();wx.config({debug : true,appId : appId,timestamp : timestamp,nonceStr : nonceStr,signature : signature,jsApiList : [ 'chooseWXPay', 'checkJsApi', 'closeWindow','onMenuShareTimeline', 'onMenuShareAppMessage' ]});wx.error(function(res) {//alert(JSON.stringify(res));// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。});wx.checkJsApi({jsApiList : [ 'checkJsApi', 'onMenuShareTimeline','onMenuShareAppMessage' ], // 需要检测的JS接口列表,所有JS接口列表见附录2,success : function(res) {//alert(res);// 以键值对的形式返回,可用的api值true,不可用为false// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}}});});wx.ready(function() {var title = "分享朋友圈?";var desc = "晒能力,抢大红包";var link = "https://blog.csdn.net/TOP__ONE/article/details/78183209";var imgUrl ="https://blog.csdn.net/TOP__ONE/share_logo.png";wx.onMenuShareTimeline({title : title, // 分享标题link : link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致imgUrl : imgUrl, // 分享图标success : function() {// 用户确认分享后执行的回调函数$.ajax({type: "POST",async: false,url: "",success : function(msg) {}}); },cancel : function() {// 用户取消分享后执行的回调函数//window.location.href='*.action';}});wx.onMenuShareAppMessage({title : title, // 分享标题desc : desc, // 分享描述link : link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致imgUrl : imgUrl, // 分享图标type : '', // 分享类型,music、video或link,不填默认为linkdataUrl : '', // 如果type是music或video,则要提供数据链接,默认为空success : function() {// 用户确认分享后执行的回调函数$.ajax({type: "POST",async: false,url: "",success : function(msg) {}}); },cancel : function() {// 用户取消分享后执行的回调函数}});});</script>

此代码中appId、timestamp、nonceStr、signature均为后台封装的sign中的值,通过自己方法获取即可。

wx.config中的debug更改为true可查看配置情况。

至此,微信分享接口demo即开发完毕。更详细官方链接https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

--------------------------------------贞操 分割线---------------------------------------

在微信分享过程中也遇到了一些问题,比如

1、签名错误invalid signature,需要检查页面wx.config中的字段是否正确,需要检查js安全域名是否与项目域名一致。一般检查顺序如下:

(1)确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。

(2)确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。

(3)确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。

(4)确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。

(5)确保一定缓存access_token和jsapi_ticket。

(6)确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。

如果后台返回的config 信息 与微信签名工具校验一致的话,那很有可能是前端访问的url和后台生成签名的url不一致导致,看是否需要encodeURIComponent或者decode下。

2、安卓分享成功,ios分享不成功问题

(1) IOS分享的时候图片的链接地址 和 link 都需要在 JS安全域名下并且带http头。

(2)网上搜的资源还有说是 图片大小不能超过32kb,这个不知道有没有用,没试过

(3)分享的link等url中包含中文会导致ios分享不成功,需要对中文字段进行编码处理 例:

  var link = "*.action?name=" + encodeURIComponent($('#uname').val());

因为安卓可以解析,IOS可能解析不了

(4)微信版本低,也有可能导致分享不成功

更多错误代码请详见https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115附录5

微信公众号开发笔记(二):微信分享接口实现和问题相关推荐

  1. 微信公众号开发(二)基础接口

    微信公众号开发(二)基础接口 未经认证的订阅号只有基础接口的权限,基础接口主要包括三个部分:接收用户消息.发送被动响应消息和接收事件推送消息,开发者需要对用户消息在5秒内立即做出回应,微信服务器在五秒 ...

  2. 微信公众号开发笔记(四)搭建本地测试环境

    上一章给大家分享的是开发微信公众号(三) , 今天继续更新第四篇 搭建本地测试环境. 推荐一款软件: Ngrok(内网穿透工具) Ngrok可以实现内网穿透,也就是说我们可以将内网的服务器映射到外网给 ...

  3. 使用Python进行微信公众号开发(二)接收消息

    写在前面 <使用Python进行微信公众号开发>系列文章将与大家分享如何使用Python一步步搭建微信公众号后台服务器. 效果体验 扫码"是雯子吖"公众号进行体验 配置 ...

  4. python微信公众号开发教程_python微信公众号开发简单流程实现

    本文为大家分享了python微信公众号开发的简单过程,供大家参考,具体内容如下 网上有很多微信公众号的开发教程,但是都是好几年前的了,而且很多都是抄袭其他人的,内容几乎一模一样.真的无语了.只好自己总 ...

  5. 微信公众号开发笔记(三):微信JSAPI支付功能开发

    很久之前做了微信支付,其中也趟过很多坑,现在有时间就做个自我梳理吧算是. 公众号开发的基本配置(不明白的可以参考https://blog.csdn.net/TOP__ONE/article/detai ...

  6. java微信公众号开发及源码分享

    java微信公众号开发源码下载 刚做完微信公众号项目,分享一下代码,经验!初写博客,格式写得不好,还请见谅.有不懂的可以留言或加qq 505281494交流下. 一. 第一步进行服务器接口配置,提交信 ...

  7. JAVA微信公众号开发之二维码的创建与获取

    微信文档说明 两种二维码: 1.临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量.临时二维码主要用于帐号绑定等不要求二维码永久保存的业务 ...

  8. 微信公众号项目笔记 二

    一.项目介绍  通过公众号页面调用系统接口,完成物流系统客户签收功能. 1界面展示使用html5+css布局,使用weui样式库. 2Web项目使用asp.net MVC4技术.接口调用使用jquer ...

  9. 玩一玩微信公众号开发(二) 管理凭据和自定义菜单

    管理access_token access_token介绍 在前面我们成功的使用了Spring Boot Web程序和微信对接.但是这仅仅是一个开始,我们还需要获取access_token,也就是凭据 ...

最新文章

  1. stm32之spi之NSS管脚信号
  2. Glide控制显示4个角
  3. 使用CGContext画线操作小记
  4. 反思代码优化点:trycatch 验证类 封装用户变量
  5. 今天项目中遇到的一个问题:判断新闻Id是否存在
  6. 音视频技术开发周刊 | 160
  7. 一类动词二类动词三类动词_基于http动词的完全无效授权技术
  8. springmvd接收参数问题
  9. 前端、后端、全栈都要学什么?薪资前景如何?
  10. BI笔记之---BI通用流程zz
  11. 细数被程序员吐糟的9大困难(转)
  12. 在SpringMVC中使用@RequestBody和@ResponseBody注解处理json时,报出HTTP Status 415的解决方案
  13. 启动Tomcat时报错,一大堆的
  14. CST,CET,UTC,GMT,DST,Unix时间戳几种常见时间概述与关系(转)
  15. 耳机插入电脑插孔后只有一边有声音
  16. 阿尔伯塔计算机科学学费,留学360发布阿尔伯塔大学学费
  17. Android基站定位——通过手机信号获取基站信息
  18. 3dmax室内灯光强度一般打多少才合适
  19. IR的评价指标-MAP,NDCG和MRR
  20. 基于JAVA疫情物资商城和疫情数据可视化系统设计与实现 开题报告

热门文章

  1. 20年广西赛题技能要求(服务器)
  2. (二)Java线程与系统线程,生命周期
  3. 如何制作一寸。二寸。六寸照片 多学点,以后自己也可以弄哦
  4. 行人重识别常用数据集
  5. antd picker 使用 如何_antd-RangePicker
  6. 鲜为人知 的 人名典故
  7. 刺激战场 枪支性能雷达图分析
  8. lerna使用初体验
  9. Elasticsearch - JNA
  10. 第一积分中值定理(两种形式)的证明