微信公众号开发笔记(二):微信分享接口实现和问题
上篇文章写到了公众号开发的基本配置(不明白的可以参考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 +"×tamp=" + 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
微信公众号开发笔记(二):微信分享接口实现和问题相关推荐
- 微信公众号开发(二)基础接口
微信公众号开发(二)基础接口 未经认证的订阅号只有基础接口的权限,基础接口主要包括三个部分:接收用户消息.发送被动响应消息和接收事件推送消息,开发者需要对用户消息在5秒内立即做出回应,微信服务器在五秒 ...
- 微信公众号开发笔记(四)搭建本地测试环境
上一章给大家分享的是开发微信公众号(三) , 今天继续更新第四篇 搭建本地测试环境. 推荐一款软件: Ngrok(内网穿透工具) Ngrok可以实现内网穿透,也就是说我们可以将内网的服务器映射到外网给 ...
- 使用Python进行微信公众号开发(二)接收消息
写在前面 <使用Python进行微信公众号开发>系列文章将与大家分享如何使用Python一步步搭建微信公众号后台服务器. 效果体验 扫码"是雯子吖"公众号进行体验 配置 ...
- python微信公众号开发教程_python微信公众号开发简单流程实现
本文为大家分享了python微信公众号开发的简单过程,供大家参考,具体内容如下 网上有很多微信公众号的开发教程,但是都是好几年前的了,而且很多都是抄袭其他人的,内容几乎一模一样.真的无语了.只好自己总 ...
- 微信公众号开发笔记(三):微信JSAPI支付功能开发
很久之前做了微信支付,其中也趟过很多坑,现在有时间就做个自我梳理吧算是. 公众号开发的基本配置(不明白的可以参考https://blog.csdn.net/TOP__ONE/article/detai ...
- java微信公众号开发及源码分享
java微信公众号开发源码下载 刚做完微信公众号项目,分享一下代码,经验!初写博客,格式写得不好,还请见谅.有不懂的可以留言或加qq 505281494交流下. 一. 第一步进行服务器接口配置,提交信 ...
- JAVA微信公众号开发之二维码的创建与获取
微信文档说明 两种二维码: 1.临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量.临时二维码主要用于帐号绑定等不要求二维码永久保存的业务 ...
- 微信公众号项目笔记 二
一.项目介绍 通过公众号页面调用系统接口,完成物流系统客户签收功能. 1界面展示使用html5+css布局,使用weui样式库. 2Web项目使用asp.net MVC4技术.接口调用使用jquer ...
- 玩一玩微信公众号开发(二) 管理凭据和自定义菜单
管理access_token access_token介绍 在前面我们成功的使用了Spring Boot Web程序和微信对接.但是这仅仅是一个开始,我们还需要获取access_token,也就是凭据 ...
最新文章
- stm32之spi之NSS管脚信号
- Glide控制显示4个角
- 使用CGContext画线操作小记
- 反思代码优化点:trycatch 验证类 封装用户变量
- 今天项目中遇到的一个问题:判断新闻Id是否存在
- 音视频技术开发周刊 | 160
- 一类动词二类动词三类动词_基于http动词的完全无效授权技术
- springmvd接收参数问题
- 前端、后端、全栈都要学什么?薪资前景如何?
- BI笔记之---BI通用流程zz
- 细数被程序员吐糟的9大困难(转)
- 在SpringMVC中使用@RequestBody和@ResponseBody注解处理json时,报出HTTP Status 415的解决方案
- 启动Tomcat时报错,一大堆的
- CST,CET,UTC,GMT,DST,Unix时间戳几种常见时间概述与关系(转)
- 耳机插入电脑插孔后只有一边有声音
- 阿尔伯塔计算机科学学费,留学360发布阿尔伯塔大学学费
- Android基站定位——通过手机信号获取基站信息
- 3dmax室内灯光强度一般打多少才合适
- IR的评价指标-MAP,NDCG和MRR
- 基于JAVA疫情物资商城和疫情数据可视化系统设计与实现 开题报告