微信转发图文消息步骤
- 微信转发图文消息步骤
- 需求
- 获取凭证
- 获取aceess_token
- 获取jsapi_ticket
- 缓存获取的jsapi_ticket
- 代码
- config接口注入权限
- 引入js文件
- 微信权限注入接口
- JS-SDK分享接口调用
- 总结
- 温馨提示
需求
当用户购买成功一样产品,为了使用户能够二次消费,可以在订单详细页面加一个红包按钮,当用户点击之后,可以分享特定的内容(一个title、一段描述、一条超连接、一张图片)给朋友或者分享到朋友圈,当用户点击之后进入一个输入手机号码(即登录账号或绑定的手机号码)的页面,提交之后随机抽取代金券。如果你吃过“美团外卖”,对于这个流程可能就很清晰了。
如下图流程步骤:
获取凭证
我是利用spring封装简单的任务调度器,1个小时自动调用微信jsapi_ticket接口,获取微信使用JS-SDK使用的权限问题的。首先,为了获取jsapi_ticket需要access_token公众号的全局唯一票据。第二步,根据access_token获取jsapi_ticket。第三步,缓存获取的jsapi_ticket参数。
获取aceess_token
需要的参数:
请求连接(GET):https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
公众号AppID(应用ID):wx****************
公众号AppSecret(应用密钥):2b****************************e0
获取jsapi_ticket
需要的参数:
请求连接(GET):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
微信全局票据凭证(access_token):********…
缓存获取的jsapi_ticket
设置一个静态的字符串,运用spring任务调度器,每隔一个小时改变该字符串的值。
代码
以上三个步骤集成在一个方法里,代码如下:
import java.util.Date;
import org.json.JSONException;
import org.json.JSONObject;
import com.qq.weixin.constant.Constant;
import com.qq.weixin.publics.WXUtils;public class JsapiTicketTimeTask {public static String jsapi_ticket = "";/*** * @method getTicket* @描述: TODO(每隔一个小时调用一次微信获取jsapi的接口的任务调用器,在spring配置里面调用) * @参数* @返回类型:void* @添加时间 2015-9-1下午04:22:16* @作者:Mr.zhou*/public void getTicket() {//调用微信接口获取access_token凭证//Constant.ACCESS_TOKEN = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRETString tokenUrl = Constant.ACCESS_TOKEN.replace("APPID", Constant.APPID).replace("APPSECRET", Constant.APPSECRET);String tokenStr = WXUtils.httpsRequest(tokenUrl, "GET", null);try {JSONObject tokenJson = new JSONObject(tokenStr);String access_token = (String) tokenJson.get("access_token");if(access_token != null && !"".equals(access_token)){//如果可以获取access_token,即可以调用jsapi_tiket的凭证了String ticketUrl = Constant.JSAPI_TICKET.replace("ACCESS_TOKEN", access_token); //Constant.JSAPI_TICKET = https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapiString ticketStr = WXUtils.httpsRequest(ticketUrl, "GET", null);JSONObject ticketJson = new JSONObject(ticketStr);String errmsg = (String) ticketJson.get("errmsg");//如果调用成功,返回okif("ok".equals(errmsg)){jsapi_ticket = (String) ticketJson.get("ticket");}}} catch (JSONException e) {e.printStackTrace();}}
WXUtils.httpsRequest方法:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import javax.net.ssl.HttpsURLConnection;
import javax.servlet.http.HttpServletRequest;//http请求public static String httpsRequest(String requestUrl, String requestMethod, String outputStr){try {URL url = new URL(requestUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);// 设置请求方式(GET/POST)conn.setRequestMethod(requestMethod);conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");// 当outputStr不为null时向输出流写数据if (null != outputStr) {OutputStream outputStream = conn.getOutputStream();// 注意编码格式outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 从输入流读取返回内容InputStream inputStream = conn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;StringBuffer buffer = new StringBuffer();while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}// 释放资源bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;conn.disconnect();return buffer.toString();} catch (ConnectException ce) {System.out.println("连接超时:{}");} catch (Exception e) {System.out.println("https请求异常:{}");}return null;}
spring XML任务调度器代码:
<bean id="jsapiTask" class="cn.ly.web.quartz.JsapiTicketTimeTask"></bean><bean id="timerTask"class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean"><property name="targetObject" ref="jsapiTask"></property><!--这是要执行的对象--><property name="targetMethod" value="getTicket"></property><!--这是要执行的对象的方法--></bean><!--执行的时间 --><bean id="scheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask"><property name="delay" value="1000"></property><!--这是在spring容器实例化后的1秒后执行--><property name="period" value="3600000"></property><!--这是每隔1小时后执行 --><property name="timerTask" ref="timerTask"></property><!--这是要对哪个任务进行再执行--></bean><!--开启计划 --><bean class="org.springframework.scheduling.timer.TimerFactoryBean"><property name="scheduledTimerTasks"><list><ref bean="scheduledTask" /><!--这是要执行的任务的时间规划加载进来 --></list></property></bean>
config接口注入权限
在需要调用微信转发图文消息的订单详细页面,首先需要引入微信的js文件(http://res.wx.qq.com/open/js/jweixin-1.0.0.js),然后加载该页面的时候需要进行ajax与服务器端进行参数的交互,根据获取的参数,调用微信的权限接口验证是否能够使用微信的接口功能。
引入js文件
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
微信权限注入接口
<script type="text/javascript">$(function(){ajaxConfig();});function ajaxConfig(){$.ajax({type:"post",dataType: "json",data: {url : location.href.split('#')[0]},url: "ajax_order/testConfig",success: function(obj){if(obj.result == "success"){//微信注入权限接口wx.config({debug: false,appId: obj.appId,timestamp: obj.timestamp,nonceStr: obj.nonceStr,signature: obj.signature,jsApiList: ['onMenuShareTimeline', //分享到朋友圈'onMenuShareAppMessage' //分享给朋友]});}else{alert("加载数据错误");}},error:function(){alert("系统请求异常!");}});}</script>
ajax_order/testConfig方法:
import java.util.Date;
import java.util.Map;import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import com.opensymphony.xwork2.ActionSupport;
import com.qq.weixin.constant.Constant;
import com.qq.weixin.publics.Sign;@Component
@Scope("prototype")
public class ShareAction extends ActionSupport{private String timestamp,nonceStr,signature,appId=Constant.APPID; //签名需要的参数private String url; //JS-SDK授权的urlprivate String result;/*** * @method testConfig* @描述: TODO(微信config接口注入权限) * @参数@return* @返回类型:String* @添加时间 2015-9-2下午02:35:54* @作者:Mr.zhou*/public String testConfig(){//JsapiTicketTimeTask.jsapi_ticket 是通过spring调度器每1个小时与微信端进行通信,获取jsapi_ticket凭证String jsapi_ticket = JsapiTicketTimeTask.jsapi_ticket;if("".equals(jsapi_ticket)){result = "error";return SUCCESS;}//进行数据的加密(url,jsapi_ticket,nonceStr,timestamp)等参数进行SHA1加密Map<String, String> ret = Sign.sign(jsapi_ticket, url);timestamp = ret.get("timestamp");nonceStr = ret.get("nonceStr");signature = ret.get("signature");result = "success";return SUCCESS;}public String getTimestamp() {return timestamp;}public void setTimestamp(String timestamp) {this.timestamp = timestamp;}public String getNonceStr() {return nonceStr;}public void setNonceStr(String nonceStr) {this.nonceStr = nonceStr;}public String getSignature() {return signature;}public void setSignature(String signature) {this.signature = signature;}public String getAppId() {return appId;}public void setAppId(String appId) {this.appId = appId;}public void setUrl(String url) {this.url = url;}public String getUrl() {return url;}public void setResult(String result) {this.result = result;}public String getResult() {return result;} }
}
Sign方法请点击下载,官方例子
JS-SDK分享接口调用
在上面的config权限注入成功之后,就可以调用微信的分享接口,把设定的内容分享给朋友或者朋友圈了。当然,如果内容是动态获取的,那么你就可以在调用当前接口的时候,ajax获取一些动态的信息,然后在调用分享接口。当前我是以静态的分享案例为例子。
注意:下面的wx.**方法,都是上面jsApiList包含的方法名称哦。比如你需要调用微信的导航接口,就需要在jsApiList列表里面添加‘openLocation’这个方法了。
$(function(){//当用户点击一个id为testBtn的按钮的时候激活事件$("#testBtn").click(function(){wx.onMenuShareAppMessage({title: '互联网之子',desc: '在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。',link: 'http://movie.douban.com/subject/25785114/',imgUrl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',trigger: function (res) {// 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回alert('用户点击发送给朋友');},success: function (res) {alert('已分享');},cancel: function (res) {alert('已取消');},fail: function (res) {alert(JSON.stringify(res));}});alert('已注册获取“发送给朋友”状态事件');wx.onMenuShareTimeline({title: '互联网之子',link: 'http://movie.douban.com/subject/25785114/',imgUrl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',trigger: function (res) {// 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回alert('用户点击分享到朋友圈');},success: function (res) {alert('已分享');},cancel: function (res) {alert('已取消');},fail: function (res) {alert(JSON.stringify(res));}});alert('已注册获取“分享到朋友圈”状态事件');});
});
总结
当你熟悉了以上的大致流程之后,你就可以调用一些微信JS-SDK的功能了,比如导航当前与目标位置,转发消息到朋友圈或者QQ空间等等。如果博客写得不好,还请大家多多包涵。= =!
温馨提示
微信2017年4月25日起,分享的链接一定要与公众号JS设置的安全域名一致哦。例如安全域名是www.abc.com 那么www.abc.com/123是成功的,但是www.def.com/123就不成功了。