更新记录
1.0.0(2025-09-19)
- 前10位 一对一保姆级协助
- 使用前,使用HX导入示例项目,并咨询作者协助,完成首次配置
- 服务端API基本完成,相关凭据已处理,开发者无需关注access_token的关系和获取更新,只写unicloud代码,
- 客户端jsapi示例下期更新
平台兼容性
云函数类插件通用教程
使用云函数类插件的前提是:使用HBuilderX 2.9+
🚀 mr-wecom-developer
下载示例项目跑完后,在把改好的配置信息复制到自己项目中
Mr-wecom-developer 是 unicloud 快速接入企业微信-第三方应用-服务端API的云端插件。
✅ 解决了服务端通讯的 IP白名单 问题
- 企微已拦截(第三方运营商IP)阿里和支付宝云的固定出口IP,导致原请求失败
- 腾讯云固定IP套餐已升级至199/月起
✅ 授权企业安装你的应用后,插件自动获取 授权企业信息和永久授权码
- 客户端登录并获取永久授权码,请 右侧蓝色按钮 【使用HX导入示例项目】 查看。
✅ 云对象接管开发第三方应用需要的凭借缓存
- 应用的:"suite_access_token",
- 服务商的:"provider_access_token",
- 授权企业的:"access_token",
- 以上凭据你无需关注TA的获取和过期更新,你只要调一个方法(看下面 【示例 2】 ),就可以继续写你的业务。
✅ 云对象对企业微信服务端API请求进行封装
- 简单封装服务端API请求,看【示例 3-1 】
- 自由度高的服务端API请求,看【示例 3-2】
✅ 云对象封装服务端回调验证处理方法,支持自定义逻辑
- 系统事件回调
- 指令回调 【示例 4】
- 数据回调
✅ 📖 更多内容 请导入示例项目查看 客户端示例为vue3,vue2的朋友自己改造下可以正常使用
✅ 📖 企微自建应用
➰ 大致步骤
setp1 👉 右键云对象,命令行执行打开所在目录 npm install xml2js --save ,安装xml2js模块
setp2 👉 ./uniCloud/database/db_init.json 初始化数据库,找不到就config.json内最下面的三张表手动创建,
setp3 👉 配置云对象url化path部分设置为 /wecom-developer,保存,复制路径,最终你的【 URL化地址 】大概这样 【https://xxx.xxx.xx//wecom-developer】
setp4 👉 完成config.json参数配置,没有则创建,并复制config-template.json内容到config.json
{
"Proxy":"",
"Tips": "---【proxy 必填】代理地址",
"Provider":{
"CorpId":"",
"ProviderSecret":"",
"Tips": "---服务商凭证ProviderSecret【ProviderSecret】"
},
"Suite": {
"SuiteId": "",
"Secret": "",
"Tips": "---服务商开发的第三方应用【SuiteID、Secret 必填】"
},
"CallBack": {
"Data": {
"Token": "",
"EncodingAESKey": "",
"Tips": "---【Data.Token、Data.EncodingAESKey 数据回调 】",
},
"Command":{
"Token": "",
"EncodingAESKey": "",
"Tips": "---【Command.Token、Command.EncodingAESKey 指令回调 】"
},
"Login":{
"SuiteID":"",
"Secret":"",
"Token":"",
"EncodingAESKey":"",
"Tips": "---【登录服务商网站的回调Token,EncodingAESKey】",
},
"System":{
"Token": "",
"EncodingAESKey": "",
"Tips": "---【服务商系统事件回调】",
}
},
"CollectionName": {
"CallBackLog": "wecom-developer-back",
"CacheManage": "wecom-developer-cache",
"AuthCorps": "wecom-developer-auth-corps",
"TipsMore":"CallBackLog = 回调记录 、 CacheManage = 凭据缓存记录 、AuthCorps = 授权安装的企业信息 "
"Tips": "./uniCloud/database/db_init.json - [mr-wecom-developer:uni_modules]初始化,也可以自己到cloud后台手动自定表名创建,再把自定义表名回填这里"
},
}
setp5 👉 重新上传云对象
⚙ 相关示例
示例 1、code换取用户信息 和 获取用户所在企业的授权信息 含永久授权码
1-1 云对象的方法,【客户端示例代码 左侧 使用HX导入示例项目 查看】(用户登录时一并获取企业信息)
// code换取用户信息
codeToUserInfo:async function(data){
if(!data.code) return {code:1,msg:"codeToUserInfo() => code 不能为空"}
let utilRes = await util.codeToUserInfo({
code:data.code,//前端授权回调页面获取
needCorp:true,// needCorp = true 表示需要获取授权企业的信息含永久授权码,false表示不需要
})
return utilRes.utilCode == 0? {result:utilRes.result,code:0,msg:"codeToUserInfo success"} : {code:1,msg:"codeToUserInfo 失败",utilRes}
},
1-2 云对象的方法通过用互所在企业id获取 授权企业信息含授权码,(需要时获取)
// 获取用户所在企业的授权信息 含授权码
getPermanentCode:async function(data){
let dbName = config.CollectionName.AuthCorps
try {
let res = await db.collection(dbName)
.where({
AuthCorpId:data.AuthCorpId,//用户所在的企业id
}).get()
if(res.data && res.data.length>0){
return {result:res.data[0],code:0,msg:'getPermanentCode success'}
}else{
return {result:res,code:1,msg:'没有记录'}
}
} catch(err){
throw err
}
},
示例 2、云对象中获取access_token 用于构造自定义方法,请求企微服务端api,如 示例 3-2-1
// 获取三种 access_token 示例
getAccessToken:async function(){
// 1 获取授权企业的access_token
let corpTokenRes = await util.getAccessToken({
AccessTokenType:"AuthCorp",//必填 AuthCorp || Suite || Provider
AuthCorpId:"wwad33XXXxxxx8313a93",//当AccessTokenType= AuthCorp时,用户所在的企业ID必填,
})
let access_token = corpTokenRes.result;
// ------------------------------
// 2 获取应用的access_token
let suiteTokenRes = await util.getAccessToken({
AccessTokenType:"Suite",//必填 AuthCorp || Suite || Provider
})
let suite_access_token = suiteTokenRes.result;
// ------------------------------
// 3 获取服务商的access_token
let providerTokenRes = await util.getAccessToken({
AccessTokenType:"Provider",//必填 AuthCorp || Suite || Provider
})
let provider_access_token = providerTokenRes.result;
},
示例 3、请求企业微信服务端API
3-1-1 方式一:云对象 示例
/**
* @ 调用企业微信服务端API的示例
*
* 1- @data.params 企业微信接口的 请求包体 参数
* 2- @data.method 请求类型,GET || POST
* 3- @data.tokenType accsess_token的类型,
*
对照企业微信api的请求地址参数填 (Provider 对应 provider_accsess_token )|| ( Suite 对应 suite_accsess_token ) || ( AuthCorp 对应 accsess_token )
请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=ACCESS_TOKEN
那么tokenType = "AuthCorp",此时要多传一个AuthCorpId参数 用户所在企业ID
请求地址:https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserinfo3rd?suite_access_token=SUITE_ACCESS_TOKEN&code=CODE
那么tokenType = "Suite"
请求地址:https://qyapi.weixin.qq.com/cgi-bin/service/corpid_to_opencorpid?provider_access_token=ACCESS_TOKEN
那么tokenType = "Provider"
* 4- @data.action 接口拼接路径
*
* 例如,文档的请求地址:https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID
* 那么=>action = "user/simplelist",即"https//****cgi-bin/" 与 "?" 之间的部分
*
* return res = {code:0,msg:''} 中,code=0=成功,其他=失败,msg=错误提示
* 其他errCode,errMsg或err_code,err_msg或errcode,errmsg是企业微信返回的,实际业务根据企微文档自行判断
*/
callServer: async function(data) {
// let { action,method,tokenType,params,AuthCorpId } = data;// 前端传来的参数
if(data.tokenType == 'AuthCorp' && !data.AuthCorpId)return {code:0,msg:"AuthCorpId 不能为空"}
let utilRes = await util.Server({...data})
// let resule = utilRes.result //返回的数据
return utilRes.utilCode==0?{ code:0,msg:'云对象 callService() => succsess',resule:utilRes}:{code:1,msg:"云对象执行callService() => fail",utilRes};
},
3-1-1 方式一:客户端发起请求 示例
// 页面引入云对象
<script setup>
const developer = uniCloud.importObject('wecom-developer');
async function getTagList() {
const res = await developer.callServer({
action:"tag/list",
method:"GET",
tokenType:"AuthCorp",
AuthCorpId:"wwad33b3xxxx313a93",
params:{
}
})
// consoleLog.value.unshift({label:'获取部门列表 res =>',value:res});
}
getTagList()//跑一下
</script>
3-2-1 方式二:云对象示例
// 自由度更高的云对象调用企业微信服务端API的示例
customServerApi:async function(data){
/**
* await util.getAccessToken 参数说明1、2、
*
* 1、AccessTokenType @string
* 请求地址 示例看最后面 ?suite_access_token 时,就填AccessTokenType:"Suite"
* https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserdetail3rd?suite_access_token=SUITE_ACCESS_TOKEN
*
* "Suite" => suite_access_token
* "Provider" => provider_access_token
* "AuthCorp" => access_token
*
* 当 AccessTokenType = "AuthCorp" 时,需要传入 AuthCorpId @string = 授权企业id
* 当 AccessTokenType = "AuthCorp" 时,需要传入 AuthCorpId @string = 授权企业id
* 当 AccessTokenType = "AuthCorp" 时,需要传入 AuthCorpId @string = 授权企业id
*
* 2、AuthCorpId @string = 用户所在的授权企业id
*/
// 1、获取请求地址【对应的】 access_token
let tokenRes = await util.getAccessToken({
AccessTokenType:"AuthCorp",//必填 AuthCorp || Suite || Provider
AuthCorpId:"wwad3xxxx3a93",//当AccessTokenType= AuthCorp时,此项必填
})
if(tokenRes.utilCode != 0)return {tokenRes:tokenRes,code:1,msg:"云对象执行util.getAccessToken() 时,tokenRes获取accsess_token异常,请检查参数或检查云对象url化配置"};//如果获取失败,提示信息utilRes在里面
let token = tokenRes.result;
// 2、拼接地址 path
/**
* 如请求地址 https://qyapi.weixin.qq.com/cgi-bin/tag/list?access_token=ACCESS_TOKEN
* 则path = `tag/list?access_token=${tokenRes.result}`
* 即 https://xxxx/cgi-bin/ 这部分去掉,剩余部分开始,把后面包含所有参数的部分,全部拼接好
*/
let path = `tag/list?access_token=${token}`;
let params = {} //请求包体 参数
let method = "GET" //请求类型,GET || POST
try {
// 3、发起请求
let apiRes = await util.ServerApi({path,params,method})
// 4、判断并返回结果
// apiRes.utilCode => 指插件的http请求是否成功,0=成功,其他=失败
// apiRes.result => http返回的数据,
// apiRes.result.data企业微信返回的数据,
// apiRes.result.data.errcode = 0 表示企微成功,其他表示企微失败
return apiRes.utilCode==0?{ code:0,msg:'云对象 callServerApi() => succsess',resule:apiRes.result.data}:{code:1,msg:"云对象执行callServerApi() => fail",apiRes};
} catch(err){
return err
}
},
3-2-2 方式二:客户端示例
<script setup>
// 页面引入云对象
const developer = uniCloud.importObject('wecom-developer');
async function getCustom() {
const res = await developer.customServerApi({})
consoleLog.value.unshift({label:'getCustom res =>',value:res});
}
getCustom()//跑一下
</script>
示例 4、指令回调事件的自定义逻辑
其他回调类似,具体内容 请导入示例项目查看
backCommand:async function(data){
const handleRes = await util.handleCallBack({httpInfo:this.getHttpInfo()})
if(handleRes.utilCode == 0){
let { InfoType,AuthCode,SuiteTicket } = handleRes.result;
// 你要用的参数在这个对象里,详细内容日志表wecom-developer-back或查看 下面参考文档
// handleRes.result @object = 回调消息体中解析后的内容
// 找到你的判断参数,并执行对应的业务逻辑 参考文档: https://developer.work.weixin.qq.com/document/path/90613
// if("你的判断参数" == "你的预期值"){
// // 执行符合条件的逻辑
// // 逻辑结束不要return ,保留使用下面的 return handleRes.success;
// }
switch(InfoType){
case "create_auth":
// 如果是用户授权安装,则获取授权用户和企业信息,企业永久授权码,信息写入wecom-developer-auth-corps,
// 注意此处使用了await ,如果你那容易超时,则去除await 请求发出去即可,这样做是为了1s内响应企业微信,
await util.AuthCodeToCorpInfo({AuthCode})
break;
case "suite_ticket":
// 如果推送ticket,则更新数据表的suite_ticket
await util.updateSuiteTicket({SuiteTicket})
break;
case "你的预期值":
// 1、直接写unicloud的数据库操作代码如 unicloud.database().collection('collectionName').get()
// 2、引入其他云对象,(云函数或云对象内调用)[https://doc.dcloud.net.cn/uniCloud/cloud-obj.html#call-by-cloud]
// 3、写http请求,直接写http请求代码
// 4、写vk-router,(方式二)[https://vkdoc.fsq.pub/client/question/question.html#q107]
// 处理你自己的预期 业务逻辑,
break;
default:
break;
}
// 你上面的逻辑结束不要return ,保留使用下面的 return handleRes.success;
//----------------------------你自己的业务逻辑结束----------------------------------
return handleRes.success; // 这边不要改动
}else{
//出错了看unicloud云对象运行日志
return {code:1,msg:"backCommand-err",backCommandInfo:handleRes}
}
},