术语介绍

  1. corpid

    每个服务商同时也是一个企业微信的企业,都有唯一的corpid。获取此信息可在服务商管理后台“应用开发”-“通用开发参数”可查看

  2. provider_secret

    作为服务商身份的调用凭证,应妥善保管好该密钥,务必不能泄漏。

  3. suiteid/suite_secret

    suiteid(第三方应用ID)为应用的唯一身份标识,suite_secret为对应的调用身份密钥。

  4. suite_ticket

    suite_ticket与suite_secret配套使用,用于获取suite_access_token。

    suite_ticket由企业微信后台向登记的应用指令回调地址定期推送(10分钟),用于加强调用者身份确认(即使suite_secret泄露,也无法获取到suite_access_token)。

    若开发者丢失suite_ticket,除了等待定时推送的事件外,开发者也可以在管理端手动触发推送

  5. userid && open_userid(密文员工id)

    通过网页授权接口可以获取到当前用户的 userid && open_userid 信息,如果需要获取用户的更多信息可以调用 通讯录管理 - 成员接口 来获取。

    • userid用于在一个企业内唯一标识一个用户[企业微信帐号ID安全性全面升级后,userid=open_userid]
    • open_userid:服务商内全局唯一。对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的,最多64个字节。 [第三方应用服务商可以将此字段作为用户id]

    external_userid(客户级别)是企业微信外部联系人的标识(企业内唯一,服务商内不唯一)。

  6. 回调配置

    回调事件规则:企业微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次,每次间隔1秒,如果三次都失败后就不会再重试了!

    当接收成功后,http头部返回200表示接收ok,其他错误码企业微信后台会一律当做失败并发起重试

    • 服务商后台 -> 应用管理 -> 第三方应用 -> 数据回调URL:用于接收用户发送给应用的消息和事件,包括文本、图片、视频、位置、链接等消息和成员关注、取消关注、进入应用、通讯录变更等事件,详见消息推送文档
    • 服务商后台 -> 应用管理 -> 第三方应用 -> 指令回调URL(即第三方应用回调URL):系统将会把此应用的授权变更事件以及ticket参数推送给此URL
    • 服务商后台 -> 应用管理 -> 通用开发参数 -> 系统事件接收URL:通过推广二维码企业微信注册成功事件
  7. 应用上线与上架

    tip: 第三方应用可只上线,而不上架。

    上线应用->自有渠道推广,用户达到企业微信要求,程序达到优先要求->申请上架应用->企业微信联系联合体验优化,灰度测试优化->应用上架出现在企业微信应用市场

    上线应用的安装途径:1. 注册按钮(需程序实现自行构造测试授权链接)2. 推广二维码(设置入口:服务商管理后台 > 应用推广 > 推广二维码)

    应用开发与推广

区分三种类型access_token

在第三方应用开发提供的接口中,会涉及到三种类型的access_token。下面表格对这三类token的定义及使用场景进行说明,开发者应在不同场景中选择对应的token:

服务商、第三方应用、授权企业的关系:一个服务商下有多个第三方应用,每个第三方应用可授权多个企业使用。

类型 说明 适用场景
服务商的token(provider_access_token) 以corpid(服务商CorpID)、provider_secret(服务商密钥)换取provider_access_token,代表的是服务商的身份 用于服务商级别的接口调用,比如登录授权、推广二维码等。说明文档参考 获取服务商凭证
第三方应用的token(suite_access_token) 以suite_id(第三方应用ID)、suite_secret(第三方应用密钥)换取suite_access_token,代表第三方应用的身份 用于获取第三方应用的预授权码,获取授权企业信息等。说明文档参考 获取第三方应用凭证
授权企业的token(access_token) 企业安装第三方应用后,第三方服务商以企业的corpid、永久授权码来获取access_token 用于操作授权企业相关接口,如通讯录管理,消息推送等。说明文档参考 获取企业凭证

access_token 在调用 api 之前怎么验证它的有效性?

方案:access_token如果失效调用接口会有返回错误码的,如果返回了42001/42009错误码,就是失效了,需要重新获取一次。

  • 42001:access_token已过期或provider_access_token已过期
  • 42009:suite_access_token已过期

企业微信access_token在有效期内重复获取会返回相同结果,有效期正常情况下为7200秒(2小时)。

注意:每次获取token时,该token都有2小时有效期企业微信可能会出于运营需要,提前使access_token失效,开发者应实现access_token失效时重新获取的逻辑。

整体来说,企业微信和微信公众号、小程序等都有对旧token的有效期做延长处理,access_token可以直接用redis缓存7200秒,redis过期后直接重新获取access_token即可。

每次获取token时,该token都有2小时有效期

微信公众号每次获取token时,该token都有2小时有效期

前端JS-SDK使用权限的签名算法

JS-SDK使用权限签名算法

签名生成规则:

  • 参与签名的参数有四个: noncestr(随机字符串), jsapi_ticket(如何获取参考“获取企业jsapi_ticket”以及“获取应用的jsapi_ticket接口”), timestamp(时间戳), url(前端请求网页的URL, 不包含#及其后面部分)
  • 需实时生成签名,并缓存jsapi_ticket

jsapi_ticket:分为 企业的jsapi_ticket(corp_jsapi_ticket) 和 应用的jsapi_ticket(app_jsapi_ticket)。jsapi_ticket是H5应用调用企业微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。

应用授权流程

应用授权文档

应用授权流程

第三方应用设置

使用配置

使用配置

一些心得

对于第三方服务商来说,如何保证多个企业的所有员工唯一性?如何保证多个企业内的相同客户的唯一性?

  1. 使用我们第三方应用的是员工,不同企业的员工可以用 open_userid 保证唯一性(对于同一个服务商,不同应用获取到企业内同一个成员的open_userid是相同的)
  2. 前端只能拿到客户的 external_userid,后端用该 corpid+external_userid 保证客户的唯一性(建议使用 uuid 等其他方案标识客户的唯一性)

关于ExternalUserId

ExternalUserId是企业微信外部联系人的标识,但需要开发者(尤其是第三方开发者)注意的是,对于同一个外部联系人,不同调用方(企业/第三方服务商)获取到的ExternalUserId是不同的。

关于客户群ID

企业微信为每个客户群生成唯一的ID(chat_id),同样需要注意的是,对于同一个群,不同调用方(企业/第三方服务商)获取到的chat_id是不同的

获取客户详情API

获取客户详情API

  • 请求参数说明

    access_token: 企业的access_token,非第三方服务商的access_token

    external_userid: 外部联系人的userid,注意不是企业成员的帐号。

    对于第三方服务商来说,可以使用 external_userid 保证客户的唯一性

  • 响应参数说明

    关于返回的unionid,如果是第三方应用调用该接口,则返回的unionid是该第三方服务商所关联的微信开发者帐号下的unionid。也就是说,同一个企业客户,企业自己调用,与第三方服务商调用,所返回的unionid不同;不同的服务商调用,所返回的unionid也不同。

    这里其实是说第三方服务商调用客户详情API时,返回的客户 unionid 是第三方服务商微信开放平台上的 unionid

    第三方服务商服务于多个企业时,也可以使用 unionid 保证客户的唯一

回调消息/事件类型

- MsgType: 消息类型,third(自定义的第三方应用事件),text/image/voice等消息事件, event(其他事件)
- EventType: 事件类型,当 MsgType 为 event 时存在
- InfoType: 等同于EventType,是企业微信第三方应用的专用字段,此时我们可以自定义 MsgType="third",InfoType=EventType
- ChangeType:变更类型,当 InfoType 为 change_external_contact 时存在

客户继承

继承分在职继承、离职继承两种。在职员工客户只能转两次,有90天保护期。

-  在企业微信中离职分两种情况

    1. 员工主动退出企业(员工主动退出企业,他的客户可以当日做离职继承吗?答:不能继承,需要30天后才能继承,或者管理员主动删除员工)
    2. 管理员主动在通讯录删除成员

- 继承回调事件

    1. 在职继承成功的话会有添加外部联系人和删除外部联系人的回调事件
    2. 离职成员分配客户成功,会有添加外部联系人事件回调,没有删除外部联系人事件回调

- [在职继承介绍](https://work.weixin.qq.com/nl/act/p/6dce987927674295)

- [离职继承介绍](https://work.weixin.qq.com/wework_admin/frame#customer/pending_intro)

企业注销企业微信账号

企业注销企业微信账号,第三方应用会接收到取消授权事件。(InfoType=cancel_auth)

前端保存 token 的方案

同一个设备,不同员工账号登录,在不进行oauh登录的情况下,怎么知道切换了账号?

用cookie做下判断,企业微信在切换账号时,会清理cookie

特别留意

  1. 所有接口返回包里都有errcode、errmsg。开发者需根据errcode是否为0判断是否调用成功

  2. 接口调用请求体和响应体是 json 格式,回调接口的请求体和响应体是 xml 格式

  3. 如果第三方应用需要使用发微信小程序功能,需要先配置一个第三方小程序绑定微信小程序。授权企业需要同时安装第三方应用和第三方小程序(推广二维码支持应用和小程序混合推广)

  4. 接口调用频率限制:

    • 获取access_token频率:每日限额2000次
    • 获取jsapi_ticket频率:一小时内,一个企业最多可获取400次,且单个应用不能超过100次

    企微接口访问频率限制文档

企微微信客户端

Mac版本开启调试模式

  1. 按下command+shift+control+D进入调试模式
  2. 帮助->开发调试选项->开启webView元素审查
  3. 内置浏览器右键

debug开启

获取会话 roomid 方式,用于向腾讯客服申请群解封

同时按下Ctrl+Shift+Command+D—>进入debug模式–>右键会话–>复制会话id

一些坑

  1. 前端发视频,有时发得出去,有时发不出去,原因未知
  2. 解散企业会发送取消授权第三方应用事件,不过企微那边会延迟15天才会回调 cancel_auth 事件

前端问题

  1. 前端页面缓存问题如何解决?

    解决方案:前端路由nginx,设置浏览器不做页面缓存,直接读服务器的数据。

    1
    2
    3
    4
    5
    6
    7
    8
    
    location / {
        access_log /data/nginx/log/xxx.log api;
        root /home/www/html;
        if ($request_filename ~ .*\.(htm|html)$)
        {
                add_header Cache-Control no-cache;
        }
    }
    
  2. 如何清空local-storage?(token存储在local-storage)

    前端在代码加个版本号标识,每次加载前端页面框架时,触发检查版本号标识是否一致。如果代码的版本号标识和本地缓存中的版本号标识不一致,则清空本地缓存,重新登录。

  3. 本地开发oauth2跳转问题:使用内网穿透、代理

上线注意

设置IP白名单

将代码运行服务器的IP设置为IP白名单(支持多个ip白名单),否则无法调用企业微信的api,配置路径:服务商后台->基本信息->IP白名单

生成推广二维码并获取推广包ID(template_id)

设置入口:服务商管理后台 > 应用推广 > 推广二维码

应用市场搜索

功能位置:应用管理 -> 应用推广 -> 应用市场搜索

如果开发的第三方应用是开放性的,建议开启支持可搜。

会话内容存档

目前只支持企业自行开通会话内容存档,第三方服务商只能让企业提供corpid、secret等配置信息,然后调用会话内容存档接口获取会话数据。

会话内容存档是一个完全独立的功能,可单独部署一个服务运行,不需要建自建应用/第三方应用也可以正常运行。

会话存档两种版本

  • 服务版:单价一年300元/人。开启后,可存档内部&外部聊天(启用范围内成员的),外部聊天须外部好友同意存档(默认同意,可以拒绝)。

  • 企业版:单价一年600元/人。比服务版的多存档一项内容,企业版可以存档语音通话(非会议),视频通话暂不支持。

    按人数买的话,怎么分配额度给指定的某个员工?答:通过设置开启范围限制。 设置开启范围

下载企业微信旧版本

由于企业微信软件更新新版本时,企微Mac桌面端有时会有bug导致侧边栏部分功能不可用,只能进行版本回退,故需要下载旧版的企微Mac桌面端。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "path"
)

// 下载企业微信旧版本-Mac桌面端
func DownloadQiweiSoftwareOldVersion() {
    i := 90000
    for i < 99999 {
        var (
            version  = fmt.Sprintf("4.0.8.%d", i)                                   // 下载版本号
            fileName = fmt.Sprintf("WeCom_%s.dmg", version)                         // 保存文件名
            url      = "https://dldir1.qq.com/foxmail/wecom-mac/update/" + fileName // 下载链接
        )
        log.Printf("当前尝试下载版本号:%s", version)
        resp, err := http.Get(url)
        if err != nil {
            log.Fatal(err)
        }
        if resp.StatusCode != http.StatusOK {
            i++
            continue
        }
        filePath := path.Join("./", fileName)
        f, err := os.Create(filePath)
        if err != nil {
            log.Fatal(err)
        }
        if _, err = io.Copy(f, resp.Body); err != nil {
            log.Fatal("文件保存失败", err)
        }
        log.Println("下载成功,保存路径:", filePath)
        break
    }
}

企业微信调试工具

企业微信调试工具

服务商回调服务器宕机情况

如果服务商回调服务器宕机了几小时,没有接收企微回调事件。需要紧急修复的数据就是:增删客户、增删客户群和增删客户群成员,其他细节就不管了

参考文献

企业微信第三方服务商应用开发经验分享

企业微信服务商第三方应用开发流程