前言
首先,我们得了解一下企业微信自建应用是什么。简单来说,就是企业在企业微信上为自己的员工打造的专属应用,可以是OA系统,也可以是CRM系统等等,总之,你想要什么功能,自己来造!
最近刚好就收到一个需求基于企微微信上开发应用,那么,如何开发这样一个应用呢?过程会遇到哪些坑或者是文档不清晰的地方需要自己摸索半天?别急,跟着以下步骤,或许就能跳过一个个坑快速走向成功。
本文以企业微信自建应用开发-网页版为例(WECOM-JSSDK),若是小程序也可参考,小程序相关的配置在微信小程序平台操作。
环境准备
企业微信
企微自建应用固然是基于企业微信开发;
企微应用
管理员(负责人)登陆企业微信的管理后台 -- 创建应用
域名
申请域名,注意申请的域名备案主体与当前企业主体要相同或有关联关系的,假设本文申请的域名为 test.com
服务器
应用运行的服务器
并将域名解析至服务器
配置
配置这里建议一步到胃,不然在开发过程中调用某些API遇到错误,排查起来是真的费时间,问企微的客服我话,就像是通过飞鸽传书,即使快马加鞭,这批汗血宝马从深圳深南大道滨海大厦跑到你的位置,最快也需要40min(亲测企微技术支持对话内最快40min回复)【通道】
应用配置
secret、corpid(应用秘钥、企业ID)
这两个配置是接口鉴权需要的配置,在调用 JSAPI 前,需要先通过 ww.register 注册当前页面的身份信息。身份信息分为两种:
- 企业身份与权限
- 应用(自建应用/第三方应用等)身份与权限
注册企业身份信息需要企业ID,注册应用身份需要应用的秘钥secret,获取路径:
可信域名
在未配置可信域名时,调用API的请求都会跨域,配置域名这里也有一个注意的点:如果你的应用主页(前端)不是放在服务器默认端口(80),则要在域名后加上端口,比如我配置的是8080端口
客户联系权限
自建应用本身主要就是运用于外部联系人,当你需要调用一下获取外部联系人信息的API,如ww.getCurExternalChat,获取当前客户群的群ID,需要先配置应用的客户联系权限,否则会返回如下错误
{
"errmsg": "fail_no permission",
"errMsg": "getCurExternalContact:no permission",
"errCode": -1
}
客户联系权限配置如下:
开发应用
配置完应用,可以开始我们的开发流程,这里以一个注册JSAPI的应用demo开发为例
创建客户端(vite + vue3为例)
npm create vue@latest
<script setup lang="ts">
import { ref } from 'vue'
import { onMounted, nextTick } from 'vue'
import * as ww from '@wecom/jssdk'
import { CommonResult } from '@wecom/jssdk/types'
import Axios from 'axios'
import { message } from 'ant-design-vue'
const corpId = 'corpId' //企业ID
const appJsApiTicket = ref('')
const userID = ref('')
const groupID = ref('')
// 获取应用 jsapi_ticket
const getAppJsapiTicket = async () => {
const res: any = await Axios.get('http://test.com:5000/api/get-app-ticket')
if (res?.data?.errcode !== 0) {
message.error(res?.data?.errmsg ?? 'error')
}
message.success('ticket:' + res?.data?.ticket ?? 'null')
appJsApiTicket.value = res?.data?.ticket
}
onMounted(async () => {
await getAppJsapiTicket();
nextTick(async () => {
await registerPower();
spinning.value = false;
})
})
// 注册接口的调用权限
const registerPower = () => {
ww.register({
corpId, // 必填,当前用户企业所属企业ID
agentId: 1000004,
jsApiList: [
'selectExternalContact',
'getCurExternalContact', //获取当前外部联系人 userId
'getCurExternalChat', //获取当前客户群的群ID
'sendChatMessage', //分享消息到当前会话
'shareToExternalChat', //群发消息到客户群
], // 必填,需要使用的JSAPI列表
getAgentConfigSignature() {
return ww.getSignature(appJsApiTicket.value)
},
/**
* agentConfig 成功回调
*/
onAgentConfigSuccess: (result: CommonResult) => {
// handle your success result
},
/**
* agentConfig 完成回调(成功时与onAgentConfigSuccess返回一致)
*/
onAgentConfigComplete: (result: any) => {
// handle your callback result
}
})
}
/* 注册完企微API的调用权限,就可以使用了,例: */
const sendChatMessage = (msg: string) => {
ww.sendChatMessage({
msgtype: 'text',
text: {
content: msg || '你好,这是一条消息'
}
})
}
// 获取当前外部联系人userId
const getCurExternalContact = async () => {
let res = await ww.getCurExternalContact({
success(result: CommonResult) {
// 成功回调,result.errMsg 固定格式为“方法名:ok”
message.success(result.errMsg)
},
fail(result: CommonResult) {
// 失败回调,通过 result.errMsg 查看失败详情
message.error(result.errMsg)
}
})
if (res.userId) {
// handle you userId
}
}
</script>
简单编写测试的接口(python flask)
from flask import Flask, jsonify, send_from_directory
from flask_cors import CORS
import requests
import os
app = Flask(__name__)
CORS(app)
# 企业ID和应用密钥
corpid = 'corpid'
corpsecret = 'corpsecret'
# 获取access_token,根据token获取jsapi_ticket
@app.route('/api/get-app-ticket', methods=['GET'])
def get_app_ticket():
# 获取 access_token
token_url = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={corpsecret}'
token_response = requests.get(token_url)
if token_response.status_code != 200:
return jsonify({'error': 'Failed to get access_token'}), 500
token_data = token_response.json()
if 'access_token' not in token_data:
return jsonify({'error': 'Invalid response from gettoken'}), 500
access_token = token_data['access_token']
# 使用 access_token 获取 agent_config 类型的 jsapi_ticket
app_ticket_url = f'https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token={access_token}&type=agent_config'
app_ticket_response = requests.get(app_ticket_url)
if app_ticket_response.status_code != 200:
return jsonify({'error': 'Failed to get app jsapi_ticket'}), 500
app_ticket_data = app_ticket_response.json()
# 返回 agent_config 类型的 jsapi_ticket 信息
return jsonify(app_ticket_data)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
总体的流程大概如下:
调试技巧&常见错误总结
在开发过程中,可能由于你调用的参数有问题,接口会返回errcode, 此时可以在“全局错误码说明”查阅相应的错误原因。
有时候可能根据错误码说明仍然不知道自己的参数在哪里出错,这时候你可以在接口请求url里加上debug=1参数,之后从接口返回的errmsg复制出hint值,再用官方的工具进行查询
# 如在请求access_token时添加debug参数 ticket_url = f'https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token={access_token}&debug=1' ticket_response = requests.get(ticket_url)
- 企业微信调试,通过浏览器调试完接口想要在企微应用中验证,可以在消息界面按组合键ctrl+shift+alt+D开启debug看看报错信息,就可以像在浏览器中F12调试,不用写一堆页面消息提示
举一些在开发中遇到的错误
①. 60020,IP不安全;解决方案:将IP添加到应用的可信IP里,后面我是直接用域名访问
②. ww.register报错:errMsg: agentConfig:exception;这个是自己疏忽,将应用秘钥secret弄错了③. ww.register注册完成,但在window客户端没有继续往下走,在移动端有进入onAgentConfigFail错误回调,这里就需要用到第2点的企业微信调试,打开面板后排除后成功回调但返回以下信息
查询80001错误码:可信域名不正确,或者无ICP备案,这里又是一个配置上的坑,我的应用是放在服务器的8080端口,所以在配置中的可信域名配置,需要加上端口8080,真系阴公咯
域名已经可以,上面的ww.register已经注册成功,onAgentConfigSuccess已正常回调,但是调用里面的jsApiList错误,
如ww.getCurExternalChat:{ "errmsg": "fail_no permission", "errMsg": "getCurExternalContact:no permission", "errCode": -1 }
解决方案:需要拥有客户联系权限,这里需要配置应用的客户联系权限,在配置中的客户联系权限
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。