头图

前言

首先,我们得了解一下企业微信自建应用是什么。简单来说,就是企业在企业微信上为自己的员工打造的专属应用,可以是OA系统,也可以是CRM系统等等,总之,你想要什么功能,自己来造!

最近刚好就收到一个需求基于企微微信上开发应用,那么,如何开发这样一个应用呢?过程会遇到哪些坑或者是文档不清晰的地方需要自己摸索半天?别急,跟着以下步骤,或许就能跳过一个个坑快速走向成功。

本文以企业微信自建应用开发-网页版为例(WECOM-JSSDK),若是小程序也可参考,小程序相关的配置在微信小程序平台操作。

掘金

环境准备

企业微信

企微自建应用固然是基于企业微信开发;

企微应用

管理员(负责人)登陆企业微信的管理后台 -- 创建应用
0.png

域名

申请域名,注意申请的域名备案主体与当前企业主体要相同或有关联关系的,假设本文申请的域名为 test.com

服务器

应用运行的服务器

并将域名解析至服务器

配置

配置这里建议一步到胃,不然在开发过程中调用某些API遇到错误,排查起来是真的费时间,问企微的客服我话,就像是通过飞鸽传书,即使快马加鞭,这批汗血宝马从深圳深南大道滨海大厦跑到你的位置,最快也需要40min(亲测企微技术支持对话内最快40min回复)【通道

应用配置

secret、corpid(应用秘钥、企业ID)

这两个配置是接口鉴权需要的配置,在调用 JSAPI 前,需要先通过 ww.register 注册当前页面的身份信息。身份信息分为两种:

  • 企业身份与权限
  • 应用(自建应用/第三方应用等)身份与权限

注册企业身份信息需要企业ID,注册应用身份需要应用的秘钥secret,获取路径:
7.png
6.png

可信域名

在未配置可信域名时,调用API的请求都会跨域,配置域名这里也有一个注意的点:如果你的应用主页(前端)不是放在服务器默认端口(80),则要在域名后加上端口,比如我配置的是8080端口
1.png
3.png

客户联系权限

自建应用本身主要就是运用于外部联系人,当你需要调用一下获取外部联系人信息的API,如ww.getCurExternalChat,获取当前客户群的群ID,需要先配置应用的客户联系权限,否则会返回如下错误

{
    "errmsg": "fail_no permission",
    "errMsg": "getCurExternalContact:no permission",
    "errCode": -1
}

客户联系权限配置如下:
8.png

开发应用

配置完应用,可以开始我们的开发流程,这里以一个注册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)

总体的流程大概如下:
9.png

调试技巧&常见错误总结

  1. 在开发过程中,可能由于你调用的参数有问题,接口会返回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)
  2. 企业微信调试,通过浏览器调试完接口想要在企微应用中验证,可以在消息界面按组合键ctrl+shift+alt+D开启debug看看报错信息,就可以像在浏览器中F12调试,不用写一堆页面消息提示
  3. 举一些在开发中遇到的错误
    ①. 60020,IP不安全;解决方案:将IP添加到应用的可信IP里,后面我是直接用域名访问
    10.png
    ②. ww.register报错:errMsg: agentConfig:exception;这个是自己疏忽,将应用秘钥secret弄错了

    ③. ww.register注册完成,但在window客户端没有继续往下走,在移动端有进入onAgentConfigFail错误回调,这里就需要用到第2点的企业微信调试,打开面板后排除后成功回调但返回以下信息

11.png
查询80001错误码:可信域名不正确,或者无ICP备案,这里又是一个配置上的坑,我的应用是放在服务器的8080端口,所以在配置中的可信域名配置,需要加上端口8080,真系阴公咯

  1. 域名已经可以,上面的ww.register已经注册成功,onAgentConfigSuccess已正常回调,但是调用里面的jsApiList错误,
    如ww.getCurExternalChat:

    {
      "errmsg": "fail_no permission",
      "errMsg": "getCurExternalContact:no permission",
      "errCode": -1
    }

    解决方案:需要拥有客户联系权限,这里需要配置应用的客户联系权限,在配置中的客户联系权限


Henryk
3 声望2 粉丝