h5 微信分享和踩坑指南

思路

h5 微信分享的官方文档在 这里,如果链接挂了,可以按照一下路径去查找:【微信开放社区】 - 【文档】 - 【公众号】 - 【微信网页开发】 - 【JS-SDK 说明文档】找到。

从上面可以看出,网页分享必须要有公众号,公众号分两种,服务号和订阅号,必须要先注册。

注册后就是按照官方文档进行 【绑定域名】 的操作:

步骤一:绑定域名

先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS 接口安全域名”。

备注:登录后可在“开发者中心”查看对应的接口权限。

绑定完就引入 sdk 文件:

步骤二:引入 JS 文件

在需要调用 JS 接口的页面引入如下 JS 文件,(支持 https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js

微信会 sdk 会在全局暴露一个 wx 对象供我们访问,使用如 window.wx

但是但是,现在的 sdk 根本用不成,需要进行权限配置。 权限配置全部丢给后端做,我特么把文档读完了才看到这部分是后端的内容,垃圾文档。反正就是请求 access_token,然后又去取啥 jsapi_ticket 票据,然后拿着票据又特么用随机字符串、时间戳和当前页面的 url 来加密获取签名,反正就全是安全的操作。注意,这部分逻辑不能写在客户端,让后端写接口。

注意这个签名的流程里面需要当前页面的 url,一般后端会让前端发给他们,其实后端也可以从请求报文里面拿,看业务需求。

然后就是通过后端返回的相关数据进行微信权限验证:

步骤三:通过 config 接口注入权限验证配置

所有需要使用 JS-SDK 的页面必须先注入配置信息,否则将无法调用(同一个 url 仅需调用一次,对于变化 url 的 SPA 的 web app 可在每次 url 变化时进行调用,目前 Android 微信客户端不支持 pushState 的 H5 新特性,所以使用 pushState 来实现 web app 的页面会导致签名失败,此问题会在 Android6.2 中修复)。

通过以下方式进行注册:

wx.config({
  debug: true, // 开启调试模式,调用的所有 api 的返回值会在客户端 alert 出来,若要查看传入的参数,可以在 pc 端打开,参数信息会通过 log 打出,仅在 pc 端时才会打印。
  appId: '', // 必填,公众号的唯一标识,这个可以让后端返回,也可以直接配置
  timestamp: , // 必填,生成签名的时间戳,这个让后端返回
  nonceStr: '', // 必填,生成签名的随机串,这个让后端返回
  signature: '',// 必填,签名,这个让后端返回
  jsApiList: [] // 必填,需要使用的 JS 接口列表
});

大致就是那么回事,该让后端返回的就让后端返回就行。注意正常开发不要开启 debug,debug 只是用来测试是否正常完成注册

注册完成就可以使用了:

步骤四:通过 ready 接口处理成功验证

步骤五:通过 error 接口处理失败验证

踩坑集锦

链接不能直接作用与分享

我特么都把分享流程写完了,而且 debug 也跑通了,问题他么的我点击链接进去分享出来就是不成功。后来才知道,必须使用扫码打开才行。所以测试时候要把准备的页面转化为二维码,然后扫码打开。

解决:

chrome 自带二维码生成,不过只支持 250 字符以内,真的是个二百五。然后我又用了 草料。然后扫码打开可以完成测试。

url 参数不能携带特殊字符,比如花括号 “{}”

这也是个大坑,我在网上居然没找到相关踩坑。我的分享网址的查询参数上有 json 字符串,所以自然好多的花括号 {},这特么微信文档也不说,估计是个 bug。

解决:

本来我尝试把发给后端的 url 使用 encodeURI 把 json 字符串转义了,结果特喵的还是不行,匹配当前页面的 url 和签名里的 url 不一致。所以必须把当前 url 重定向到一个已经转义后的 url 上。

那就重定向咯,我在进入页面直接进行判断是否转义,没转义就重定向到转义后的 url 上,就这样,才最终好使。

我写了那么一段无用代码才解决这个 bug:

/** 修复微信屎一样的 bug,meta 是 json 类型,含有花括号 {},微信他么用来加密使用的 url 解析会出错,分享导致失败。如果发给后端的 url 使用转义后的,微信加密又会不匹配。最后无法,直接重定向到一个解析后的 url,使用该 url 来作为分享链接。encode 字段用来标识该 url 是转义过的,满足微信 sdk 调用要求。 */
if (!params.get("encode") && uaCheck().isWeChatBrowser) {
  const lo = window.location;
  lo.href = `${lo.origin}${lo.pathname}?type=${type}&payload=${payload}&meta=${encodeURI(meta!)}&encode=1`;
}

上面代码中,params 就是 URLSearchParams 的实例,uaCheck 来源于库 ua-check

代码实现

项目在 react + ts 中,微信全局 api 需要现在全局上定义个类型,在 global.d.ts 注册微信的全局引用:

export const thisIsAModule = true; // <-- definitely in a module

declare global {
  var wx: any;
}

接着编写分享文件:

我创建了个 wechatShare.ts 文件来封装相关微信分享逻辑:

import { apiGetUserShareWechatSignature } from "lib/api";

/** 加载 wechat sdk */
function wechatSDKLoad(): Promise<any> {
  if (window.wx) return Promise.resolve(window.wx);

  return new Promise((resolve) => {
    const script = document.createElement("script");
    script.src = `https://res.wx.qq.com/open/js/jweixin-1.6.0.js`;
    document.head.append(script);

    script.onload = () => resolve(window.wx);
  });
}

/** 微信 api 是否已经准备好了 */
let ready = false;

/**
 *
 * @param cb 微信 api 准备好的时候的回调函数
 */
export async function wechatReady(cb: (wx: any) => void) {
  // 二次执行直接执行回调
  if (ready) return void cb(window.wx);

  // 获取签名并加载微信 sdk
  const [res, wechat] = await Promise.all([apiGetUserShareWechatSignature(window.location.href), wechatSDKLoad()]);
  const d = res.data.data;

  wechat.config({
    debug: false,
    appId: d.appId,
    timestamp: d.timestamp,
    nonceStr: d.noncestr,
    signature: d.signature,
    jsApiList: [
      "updateAppMessageShareData", // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
      "updateTimelineShareData", // 自定义“分享到朋友圈”及“分享到 QQ 空间”按钮的分享内容
    ],
  });

  wechat.ready(() => {
    cb(wx);
    ready = true;
  });

  wechat.error((e: Error) => console.error(e));
}

interface ShareParams {
  title: string; // 分享标题
  desc: string; // 分享描述
  link: string; // 分享链接,该链接域名或路径必须与当前页面对应的公众号 JS 安全域名一致
  imgUrl: string; // 分享图标
  success?(): void; // 设置成功
}

/** 分享给朋友或到朋友圈圈 */
export function wechatShare(params: ShareParams) {
  wechatReady((wechat) => {
    wechat.updateAppMessageShareData(params);
    wechat.updateTimelineShareData(params);
  });
}

使用就比较方便了,在需要使用的地方对 wechatShare 进行进入,然后执行就行:

wechatShare({
  title: "分享的标题",
  desc: "分享的描述",
  imgUrl: "图片路径",
  link: window.location.href.split("#")[0], // 不能包含 url 的片段部分,不然也会报错
});

打完收工,垃圾微信 sdk 再说一次!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值