微信转发指定的图文消息到朋友圈(JAVA版)

微信转发图文消息步骤

需求

当用户购买成功一样产品,为了使用户能够二次消费,可以在订单详细页面加一个红包按钮,当用户点击之后,可以分享特定的内容(一个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=APPSECRET
        String 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=jsapi
                String ticketStr = WXUtils.httpsRequest(ticketUrl, "GET", null);
                JSONObject ticketJson = new JSONObject(ticketStr);
                String errmsg = (String) ticketJson.get("errmsg");
                //如果调用成功,返回ok
                if("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授权的url
    private 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就不成功了。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值