Files
sixGuoDjango/wechat_项目工具包/企业微信工具包/客户管理.py
T
2026-08-02 14:07:04 +08:00

221 lines
14 KiB
Python

import io
from typing import List, Literal
import pydash
import requests
from pydantic import BaseModel
from wechat_token.token工具包 import sixToken
from wechat_数据库.企业微信数据库.企微用户表 import wecom企微用户
from wechat_数据库.用户数据库.小程序登陆用户 import weiuser
from wechat_项目工具包.数据库的工具包.更新用户积分 import miniUser用户角色
from 第三方工具目录.腾讯云 import oss上传腾讯云图片
class wecomData客户列表响应(BaseModel):
errcode: int
errmsg: str
external_userid: List[str]
from pydantic import BaseModel
from typing import List, Optional
class wecomData外部联系人基本信息(BaseModel):
"""外部联系人基本信息"""
external_userid: str
name: str
type: int
avatar: str
gender: int
unionid: Optional[str] = None
class wecomData跟进人标签(BaseModel):
"""跟进人标签"""
group_name: str
tag_name: str
type: int
tag_id: Optional[str] = None
class wecomData跟进成员信息(BaseModel):
"""跟进成员信息"""
userid: str
remark: Optional[str] = None
description: Optional[str] = None
createtime: int
state: Optional[str] = None
tags: List[wecomData跟进人标签] = []
remark_mobiles: List[str] = []
remark_corp_name: Optional[str] = None
add_way: int
oper_userid: str
class wecomData获取客户详情响应(BaseModel):
"""获取客户详情接口返回"""
errcode: int
errmsg: str
external_contact: Optional[wecomData外部联系人基本信息] = None
follow_user: List[wecomData跟进成员信息] = []
six六果对象xiao, six是否新创建值 = weiuser.objects.update_or_create(unionid="六果",
defaults={
"user_IP地址": None, "user_昵称": "六果", "user_用户当前的等级": 0, "user_省份": "六果", "user_城市": "六果", "user_区县": "六果",
"user_街道信息": "六果", "user_头像": "https://hudie.xiao.band/%E6%9C%AA%E5%91%BD%E5%90%8D.png", "user_绑定企微usrID账号": "六果", "user_角色权限": "六果", "external_userid": "六果",
"parent_id": "六果", "mini_openid": "wxf612e825377328f0", "wechat_openid": "六果", "wecom_openid": "wwbe6369dc26a9d83a", "codeConfigId": "六果", "codeRemark": "六果",
"codeQrCode": "https://hudie.xiao.band/mini.jpg",
"user_企微角色权限": "六果", "user_绑定企微UNIONID": "六果"
})
class wecom客户好友管理(BaseModel):
# demo_必填: int = Field(..., description="描述") # 必传属发生
# demo_可选: Optional[int] = None # 可选值
# demo_默认值: int = Field(default=100001, description="描述") # 有默认值
# demo_联合类型: Literal["xiao", "zizi"] = Field(..., description="描述")
def 企微原用户处理接口(self, data):
""""""
state上级用户 = pydash.get(obj=data, path="state", default="六果") # 上级分享者的uniond值 这里是企微二维码绑定的 uninoid
external_userid = pydash.get(obj=data, path="external_userid")
unionid下级用户 = pydash.get(obj=data, path="unionid")
print(f"state上级用户===>{state上级用户}", f"unionid下级用户===>{unionid下级用户}")
上级用户, 上级用户状态 = weiuser.objects.get_or_create(unionid=state上级用户) # 如果state的状态不为None:则创建这个用户
下级用户, 下级用户状态 = weiuser.objects.get_or_create(unionid=unionid下级用户)
six六果对象, sixBool = weiuser.objects.get_or_create(unionid="六果")
if 上级用户.parent is None:
# 当这里企微号的state绑定的小程序用户的时候 的 上级用户为None的时候
上级用户.parent = six六果对象
上级用户.external_userid = external_userid
上级用户.user_用户当前的等级 = six六果对象.user_用户当前的等级 + 1
上级用户.codeQrCode = six六果对象.codeQrCode
上级用户.codeRemark = six六果对象.codeRemark
上级用户.codeConfigId = six六果对象.codeConfigId
上级用户.user_绑定企微UNIONID = six六果对象.user_绑定企微UNIONID
上级用户.save()
# # 第二步就只需要查询,如果下级用户已经有上级了就直接忽略
if 上级用户.parent is not None:
print("这里是上上级用户不为None的时候", )
# 还需要判断一下,下级用户的 父元素为six公司对象的时候,还得更新一下当前的数据,因为这个用户原来就是属于 企微员工的绑定者
if 下级用户.parent == six六果对象 and 下级用户.user_企微角色权限 != miniUser用户角色().企微员工:
print(下级用户, "🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎判断成功了")
下级用户.parent = 上级用户
下级用户.user_用户当前的等级 = 上级用户.user_用户当前的等级 + 1
下级用户.user_绑定企微UNIONID = 上级用户.user_绑定企微UNIONID
下级用户.codeConfigId = 上级用户.codeConfigId
下级用户.codeQrCode = 上级用户.codeQrCode
下级用户.codeRemark = 上级用户.codeRemark
下级用户.user_绑定企微usrID账号 = 上级用户.user_绑定企微usrID账号
下级用户.save()
if 下级用户.parent is not None:
# 这里判断出下级用户有上级,直接原样处理,不做任何的更改状态
print("下级用户的父不为不为不为元素为None的时候", 上级用户)
下级用户.external_userid = external_userid
下级用户.save()
if 下级用户.parent is None:
print("下级用户的父元素为None的时候", 上级用户)
下级用户.parent = 上级用户
下级用户.user_用户当前的等级 = 上级用户.user_用户当前的等级 + 1
下级用户.external_userid = external_userid
下级用户.codeQrCode = 上级用户.codeQrCode
下级用户.codeRemark = 上级用户.codeRemark
下级用户.codeConfigId = 上级用户.codeConfigId
下级用户.user_绑定企微UNIONID = 上级用户.user_绑定企微UNIONID
下级用户.save()
def 获取客户列表(self, userid: Literal["YuanBao1975"]) -> wecomData客户列表响应:
"""根据企微员工的ID,一次获取当前企微员所有的好友列表"""
wecom_token = sixToken.get_wecom_token()
uri = f"https://qyapi.weixin.qq.com/cgi-bin/externalcontact/list"
json_data = requests.get(url=uri, params={"access_token": wecom_token, "userid": userid})
# print("获取客户列表获取客户列表获取客户列表获取客户列表获取客户列表获取客户列表获取客户列表", json_data.json())
get_data = wecomData客户列表响应(**json_data.json())
return get_data.model_dump()
def 获取客户详情(self, external_userid) -> wecomData获取客户详情响应:
"""通过 external_userid 获取用户的详情,最主要的就是拿到用户的 unionid """
wecom_token = sixToken.get_wecom_token()
uri = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get"
data = requests.get(url=uri, params={"access_token": wecom_token, "external_userid": external_userid})
print("\n🍎 🍏 🍊获取客户详情 🍎 🍏 \n", data.json())
return wecomData获取客户详情响应(**data.json())
def 批量获取客户详情并存储到数据库(self, state企微员工创建时添加的唯一值, userid企微员工账号ID: Literal["YuanBao1975"]):
"""根据企微员工的ID,获取当前企微员添加的所有的外 部联系人好友,并存储到数据库"""
def request_recursive(userid_list=None, cursor="", ):
""""""
# 初始化参数
wecom_token_inner = sixToken.get_wecom_token()
# 构建请求参数
uri = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user"
json_data = {"userid_list": userid_list, "limit": 200, "cursor": cursor}
# 发送请求
try:
data = requests.post(url=uri, params={"access_token": wecom_token_inner}, json=json_data, )
response_json = data.json()
# 提取当前页的外部联系人
# 获取下一页游标
external_contact_list = pydash.get(obj=response_json, path="external_contact_list")
next_cursor = pydash.get(obj=response_json, path="next_cursor", default="")
print(f"当前获取到 {len(external_contact_list)} 个外部联系人,总计 {len(external_contact_list)} 个")
# 如果还有下一页,递归调用
for post_data in external_contact_list:
userid = pydash.get(obj=post_data, path="follow_info.userid") # 添加了此外部联系人的企业成员userid 如 HuDie_1
remark = pydash.get(obj=post_data, path="follow_info.remark") # 该成员对此微信客户备注的企业名称(仅微信客户有该字段)
description = pydash.get(obj=post_data, path="follow_info.description")
createtime = pydash.get(obj=post_data, path="follow_info.createtime")
state = pydash.get(obj=post_data, path="follow_info.state") # 企业自定义的state参数,用于区分客户具体是通过哪个「联系我」或获客链接添加;由企业通过创建「联系我」或在获客链接中添加customer_channel参数进行指定
tag_id = pydash.get(obj=post_data, path="follow_info.tag_id")
remark_mobiles = pydash.get(obj=post_data, path="follow_info.remark_mobiles") # 该成员对此客户备注的手机号码,第三方应用和代开发应用均不可获取,上游企业不可获取下游企业客户该字段
add_way = pydash.get(obj=post_data, path="follow_info.add_way") # 该成员添加此客户的来源add_way为10时,对应的视频号信息
oper_userid = pydash.get(obj=post_data, path="follow_info.oper_userid") # 发起添加的userid,如果成员主动添加,为成员的userid;如果是客户主动添加,则为客户的外部联系人userid;如果是内部成员共享/管理员分配,则为对应的成员/管理员userid
external_userid = pydash.get(obj=post_data, path="external_contact.external_userid") # 外部联系人的userid
name = pydash.get(obj=post_data, path="external_contact.name") # 外部联系人的名称[注1]
type_data = pydash.get(obj=post_data, path="external_contact.type") # 外部联系人的类型,1表示该外部联系人是微信用户,2表示该外部联系人是企业微信用户
avatar = pydash.get(obj=post_data, path="external_contact.avatar") # 外部联系人头像。第三方应用和代开发应用均不可获取,上游企业不可获取下游企业客户该字段
gender = pydash.get(obj=post_data, path="external_contact.gender") # 外部联系人性别 0-未知 1-男性 2-女性。
unionid = pydash.get(obj=post_data, path="external_contact.unionid") # 外部联系人在微信开放平台的唯一身份标识(微信unionid),
print("看看这里的值是多少看看这里的值是多少看看这里的值是多少看看这里的值是多少看看这里的值是多少看看这里的值是多少看看这里的值是多少看看这里的值是多少", state)
if avatar and type_data == 1:
img_file = requests.get(url=avatar).content
src = oss上传腾讯云图片.上传图片(key=f"{userid}/{name}.png", file=io.BytesIO(img_file), )
avatar = src
# time.sleep( 1 )
# avatar = "https://hudie.xiao.band/%E6%9C%AA%E5%91%BD%E5%90%8D.png"
if bool(avatar) == False and type_data == 1:
avatar = "https://hudie.xiao.band/%E6%9C%AA%E5%91%BD%E5%90%8D.png"
if type_data == 1:
weiuser.objects.update_or_create(unionid=unionid, defaults={"user_头像": avatar, "user_昵称": name, "external_userid": external_userid, })
wecomData = {"state": state企微员工创建时添加的唯一值, "external_userid": external_userid, "unionid": unionid}
self.企微原用户处理接口(data=wecomData)
wecom企微用户.objects.update_or_create(wecom企微ID=userid, wecom企微对好友添加的手机号码=remark_mobiles, wecom企微好友添加方式=oper_userid, wecom企微状态State=state企微员工创建时添加的唯一值, wecom对好友打的标签=tag_id,
wecom对好友的备注信息=description, wecom对好友的备注名称=remark, wecom对好友的添加时间=createtime, wecom好友头像=avatar, wecom好友性别=gender, wecom好友昵称=name, wecom好友的ID=external_userid,
wecom好友UNIONID=unionid, )
if next_cursor:
print(f"发现下一页,游标: {next_cursor}") # 递归调用
request_recursive(userid_list=userid_list, cursor=next_cursor, )
except requests.exceptions.RequestException as e:
print(f"网络请求异常: {e}", )
except Exception as e:
print(f"处理异常: {e}")
request_recursive(userid_list=[userid企微员工账号ID], )
if __name__ == "__main__":
pass
wai_external_userid = "wmj4zANAAAGlCZ2zNRhu1qzEMSBF0a9g"
# data_wecom_客户详情数据 = wecom客户好友管理().获取客户详情(external_userid=wai_external_userid)
wecom客户好友管理().批量获取客户详情并存储到数据库(state企微员工创建时添加的唯一值="oy4Jw6A1T3WkKOOhMxcbQTDSM8rs", userid企微员工账号ID="YuanBao1975") # 此方法会直接更新数据库并且保存数据