企业微信三方应用服务商获取通讯录及扫码登录(测试应用)

一、前言

公司作为企业微信第三方应用服务商,想要获取到授权企业的通讯录信息中的用户信息和部门信息,以及授权企业的成员可以扫码进行登录。

二、流程梳理

1.后台配置

image.png
红色箭头标记的是最基本的需要的东西。
可信域名:设置可信域名后支持应用的OAuth2授权、JSSDK调用、通讯录名称转义等大部分操作都必须在这个域名下发起才能成功。
指令回调URL:系统将会把此应用的授权变更事件、ticket参数、通讯录变更信息等推送给此URL
TOKEN:主要是用来进行校验回调请求的合法性。
EncodingAESKey:回调消息加解密参数,是AES密钥的Base64编码,用于解密回调消息内容对应的密文。后续所有托管的企业产生的回调消息都使用该值来解密。
这里的TOKEN和EncodingAESKey主要是用来校验数据回调URL和指令回调URL是否能够被企业微信服务器调用成功。
校验URL
企业微信验证URL是否能够被调用是GET请求,各项信息的通知是相同URL下的POST请求。也就是需要用配置的URL
写一个GET用来校验,一个POST请求接受信息。
校验信息

router.GET("/wx/cmdback", func(c *gin.Context) {/*数据回调验证*///企业微信加密签名msgSignature := cast.ToString(c.Query("msg_signature"))//时间戳timestamp := cast.ToInt64(c.Query("timestamp"))//随机数nonce := cast.ToString(c.Query("nonce"))//加密字符串echostr, err := url.PathUnescape(c.Query("echostr"))if err != nil {fmt.Println("url解码失败")return}//企业微信api 详情可以看企业微信文档wxcpt := wxbizmsgcrypt.NewWXBizMsgCrypt(model.Token, model.EncodingAesKey, model.CorpId, wxbizmsgcrypt.XmlType)echoStr, cryptErr := wxcpt.VerifyURL(msgSignature, cast.ToString(timestamp), nonce, echostr)if nil != cryptErr {fmt.Println("verifyUrl fail", cryptErr)return}fmt.Println("verifyUrl success echoStr")c.String(util.Success, string(echoStr))//返回解密出来的字符串给企业微信校验})

接收信息

router.POST("/wx/cmdback", func(c *gin.Context) {/*指令回调URL: 微信服务器推送suite_ticket以及安装应用时推送auth_code时。*///企业微信加密签名msgSignature := cast.ToString(c.Query("msg_signature"))//时间戳timestamp := cast.ToString(c.Query("timestamp"))//随机数nonce := cast.ToString(c.Query("nonce"))// post请求的密文数据defer c.Request.Body.Close()con, _ := ioutil.ReadAll(c.Request.Body) //获取post的数据// 访问应用和企业回调传不同的IDwxcpt := wxbizmsgcrypt.NewWXBizMsgCrypt(model.Token, model.EncodingAesKey, model.SuitId, wxbizmsgcrypt.XmlType)msg, cryptErr := wxcpt.DecryptMsg(msgSignature, timestamp, nonce, con)if nil != cryptErr {fmt.Println("DecryptMsg fail", cryptErr)return}fmt.Println(string(msg))var content MsgContentxml.Unmarshal(msg, &content)var changeContent ChangeContentxml.Unmarshal(msg, &changeContent)fmt.Println(changeContent)//业务逻辑,根据信息需要进行的业务逻辑'''c.String(util.Success, "success")//需要返回"success"不然企业微信认为此次请求错误
})

2.安装应用

未命名文件 (3).png

  1. 企业首先需要安装第三方应用和授权,企业有两种方式进行安装授权。从第三方服务商发起授权比应用商店授权相比,无非是需要第三方服务商自己生成跳转到微信授权网站的链接
  • 从第三方服务商

(1) 获取第三方应用凭证(suite_access_token)

企业微信服务器会定时(每十分钟)推送ticket。ticket会实时变更,并用于后续接口的调用。

请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token

请求包体:

{"suite_id":"wwddddccc7775555aaa" ,"suite_secret": "ldAE_H9anCRN21GKXVfdAAAAAAAAAAAAAAAAAA", "suite_ticket": "Cfp0_givEagXcYJIztF6sfbdmIZCmpaR8ZBsvJEFFNBrWmnD5-CGYJ3_NhYexMyw" 
}

参数说明:

参数是否必须说明
suite_id以ww或wx开头应用id(对应于旧的以tj开头的套件id)
suite_secret应用secret
suite_ticket企业微信后台推送的ticket

代码实现:

func GetSuiteAccessToken(ticket string) {result, err := util.Post(util.PostSuiteAccessToken, util.WxSuite{SuiteId: model.SuitId, SuiteTicket: ticket, SuiteSecret: model.SuitSecret})if err != nil {fmt.Println("Post Suite Token Fail")}var wxRspSuiteToken util.WxRspSuiteTokenerr = json.Unmarshal([]byte(result), &wxRspSuiteToken)if err != nil {fmt.Println(err)}if wxRspSuiteToken.ErrCode == 0 {model.GetRedis().Set("suiteAccessToken", wxRspSuiteToken.SuiteAccessToken, time.Minute*30)fmt.Println("获取成功,suiteAccessToken==>", cast.ToString(wxRspSuiteToken.SuiteAccessToken))} else {fmt.Println("errCode==>", wxRspSuiteToken.ErrCode)fmt.Println("errMsg==>", wxRspSuiteToken.ErrMsg)}
}

获取到的suite_access_token有效期为2小时,应当进行缓存,接下来各项操作需要携带。

(2) 获取预授权码

请求方式: GET(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_pre_auth_code?suite_access_token=SUITE_ACCESS_TOKEN

参数说明:

参数是否必须说明
suite_access_token第三方应用access_token,最长为512字节

返回结果:

{"errcode":0 ,"errmsg":"ok" ,"pre_auth_code":"Cx_Dk6qiBE0Dmx4EmlT3oRfArPvwSQ-oa3NL_fwHM7VI08r52wazoZX2Rhpz1dEw","expires_in":1200
}

代码实现:

/*预授权码
*/
func GetAuthCode(suiteAccessToken string) string {data, err := util.Get(util.GetAuthCode + "?suite_access_token=" + suiteAccessToken)if err != nil {fmt.Println("预授权码wx请求失败")return ""}var rsp util.WxRspAuthorizationCodeerr = json.Unmarshal(data, &rsp)if err != nil {fmt.Println("预授权码解析失败")return ""}if rsp.ErrCode != 0 {fmt.Println("ErrorCode==>", rsp.ErrCode)fmt.Println("ErrMsg==>", rsp.ErrMsg)return ""}return rsp.PreAuthCode}

*注意:因为是测试应用,还未进行发布,所以要对预授权设置授权,让其支持测试,正式应用不需要此操作。

设置授权配置

该接口可对某次授权进行配置。可支持测试模式(应用未发布时)。

请求方式: POST(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/set_session_info?suite_access_token=SUITE_ACCESS_TOKEN

请求包体:

{"pre_auth_code":"xxxxx","session_info":{"appid":[1,2,3],"auth_type":1}
}

参数说明:

参数是否必须说明
suite_access_token第三方应用access_token
pre_auth_code预授权码
session_info本次授权过程中需要用到的会话信息
appid允许进行授权的应用id,如1、2、3, 不填或者填空数组都表示允许授权套件内所有应用(仅旧的多应用套件可传此参数,新开发者可忽略)
auth_type授权类型:0 正式授权, 1 测试授权。 默认值为0。注意,请确保应用在正式发布后的授权类型为“正式授权”

返回结果:

{"errcode": 0,"errmsg": "ok"
}

代码实现:

PreAuthCode := GetAuthCode(suiteAccessToken)
//应用未发布时。测试
req := map[string]interface{}{"pre_auth_code": PreAuthCode,"session_info": map[string]interface{}{"auth_type": 1,},
}
util.Post("https://qyapi.weixin.qq.com/cgi-bin/service/set_session_info"+"?suite_access_token="+suiteAccessToken, &req)

(3) 获取永久授权码

该API用于使用临时授权码换取授权方的永久授权码,并换取授权信息、企业access_token,临时授权码一次有效。

请求方式: POST(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=SUITE_ACCESS_TOKEN

请求包体:

{"auth_code": "auth_code_value"
}

代码实现:

/*永久授权码
*/
func GetPermanentCode(suiteAccessToken string, authCode string) (string, util.AuthCorpInfo) {post, err := util.Post(util.PostPermanentCode+"?suite_access_token="+suiteAccessToken, util.WxAuthCode{AuthCode: authCode})if err != nil {fmt.Println("Post PermanentCode Fail")return "", util.AuthCorpInfo{}}var wxAuthCode util.WxRspAuthCodeerr = json.Unmarshal([]byte(post), &wxAuthCode)if err != nil {fmt.Println("解析失败")return "", util.AuthCorpInfo{}}if wxAuthCode.ErrCode != 0 {fmt.Println(wxAuthCode.ErrCode)fmt.Println(wxAuthCode.ErrMsg)return "", util.AuthCorpInfo{}} else {return wxAuthCode.PermanentCode, wxAuthCode.AuthCorpInfo}
}

当企业成功安装应用后,企业微信会通过第三方应用后台配置的数据回调URL,将企业的各项信息返回,开发者可以根据自己需要存储信息,最重要的存储授权企业的id(corp_id)永久授权码(permanent_code),后面需要根据指定企业的id,取到相应的永久授权码,从而获取到能获取到指定企业的access_token

3.获取通讯录信息

未命名文件 (3).png
*注意:在企业安装应用时,在同意安装页面记得需要可见范围范围,不然获取不到整个企业的部门和成员信息

(1)获取企业凭证(access_token)

第三方服务商在取得企业的永久授权码后,通过此接口可以获取到企业的access_token。
获取后可通过通讯录、应用、消息等企业接口来运营这些应用。
此处获得的企业access_token与企业获取access_token拿到的token,本质上是一样的,只不过获取方式不同。获取之后,就跟普通企业一样使用token调用API接口。
*注意:因权限问题获取的信息可能不同。如三方无法直接获取用户名称等

请求方式: POST(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=SUITE_ACCESS_TOKEN

请求包体:

 {"auth_corpid": "auth_corpid_value","permanent_code": "code_value"}

参数说明:

参数是否必须说明
auth_corpid授权方corpid
permanent_code永久授权码,通过get_permanent_code获取

返回结果:

{"errcode":0 ,"errmsg":"ok" ,"access_token": "xxxxxx", "expires_in": 7200
}

参数说明:

参数说明
access_token授权方(企业)access_token,最长为512字节
expires_in授权方(企业)access_token超时时间

代码实现:

/*第三方应用获取指定企业凭证*/
func GetAccessToken(companyId int) string {var company model.Companymodel.GetDB().Where("company_id = ?", companyId).First(&company)if company.CompanyId == 0 {fmt.Println("公司匹配失败")}preCode := company.PermanentCodeCorpId := company.CorPidsuitToken := model.GetRedis().Get("suiteAccessToken").Val()wxReq := util.WxReqDepartment{AuthCorpid: CorpId, PermanentCode: preCode}data, err := util.Post(util.PostAccessToken+"?suite_access_token="+suitToken, wxReq)if err != nil {fmt.Println(err)}var wxAccessToken util.WxRspAccessTokenjson.Unmarshal([]byte(data), &wxAccessToken)fmt.Println(wxAccessToken)if wxAccessToken.ErrCode != 0 {fmt.Println(wxAccessToken.ErrMsg)return ""} else {fmt.Println("获取成功,AccessToken==>", wxAccessToken.AccessToken)return wxAccessToken.AccessToken}
}

拿到access_token需要先缓存起来,因为企业微信做了频率校验,超过次数将无法获取access_token,token有效期为两个小时,两个小时内获取到的access_token是一样的。有了token就可以访问通讯录的各项信息。

(2)获取部门成员详情

请求方式: GET(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=FETCH_CHILD

参数说明:

参数必须说明
access_token调用接口凭证
department_id获取的部门id
fetch_child1/0:是否递归获取子部门下面的成员

权限说明:

应用须拥有指定部门的查看权限。
返回结果:

{"errcode": 0,"errmsg": "ok","userlist": [{"userid": "userid","name": "name","department": [1],"gender": "0","avatar": "https://rescdn.qqmail.com/node/wwmng/wwmng/style/images/independent/DefaultAvatar$73ba92b5.png","status": 1,"order": [0],"main_department": 1,"is_leader_in_dept": [],"thumb_avatar": "https://rescdn.qqmail.com/node/wwmng/wwmng/style/images/independent/DefaultAvatar$73ba92b5.png","open_userid": "","direct_leader": []},]
}

第三方应用能拿到企业成员的信息不多,详情可以参照企业微信文档https://developer.work.weixin.qq.com/document/path/90337

(3)获取部门列表

请求方式: GET(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=ID

参数说明 :

参数必须说明
access_token调用接口凭证
id部门id。获取指定部门及其下的子部门(以及子部门的子部门等等,递归)。 如果不填,默认获取全量组织架构

权限说明:

只能拉取token对应的应用的权限范围内的部门列表

返回结果:

{"errcode": 0,"errmsg": "ok","department": [{"id": 2,"name": "广州研发中心","name_en": "RDGZ","department_leader":["zhangsan","lisi"],"parentid": 1,"order": 10},{"id": 3,"name": "邮箱产品部","name_en": "mail","department_leader":["lisi","wangwu"],"parentid": 2,"order": 40}]
}

(4)通讯录转义

当第三方拉取到信息时会发现,部门名和成员名都等于部门id和成员id,无法显示真实的名称,主要是因为企业微信为了保护隐私,第三方将不再直接获取到授权企业的通讯录数据(接口将不再返回人名与部门名)。
所以开发者如果需要展示名称就需要对名称进行转义,有两种方法可以进行转义。

通讯录组件转换名称

这种方法主要是前端实现,后端只需要返回前端需要的相关配置信息。
详情参照企业微信文档 https://developer.work.weixin.qq.com/document/path/91958

通讯录ID转义

需要前后端配合实现,详情参照企业微信文档 https://developer.work.weixin.qq.com/document/path/91889

实现流程

未命名文件 (3).png
实现步骤
1.需要先创建一个文件(txt,csv,xls,xlsx,doc,docx),并替换模板,效果如下图所示:

QQ图片20220512122236.png
要获取部门名称同理,模板如下:
$departmentName=DEPARTMENT_ID$
$userName=USERID$
将你要查的id替换大写英文的部分,只能转义同一公司的id,不然不会进行转义。
2.上传文件到企业微信,这里是在后端进行上传。

client := http.Client{}
bodyBuf := &bytes.Buffer{}
bodyWrite := multipart.NewWriter(bodyBuf)
//上传给企业微信
//创建请求并设置内容类型
fileWrite, err := bodyWrite.CreateFormFile("media", "file.xlsx")
_, err = io.Copy(fileWrite, excel)
if err != nil {log.Println("err")
}
bodyWrite.Close() //要关闭,会将w.w.boundary刷写到w.writer中
// 创建请求
contentType := bodyWrite.FormDataContentType()
req, err := http.NewRequest(http.MethodPost, util.PostMediaFile+"?provider_access_token="+token+"&type=file", bodyBuf)
if err != nil {log.Println("err")
}
// 设置头
req.Header.Set("Content-Type", contentType)
resp, err := client.Do(req)
if err != nil {log.Println("err")
}
defer resp.Body.Close()
var data1 util.WxRspUploadFile
all, err := ioutil.ReadAll(resp.Body)
if err == nil {//解析responsejson.Unmarshal(all, &data1)
}//返回
{"errcode": 0,"errmsg": "ok. Warning: wrong json format. ","type": "file","media_id": "3zwYR2FyKTQZuuCvvVyrCGb9j8yNrUqjwqA97cXHQBoZF46rDsIWX4l4fzZCBDYzp","created_at": "1652335969"
}

素材上传得到media_id,该media_id仅三天内有效
media_id在同一企业内应用之间可以共享

3.异步通讯录id转译

post, err := util.Post(util.PostTransId+"?provider_access_token="+token,map[string]interface{}{"auth_corpid":      "ww*******",//授权企业corpid ,也就是需要转义的用户、部门id的所属企业的corpid,安装应用时进行了存储。"media_id_list":    []string{data1.MediaId},//上一步上传文件得到的媒体id(media_id),可以上传多个。"output_file_name": "trans_id",//输出的文件名//"output_file_format": "xlsx"//输出格式,若不指定,则输出格式跟输入格式相同。})
fmt.Println(post)
if err != nil {fmt.Println(err)
}var data2 util.WxRspTranId
json.Unmarshal([]byte(post), &data2)
fmt.Println(data2.JobId)//结果
{"errcode": 0,"errmsg": "ok","jobid": "Xq24rw360-NyvhqHnK9ztC_Nr4zeHPyqMbJF-SjwGL0"
}

注:若生成的文件不需要压缩,则 media_id_list列表只能指定一项,同时 output_file_name 不需要传值

4.获取异步任务的结果

get, err := util.Get(util.GetJobResult + "?provider_access_token=" + token + "&jobid=" + data2.JobId + "&debug=1")
var data3 util.WxRspJobResult
json.Unmarshal(get, &data3)
result := cast.ToString(data3.Result["contact_id_translate"].(map[string]interface{})["url"])
fmt.Println(result)//结果
{"errcode": 0,"errmsg": "ok","status": 3,"type": "contact_id_translate","result": {"contact_id_translate": {"url": "https://open.work.weixin.qq.com/wwopen/openData/getTranslateContactOpenData?dataid=j9otnBMVKUDSf4xrAxxxxxxxxxxxxxxxxxxxxxx"}}
}

注:返回的url参数,开发者在使用时以a标签引用,download属性不可指定(浏览器兼容性问题)

5.下载转义后文件,这是最后也是最麻烦的一步,能够下载的条件是:
1.当前浏览器页面进行了授权登录,存在登录态。
可以通过https://open.work.weixin.qq.com/wwopen/openData/debug 来检查当前登录态。
QQ图片20220512144056.png
2.需要在配置好的可信域名下进行访问。(不是直接在浏览器中输入打开链接)
满足这两个条件后才会下载id转义后的文件。

4.扫码登录

这里主要讲从第三方进行单点登录,需要构造登录链接以及登录成功回调url大致流程如图所示:

未命名文件 (3).png\

(1)构造链接

1、用户进入服务商网站。
2、服务商网站引导用户进入登录授权页。
服务商可以在自己的网站首页中放置“企业微信登录”的入口,引导用户进入登录授权页。网址为:

https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect?appid=ww100000a5f2191&redirect_uri=http%3A%2F%2Fwww.oa.com&state=web_login@gyoss9&usertype=admin

3、用户确认并同意授权。
用户进入登录授权页后,需要确认并同意将自己的企业微信和登录账号信息授权给企业或服务商,完成授权流程。
4、授权后回调URI,得到授权码和过期时间。
登录授权发起域名和授权成功回调域名需要在服务商后台进行配置,只能在该域名下才能发起授权和完成授权回调。

image.png

参数是否必须说明
appid服务商的CorpID
redirect_uri授权登录之后目的跳转网址,需要做urlencode处理。所在域名需要与授权完成回调域名一致
state用于企业或服务商自行校验session,防止跨域攻击
usertype支持登录的类型。admin代表管理员登录(使用微信扫码),member代表成员登录(使用企业微信扫码),默认为admin
lang自定义语言,支持zh、en;lang为空则从Headers读取Accept-Language,默认值为zh

代码实现

encode := url.QueryEscape("http://qr-login.xxxxxxxx/wx/returnLogin")//回调地址,需要做urlencode处理
redirect := "https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect?appid=" + model.CorpId + "&redirect_uri=" + encode + "&state=" + key + "&usertype=member"
//这里是后端直接跳转到扫码页面
c.Header("Content-Type", "text/html")
c.String(200, "<script type="text/javascript"> window.location.href = ""+redirect+""</script>")

(2)获取登录用户信息

1.先获取服务商凭证(provider_access_token),需要先从服务商后台拿到CorpID和ProviderSecret

QQ图片20220512155333.png
2.第三方可通过如下接口,获取登录用户的信息。建议用户以返回信息中的corpid及userid为主键匹配用户。

请求方式: POST(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info?access_token=PROVIDER_ACCESS_TOKEN

请求包体:

 {"auth_code":"xxxxx" //扫码登录成功回调url携带参数}

参数说明:

参数是否必须说明
access_token授权登录服务商的网站时,使用应用提供商的provider_access_token,获取方法参见服务商的凭证
auth_codeoauth2.0授权企业微信管理员登录产生的code,最长为512字节。只能使用一次,5分钟未被使用自动过期

代码实现

data, err := util.Post(util.GetLoginInfo+"?access_token="+corpToken, map[string]interface{}{"auth_code": authCode,
})
fmt.Println(data)
if err != nil {fmt.Println("post获取用户信息失败")return
}
var result util.WxRspLoginInfo
json.Unmarshal([]byte(data), &result)
if result.ErrCode != 0 {fmt.Println("获取用户信息失败")return
}

返回结果中可以获取到成员id就可以进行身份校验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/50979.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ThinkPHP和uniapp开发的CRM售后管理系统(客户、合同、工单、任务、报价、产品、库存、出纳、收费)

ThinkPHP和uniapp开发的CRM售后管理系统无加密的开源源码(可用于自营外包项目(多主体)、可用于外包定制开发项目) 主要功能&#xff1a;客户、合同、工单、任务、报价、产品、库存、出纳、收费&#xff0c; 适用于&#xff1a;服装鞋帽、化妆品、机械机电、家具装潢、建材行业…

最新TP开源的淘宝客系统/推券客CMS系统+功能强大

正文: 最新TP开源的淘宝客系统/推券客CMS系统功能强大&#xff0c;由于程序标题太长了&#xff0c;所以本文简略写了&#xff0c;下方才是完整标题: 关于程序本身就没什么好介绍的了&#xff0c;有视频搭建教程&#xff0c;有兴趣的自己去跟着搭建吧。 程序: wwegu.lanzouv.…

巨准拓客CRM【工商财税】行业获客解决方案

工商财税行业现状 一直以来传统财税管理行业普遍存在竞争激烈、同行内卷、服务同质化、人员流动性高、数字化程度低的问题。绝大多数的财税公司都把企业盈利重点依托于基础的代记账报税业务和部分例如税筹的增值业务上。 但是很多财税管理公司业务拓展都依赖于人力资源…

新品上线 | 企企通推出达人管理系统,助力达人营销提效增速

01、直播市场发展迅速 企企通达人管理系统应运而生 近年来&#xff0c;直播凭借其即时性、互动性、多样化的优势&#xff0c;迅速在互联网占据一席之地&#xff0c;“直播”模式不断扩展&#xff0c;直播电商应运而生。 在技术发展与市场需求双重驱动下&#xff0c;中国直播市…

外贸客源软件大盘点,帮您精准拓客

随着时代的不断发展&#xff0c;数据已成为企业提升的新标准。 在进入新市场之前&#xff0c;我们需要收集供需双方的信息&#xff0c;而客户获取软件仅具有数据集成、精确搜索、客户收集、精确推广、一键添加等功能。 下面我将为大家总结几款比较实用的外贸搜索软件&#xff0…

企业微信HOOK接口,企业微信营销软件

【简单介绍】 使用hook将系统功能封装成dll&#xff0c;然后通过其他语言调用dll实现功能的操作 支持调用的开发语言C/C&#xff0c;C#&#xff0c;易语言&#xff0c;Python, Java, Go, VB, Delphi 支持企微版本&#xff1a;【3.1.7.3005】【3.1.10.3010】【4.0.0.6024】【…

这是一套基于THINKPHP6+SCUI+VUE2.6开发的CRM客户管理系统

这是一套基于THINKPHP6SCUIVUE2.6开发的CRM客户管理系统 演示&#xff1a;http://v2.antsys.cn 用户名admin 密码123456

泛微发布内外协同的客服管理系统-睦客邻

客户服务是企业业务环节中的关键一环&#xff0c;也是确保客户最终满意度的关键一环。好的客户服务是一个组织能持续经营的有力保证。 如何让客服成为客户的好邻里&#xff0c;让客户真实地感受到全方位的服务&#xff0c;从而让组织的服务产生力量和价值。企业对客服有着系统…

这家芯片企业,从创立之初就用 Authing 管理身份

在德州仪器和苹果的经验&#xff0c;让我深知统一身份管理要从 Day 1 做起。——Alpha Cen 联合创始人 & CEO 王璠 案例亮点&#xff1a; 打通 2000 主流应用、满足芯片初创企业统一身份需求 一周快速上线&#xff0c;产品开箱即用&#xff0c;后续无需费力运维 基于协同…

国足历届世界杯对战图关系

奥运会与世界杯&#xff0c;这两大顶级运动赛事交替着为我们的夏天带来激情与拼搏&#xff0c;许多男生看完一届奥运就会等着后年夏天的世界杯。但是突如其来的全球性疫情打乱了运动健儿们的脚步&#xff0c;2020年的东京奥运会推迟了一年&#xff0c;各项球类的联赛也被延期到…

关于卡塔尔世界杯的活动介绍

四年一度的世界杯已经揭开序幕&#xff0c;早从前天开始已经有多个品牌陆续推出推文&#xff0c;预热自家产品的世界杯限时活动。活动形式主要为&#xff1a;优惠活动、限时竞猜、世界杯套餐等&#xff0c;旨在将特定产品与世界杯结合销售&#xff0c;唤醒球迷们的情怀&#xf…

最后一场2022卡塔尔世界杯预选赛,巴西队与阿根廷队不踢了

2022卡塔尔世界杯的所有预选赛全数都已告一段落&#xff0c;但唯独南美洲赛区有一场比赛因故未能如期完成&#xff0c;对战组合是南美两大足球强权巴西队与阿根廷队。原本国际足联&#xff08;FIFA&#xff09;与南美足联&#xff08;CONMEBOL&#xff09;排定这场2022卡塔尔世…

当 AI 踢进世界杯......

近日&#xff0c;2022 年卡塔尔世界杯的举办吸引了全球众人的目光&#xff0c;除了日常网友调侃的“小馄饨皮王子”、“2200 亿美元”、“头顶一块布&#xff0c;全球我最富”的梗之外&#xff0c;与之登上热搜榜单的还有「足球传感器显示 C 罗未触球」、「半越位识别技术」、「…

【致敬世界杯】球迷(我)和足球的故事

目录 一、第一次接触足球 二、回味无穷的2018世界杯 三、致敬世界杯 3.1 源代码 3.2 思路 3.3 关于图片 一、第一次接触足球 踢足球是一项优秀的运动&#xff0c;它可以锻炼身体&#xff0c;增强团队合作精神&#xff0c;并为人们带来快乐和满足感。回忆起小学时候第一次…

观世界赛事,品足球人生--2022世界杯

观世界赛事&#xff0c;品足球人生 – 2022世界杯 1.卡塔尔世界杯百科 2022年卡塔尔世界杯&#xff08;英语&#xff1a;FIFA World Cup Qatar 2022&#xff09;是第二十二届世界杯足球赛&#xff0c;是历史上首次在卡塔尔和中东国家境内举行、也是第二次在亚洲举行的世界杯足…

2022世界杯不扩军!国足教练:机会来了

北京时间5月23日凌晨&#xff0c;国际足联发表官方声明称&#xff0c;2022年卡塔尔世界杯确认依然是32支球队参加&#xff0c;不会扩军&#xff0c;也不会再由其他海湾国家来共同承办部分比赛。对中国男足而言&#xff0c;这或许并不是一个什么好消息&#xff0c;但却可以让中国…

我与足球以及世界杯的过往

中东土豪卡塔尔斥资2000亿举办的世界杯正在如火如荼的进行中&#xff0c;我也是几乎一场不落的看完了每一场的比赛直播【最近都没怎么更文。。。】&#xff0c;目前小组赛已经结束&#xff0c;我们也见证了很多球星的落寞背影与不甘&#xff0c;也见证了新星的天赋与成长&#…

程序员转行后都怎么样了,分享我身边的真实经历!

最近跟同事中午出去吃饭的时候&#xff0c;聊起了程序员转行&#xff08;35岁被毕业&#xff09;应该干什么的问题。 其中一个同事说&#xff0c;他准备以后混不下去了就在老家开一家茶馆&#xff08;麻将馆&#xff09;&#xff0c;因为他父母就是开茶馆的&#xff0c;所以知道…

我的程序员转行过程,聊聊程序员的职业出路在哪里?

程序员这个职业&#xff0c;对于很多人来说是一个注重细节&#xff0c;需要不断学习&#xff0c;却又看似缺少成就感的职业。在这个瞬息万变的互联网环境中&#xff0c;程序员们需要时刻保持学习心态&#xff0c;不断地提升自己的技术水平。但是&#xff0c;这个职业到底有没有…

后端从入门到转岗,如何转型

一、技术介绍 我学习的技术很多&#xff1a; 例如&#xff1a;JAVA JS C# python vue mysql Oracle 等等。 学习也是从入门开始 &#xff0c;入口是JAVA 二、学习前的准备工作 学习前需要准备什么呢&#xff1f; 我觉得学习前最需要准备的是下定决心吃苦&#xff…