Hello World

Your description here.

为 Typecho 文章页加入微信分享功能

默认分类 0 评

不使用 JSSDK 的页面,微信分享后的样子会变得很糟糕。今天来为文章页加上这个功能,以后分享内容给朋友,分享卡片也会变得美美哒。

这里需要准备一些必要的东西:

测试号

使用微信扫码进入测试号页面就可以拿到 appIDappsecret

测试号信息-
appIDwx7e2dbb91447*
appsecret0f29148f623301adc7b2ccfd2c2*
关注测试号

为了后续功能的开发与测试,扫描页面测试号的二维码,关注自己的测试号。

设置JS接口安全域名 misaka.im

只有该域名下的代码才能使用 JSSDK 的功能,否则会出现域名无效的错误。

后端

这里有个比较奇葩的操作,要在微信中使用 JSSDK 的功能,必须先发送浏览器当前 URL 到后端进行签名,得到 JSSDK 初始化必要的信息,才能进行初始化。

路由

使用 test.misaka.im 子域来做签名处理,使用 laravel/lumen 框架,避免与博客环境冲突。

$router->group(['prefix' => 'weixin'], function () use ($router){
    $router->get('/sign', 'wxController@sign');
});

添加路由,就是前端请求获得配置参数的地址 https://test.misaka.im/weixin/sign?url=,额外的 url 参数通过控制器函数获得。

控制器

直接使用别人写好的轮子 thenbsp/wechat,集成了微信开发的大部分功能。

namespace App\Http\Controllers;

use Doctrine\Common\Cache\FilesystemCache;

use Illuminate\Http\Request;

use Thenbsp\Wechat\Wechat\AccessToken;

use Thenbsp\Wechat\Wechat\Jsapi;

//AppSecret
const AppSecret = '0f29148f623301adc7b2ccfd2c2*****';
//AppId
const AppId = 'wx7e2dbb91447*******';


protected $cacheDriver;

/**

 * wxController constructor.

 */

public function __construct()
{
    $this->cacheDriver = new FilesystemCache('../cache');
}


public function sign(Request $request)
{
    $accessToken = new AccessToken(static::AppId, static::AppSecret);

    if (!$accessToken->getTokenString()) {
        $accessToken->setCache($this->cacheDriver);
    }

    $jsapi = new Jsapi($accessToken);

    $jsapi->setCache($this->cacheDriver);

    if ($request->has('url')) {
        $jsapi->setCurrentUrl($request->get('url'));
    }

    if ($request->has('apis')) {
        foreach (explode(',', $request->get('apis')) as $api) {
            try {
                $jsapi->addApi($api);
            } catch (\Exception $e) {
                return response($e->getMessage(), 400);
            }
        }
    }

    return response(['data' => $jsapi->getConfig(true)])->header('Access-Control-Allow-Origin', '*');
}

逻辑代码中填写测试号的 AppSecretAppId 。通过获取 url 参数来签名,返回 JSSDK 所需的初始化参数。

因为前端请求域名不是主站,存在跨域问题,另外返回了允许跨域的 HTTP header。

响应结果

浏览器访问 https://test.misaka.im/weixin/sign?url=https%3A%2F%2Fmisaka.im%2Findex.php%2Farchives%2F41%2F 可以测试签名结果:

{
    "data": {
        "appId"    : "wx7e2dbb91447*****",
        "nonceStr" : "vFMyHt6OoE",
        "timestamp": "1544497646",
        "signature": "bc29b6bbffea958f1928bbf083828f4bf87cace8",
        "jsApiList": [],
        "debug"    : false
    }
}

前端

官方 demo 使用了后端渲染的页面直接获取当前浏览器的 URL ,当多数情况是通过接口方式获取前端的:

encodeURIComponent(window.location.href)

如果前端使用 Vue 这些 SPA 框架时,这个情况变得更加复杂:

同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化(路由)时进行调用
引入 JSSDK

在主题模板 header.php 中引入

<script src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
初始化

Typecho 中使用了 jQuery 1.9 ,直接使用 jQuery Ajax 来发起请求。

在模板 footer.php 中加入:

var desc        = "一眨眼一年,我的钱呢?";
var share_title = $(".content > h1").text();
var share_icon  = 'http://ww1.sinaimg.cn/large/8b2a5a08gy1fy1s3tn6j8j203u03saa0.jpg';
var share_link  = window.location.href.split("#")[0].split("?")[0];

$.getJSON('//test.misaka.im/weixin/sign?url=' + encodeURIComponent(window.location.href), function (res) {
  console.log(res)
  
  wx.config({
    debug:     false,              // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId:     res.data.appId,     // 必填,企业号的唯一标识,此处填写企业号corpid
    timestamp: res.data.timestamp, // 必填,生成签名的时间戳
    nonceStr:  res.data.nonceStr,  // 必填,生成签名的随机串
    signature: res.data.signature, // 必填,签名,见附录1
    jsApiList: [
      'onMenuShareTimeline',       // 分享给好友
      'onMenuShareAppMessage',     // 分享到朋友圈
      'onMenuShareQQ',             // 分享到QQ
    ]                              // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
  })
  
  wx.ready(function () {
  
    wx.onMenuShareTimeline({       // 例如分享到朋友圈的API
      title:    share_title,       // 分享标题
      link:     location.href,     // 分享链接  
      imgUrl:   share_icon,        // 分享图标
      success:  function () {},
      cancel:   function () {}
    })
    
    wx.onMenuShareAppMessage({
      title:    share_title,       // 分享标题
      desc:     desc,              // 分享描述
      link:     location.href,     // 分享链接
      imgUrl:   share_icon,        // 分享图标
      type:     '',                // 分享类型,music、video或link,不填默认为link
      dataUrl:  '',                // 如果type是music或video,则要提供数据链接,默认为空
      success:  function () {},
      cancel:   function () {}
    })
    
    wx.onMenuShareQQ({
      title:    share_title,       // 分享标题
      desc:     desc,              // 分享描述
      link:     location.href,     // 分享链接
      imgUrl:   share_icon,        // 分享图标
      success:  function () {},
      cancel:   function () {}
    })
  })
  
  wx.error(function (res) {
    console.log(res.errMsg);       // 打印错误消息。及把 debug:false,设置为debug:ture就可以直接在网页上看到弹出的错误提示
  })
})

使用开发者工具调试

鉴于国内的特殊情况,微信成了独立的一种生态环境,针对它形成的产品场景也不少。使用微信web开发者工具 来调试应用,这样就不用每次提交代码到线上再用手机测试啦。

微信web开发者工具
使用公众号网页调试,开发者可以调试微信网页授权和微信JS-SDK

打开这个工具之后提示使用微信扫码登录,有确认登录界面,并显示了你拥有哪些公众号开发者权限

看界面就是套了个 Chromium,聚合了微信大部分 SDK 功能,模拟 SDK 输入和输出。

访问文章页

修改了模板文件 header.phpfooter.php ,来测试下效果。调试工具直接访问 https://misaka.im/index.php/archives/41/

页面加载完后,会发出一条 XHR 请求,url 参数是 urlencode 之后的当前地址

点击展开详细面板

当 JSSDK 初始化完成后会在 Console 调试台中打印出相关信息

  • wx.config begin 表示 wx.config() 被调用,及传入的参数
  • wx.config end 表示 JSSDK 初始化完成, errMsg:ok 代表初始成功
  • 可用的操作权限列表
模拟分享操作

点击右上角更多的操作,点击发送给朋友或朋友圈

分享前后, Console 调试台会打印出分享的具体信息:

  • wx.onMenuShareAppMessage begin 触发 onMenuShareAppMessage() 配置好的分享信息
  • wx.onMenuShareAppMessage end 触发 onMenuShareAppMessage() 配置好的分享回调
DEMO

使用微信web开发者工具打开 前端 demohttp://203.195.235.76/jssdk/), 右侧调试面板显示了代码是如何运作的。

至于签名的一些逻辑操作,官方那个给出了签名的正确姿势前端 demo

JSX 在 Vue 项目上的应用
快来做第一个评论的人吧~