300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 微信公众号开发笔记(二):微信分享接口实现和问题

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

时间:2023-09-28 03:27:02

相关推荐

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

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

如果以下代码涉及到微信工具类方法,而我没有提到的,请到链接下载:/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 = "";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./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./open/js/jweixin-1.4.0.js

如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2./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 = "/TOP__ONE/article/details/78183209";var imgUrl ="/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./wiki?t=resource/res_main&id=mp1421141115

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

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

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

(1)确认签名算法正确,可用 http://mp./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./wiki?t=resource/res_main&id=mp1421141115附录5

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。