微信分享常见问题--避坑指北

构造网页授权链接 

再讲微信分享需要躲避的一些坑之前,先说说微信分享的一些背景知识

1.JS-SDK的用途

微信JS-SDK是 微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包。通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。微信开放这些能力给开发者,要对开发者进行鉴权。防止开发者对某些接口滥用,比如说传播类的接口。鉴权的时候需要签名,签名需要票据,随机字符串,时间戳,网址。比较麻烦的参数票据,票据的生成,需要调用另外一个接口,参数是appId和serect。这个接口每天只能调用2000次,每次调用的有效期是2小时。

2.签名的获取方法

2.1 准备工作

1.登录微信公众平台,在开发设置中查看AppID和AppSecret

2 设置JS接口安全域名。这里填写的是一级域名,不带www和http。最多可以设置三个域名。相比以前的分享没有任何域名限制,现在设置安全域名,目的是为了当微信发现此公众平台发现诱导分享行为时,可以根据此域名追溯到所有分享出去的链接,以及通过这些链接增加的粉丝。这样,微信就可以牢牢控制了你的微信平台,一旦发现违规,让分享链接失效,删除掉诱导行为增加的粉丝,是瞬间就可以完成的。因此,一定要合理来使用分享功能,不要因小失大。等到你的微信平台被封,估计哭都来不及。

2.2 获得Access Token

access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。正常情况下 access_token有效期为7200秒,重复获取将导致上次获取的access_token失效。公众号可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在微信公众平台中获得(见上图)。 注意调用所有微信接口时均需使用https协议。

// https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

参数说明

返回说明
正常情况下,微信会返回下述JSON数据包:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):

{"errcode":40013,"errmsg":"invalid appid"}

2.3 获取jsapi_ticket

生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
用第一步拿到的access_token , 采用https GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket),接口地址如下

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

成功返回如下JSON:

{
  "errcode":0,
  "errmsg":"ok",
  "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  "expires_in":7200
}

获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。

2.4 签名算法实现

签名生成规则如下:

对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string。这里需要注意的是所有参数名均为小写字符。对string作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。即** signature=sha1(string)**。 示例:

2.4.1 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value

2.4.2 对string进行sha1签名,得到signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

2.5 企业微信获取JS-SDK使用权限签名步骤

参见 企业微信JS-SDK使用授权签名算法,其中jsapi_ticket的获取比较麻烦一些,需要向如下地址发起get请求

https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN

入参access_token的获取分两种情况:

如果是第三方应用开发,需要以post方式向如下地址发起请求

 https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=SUITE_ACCESS_TOKEN

入参为:

{
  "auth_corpid": "auth_corpid_value", // 授权方corpid
  "permanent_code": "code_value"      // 永久授权码,通过get_permanent_code获取
}

permanent_code的获取方式是,向如下地址发起post请求

https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=SUITE_ACCESS_TOKEN

入参:

{
    "auth_code": "auth_code_value"  // 临时授权码,会在授权成功时附加在redirect_uri中跳转回第三方服务商网站,或通过授权成功通知回调推送给服务商。长度为64至512个字节
}

第三方服务商在得到公众号或小程序运营者(简称运营者)授权 后,第三方平台开发者可以通过调用微信开放平台的接口能力,为公众号或小程序的运营者提供账号申请、小程序创建、技术开发、行业方案、活动营销、插件能力等全方位服务。

3 项目中的问题

3.1 IOS下微信环境 -- 分享的文章内容描述与图标不对

微信应用右上角自带的分享功能,在分享内容之前需要调用wx.config对微信分享JS-SDK鉴权,需要的传参如下:

wx.config({
  debug: true, // 开启调试模式
  appId: "xxx", // 必填,公众号的唯一标识
  timestamp: "timestamp", // 必填,生成签名的时间戳
  nonceStr: "nonceStr", // 必填,生成签名的随机串
  signature: "signature",// 必填,签名
  jsApiList: ['onMenuShareAppMessage','onMenuShareTimeline'] // 必填
});

其中不好获取的参数是signature。signature是怎么获取的呢?在我们的项目中,是通过请求getTicket接口,获取signature,而请求getTicket接口的参数中,最容易出问题的就是jsUrl。

const params = {
    appId: newAppId || appId,
    corpId: env === "wx" ? authCorpId : currentCorpId,
    wechatType: env,
    jsUrl: url,
    agentId,
  };
  const res = await ajax('getTicket', params, isShowError);
  const { retdata = {} } = res;
  const { appId, noncestr, signature, timestamp, nextUpdateTime } = retdata;
  const obj = {
    debug: false, // 是否开启调试模式
    appId, // appid
    timestamp, // 时间戳
    nonceStr: noncestr, // 随机字符串
    signature, // 签名
    jsApiList,
    openTagList: [],
  };
  if (env === 'qywx') {
    obj.beta = true;
    obj.appId = currentCorpId;
  }
  wx.config(obj);

这个jsUrl参数,按理说要取当前分享页面的url,在Android上确实是这样,可是在IOS手机上,企业微信环境下没有问题,可是微信环境如果取当前分享页面的url,

url = encodeURIComponent(window.location.href);

分享出去的内容,图标和描述的展示会有问题

应该取进入单页应用首页的url,而不是当前页面的url

url = encodeURIComponent(localStorage.getItem(keyDict.entryUrl));

所以获取jsUrl的时候,要添加判断条件:

// 如果是 iOS 设备,个人微信环境,则使用应用首页的 URL 去请求 wxConfig,不然的话会导致 iOS 中分享的链接描述信息或者图标不对
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent) && env === "wx") {
  // console.log('签名地址=======================', localStorage.getItem(keyDict.entryUrl))
  url = encodeURIComponent(localStorage.getItem(keyDict.entryUrl));
} else {
  // console.log('签名地址=======================', window.location.href)
  url = encodeURIComponent(window.location.href);
}

鉴权失败会报如下错误,此时重点要检查一下url有没有多次调用encodeURIComponent编码

wx.config {"errMsg": "config:invalid signature"}

3.2 有些JS-SDK接口,比如说h5跳转微信小程序, 除了调用wx.config之后,还要调用 wx.agentConfig,否则会报no_permission错误

3.2.1 wx.config和wx.agentConfig的区别

wx.config注入的是企业的身份与权限,而wx.agentConfig注入的是应用的身份与权限。尤其是当调用者为第三方服务商时,通过config无法准确区分出调用者是哪个第三方应用,而在部分场景下,又必须严谨区分出第三方应用的身份,此时即需要通过agentConfig来注入应用的身份信息。wx.agentConfig配置步骤:

3.2.2 先要引入 jwxwork sdk

<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>

3.2.3 wx.agentConfig配置参数

wx.agentConfig({
  corpid: '', // 必填,企业微信的corpid,必须与当前登录的企业一致
  agentid: '', // 必填,企业微信的应用id (e.g. 1000247)
  timestamp: , // 必填,生成签名的时间戳
  nonceStr: '', // 必填,生成签名的随机串
  signature: '',// 必填,签名,见附录-JS-SDK使用权限签名算法
  jsApiList: ['selectExternalContact'], //必填,传入需要使用的接口名称
  success: function(res) {
  // 回调
  },
  fail: function(res) {
    if(res.errMsg.indexOf('function not exist') > -1){
      alert('版本过低请升级')
    }
  }
});

3.2.4 调用agentConfig的注意事项(摘录于企微官方文档)

1. agentConfig与config的签名算法完全一样,但是jsapi_ticket的获取方法不一样,请特别注意,查看获取应用身份的ticket
2. agentConfig仅在企业微信2.5.0及以后版本支持,微信客户端不支持(微信开发者工具也不支持)
3. 调用wx.agentConfig之前,必须确保先成功调用wx.config. 注意:从企业微信3.0.24及以后版本,无须先调用wx.config,可直接wx.agentConfig. 可通过 企业微信UA 判断版本号
4. 当前页面url中的域名必须是在该应用中设置的可信域名。
5. 仅部分接口才需要调用agentConfig,需注意每个接口的说明

 

3.3 跨企业微信分享内容,在另一企业打开,再次分享,分享出去的文章的描述不对,有时图标也不显示,  wx.config报如下错误

errMsg: "config:invalid corpid more info at https://open.work.weixin.qq.com/devtool/query?e=40013"

原因是: 当前登录的企业微信与获取签名使用的企业微信不一致。 在B企业下,无法用A企业的JS-SDK授权功能。即使A, B企业下,配置了相同的可信域名。也无法共享授权。只能在各自的企业下,调用微信提供的JS-SDK。
因为在B企业下打开分享内容时,hideMenuItems是第一个被调用的JS-SDK,所以第一个报的JS-SDK调用错误是hideMenuItems接口:

 

wx.config配置出错的情况下,文章虽能分享。可是分享出去的文章,是有问题的。从下图可以看出,描述变成了文章的网址。这个错误比较迷惑人。

3.4 wx.agentConfig 授权配置客户聊天JSSDK ['sendChatMessage', 'getCurExternalChat', 'getContext']时,报错

 

 解决方法: 在企业微信管理后台,给对应的应用授予 可调用外部联系人接口的权限。如果企业创建了上下游,则菜单导航是" 客户与上下游 ",否则导航菜单是" 客户联系 "

 

 

3.4.2 报getCurExternalContact:fail_without context of external contact   这个报错是未从特定的入口进入,需要在聊天工具栏或个人信息栏界面使用

3.5 在特殊业务场景下,需要本地加载微信SDK,奇怪的是,本地加载的微信SDK,会缺少一些方法,比如说wx.agentConfig,而通过官方提供的在线方式加载,无此问题。

所以微信sdk不能本地加载。只能使用下面的地址加载 https://res.wx.qq.com/open/js/${sdkVerion}

3.6 有些网页在微信中打开之后,缺少分享给微信好友,发送到朋友圈系统菜单。是由于分享的链接没有绑定微信公众号

3.7 微信小程序可以获取手机号,微信公众号h5页面,不能获取手机号。只能获取头像,昵称,地区,性别这些。

3.8 企业微信--从聊天附件栏发送信息给好友,三天之后消息无法发送

参见 https://work.weixin.qq.com/api/doc/90001/90143/90389

3.9.在微信环境中,可以用wx.chooseImage上传图片,返回的信息特别有限,只有一个文件id,无法判断上传文件的尺寸。

3.10 微信登陆失败, redirect_uri与后台配置域名不一致。解决方案:   在企微后台配置网页授权域名,  在运营后台对配置的可信域名进行认证。

3.11.企微欢迎语图标不展示的问题

第一,不能用new Image()的方式加载图片,要采用img标签加载图片,img标签设置成display:none, 资源也会正常下载;

第二,欢迎语的图片尺寸要大于或接近200px*200px。

3.12 IOS下签名无效 invalid signature more info at https://open.work.weixin.qq.com/devtool/query?e=40093

解决方法: 获取签名时传的url必须是当前页面的地址

3.13 wx.agentConfig: invalid corpId more info athttps://open.work.weixin.qq.com/devtool/query?e=40013

解决方法: 第三方公司配置的公司corpId须和提供的企业微信corpId保持一致

3.14  个别机型,分享出去的页面,标题和描述正常,图标显示为回形针。JS-SDK调用没有任何问题。

解决方案: 如果分享图片原来是png,替换成jpg格式就可以了

3.15 服务商代开发自建应用, redirect_uri需使用应用可信域名

解决方法:企微管理后台==>应用管理==>网页授权及JSSDK==>设置可信域名

注意有的应用时服务商代开发应用,需要服务商去配置

 

 

 

 

 

 

 
posted @ 2021-07-28 17:14  孤舟蓑翁  阅读(2085)  评论(0编辑  收藏  举报