微信分享接口调用
微信服务号中做运营活动,需要把页面分享到朋友圈,或者转发用户。这个功能很普遍,在写的时候有几个问题需要注意,在此记录,方便新接触的同学有个参考。
首先,如果之前没有接触过这个接口,还是要看下官方文档,有个基础的印象,链接如下:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
接下来,可以自己试一下,如果还是有点问题,比如wx.config一直出现invalidsignature,可以来参考下我的写法。
基本的方法就是js调用微信的wx.config().以及在config参数正确的时候调用相关的onMenuShareTimeline,onMenuShareAppMessage也就是分享给朋友,分享给朋友圈。invalidsignature问题可以先在微信JS接口签名校验工具上http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign把各个参数录入进去,看看是否正确。如果正确,还报错,就说明你的url多半是错了,对此我的做法是在页面上把当前request传到后端,解析出当前的全路径url,然后再来生成signature,简单粗暴,挺有效的
我的前端页面是用velocity写的,通过springmvc来调用,页面调用以及js的写法如下
#set($weiMap=$!dataTag.getWeiMap($request,$!code)) <input type="hidden" id="shareUrl" name="shareUrl" value='https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxb7bd46a3ecfe69bb&redirect_uri=$!appTag.getAppUrl()/operate/operationShare.htm?id=$!userId&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect'/> <input type="hidden" id="appId" name="appId" value='$weiMap.get("appId")'/> <input type="hidden" id="timestamp" name="timestamp" value='$weiMap.get("timestamp")'/> <input type="hidden" id="nonceStr" name="nonceStr" value='$weiMap.get("nonceStr")'/> <input type="hidden" id="signature" name="signature" value='$weiMap.get("signature")'/> <input type="hidden" id="position" name="position" value='$!position'/> <input type="hidden" id="url" name="url" value='$weiMap.get("url")'/> <script src="$!appTag.getWebUrl()/js/sea.js" data-main="$!appTag.getWebUrl()/js/page/share_friend" data-config="$!appTag.getWebUrl()/js/config" type="text/javascript"></script> </body> <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script> wx.config({ appId: $("#appId").val(), timestamp: $("#timestamp").val(), nonceStr: $("#nonceStr").val(), signature: $("#signature").val(), jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] }); wx.ready(function(){ wx.onMenuShareAppMessage({ title: '“sidda杯”刷牙pk赛,迪士尼门票免费送!快来给我点赞助力,我要去迪士尼!', desc: '我当前排名第'+$("#position").val()+'位,快来点赞帮我投票吧亲!我要去迪士尼', link: $("#shareUrl").val(), imgUrl: 'http://mengya-web.oss-cn-hangzhou.aliyuncs.com/20160815142840.jpg', }); wx.onMenuShareTimeline({ title: '“sidda杯”刷牙pk赛,迪士尼门票免费送!快来给我点赞助力,我要去迪士尼!', link: $("#shareUrl").val(), imgUrl: 'http://mengya-web.oss-cn-hangzhou.aliyuncs.com/20160815142840.jpg', }); }); </script>
我用set在页面注入了后端的方法调用$weiMap=$!dataTag.getWeiMap($request,$!code),主要用来生成weiMap这样一个对象,来给wx.config配置相应的微信验证参数
在java中生成weiMap的参数是这样写的
public Map<String, String> getWeiMap(HttpServletRequest request,String code) { String jsapi_ticket = weixinService.getJsapiTicket(); Map<String, String> ret = new HashMap<String, String>(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String string1; String signature = ""; String url = getUrl(request); // 注意这里参数名必须全部小写,且必须有序 string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; 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("appId", weixinService.getAppId()); ret.put("nonceStr", nonce_str); ret.put("timestamp", timestamp); ret.put("signature", signature); ret.put("url", url); ret.put("jsapi_ticket", jsapi_ticket); return ret; } public String getUrl(HttpServletRequest request){ StringBuffer url=request.getRequestURL(); if(StringUtils.isNotBlank(request.getQueryString())){ url.append("?"+request.getQueryString()); } return url.toString(); }
其中getJsapiTicket这个方法主要是通过https的方式调用微信接口,我用redis缓存做了记录,代码如下,设计到https的请求实现,以及reids对应的key我就不贴出来了,大家应该有自己的方法来实现
public String getJsapiTicket() { String vresult = redisService.getRedis(null, Constant.RedisKeyEnum.WEIJSTICKET); if (StringUtils.isNotBlank(vresult)) { return vresult; } String url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+getToken()+"&type=jsapi"; String params = null; try { String result = Https.doPost(url, params, "UTF-8", 604800, 604800); JSONObject jo = JSONObject.parseObject(result); String ticket=jo.get("ticket").toString(); redisService.insertRedis(null, Constant.RedisKeyEnum.WEIJSTICKET, ticket, 60); return ticket; } catch (Exception e) { weixinServiceLogger.error("获取微信jsticket出错 ", e); e.printStackTrace(); return null; } }
注意jsticket这个方法调用微信是有次数限制的,所以大家最好缓存起来
后端的public Map<String, String> getWeiMap(HttpServletRequest request,String code)这个方法主要是用到veloctiy的toolbox这个东西来连接前后端调用的,另外对与request的调用也要在springmvc的配置veloctiy中的ViewResolver中放开,配置如下<!-- 配置视图的显示 --> <bean id="ViewResolver" class="com.healthy.business.velocity.resolver.FixedVelocityLayoutViewResolver"> <property name="order" value="10" /> <property name="suffix" value=".vm" /> <property name="prefix" value="screen" /> <property name="layoutUrl" value="layout/default.vm"/> <property name="exposeSpringMacroHelpers" value="true" /> <property name="dateToolAttribute" value="dateTool" /> <property name="numberToolAttribute" value="numberTool" /> <property name="toolboxConfigLocation" value="WEB-INF/conf/vm-toolbox.xml" /> <property name="contentType" value="${web.contentType}"></property> <property name="templateEncoding" value="UTF-8"></property> <property name="exposeRequestAttributes" value="true"></property> <property name="exposeSessionAttributes" value="true" /> <property name="allowSessionOverride" value="true" /> </bean>
注意dateToolAttribute,toolboxConfigLocation,exposeRequestAttributes这些配置