微信分享

微信上做推广活动一般都是着眼于微信分享,这篇文章介绍如何在页面中加入微信分享的处理。本文使用语言为Java+js。

原理

微信分享功能的难点,在于用户是否真正的分享了推广页面,所以我们要知道用户分享成功的操作。经过查询文档,微信提供了对应的JS接口。对应文档在这里 .

大体流程是这样的:

  • 绑定域名
  • 引入JS文件
  • 通过config接口注入权限验证配置
  • 通过ready接口处理成功验证
  • 通过error接口处理失败验证
  • 编写对应回调

如果你自信满满的完成了上面这些步骤,就可以开始着手测试了。 当点击对应功能时,微信会回调对应的接口。我的需求是当用户分享到自己的朋友圈时,做一些猥琐的操作 

 ,因此下面以分享朋友圈为例,当然其他功能也很类似,此处按下不表。

实现

上面概括了原理了原理,接下来一步一步看。本文可以结合 官方文档 一起看,毕竟它更新维护的比较勤。

绑定域名

先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。 备注:登录后可在“开发者中心”查看对应的接口权限。

此处要注意了,微信服务号还没验证的程序狗,赶紧催促贵公司的商务人员,申请微信服务号验证,目前没有认证的服务号是没法使用大多数JS接口的 

android 微信分享 file 微信文件分享0b_公众平台

引入JS文件

在需要调用JS接口的页面引入如下JS文件,(支持https):

http://res.wx.qq.com/open/js/jweixin-1.0.0.js

备注:支持使用 AMD/CMD 标准模块加载方法加载

这个没啥说的,就是注意要把引入放到其他步骤的上面,JS脚本按顺序加载,大家都懂的。

通过config接口注入权限验证配置

这个最麻烦了,首先说脚本的格式:

1. wx.config({  
2. true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。  
3. '', // 必填,公众号的唯一标识  
4. // 必填,生成签名的时间戳  
5. '', // 必填,生成签名的随机串  
6. '',// 必填,签名,见附录1  
7. // 必填,需要使用的JS接口列表,所有JS接口列表见附录2  
8. });

这部分信息的获取,推荐使用ajax请求一下自己的服务器,毕竟加密这东西没法在客户端搞。所以大体流程是用户打开网页,运行ajax脚本请求服务器一堆信息,成功发下来后,在写到js里面。下面上代码:

    1. var url = location.href.split('#').toString();  
    2. $.ajax({  
    3. "POST",  
    4. "yourInterfaceURL",  
    5. "html",  
    6. false,  
    7. "url="+url,  
    8.     success : function(dataStr) {  
    9.         var data = $.parseJSON(dataStr);  
    10.         wx.config({  
    11. true,  
    12.             appId: data.appid,  
    13.             timestamp: data.timestamp,  
    14.             nonceStr: data.nonceStr,  
    15.             signature: data.signature,          
    16.             jsApiList: [  
    17. 'checkJsApi',  
    18. 'onMenuShareTimeline'  
    19.             ]  
    20.         });  
    21.     },  
    22.     error: function(xhr, status, error) {  
    23.         alert(status);  
    24.         alert(xhr.responseText);  
    25.     },  
    26. });


    这里有一点要注意,我们需要将请求页面的URL传上去,因为微信会在页面后面加入一些后缀比如&isInstall=0之类的。所以它要求你动态算一个URL地址,而不能硬编码。

    然后服务器收到这请求就加密去。要加密要一个jsapi_ticket,而要jsapi_ticket又需要token.

    由于原理一样,这里仅以jsapi_ticket为例:


    1. public String jsapi_ticket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";  
    2.   
    3. public String getJsapiTicket() {  
    4. long now = System.currentTimeMillis();  
    5. if(now - curJSTokenTime > expiresJSToken*1000)  
    6.     {  
    7. "ACCESS_TOKEN", getToken());  
    8. "GET", null);  
    9. "Getting weixin js_token...URL:"+requestUrl);  
    10.   
    11. if (null != jsonObject) {  
    12. try {  
    13. "ticket");  
    14. "expires_in");  
    15.                 curJSTokenTime = System.currentTimeMillis();  
    16. "update weixin token:"+curJSToken+"expires_in is:"+expiresJSToken+" curTime:"+curJSTokenTime);  
    17. catch (JSONException e) {  
    18. "Get JS_Token Error! errcode:{} errmsg:{}"+jsonObject.getInt("errcode")+jsonObject.getString("errmsg")+e);  
    19.             }  
    20. else {  
    21. "http for weixin return null");  
    22. "";  
    23.         }  
    24.     }   
    25. return curJSToken;  
    26. }


    拿到了这个东西就可以算加密串了。当然用这个函数需要先去取Access_Token,这就又要用到appid和appSercet,你必然知道在哪找到这货,啥?不知道?去微信的开发者中心的配置项那边碰碰运气吧。

      1. public Map<String, String> makeWXTicket(String jsapi_ticket, String url) {  
      2. new HashMap<String, String>();  
      3.     String nonce_str = create_nonce_str();  
      4.     String timestamp = create_timestamp();  
      5.     String string1;  
      6. "";  
      7.   
      8. //注意这里参数名必须全部小写,且必须有序  
      9. "jsapi_ticket=" + jsapi_ticket +  
      10. "&noncestr=" + nonce_str +  
      11. "×tamp=" + timestamp +  
      12. "&url=" + url;  
      13. try  
      14.     {  
      15. "SHA-1");  
      16.         crypt.reset();  
      17. "UTF-8"));  
      18.         signature = byteToHex(crypt.digest());  
      19.     }  
      20. catch (NoSuchAlgorithmException e)  
      21.     {  
      22.         e.printStackTrace();  
      23.     }  
      24. catch (UnsupportedEncodingException e)  
      25.     {  
      26.         e.printStackTrace();  
      27.     }  
      28.   
      29. "url", url);  
      30. "jsapi_ticket", jsapi_ticket);  
      31. "nonceStr", nonce_str);  
      32. "timestamp", timestamp);  
      33. "signature", signature);  
      34. "appid", appId);  
      35.   
      36. return ret;  
      37. }  
      38.   
      39. private static String byteToHex(final byte[] hash) {  
      40. new Formatter();  
      41. for (byte b : hash)  
      42.     {  
      43. "%02x", b);  
      44.     }  
      45.     String result = formatter.toString();  
      46.     formatter.close();  
      47. return result;  
      48. }  
      49.   
      50. private static String create_nonce_str() {  
      51. return UUID.randomUUID().toString();  
      52. }  
      53.   
      54. private static String create_timestamp() {  
      55. return Long.toString(System.currentTimeMillis() / 1000);  
      56. }


      makeWXTicket这个函数有俩参数,第一个是上面的jsapi_ticket,第二个是页面传上来的url,返回值是一个Map。后面就看各路大神八仙过海了,大死不灵啥的,总之你肯定有办法把这货传回去的。传回去后,就到wx.config中把内容填充进去了。

      ready & error & 功能调用

      最恶心的部分搞过去,其他就一马平川了。



        1. wx.ready(function () {  
        2.     wx.onMenuShareTimeline({  
        3. '互联网之子?',  
        4. 'http://movie.douban.com/subject/25785114/',  
        5. 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',  
        6.       trigger: function (res) {  
        7. // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回.  
        8. 'click shared');  
        9.       },  
        10.       success: function (res) {  
        11. 'shared success');  
        12. //some thing you should do  
        13.       },  
        14.       cancel: function (res) {  
        15. 'shared cancle');  
        16.       },  
        17.       fail: function (res) {  
        18.         alert(JSON.stringify(res));  
        19.       }  
        20.     });  
        21.   
        22.   wx.error(function (res) {  
        23.       alert(res.errMsg);  
        24.   });  
        25. });


        在网页中添加以上内容,用户点击对应的操作就会弹出提示对话框啦 

        android 微信分享 file 微信文件分享0b_公众平台_02

         如果没有回调,签名又没有问题,去开发者中心检查一下接口是否开通了吧。

        总结

        接入过程很纠结,测试比较麻烦,微信服务器的回调只认有备案的域名。验签可以使用这个网址 做测试。总之,祝你好运~