项目初始化

This commit is contained in:
AKW 2023-12-13 11:41:22 +08:00
commit 56a24de3cb
108 changed files with 8007 additions and 0 deletions

3
.dockerignore Normal file
View File

@ -0,0 +1,3 @@
.idea
**/.vscode
/yzk/settings/local.py

173
.gitignore vendored Normal file
View File

@ -0,0 +1,173 @@
.vscode
.idea
.coverage*
.DS_Store
staticfiles
mediafiles
client/node_modules
node_modules
*/node_modules
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
tests
tests/*
# C extensions
*.so
logs/*.log
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
celerybeat-*.bak
celerybeat-*.dat
celerybeat-*.dir
/yzk_wechat_event/settings/local.py

26
Dockerfile Normal file
View File

@ -0,0 +1,26 @@
FROM python:3.11.4
ENV APP_HOME=/app
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
LABEL maintainer='AKW'
LABEL bilibili='https://www.bilibili.com'
LABEL description='Development image for Real Estate Project'
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN mkdir logs
RUN mkdir ~/.pip
RUN echo "[global]" > ~/.pip/pip.conf
RUN echo "index-url = https://pypi.tuna.tsinghua.edu.cn/simple" >> ~/.pip/pip.conf
RUN pip3 install --upgrade pip
COPY ./requirements.txt /app/requirements.txt
RUN pip3 install -r requirements.txt
ENTRYPOINT ["sh"]

0
apps/jqr/__init__.py Normal file
View File

3
apps/jqr/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
apps/jqr/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class JqrConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.jqr'

200
apps/jqr/choices.py Normal file
View File

@ -0,0 +1,200 @@
from django.db import models
class JqrHookUserGenderChoices(models.IntegerChoices):
"""
微信用户性别
"""
UNKNOWN = 0, '未知'
MALE = 1, ''
FEMALE = 2, ''
class JqrHookUserStatusChoices(models.IntegerChoices):
ACTIVE = 1, '已激活'
DISABLED = 2, '已禁用'
UN_ACTIVE = 4, '未激活'
QUIQ_CORP = 5, '退出企业'
class JqrExternalUserTypeChoices(models.IntegerChoices):
WECHAT = 1, '微信用户'
COMPANY_WECHAT = 2, '企业微信用户'
class JqrSendSettingPlatformTypeChoices(models.IntegerChoices):
ELM = 1, '饿了么'
MT = 2, '美团'
TB = 3, '淘宝'
JD = 4, '京东'
PDD = 5, '拼多多'
WPH = 6, '唯品会'
class JqrSendMsgMtActivityImageChoices(models.IntegerChoices):
ORIGIN = 1, '原始图片'
POSTER = 2, '海报图片'
class JqrUserAddTypeChoices(models.IntegerChoices):
UNKNOWN_SOURCE = 0, '未知来源'
SCAN_QRCODE = 1, '扫描二维码'
SEARCH_PHONE = 2, '搜索手机号'
CARD_SHARE = 3, '名片分享'
GROUP_CHAT = 4, '群聊'
PHONE_BOOK = 5, '手机通讯录'
WECHAT_CONTACT = 6, '微信联系人'
THIRD_APP_AUTO_ADD = 8, '安装第三方应用时自动添加的客服人员'
SEARCH_EMAIL = 9, '搜索邮箱'
WECHAT_VIDEO = 10, '视频号添加'
SCHEDULE_PARTICIPANT = 11, '通过日程参与人添加'
MEETING_PARTICIPANT = 12, '通过会议参与人添加'
WECHAT_BUSINESS = 13, '添加微信好友对应的企业微信'
SMART_HADWARE_DEDICATED_SERVICE = 14, '通过智慧硬件专属客服添加'
HOME_SERVICE = 15, '通过上门服务客服添加'
CUSTOMER_LINK = 16, '通过客户链接添加'
INTERNAL_COLLABORATION = 201, '内部成员共享'
ADMIN_ALLOCATE = 202, '管理员或负责人分配'
class JqrSendMsgMtTextConvertChoices(models.IntegerChoices):
MP = 0, 'mp'
URL = 1, 'url'
class JqrSendMsgElmTextConvertChoices(models.IntegerChoices):
MP = 0, 'mp'
URL = 1, 'url'
TKL = 2, '淘口令'
class JqrSendMsgTextTypeChoices(models.IntegerChoices):
REPLACE = 1, '替换文案'
CONVERT = 2, '转链'
class JqrSendMsgAttachmentItemMsgTypeChoices(models.IntegerChoices):
TEXT = 1, '文本'
ACTIVITY_POSTER = 2, '活动海报'
FIXED_IMAGE = 3, '固定图片'
ELM_ACTIVITY_IMAGE = 4, '饿了么活动图片'
MT_ACTIVITY_IMAGE = 5, '美团活动图片'
VIDEO = 6, '视频'
FIXED_LINK = 7, '固定链接'
OUR_ACTIVITY_PAGE = 8, '我们自己的活动页'
ELM_ACTIVITY_LINK = 9, '饿了么活动链接'
MT_ACTIVITY_LINK = 10, '美团活动链接'
VIDEO_NUMBER = 11, '视频号'
FIXED_MINI_PROGRAM = 12, '固定小程序'
ELM_MINI_PROGRAM = 13, '饿了么小程序'
MT_MINI_PROGRAM = 14, '美团小程序'
class JqrSendGroupMsgNeedSidChoices(models.IntegerChoices):
NOT_NEED = 0, '不需要'
NEED = 1, '需要'
class JqrSendGroupMsgIsOpenChoices(models.IntegerChoices):
NOT_OPEN = 0, '未开启'
OPEN = 1, '已开启'
class JqrSendGroupMsgTimeTypeChoices(models.IntegerChoices):
# 1.指定2.每日3.每周4.每月
SPECIFIED = 1, '指定'
DAILY = 2, '每日'
WEEKLY = 3, '每周'
MONTHLY = 4, '每月'
class JqrSendGroupMsgSendTypeChoices(models.IntegerChoices):
# 1=高级群发2=极速群发
ADVANCED = 1, '高级群发'
FAST = 2, '极速群发'
class JqrAddTypeChoices(models.IntegerChoices):
API = 1, 'API拉取'
EVENT_CALLBACK = 2, '事件回调'
HOOK = 3, 'hook'
class JqrWechatbizuserinfoDeleteTypeChoices(models.IntegerChoices):
EVENT_CALLBACK = 1, '事件回调'
SEND_SYNC_RECORD = 2, '发送同步记录'
class JqrSendMsgSendUserTypeChoices(models.IntegerChoices):
# 0, 全部, 1 部分
ALL = 0, '全部'
PART = 1, '部分'
class JqrSendGroupMsgSendUserTypeChoices(models.IntegerChoices):
# 发送用户类型 0 全部1 部分企业2 企业用户
ALL = 0, '所有接粉号'
CORP_PART = 1, '企业下所有接粉号'
CORP_USER = 2, '指定接粉号'
class JqrSendGroupMsgSendTagTypeChoices(models.IntegerChoices):
ALL_USER = 0, '所有用户'
SOME_EXTERNAL_USER = 1, '指定用户'
CORP_TAGS = 2, '满足任意标签的用户'
class JqrNewUserSendGroupMsgTypeChoices(models.IntegerChoices):
"""新客欢迎类型"""
PRIVATE = 0, '私聊'
QUN = 1, '群聊'
ORDER = 2, '催单'
class JqrTimeSendGroupMsgTypeChoices(models.IntegerChoices):
"""定时发送类型"""
PRIVATE = 0, '私聊'
QUN = 1, '群聊'
class JqrKeywordSendGroupMsgTypeChoices(models.IntegerChoices):
"""关键字发送类型"""
PRIVATE = 0, '私聊'
QUN = 1, '群聊'
class JqrKeywordSendGroupMsgPatternChoices(models.IntegerChoices):
"""关键字发送模式"""
ANY = 0, '匹配任意信息'
EXACT = 1, '精准匹配'
FUZZY = 2, '模糊匹配'
class JqrGroupMsgListChatTypeChoices(models.TextChoices):
# 默认为single表示发送给客户group表示发送给客户群
SINGLE = 'single', '私聊'
GROUP = 'group', '群聊'
class JqrGroupMsgListFilterTypeChoices(models.IntegerChoices):
CORP = 0, '企业'
PERSONAL = 1, '个人'
ALL = 2, '全部'
class JqrGroupMsgListCreateTypeChoices(models.IntegerChoices):
CORP = 0, '企业'
PERSONAL = 1, '个人'
class JqrGroupMsgTaskStatusChoices(models.IntegerChoices):
UNSENT = 0, '未发送'
SENT = 2, '已发送'
class JqrGrouMsgSendGroupMsgStatusChoices(models.IntegerChoices):
# 发送状态0-未发送 1-已发送 2-因客户不是好友导致发送失败 3-因客户已经收到其他群发消息导致发送失败
UNSENT = 0, '未发送'
SENT = 1, '已发送'
FAIL_SEND_TO_FRIEND = 2, '因客户不是好友导致发送失败'
FAIL_SEND_TO_OTHER_MSG = 3, '因客户已经收到其他群发消息导致发送失败'

View File

388
apps/jqr/models.py Normal file
View File

@ -0,0 +1,388 @@
from .choices import *
class JqrWechatbizuserinfo(models.Model):
id = models.BigAutoField(primary_key=True)
userid = models.CharField(max_length=50, verbose_name='UserId')
corpid = models.CharField(max_length=32, verbose_name='企业微信corpid')
username = models.CharField(
max_length=50, verbose_name='用户名', null=True, blank=True)
alias = models.CharField(
max_length=64, verbose_name='别名', null=True, blank=True)
department = models.JSONField(verbose_name='部门ID集合')
maindepartment = models.IntegerField(verbose_name='主部门ID')
telephone = models.CharField(
max_length=20, verbose_name='座机', null=True, blank=True)
position = models.CharField(
max_length=64, verbose_name='职位', null=True, blank=True)
external_position = models.CharField(
max_length=64, verbose_name='对外职务', null=True, blank=True)
direct_leader = models.JSONField(
verbose_name='直属上级userid', null=True, blank=True)
is_leader_in_dept = models.JSONField(
verbose_name='表示在所在的部门内是否为部门负责人,数量与department一致', null=True, blank=True)
status = models.IntegerField(
verbose_name='激活状态: 1=已激活,2=已禁用,4=未激活,5=退出企业',
choices=JqrHookUserStatusChoices.choices)
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
dtime = models.DateTimeField(verbose_name='删除时间', null=True, blank=True)
deletetype = models.IntegerField(
verbose_name='删除方式', choices=JqrWechatbizuserinfoDeleteTypeChoices.choices, null=True, blank=True)
addtype = models.IntegerField(
verbose_name='添加方式', choices=JqrUserAddTypeChoices.choices, default=JqrAddTypeChoices.API)
class Meta:
db_table = 'jqr_wechatbizuserinfo'
ordering = ['-ctime']
verbose_name = '机器人用户表'
class JqrHookUser(models.Model):
id = models.BigAutoField(primary_key=True)
uid = models.IntegerField(verbose_name='用户Id')
corpid = models.CharField(max_length=255, verbose_name='企业唯一标识')
userid = models.CharField(max_length=50, verbose_name='接粉号userid')
vid = models.CharField(max_length=255, verbose_name='hook vid')
new_user = models.BooleanField(default=True, verbose_name='新科欢迎开关')
new_user_order = models.BooleanField(
default=False, verbose_name='新科欢迎催单开关')
time_qun = models.BooleanField(default=True, verbose_name='定时群聊开关')
time_private = models.BooleanField(default=True, verbose_name='定时私聊开关')
time_quan = models.BooleanField(default=True, verbose_name='定时朋友圈开关')
hook_time = models.DateTimeField(
null=True, blank=True, verbose_name='hook时间')
utime = models.DateTimeField(verbose_name='更新时间', null=True, blank=True)
name = models.CharField(
max_length=255, verbose_name='用户名', null=True, blank=True)
mobile = models.CharField(
max_length=30, verbose_name='手机号', null=True, blank=True)
phone = models.CharField(
max_length=30, verbose_name='手机号', null=True, blank=True)
gender = models.IntegerField(
verbose_name='性别,0表示未定义,1表示男性,2表示女性', choices=JqrHookUserGenderChoices.choices)
english_name = models.CharField(
max_length=255, verbose_name='别名', null=True, blank=True)
bind_email = models.CharField(
max_length=255, verbose_name='绑定邮箱', null=True, blank=True)
external_custom_info = models.JSONField(
verbose_name='对外展示信息', null=True, blank=True)
qrcode = models.CharField(
max_length=255, verbose_name='二维码', null=True, blank=True)
class Meta:
unique_together = ('corpid', 'userid', 'vid')
db_table = 'jqr_hook_user'
verbose_name = '机器人hook用户详细表'
class JqrExternalUser(models.Model):
id = models.BigAutoField(primary_key=True)
corpid = models.CharField(max_length=32, verbose_name='企业微信corpid')
external_userid = models.CharField(max_length=60, verbose_name='外部用户id')
vid = models.CharField(
max_length=50, verbose_name='接粉号vid', null=True, blank=True)
name = models.CharField(max_length=255, verbose_name='用户名')
avatar = models.CharField(
max_length=255, verbose_name='头像', null=True, blank=True)
type = models.IntegerField(
verbose_name='外部联系人的类型', choices=JqrExternalUserTypeChoices.choices)
gender = models.IntegerField(
verbose_name='性别', choices=JqrHookUserGenderChoices.choices)
unionid = models.CharField(
max_length=255, verbose_name='微信unionid', null=True, blank=True)
position = models.CharField(
max_length=255, verbose_name='职位', null=True, blank=True)
corp_name = models.CharField(
max_length=255, verbose_name='企业简称', null=True, blank=True)
corp_full_name = models.CharField(
max_length=255, verbose_name='企业名称', null=True, blank=True)
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
dtime = models.DateTimeField(verbose_name='删除时间', null=True, blank=True)
addtype = models.IntegerField(
verbose_name='添加方式', choices=JqrUserAddTypeChoices.choices, default=JqrAddTypeChoices.API)
deletetype = models.IntegerField(
verbose_name='删除方式', choices=JqrWechatbizuserinfoDeleteTypeChoices.choices, null=True, blank=True)
class Meta:
db_table = 'jqr_external_user'
verbose_name = '机器人外部联系人表'
ordering = ['-ctime']
unique_together = ('corpid', 'external_userid')
class JqrExternalFollowUser(models.Model):
corpid = models.CharField(max_length=32, verbose_name='企业微信corpid')
external_userid = models.CharField(max_length=60, verbose_name='外部用户id')
id = models.BigAutoField(primary_key=True)
userid = models.CharField(max_length=50, verbose_name='接粉号userid')
remark = models.TextField(
verbose_name='该成员对此外部联系人的备注', null=True, blank=True)
description = models.TextField(
verbose_name='该成员对此外部联系人的描述', null=True, blank=True)
createtime = models.BigIntegerField(verbose_name='添加好友时间')
tags = models.JSONField(verbose_name='标签')
remark_mobiles = models.JSONField(verbose_name='该成员对此客户备注的手机号码')
add_way = models.IntegerField(
verbose_name='添加方式', choices=JqrUserAddTypeChoices.choices)
state = models.CharField(
max_length=255, verbose_name='企业自定义的state参数', null=True, blank=True)
oper_userid = models.CharField(
max_length=50, verbose_name='添加人userid', null=True, blank=True)
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
dtime = models.DateTimeField(verbose_name='删除时间', null=True, blank=True)
addtype = models.IntegerField(
verbose_name='添加方式', choices=JqrUserAddTypeChoices.choices, default=JqrAddTypeChoices.API)
deletetype = models.IntegerField(
verbose_name='删除方式', choices=JqrWechatbizuserinfoDeleteTypeChoices.choices, null=True, blank=True)
class Meta:
db_table = 'jqr_external_follow_user'
verbose_name = '机器人外部联系人关系表'
ordering = ['-ctime']
unique_together = ('corpid', 'userid', 'external_userid')
class JqrExternalQun(models.Model):
id = models.BigAutoField(primary_key=True)
corpid = models.CharField(max_length=32, verbose_name='企业微信corpid')
vid = models.CharField(
max_length=50, verbose_name='接粉号vid', null=True, blank=True)
chat_id = models.CharField(max_length=60, verbose_name='群id')
name = models.CharField(max_length=255, verbose_name='群名')
owner = models.CharField(max_length=50, verbose_name='接粉号userid')
create_time = models.BigIntegerField(verbose_name='群创建时间')
notice = models.TextField(verbose_name='群通知', null=True, blank=True)
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
dtime = models.DateTimeField(verbose_name='删除时间', null=True, blank=True)
addtype = models.IntegerField(
verbose_name='添加方式', choices=JqrUserAddTypeChoices.choices, default=JqrAddTypeChoices.API)
class Meta:
db_table = 'jqr_external_qun'
verbose_name = '机器人外部联系人群表'
ordering = ['-create_time']
class JqrSendSetting(models.Model):
corpid = models.CharField(max_length=32, verbose_name='企业微信corpid', null=True, blank=True)
agentid = models.CharField(
max_length=128, verbose_name='自建应用agentid', null=True, blank=True)
id = models.BigAutoField(primary_key=True)
uid = models.IntegerField(verbose_name='用户Id')
userid = models.CharField(
max_length=50, verbose_name='接粉号id', null=True, blank=True)
chat_id = models.CharField(
max_length=60, verbose_name='群id', null=True, blank=True)
scene = models.CharField(
max_length=255, verbose_name='场景', null=True, blank=True)
platform_type = models.IntegerField(
verbose_name='平台类型', choices=JqrSendSettingPlatformTypeChoices.choices)
setting = models.JSONField(verbose_name='配置')
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
is_delete = models.BooleanField(verbose_name='是否删除', default=False)
class Meta:
db_table = 'jqr_send_setting'
verbose_name = '发送配置'
ordering = ['-ctime']
class JqrBaseSendMsg(models.Model):
id = models.AutoField(primary_key=True)
uid = models.IntegerField(verbose_name='用户Id')
taskname = models.CharField(max_length=64, verbose_name='任务名称')
sendusertype = models.IntegerField(
verbose_name='发送用户类型', choices=JqrSendGroupMsgSendUserTypeChoices.choices)
senduserids = models.JSONField(verbose_name='发送用户')
sendcontent = models.JSONField(verbose_name='发送内容')
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
isopen = models.IntegerField(verbose_name='是否开启', choices=JqrSendGroupMsgIsOpenChoices.choices)
scene = models.CharField(max_length=128, verbose_name='场景', null=True, blank=True)
class Meta:
abstract = True
class JqrSendGroupMsg(JqrBaseSendMsg):
needsid = models.IntegerField(verbose_name='是否需要sid', choices=JqrSendGroupMsgNeedSidChoices.choices,
default=JqrSendGroupMsgNeedSidChoices.NOT_NEED)
timetype = models.IntegerField(verbose_name='发送时间类型', choices=JqrSendGroupMsgTimeTypeChoices.choices,
default=None)
timejson = models.JSONField(verbose_name='发送时间对象', default=None)
sendtime = models.DateTimeField(verbose_name='下次具体发送时间', null=True, blank=True)
class Meta:
db_table = 'jqr_sendgroupmsg'
verbose_name = 'JQR Send Group Message'
verbose_name_plural = 'JQR Send Group Messages'
ordering = ['-ctime']
def __str__(self):
return self.taskname
class JqrNewUserSendGroupMsg(JqrBaseSendMsg):
# 优先级
priority = models.IntegerField(verbose_name='优先级', default=0)
type = models.IntegerField(verbose_name='类型', choices=JqrNewUserSendGroupMsgTypeChoices.choices,
default=JqrNewUserSendGroupMsgTypeChoices.PRIVATE)
class Meta:
db_table = 'jqr_newusersendgroupmsg'
verbose_name = 'JQR New User Send Group Message'
verbose_name_plural = 'JQR New User Send Group Messages'
ordering = ['-ctime']
def __str__(self):
return self.taskname
class JqrNewUserOrderSendGroupMsg(JqrBaseSendMsg):
# 优先级
priority = models.IntegerField(verbose_name='优先级', default=0)
class Meta:
db_table = 'jqr_newuserordersendgroupmsg'
verbose_name = 'JQR New User Order Send Group Message'
verbose_name_plural = 'JQR New User Order Send Group Messages'
ordering = ['-ctime']
def __str__(self):
return self.taskname
class JqrTimePrivateSendGroupMsg(JqrBaseSendMsg):
sendtype = models.IntegerField(verbose_name='发送类型1=高级群发2=极速群发',
choices=JqrSendGroupMsgSendTypeChoices.choices,
default=JqrSendGroupMsgSendTypeChoices.ADVANCED)
needsid = models.IntegerField(verbose_name='是否需要sid', choices=JqrSendGroupMsgNeedSidChoices.choices,
default=JqrSendGroupMsgNeedSidChoices.NOT_NEED)
timetype = models.IntegerField(verbose_name='发送时间类型', choices=JqrSendGroupMsgTimeTypeChoices.choices,
default=None)
timejson = models.JSONField(verbose_name='发送时间对象', default=None)
sendtime = models.DateTimeField(verbose_name='下次具体发送时间', null=True, blank=True)
type = models.IntegerField(verbose_name='类型', choices=JqrTimeSendGroupMsgTypeChoices.choices,
default=JqrTimeSendGroupMsgTypeChoices.PRIVATE)
class Meta:
db_table = 'jqr_timeprivatesendgroupmsg'
verbose_name = 'JQR Time Private Send Group Message'
verbose_name_plural = 'JQR Time Private Send Group Messages'
ordering = ['-ctime']
def __str__(self):
return self.taskname
class JqrTimeQunSendGroupMsg(JqrBaseSendMsg):
sendtype = models.IntegerField(verbose_name='发送类型1=高级群发2=极速群发',
choices=JqrSendGroupMsgSendTypeChoices.choices,
default=JqrSendGroupMsgSendTypeChoices.ADVANCED)
needsid = models.IntegerField(verbose_name='是否需要sid', choices=JqrSendGroupMsgNeedSidChoices.choices,
default=JqrSendGroupMsgNeedSidChoices.NOT_NEED)
timetype = models.IntegerField(verbose_name='发送时间类型', choices=JqrSendGroupMsgTimeTypeChoices.choices,
default=None)
timejson = models.JSONField(verbose_name='发送时间对象', default=None)
sendtime = models.DateTimeField(verbose_name='下次具体发送时间', null=True, blank=True)
class Meta:
db_table = 'jqr_timequnsendgroupmsg'
verbose_name = 'JQR Time Private Send Group Message'
verbose_name_plural = 'JQR Time Private Send Group Messages'
ordering = ['-ctime']
def __str__(self):
return self.taskname
class JqrKeywordSendGroupMsg(JqrBaseSendMsg):
type = models.IntegerField(verbose_name='类型', choices=JqrKeywordSendGroupMsgTypeChoices.choices,
default=JqrKeywordSendGroupMsgTypeChoices.PRIVATE)
pattern = models.IntegerField(verbose_name='匹配规则', null=True, blank=True,
choices=JqrKeywordSendGroupMsgPatternChoices.choices,
default=JqrKeywordSendGroupMsgPatternChoices.ANY)
keyword_text = models.TextField(verbose_name='关键字数组', null=True, blank=True)
class Meta:
db_table = 'jqr_keywordsendgroupmsg'
verbose_name = 'JQR Keyword Send Group Message'
verbose_name_plural = 'JQR Keyword Send Group Messages'
ordering = ['-ctime']
class JqrGroupMsgList(models.Model):
corpid = models.CharField(max_length=32, verbose_name='企业id', db_index=True)
msgid = models.CharField(max_length=255, verbose_name='消息id', db_index=True)
chat_type = models.CharField(max_length=32, verbose_name='群发任务的类型',
default=JqrGroupMsgListChatTypeChoices.SINGLE,
choices=JqrGroupMsgListChatTypeChoices.choices)
filter_type = models.IntegerField(
verbose_name='创建人类型。0企业发表 1个人发表 2所有包括个人创建以及企业创建默认情况下为所有类型',
choices=JqrGroupMsgListFilterTypeChoices.choices)
creator = models.CharField(max_length=255, verbose_name='创建人')
create_time = models.BigIntegerField(verbose_name='消息创建时间')
create_type = models.IntegerField(verbose_name='创建类型: 0企业 1个人',
choices=JqrGroupMsgListCreateTypeChoices.choices)
text = models.JSONField(verbose_name='文本消息内容', null=True, blank=True)
attachments = models.JSONField(verbose_name='附件消息内容', null=True, blank=True)
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
class Meta:
db_table = 'jqr_groupmsglist'
verbose_name = '群发记录列表'
verbose_name_plural = '群发记录列表'
ordering = ['-create_time']
unique_together = ('corpid', 'msgid')
class JqrGroupMsgTask(models.Model):
corpid = models.CharField(max_length=32, verbose_name='企业id', db_index=True)
msgid = models.CharField(max_length=255, verbose_name='消息id', db_index=True)
userid = models.CharField(max_length=255, verbose_name='接粉号Id')
status = models.IntegerField(verbose_name='发送状态0-未发送 2-已发送',
choices=JqrGroupMsgTaskStatusChoices.choices)
send_time = models.BigIntegerField(verbose_name='发送时间', null=True, blank=True)
chat_type = models.CharField(max_length=32, verbose_name='群发任务的类型',
default=JqrGroupMsgListChatTypeChoices.SINGLE,
choices=JqrGroupMsgListChatTypeChoices.choices)
is_handled = models.BooleanField(verbose_name='是否已处理', default=False)
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
class Meta:
db_table = 'jqr_groupmsgtask'
verbose_name = '群发任务'
verbose_name_plural = '群发任务'
ordering = ['-send_time']
class JqrGrouMsgSendGroupMsgResult(models.Model):
corpid = models.CharField(max_length=32, verbose_name='企业id', db_index=True)
msgid = models.CharField(max_length=255, verbose_name='消息id', db_index=True)
userid = models.CharField(max_length=255, verbose_name='接粉号Id')
external_userid = models.CharField(max_length=255, verbose_name='外部联系人Id', null=True, blank=True)
chat_id = models.CharField(max_length=255, verbose_name='群聊id', null=True, blank=True)
status = models.IntegerField(
verbose_name='发送状态0-未发送 1-已发送 2-因客户不是好友导致发送失败 3-因客户已经收到其他群发消息导致发送失败',
choices=JqrGrouMsgSendGroupMsgStatusChoices.choices,
null=True, blank=True)
send_time = models.BigIntegerField(verbose_name='发送时间', null=True, blank=True)
task_send_time = models.BigIntegerField(verbose_name='任务发送时间', null=True, blank=True)
chat_type = models.CharField(max_length=32, verbose_name='群发任务的类型',
default=JqrGroupMsgListChatTypeChoices.SINGLE,
choices=JqrGroupMsgListChatTypeChoices.choices)
ctime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
utime = models.DateTimeField(verbose_name='更新时间', auto_now=True)
class Meta:
db_table = 'jqr_groupmsgsendresult'
verbose_name = '群发成员执行结果'
verbose_name_plural = '群发成员执行结果'
ordering = ['-send_time']

0
apps/jqr/serializers.py Normal file
View File

0
apps/jqr/tasks.py Normal file
View File

3
apps/jqr/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

6
apps/jqr/urls.py Normal file
View File

@ -0,0 +1,6 @@
from rest_framework.routers import SimpleRouter
from . import views
router = SimpleRouter(trailing_slash=False)
urlpatterns = router.urls

0
apps/jqr/views.py Normal file
View File

5
deploy.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/bash
git pull origin master
docker rm -f yzk_wechat_event-api
docker rm -f yzk_wechat_event-celery_worker
docker compose up --build -d

30
docker-compose.yml Normal file
View File

@ -0,0 +1,30 @@
version: "3.9"
services:
api:
container_name: yzk_wechat_event-api
build:
context: .
dockerfile: ./Dockerfile
command: ./start
volumes:
- .:/app
ports:
- "8001:8000"
networks:
- yzk_wechat_event
celery_worker:
container_name: yzk_wechat_event-celery_worker
build:
context: .
dockerfile: ./Dockerfile
command: ./start-celeryworker
volumes:
- .:/app
networks:
- yzk_wechat_event
networks:
yzk_wechat_event:
driver: bridge

0
libs/__init__.py Normal file
View File

48
libs/dingding/dingding.py Normal file
View File

@ -0,0 +1,48 @@
import base64
import hashlib
import hmac
import logging
import time
import urllib.parse
import requests
logger = logging.getLogger('apps')
def get_timestamp_and_sign(secret: str):
timestamp = str(round(time.time() * 1000))
secret_enc = secret.encode('utf-8')
string_to_sign = f'{timestamp}\n{secret}'
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
return timestamp, sign
class DingDing(object):
@classmethod
def send_message(cls, text, webhook, secret):
headers = {
"Content-Type": "application/json",
"Charset": "UTF-8"
}
# 构建请求数据
data = {
"msgtype": "text",
"text": {
"content": text
},
"at": {
"isAtAll": True
}
}
timestamp, sign = get_timestamp_and_sign(secret)
url = f'{webhook}&timestamp={timestamp}&sign={sign}'
res = requests.post(json=data, url=url, headers=headers)
logger.info(f'钉钉消息发送--->{res.json()}')
res = res.json()
return res.get('errcode') == 0

1
libs/kz/__init__.py Normal file
View File

@ -0,0 +1 @@
from .kz import KZ

79
libs/kz/kz.py Normal file
View File

@ -0,0 +1,79 @@
import hashlib
import json
import logging
import urllib.parse
from django.conf import settings
import requests
loger = logging.getLogger('apps')
class KZ:
def __init__(self, appkey=settings.KZ.get('appkey'), secret=settings.KZ.get('secret')):
self.appkey = appkey
self.secret = secret
self.base_url = 'https://cloud.kuaizhan.com/api'
def sign_top_request(self, params, secret=None):
secret = secret or self.secret
# 第一步:检查参数是否已经排序
keys = sorted(params.keys())
# 第二步:把所有参数名和参数值串在一起
query = secret
for key in keys:
value = params[key]
if isinstance(value, bool):
value = json.dumps(value)
if key and str(key).strip() and value and str(value).strip() and key != "sign":
query += key + str(value)
query += secret
# 第三步使用MD5加密
return hashlib.md5(query.encode('utf-8')).hexdigest()
def gen_short_link(
self,
link,
appkey=None,
response_format='json',
callback=None,
expire=None,
domain=None,
use_domain_pool=None,
):
link = urllib.parse.quote(link)
params = {
'appKey': appkey or self.appkey,
'link': link,
'format': response_format,
'callback': callback,
'expire': expire,
'domain': domain,
'useDomainPool': use_domain_pool,
}
sign = self.sign_top_request(params, secret=self.secret)
params['sign'] = sign
url = f'{self.base_url}/v1/km/genShortLink'
res = requests.get(url, params)
data = res.json()
if data.get('code') == 0:
return True, data.get('url')
loger.error(f'获取快码失败---->{data}')
return False, data
def change_domain_https_forward(self, site_id=8081085619, https_forward=True, domain='elmbwc.kuaizhan.com'):
"""
API-开启域名Https跳转
"""
data = {
'appKey': self.appkey,
'siteId': site_id,
'httpsForward': https_forward,
'domain': domain
}
sign = self.sign_top_request(data)
data['sign'] = sign
url = f'{self.base_url}/v1/tbk/changeDomainHttpsForward'
res = requests.post(url, data=data)
print(res.json())

1
libs/topsdk/__init__.py Normal file
View File

@ -0,0 +1 @@
from .top import TopUtils

View File

View File

@ -0,0 +1,52 @@
from libs.topsdk.client import TopApiClient, BaseRequest
class Ability132:
def __init__(self, client: TopApiClient):
self._client = client
"""
批量发送消息
"""
def taobao_tmc_messages_produce(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
获取自定义用户分组列表
"""
def taobao_tmc_groups_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
删除指定的分组或分组下的用户
"""
def taobao_tmc_group_delete(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
为已开通用户添加用户分组
"""
def taobao_tmc_group_add(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
删除消息topic分组路由
"""
def taobao_tmc_topic_group_delete(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
topic分组路由
"""
def taobao_tmc_topic_group_add(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
确认消费消息的状态
"""
def taobao_tmc_messages_confirm(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
消费多条消息
"""
def taobao_tmc_messages_consume(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
TMC授权token
"""
def taobao_tmc_auth_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())

View File

@ -0,0 +1,43 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcAuthGetRequest(BaseRequest):
def __init__(
self,
group: str = None
):
"""
tmc组名
"""
self._group = group
@property
def group(self):
return self._group
@group.setter
def group(self, group):
if isinstance(group, str):
self._group = group
else:
raise TypeError("group must be str")
def get_api_name(self):
return "taobao.tmc.auth.get"
def to_dict(self):
request_dict = {}
if self._group is not None:
request_dict["group"] = convert_basic(self._group)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,81 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcGroupAddRequest(BaseRequest):
def __init__(
self,
group_name: str = None,
nicks: list = None,
user_platform: str = None
):
"""
分组名称同一个应用下需要保证唯一性最长32个字符添加分组后消息通道会为用户的消息分配独立分组但之前的消息还是存储于默认分组中不能以default开头default开头为系统默认组
"""
self._group_name = group_name
"""
用户昵称列表以半角逗号分隔支持子账号支持增量添加用户
"""
self._nicks = nicks
"""
用户所属于的平台类型tbUIC:淘宝用户; icbu: icbu用户;ae:ae用户
"""
self._user_platform = user_platform
@property
def group_name(self):
return self._group_name
@group_name.setter
def group_name(self, group_name):
if isinstance(group_name, str):
self._group_name = group_name
else:
raise TypeError("group_name must be str")
@property
def nicks(self):
return self._nicks
@nicks.setter
def nicks(self, nicks):
if isinstance(nicks, list):
self._nicks = nicks
else:
raise TypeError("nicks must be list")
@property
def user_platform(self):
return self._user_platform
@user_platform.setter
def user_platform(self, user_platform):
if isinstance(user_platform, str):
self._user_platform = user_platform
else:
raise TypeError("user_platform must be str")
def get_api_name(self):
return "taobao.tmc.group.add"
def to_dict(self):
request_dict = {}
if self._group_name is not None:
request_dict["group_name"] = convert_basic(self._group_name)
if self._nicks is not None:
request_dict["nicks"] = convert_basic_list(self._nicks)
if self._user_platform is not None:
request_dict["user_platform"] = convert_basic(self._user_platform)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,81 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcGroupDeleteRequest(BaseRequest):
def __init__(
self,
group_name: str = None,
nicks: list = None,
user_platform: str = None
):
"""
分组名称分组删除后用户的消息将会存储于默认分组中警告由于分组已经删除用户之前未消费的消息将无法再获取不能以default开头default开头为系统默认组
"""
self._group_name = group_name
"""
用户列表不传表示删除整个分组如果用户全部删除后也会自动删除整个分组
"""
self._nicks = nicks
"""
用户所属于的平台类型tbUIC:淘宝用户; icbu: icbu用户;ae:ae用户
"""
self._user_platform = user_platform
@property
def group_name(self):
return self._group_name
@group_name.setter
def group_name(self, group_name):
if isinstance(group_name, str):
self._group_name = group_name
else:
raise TypeError("group_name must be str")
@property
def nicks(self):
return self._nicks
@nicks.setter
def nicks(self, nicks):
if isinstance(nicks, list):
self._nicks = nicks
else:
raise TypeError("nicks must be list")
@property
def user_platform(self):
return self._user_platform
@user_platform.setter
def user_platform(self, user_platform):
if isinstance(user_platform, str):
self._user_platform = user_platform
else:
raise TypeError("user_platform must be str")
def get_api_name(self):
return "taobao.tmc.group.delete"
def to_dict(self):
request_dict = {}
if self._group_name is not None:
request_dict["group_name"] = convert_basic(self._group_name)
if self._nicks is not None:
request_dict["nicks"] = convert_basic_list(self._nicks)
if self._user_platform is not None:
request_dict["user_platform"] = convert_basic(self._user_platform)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,81 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcGroupsGetRequest(BaseRequest):
def __init__(
self,
group_names: list = None,
page_no: int = None,
page_size: int = None
):
"""
要查询分组的名称多个分组用半角逗号分隔不传代表查询所有分组信息但不会返回组下面的用户信息如果应用没有设置分组则返回空组名不能以default开头default开头是系统默认的组
"""
self._group_names = group_names
"""
页码
"""
self._page_no = page_no
"""
每页返回多少个分组
"""
self._page_size = page_size
@property
def group_names(self):
return self._group_names
@group_names.setter
def group_names(self, group_names):
if isinstance(group_names, list):
self._group_names = group_names
else:
raise TypeError("group_names must be list")
@property
def page_no(self):
return self._page_no
@page_no.setter
def page_no(self, page_no):
if isinstance(page_no, int):
self._page_no = page_no
else:
raise TypeError("page_no must be int")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
def get_api_name(self):
return "taobao.tmc.groups.get"
def to_dict(self):
request_dict = {}
if self._group_names is not None:
request_dict["group_names"] = convert_basic_list(self._group_names)
if self._page_no is not None:
request_dict["page_no"] = convert_basic(self._page_no)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,81 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcMessagesConfirmRequest(BaseRequest):
def __init__(
self,
group_name: str = None,
s_message_ids: list = None,
f_message_ids: list = None
):
"""
分组名称不传代表默认分组
"""
self._group_name = group_name
"""
处理成功的消息ID列表 最大 200个ID
"""
self._s_message_ids = s_message_ids
"""
处理失败的消息ID列表--已废弃无需传此字段
"""
self._f_message_ids = f_message_ids
@property
def group_name(self):
return self._group_name
@group_name.setter
def group_name(self, group_name):
if isinstance(group_name, str):
self._group_name = group_name
else:
raise TypeError("group_name must be str")
@property
def s_message_ids(self):
return self._s_message_ids
@s_message_ids.setter
def s_message_ids(self, s_message_ids):
if isinstance(s_message_ids, list):
self._s_message_ids = s_message_ids
else:
raise TypeError("s_message_ids must be list")
@property
def f_message_ids(self):
return self._f_message_ids
@f_message_ids.setter
def f_message_ids(self, f_message_ids):
if isinstance(f_message_ids, list):
self._f_message_ids = f_message_ids
else:
raise TypeError("f_message_ids must be list")
def get_api_name(self):
return "taobao.tmc.messages.confirm"
def to_dict(self):
request_dict = {}
if self._group_name is not None:
request_dict["group_name"] = convert_basic(self._group_name)
if self._s_message_ids is not None:
request_dict["s_message_ids"] = convert_basic_list(self._s_message_ids)
if self._f_message_ids is not None:
request_dict["f_message_ids"] = convert_basic_list(self._f_message_ids)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,62 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcMessagesConsumeRequest(BaseRequest):
def __init__(
self,
group_name: str = None,
quantity: int = None
):
"""
用户分组名称不传表示消费默认分组如果应用没有设置用户分组传入分组名称将会返回错误
"""
self._group_name = group_name
"""
每次批量消费消息的条数最小值10最大值200
"""
self._quantity = quantity
@property
def group_name(self):
return self._group_name
@group_name.setter
def group_name(self, group_name):
if isinstance(group_name, str):
self._group_name = group_name
else:
raise TypeError("group_name must be str")
@property
def quantity(self):
return self._quantity
@quantity.setter
def quantity(self, quantity):
if isinstance(quantity, int):
self._quantity = quantity
else:
raise TypeError("quantity must be int")
def get_api_name(self):
return "taobao.tmc.messages.consume"
def to_dict(self):
request_dict = {}
if self._group_name is not None:
request_dict["group_name"] = convert_basic(self._group_name)
if self._quantity is not None:
request_dict["quantity"] = convert_basic(self._quantity)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,73 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcMessagesProduceRequest(BaseRequest):
def __init__(
self,
messages: list = None
):
"""
tmc消息列表, 最多50条元素结构与taobao.tmc.message.produce一致用json表示的消息列表例如[{"content": "{\"tid\":1234554321,\"status\":\"X_LOGISTICS_PRINTED\",\"action_time\":\"2014-08-08 18:24:00\",\"seller_nick\": \"向阳aa\",\"operator\":\"小张\"}","topic": "taobao_jds_TradeTrace"},{"content": "{\"tid\":1234554321,\"status\":\"X_LOGISTICS_PRINTED\",\"action_time\":\"2014-08-08 18:24:00\",\"seller_nick\": \"向阳aa\",\"operator\":\"小张\"}","topic": "taobao_jds_TradeTrace"}]
"""
self._messages = messages
@property
def messages(self):
return self._messages
@messages.setter
def messages(self, messages):
if isinstance(messages, list):
self._messages = messages
else:
raise TypeError("messages must be list")
def get_api_name(self):
return "taobao.tmc.messages.produce"
def to_dict(self):
request_dict = {}
if self._messages is not None:
request_dict["messages"] = convert_struct_list(self._messages)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class TaobaoTmcMessagesProduceTmcPublishMessage:
def __init__(
self,
content: str = None,
json_ex_content: str = None,
target_app_key: str = None,
target_group: str = None,
topic: str = None
):
"""
消息内容的JSON表述必须按照topic的定义来填充
"""
self.content = content
"""
消息的扩增属性用json格式表示
"""
self.json_ex_content = json_ex_content
"""
直发消息需要传入目标appkey
"""
self.target_app_key = target_app_key
"""
目标分组
"""
self.target_group = target_group
"""
消息类型
"""
self.topic = topic

View File

@ -0,0 +1,62 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcTopicGroupAddRequest(BaseRequest):
def __init__(
self,
group_name: str = None,
topics: list = None
):
"""
消息分组名如果不存在会自动创建
"""
self._group_name = group_name
"""
消息topic名称多个以逗号(,)分割
"""
self._topics = topics
@property
def group_name(self):
return self._group_name
@group_name.setter
def group_name(self, group_name):
if isinstance(group_name, str):
self._group_name = group_name
else:
raise TypeError("group_name must be str")
@property
def topics(self):
return self._topics
@topics.setter
def topics(self, topics):
if isinstance(topics, list):
self._topics = topics
else:
raise TypeError("topics must be list")
def get_api_name(self):
return "taobao.tmc.topic.group.add"
def to_dict(self):
request_dict = {}
if self._group_name is not None:
request_dict["group_name"] = convert_basic(self._group_name)
if self._topics is not None:
request_dict["topics"] = convert_basic_list(self._topics)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,81 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcTopicGroupDeleteRequest(BaseRequest):
def __init__(
self,
group_name: str = None,
group_id: int = None,
topics: list = None
):
"""
消息分组名
"""
self._group_name = group_name
"""
消息分组Id一般不用填写如果分组已经被删除则根据问题排查工具返回的ID删除路由关系
"""
self._group_id = group_id
"""
消息topic名称多个以逗号(,)分割
"""
self._topics = topics
@property
def group_name(self):
return self._group_name
@group_name.setter
def group_name(self, group_name):
if isinstance(group_name, str):
self._group_name = group_name
else:
raise TypeError("group_name must be str")
@property
def group_id(self):
return self._group_id
@group_id.setter
def group_id(self, group_id):
if isinstance(group_id, int):
self._group_id = group_id
else:
raise TypeError("group_id must be int")
@property
def topics(self):
return self._topics
@topics.setter
def topics(self, topics):
if isinstance(topics, list):
self._topics = topics
else:
raise TypeError("topics must be list")
def get_api_name(self):
return "taobao.tmc.topic.group.delete"
def to_dict(self):
request_dict = {}
if self._group_name is not None:
request_dict["group_name"] = convert_basic(self._group_name)
if self._group_id is not None:
request_dict["group_id"] = convert_basic(self._group_id)
if self._topics is not None:
request_dict["topics"] = convert_basic_list(self._topics)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

132
libs/topsdk/client.py Normal file
View File

@ -0,0 +1,132 @@
from datetime import datetime
from urllib.parse import urlencode
from abc import ABC, abstractmethod
import requests
import json
from libs.topsdk.util import get_sign
P_APPKEY = "app_key"
P_METHOD = "method"
P_SESSION = "session"
P_VERSION = "v"
P_FORMAT = "format"
P_TIMESTAMP = "timestamp"
P_SIGN = "sign"
P_SIGN_METHOD = "sign_method"
P_PARTNER_ID = "partner_id"
P_SIMPLIFY = "simplify"
P_CODE = "code"
P_SUB_CODE = "sub_code"
P_MSG = "msg"
P_SUB_MSG = "sub_msg"
P_REQUEST_ID = "request_id"
class TopApiClient:
def __init__(self, appkey: str, app_sercet: str, top_gateway_url: str, simplify: bool = True, timeout=10,
proxy=None, verify_ssl=True):
self.appkey = appkey
self.app_sercet = app_sercet
self.top_gateway_url = top_gateway_url
self.format = "json"
self.version = "2.0"
self.sign_method = "hmac-sha256"
self.simplify = simplify
self.timeout = timeout
self.proxy = proxy
self.verify_ssl = verify_ssl
def execute(self, api_code: str, request_dict: dict, file_dict: dict):
return self.execute_with_session(api_code, request_dict, file_dict, "")
def execute_with_session(self, api_code: str, request_dict: dict, file_dict: dict, session: str):
public_param = {
P_METHOD: api_code,
P_APPKEY: self.appkey,
P_FORMAT: self.format,
P_VERSION: self.version,
P_TIMESTAMP: datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
P_SIGN_METHOD: self.sign_method,
P_SIMPLIFY: str(self.simplify).lower(),
P_PARTNER_ID: "new_python3_sdk"
}
if session:
public_param[P_SESSION] = session
sign = get_sign(public_param.copy(), request_dict, self.app_sercet, self.sign_method)
public_param[P_SIGN] = sign
url = self.top_gateway_url + "?" + urlencode(public_param)
if file_dict:
response = requests.post(url, data=request_dict, files=file_dict, timeout=self.timeout, proxies=self.proxy,
verify=self.verify_ssl)
else:
response = requests.post(url, data=request_dict, timeout=self.timeout, proxies=self.proxy,
verify=self.verify_ssl)
if response.status_code != 200:
raise Exception('invalid http status ' + str(response.status_code) + ',detail body:' + response.text)
jsonobj = json.loads(response.text)
if "error_response" in jsonobj:
error = TopException()
if P_CODE in jsonobj["error_response"]:
error.top_code = jsonobj["error_response"][P_CODE]
if P_MSG in jsonobj["error_response"]:
error.msg = jsonobj["error_response"][P_MSG]
if P_SUB_CODE in jsonobj["error_response"]:
error.sub_code = jsonobj["error_response"][P_SUB_CODE]
if P_SUB_MSG in jsonobj["error_response"]:
error.sub_msg = jsonobj["error_response"][P_SUB_MSG]
if P_REQUEST_ID in jsonobj["error_response"]:
error.request_id = jsonobj["error_response"][P_REQUEST_ID]
raise error
return jsonobj
class TopException(Exception):
# ===========================================================================
# 业务异常类
# ===========================================================================
def __init__(self):
self.top_code = None
self.msg = None
self.sub_code = None
self.sub_msg = None
self.request_id = None
def mix_str(self, pstr):
if (isinstance(pstr, str)):
return pstr
elif (isinstance(pstr, str)):
return pstr.encode('utf-8')
else:
return str(pstr)
def __str__(self, *args, **kwargs) -> str:
sb = "top_code=" + self.mix_str(self.top_code) + \
" msg=" + self.mix_str(self.msg) + \
" sub_code=" + self.mix_str(self.sub_code) + \
" sub_msg=" + self.mix_str(self.sub_msg) + \
" request_id=" + self.mix_str(self.request_id)
return sb
class BaseRequest(ABC):
@abstractmethod
def to_dict(self):
"""
TOPAPI Request类需要实现此方法, 转换Request对象为dict
"""
@abstractmethod
def get_api_name(self):
"""
TOPAPI Request类需要实现此方法, 获取api名称
"""
@abstractmethod
def get_file_param_dict(self):
"""
TOPAPI Request类需要实现此方法, 获取文件类型dict
"""

View File

View File

@ -0,0 +1,187 @@
from libs.topsdk.client import TopApiClient, BaseRequest
class Defaultability:
def __init__(self, client: TopApiClient):
self._client = client
"""
本地生活爆爆团选品筛选集合
"""
def alibaba_alsc_union_kb_bbt_item_promotion_filter_list(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟爆爆团商品详情
"""
def alibaba_alsc_union_kb_bbt_item_detail_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟爆爆团商品门店关系
"""
def alibaba_alsc_union_kb_bbt_item_store_relation_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟爆爆团门店详情
"""
def alibaba_alsc_union_kb_bbt_item_store_detail_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体平台口碑选品筛选项集合
"""
def alibaba_alsc_union_kb_item_promotion_filter_list(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广位查询
"""
def alibaba_alsc_union_media_zone_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体平台口碑选品
"""
def alibaba_alsc_union_kb_item_promotion(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
加密方法
"""
def alibaba_alsc_union_kb_common_encrypt(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广位创建
"""
def alibaba_alsc_union_media_zone_add(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟口碑商品列表
"""
def alibaba_alsc_union_kb_item_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
openapi预下单订单支付
"""
def alibaba_alsc_union_kb_order_pay(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广口碑CPA用户反作弊订单数据报表
"""
def alibaba_alsc_union_kbcpa_punish_order_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟媒体出资活动红包发放
"""
def alibaba_alsc_union_eleme_media_activity_coupon_send(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
获取用户已开通消息
"""
def taobao_tmc_user_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟饿了么单店推广店铺列表
"""
def alibaba_alsc_union_eleme_promotion_storepromotion_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟饿了么单店推广单店铺查询
"""
def alibaba_alsc_union_eleme_promotion_storepromotion_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟饿了么推广官方活动查询
"""
def alibaba_alsc_union_eleme_promotion_officialactivity_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
发布单条消息
"""
def taobao_tmc_message_produce(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广口碑CPA用户维权订单数据报表
"""
def alibaba_alsc_union_kbcpa_refund_order_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟口碑商户列表
"""
def alibaba_alsc_union_kb_store_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体创建商品推广链接
"""
def alibaba_alsc_union_kb_item_promotion_share_create(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟口碑门店商品列表
"""
def alibaba_alsc_union_kb_store_item_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
取消用户的消息服务
"""
def taobao_tmc_user_cancel(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟爆爆团商品列表
"""
def alibaba_alsc_union_kb_bbt_item_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
为已授权的用户开通消息服务
"""
def taobao_tmc_user_permit(self, request: BaseRequest, session: str):
return self._client.execute_with_session(request.get_api_name(), request.to_dict(), request.get_file_param_dict(), session)
"""
openapi订单创建
"""
def alibaba_alsc_union_kb_order_create(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
openapi订单查询
"""
def alibaba_alsc_union_kb_order_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
openapi订单售中退
"""
def alibaba_alsc_union_kb_order_refund(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟推广链接推广对象解析
"""
def alibaba_alsc_union_promotion_link_analyze(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广订单明细查询
"""
def alibaba_alsc_union_kbcpa_order_details_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟口碑商品详情
"""
def alibaba_alsc_union_kb_item_detail_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟口碑商品门店关系
"""
def alibaba_alsc_union_kb_item_store_relation_query(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广订单明细报表查询
"""
def alibaba_alsc_union_kbcpx_positive_order_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地联盟口碑门店详情
"""
def alibaba_alsc_union_kb_item_store_detail_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广用户维权订单数据报表
"""
def alibaba_alsc_union_kbcpx_refund_order_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())
"""
本地生活媒体推广用户反作弊订单数据报表
"""
def alibaba_alsc_union_kbcpx_punish_order_get(self, request: BaseRequest):
return self._client.execute(request.get_api_name(), request.to_dict(), request.get_file_param_dict())

View File

@ -0,0 +1,58 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionElemeMediaActivityCouponSendRequest(BaseRequest):
def __init__(
self,
send_request: object = None
):
"""
请求对象
"""
self._send_request = send_request
@property
def send_request(self):
return self._send_request
@send_request.setter
def send_request(self, send_request):
if isinstance(send_request, object):
self._send_request = send_request
else:
raise TypeError("send_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.eleme.media.activity.coupon.send"
def to_dict(self):
request_dict = {}
if self._send_request is not None:
request_dict["send_request"] = convert_struct(self._send_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionElemeMediaActivityCouponSendMediaActivityCouponSendRequest:
def __init__(
self,
mobile: str = None,
media_activity_id: str = None
):
"""
领券手机号
"""
self.mobile = mobile
"""
媒体出资活动ID
"""
self.media_activity_id = media_activity_id

View File

@ -0,0 +1,73 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionElemePromotionOfficialactivityGetRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.eleme.promotion.officialactivity.get"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionElemePromotionOfficialactivityGetActivityRequest(AlibabaAlscUnionElemePromotionOfficialactivityGetRequest):
def __init__(
self,
pid: str = None,
activity_id: str = None,
sid: str = None,
include_wx_img: bool = None,
include_qr_code: bool = None
):
"""
渠道PID
"""
self.pid = pid
"""
活动ID
"""
self.activity_id = activity_id
"""
三方会员id长度限制50
"""
self.sid = sid
"""
是否返回微信推广图片
"""
self.include_wx_img = include_wx_img
"""
是否包含二维码如果为false不返回二维码和图片只有链接
"""
self.include_qr_code = include_qr_code

View File

@ -0,0 +1,78 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionElemePromotionStorepromotionGetRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.eleme.promotion.storepromotion.get"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionElemePromotionStorepromotionGetSingleStorePromotionRequest:
def __init__(
self,
pid: str = None,
shop_id: str = None,
activity_id: str = None,
sid: str = None,
include_wx_img: bool = None,
media_activity_id: str = None
):
"""
渠道PID
"""
self.pid = pid
"""
门店ID加密具有时效性建议每天更新一次
"""
self.shop_id = shop_id
"""
活动ID
"""
self.activity_id = activity_id
"""
三方扩展id
"""
self.sid = sid
"""
是否返回微信推广图片
"""
self.include_wx_img = include_wx_img
"""
媒体出资活动ID
"""
self.media_activity_id = media_activity_id

View File

@ -0,0 +1,143 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionElemePromotionStorepromotionQueryRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.eleme.promotion.storepromotion.query"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionElemePromotionStorepromotionQueryPromotionQueryRequest:
def __init__(
self,
session_id: str = None,
pid: str = None,
longitude: str = None,
latitude: str = None,
city_id: str = None,
sort_type: str = None,
in_activity: bool = None,
has_bonus_stock: bool = None,
min_commission_rate: str = None,
page_size: int = None,
sid: str = None,
biz_type: str = None,
recall_overlay_coupon: bool = None,
filter_has_overlay_coupon: bool = None,
min_overlay_coupon_amount: str = None,
filter_first_categories: str = None,
filter_one_point_five_categories: str = None,
media_activity_id: str = None,
search_content: str = None
):
"""
会话ID分页场景首次请求结果返回后续请求必须携带服务根据session_id相同请求次数自动翻页返回
"""
self.session_id = session_id
"""
渠道PID
"""
self.pid = pid
"""
经度
"""
self.longitude = longitude
"""
纬度
"""
self.latitude = latitude
"""
城市编码只用于经纬度覆盖多个城市时过滤
"""
self.city_id = city_id
"""
排序类型默认normal排序规则包括:{"normal":"佣金倒序","distance":"距离由近到远","commission":"佣金倒序","monthlySale":"月销量","couponAmount":"叠加券金额倒序","activityReward":"奖励金金额倒序","commissionRate":"佣金比例倒序"}
"""
self.sort_type = sort_type
"""
是否参与奖励金活动默认false不做过滤
"""
self.in_activity = in_activity
"""
否当前有c端奖励金活动库存默认false不做过滤
"""
self.has_bonus_stock = has_bonus_stock
"""
店铺佣金比例下限代表筛选店铺全店佣金大于等于0.01的店铺
"""
self.min_commission_rate = min_commission_rate
"""
每页数量1~20默认20
"""
self.page_size = page_size
"""
三方扩展id
"""
self.sid = sid
"""
指定召回供给枚举
"""
self.biz_type = biz_type
"""
in_activity=false的条件下召回的非奖励金活动cps商家是否需要带出叠加券
"""
self.recall_overlay_coupon = recall_overlay_coupon
"""
filter_has_overlay_coupon=true的条件下限定只召回带叠加券的cps商户
"""
self.filter_has_overlay_coupon = filter_has_overlay_coupon
"""
filter_has_overlay_coupon=true的情况下限定的最小叠加券券金额单位元
"""
self.min_overlay_coupon_amount = min_overlay_coupon_amount
"""
以一级类目进行类目限定,或者|进行类目分隔
"""
self.filter_first_categories = filter_first_categories
"""
1.5级类目查询"|"分隔
"""
self.filter_one_point_five_categories = filter_one_point_five_categories
"""
媒体出资活动ID
"""
self.media_activity_id = media_activity_id
"""
检索内容支持门店名称
"""
self.search_content = search_content

View File

@ -0,0 +1,58 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbBbtItemDetailGetRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
爆爆团商品详情rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.bbt.item.detail.get"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbBbtItemDetailGetBbtItemDetailRequest:
def __init__(
self,
item_id: str = None,
city_id: str = None
):
"""
品ID
"""
self.item_id = item_id
"""
城市ID
"""
self.city_id = city_id

View File

@ -0,0 +1,81 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbBbtItemPromotionFilterListRequest(BaseRequest):
def __init__(
self,
filter_type: str = None,
biz_type: str = None,
biz_unit: int = None
):
"""
获取筛选项集合的类型category类目列表city城市列表
"""
self._filter_type = filter_type
"""
产品线固定bbt
"""
self._biz_type = biz_type
"""
固定2cps
"""
self._biz_unit = biz_unit
@property
def filter_type(self):
return self._filter_type
@filter_type.setter
def filter_type(self, filter_type):
if isinstance(filter_type, str):
self._filter_type = filter_type
else:
raise TypeError("filter_type must be str")
@property
def biz_type(self):
return self._biz_type
@biz_type.setter
def biz_type(self, biz_type):
if isinstance(biz_type, str):
self._biz_type = biz_type
else:
raise TypeError("biz_type must be str")
@property
def biz_unit(self):
return self._biz_unit
@biz_unit.setter
def biz_unit(self, biz_unit):
if isinstance(biz_unit, int):
self._biz_unit = biz_unit
else:
raise TypeError("biz_unit must be int")
def get_api_name(self):
return "alibaba.alsc.union.kb.bbt.item.promotion.filter.list"
def to_dict(self):
request_dict = {}
if self._filter_type is not None:
request_dict["filter_type"] = convert_basic(self._filter_type)
if self._biz_type is not None:
request_dict["biz_type"] = convert_basic(self._biz_type)
if self._biz_unit is not None:
request_dict["biz_unit"] = convert_basic(self._biz_unit)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,88 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbBbtItemQueryRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
爆爆团商品查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.bbt.item.query"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbBbtItemQueryBbtItemQueryRequest:
def __init__(
self,
page_number: int = None,
sort_type: int = None,
session_id: str = None,
category2_id: str = None,
page_size: int = None,
city_id: str = None,
include_phone: bool = None,
tripartite_appkeys: str = None
):
"""
页码
"""
self.page_number = page_number
"""
排序类型0-时间倒序1-佣金比例倒序
"""
self.sort_type = sort_type
"""
会话ID
"""
self.session_id = session_id
"""
二级类目ID
"""
self.category2_id = category2_id
"""
每页数目
"""
self.page_size = page_size
"""
城市ID
"""
self.city_id = city_id
"""
是否返回需要手机号的商品false仅返回不需要手机号的品true全部返回
"""
self.include_phone = include_phone
"""
三方供给标识","隔开不为空时include_phone必须为true
"""
self.tripartite_appkeys = tripartite_appkeys

View File

@ -0,0 +1,53 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbBbtItemStoreDetailGetRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
门店详情查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.bbt.item.store.detail.get"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbBbtItemStoreDetailGetBbtItemShopDetailRequest:
def __init__(
self,
store_id: str = None
):
"""
门店ID
"""
self.store_id = store_id

View File

@ -0,0 +1,58 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbBbtItemStoreRelationQueryRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
商品门店关系查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.bbt.item.store.relation.query"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbBbtItemStoreRelationQueryBbtItemShopRelationRequest:
def __init__(
self,
item_id: str = None,
city_id: str = None
):
"""
商品ID
"""
self.item_id = item_id
"""
城市ID
"""
self.city_id = city_id

View File

@ -0,0 +1,53 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbCommonEncryptRequest(BaseRequest):
def __init__(
self,
encrypt_model: object = None
):
"""
待加密对象
"""
self._encrypt_model = encrypt_model
@property
def encrypt_model(self):
return self._encrypt_model
@encrypt_model.setter
def encrypt_model(self, encrypt_model):
if isinstance(encrypt_model, object):
self._encrypt_model = encrypt_model
else:
raise TypeError("encrypt_model must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.common.encrypt"
def to_dict(self):
request_dict = {}
if self._encrypt_model is not None:
request_dict["encrypt_model"] = convert_struct(self._encrypt_model)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbCommonEncryptBlowfishModel:
def __init__(
self,
text: str = None
):
"""
待加密字符串
"""
self.text = text

View File

@ -0,0 +1,63 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbItemDetailGetRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
商品详情rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.item.detail.get"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbItemDetailGetKbItemDetailRequest:
def __init__(
self,
item_id: str = None,
city_id: str = None,
biz_type: str = None
):
"""
商品ID
"""
self.item_id = item_id
"""
城市ID
"""
self.city_id = city_id
"""
业务类型cps/cpa
"""
self.biz_type = biz_type

View File

@ -0,0 +1,62 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbItemPromotionFilterListRequest(BaseRequest):
def __init__(
self,
filter_type: str = None,
biz_unit: int = None
):
"""
获取筛选项集合的类型
"""
self._filter_type = filter_type
"""
1-cpa,2-cps.默认不填为cpa
"""
self._biz_unit = biz_unit
@property
def filter_type(self):
return self._filter_type
@filter_type.setter
def filter_type(self, filter_type):
if isinstance(filter_type, str):
self._filter_type = filter_type
else:
raise TypeError("filter_type must be str")
@property
def biz_unit(self):
return self._biz_unit
@biz_unit.setter
def biz_unit(self, biz_unit):
if isinstance(biz_unit, int):
self._biz_unit = biz_unit
else:
raise TypeError("biz_unit must be int")
def get_api_name(self):
return "alibaba.alsc.union.kb.item.promotion.filter.list"
def to_dict(self):
request_dict = {}
if self._filter_type is not None:
request_dict["filter_type"] = convert_basic(self._filter_type)
if self._biz_unit is not None:
request_dict["biz_unit"] = convert_basic(self._biz_unit)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,252 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbItemPromotionRequest(BaseRequest):
def __init__(
self,
page_number: int = None,
sort_type: str = None,
page_size: int = None,
pid: str = None,
session_id: str = None,
settle_type: int = None,
filter_category_ids: str = None,
filter_city_ids: str = None,
search_keyword: str = None,
hit_item_ids: str = None,
sid: str = None,
item_type: int = None
):
"""
页码默认第一页取值范围1~50
"""
self._page_number = page_number
"""
排序类型 normal-默认排序 reservePrice-折后价从高到低 commission-佣金从高到低 totalSales-月销量从高到低
"""
self._sort_type = sort_type
"""
每页返回数据大小默认20最大返回20
"""
self._page_size = page_size
"""
推广参数
"""
self._pid = pid
"""
用来分页翻页时将上一次结果的sessionId带下来
"""
self._session_id = session_id
"""
推广物料结算模型 1-cpa 2-cps3spu
"""
self._settle_type = settle_type
"""
类目筛选多个类目逗号分隔通过alibaba.alsc.union.kb.item.promotion.filter.list获取
"""
self._filter_category_ids = filter_category_ids
"""
城市id(国标)筛选多个城市逗号分隔通过alibaba.alsc.union.kb.item.promotion.filter.list获取
"""
self._filter_city_ids = filter_city_ids
"""
关键词搜索多个词逗号分割
"""
self._search_keyword = search_keyword
"""
指定itemId查询推广信息多个逗号分割
"""
self._hit_item_ids = hit_item_ids
"""
第三方会员id扩展
"""
self._sid = sid
"""
商品可售卖的端类型1支付宝端商品2微信端商品3全部
"""
self._item_type = item_type
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def sort_type(self):
return self._sort_type
@sort_type.setter
def sort_type(self, sort_type):
if isinstance(sort_type, str):
self._sort_type = sort_type
else:
raise TypeError("sort_type must be str")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
@property
def session_id(self):
return self._session_id
@session_id.setter
def session_id(self, session_id):
if isinstance(session_id, str):
self._session_id = session_id
else:
raise TypeError("session_id must be str")
@property
def settle_type(self):
return self._settle_type
@settle_type.setter
def settle_type(self, settle_type):
if isinstance(settle_type, int):
self._settle_type = settle_type
else:
raise TypeError("settle_type must be int")
@property
def filter_category_ids(self):
return self._filter_category_ids
@filter_category_ids.setter
def filter_category_ids(self, filter_category_ids):
if isinstance(filter_category_ids, str):
self._filter_category_ids = filter_category_ids
else:
raise TypeError("filter_category_ids must be str")
@property
def filter_city_ids(self):
return self._filter_city_ids
@filter_city_ids.setter
def filter_city_ids(self, filter_city_ids):
if isinstance(filter_city_ids, str):
self._filter_city_ids = filter_city_ids
else:
raise TypeError("filter_city_ids must be str")
@property
def search_keyword(self):
return self._search_keyword
@search_keyword.setter
def search_keyword(self, search_keyword):
if isinstance(search_keyword, str):
self._search_keyword = search_keyword
else:
raise TypeError("search_keyword must be str")
@property
def hit_item_ids(self):
return self._hit_item_ids
@hit_item_ids.setter
def hit_item_ids(self, hit_item_ids):
if isinstance(hit_item_ids, str):
self._hit_item_ids = hit_item_ids
else:
raise TypeError("hit_item_ids must be str")
@property
def sid(self):
return self._sid
@sid.setter
def sid(self, sid):
if isinstance(sid, str):
self._sid = sid
else:
raise TypeError("sid must be str")
@property
def item_type(self):
return self._item_type
@item_type.setter
def item_type(self, item_type):
if isinstance(item_type, int):
self._item_type = item_type
else:
raise TypeError("item_type must be int")
def get_api_name(self):
return "alibaba.alsc.union.kb.item.promotion"
def to_dict(self):
request_dict = {}
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._sort_type is not None:
request_dict["sort_type"] = convert_basic(self._sort_type)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
if self._session_id is not None:
request_dict["session_id"] = convert_basic(self._session_id)
if self._settle_type is not None:
request_dict["settle_type"] = convert_basic(self._settle_type)
if self._filter_category_ids is not None:
request_dict["filter_category_ids"] = convert_basic(self._filter_category_ids)
if self._filter_city_ids is not None:
request_dict["filter_city_ids"] = convert_basic(self._filter_city_ids)
if self._search_keyword is not None:
request_dict["search_keyword"] = convert_basic(self._search_keyword)
if self._hit_item_ids is not None:
request_dict["hit_item_ids"] = convert_basic(self._hit_item_ids)
if self._sid is not None:
request_dict["sid"] = convert_basic(self._sid)
if self._item_type is not None:
request_dict["item_type"] = convert_basic(self._item_type)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,214 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbItemPromotionShareCreateRequest(BaseRequest):
def __init__(
self,
pid: str = None,
item_id: str = None,
biz_unit: int = None,
include_mini_qr_code: bool = None,
include_mini_qr_code_hyaline: bool = None,
include_img_url: bool = None,
sid: str = None,
include_wx_img_url: bool = None,
include_alipay_img_url: bool = None,
include_alipay_wathword: bool = None
):
"""
推广位pid
"""
self._pid = pid
"""
商品ID默认CPA的品如果推广其他业务单元的品请填写对应的biz_unit
"""
self._item_id = item_id
"""
业务单元1-CPA2-CPS3-SPU默认1-CPA
"""
self._biz_unit = biz_unit
"""
废弃
"""
self._include_mini_qr_code = include_mini_qr_code
"""
废弃
"""
self._include_mini_qr_code_hyaline = include_mini_qr_code_hyaline
"""
废弃
"""
self._include_img_url = include_img_url
"""
第三方会员id扩展
"""
self._sid = sid
"""
是否合成微信推广图
"""
self._include_wx_img_url = include_wx_img_url
"""
是否合成支付宝推广图
"""
self._include_alipay_img_url = include_alipay_img_url
"""
是否返回吱口令
"""
self._include_alipay_wathword = include_alipay_wathword
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
@property
def item_id(self):
return self._item_id
@item_id.setter
def item_id(self, item_id):
if isinstance(item_id, str):
self._item_id = item_id
else:
raise TypeError("item_id must be str")
@property
def biz_unit(self):
return self._biz_unit
@biz_unit.setter
def biz_unit(self, biz_unit):
if isinstance(biz_unit, int):
self._biz_unit = biz_unit
else:
raise TypeError("biz_unit must be int")
@property
def include_mini_qr_code(self):
return self._include_mini_qr_code
@include_mini_qr_code.setter
def include_mini_qr_code(self, include_mini_qr_code):
if isinstance(include_mini_qr_code, bool):
self._include_mini_qr_code = include_mini_qr_code
else:
raise TypeError("include_mini_qr_code must be bool")
@property
def include_mini_qr_code_hyaline(self):
return self._include_mini_qr_code_hyaline
@include_mini_qr_code_hyaline.setter
def include_mini_qr_code_hyaline(self, include_mini_qr_code_hyaline):
if isinstance(include_mini_qr_code_hyaline, bool):
self._include_mini_qr_code_hyaline = include_mini_qr_code_hyaline
else:
raise TypeError("include_mini_qr_code_hyaline must be bool")
@property
def include_img_url(self):
return self._include_img_url
@include_img_url.setter
def include_img_url(self, include_img_url):
if isinstance(include_img_url, bool):
self._include_img_url = include_img_url
else:
raise TypeError("include_img_url must be bool")
@property
def sid(self):
return self._sid
@sid.setter
def sid(self, sid):
if isinstance(sid, str):
self._sid = sid
else:
raise TypeError("sid must be str")
@property
def include_wx_img_url(self):
return self._include_wx_img_url
@include_wx_img_url.setter
def include_wx_img_url(self, include_wx_img_url):
if isinstance(include_wx_img_url, bool):
self._include_wx_img_url = include_wx_img_url
else:
raise TypeError("include_wx_img_url must be bool")
@property
def include_alipay_img_url(self):
return self._include_alipay_img_url
@include_alipay_img_url.setter
def include_alipay_img_url(self, include_alipay_img_url):
if isinstance(include_alipay_img_url, bool):
self._include_alipay_img_url = include_alipay_img_url
else:
raise TypeError("include_alipay_img_url must be bool")
@property
def include_alipay_wathword(self):
return self._include_alipay_wathword
@include_alipay_wathword.setter
def include_alipay_wathword(self, include_alipay_wathword):
if isinstance(include_alipay_wathword, bool):
self._include_alipay_wathword = include_alipay_wathword
else:
raise TypeError("include_alipay_wathword must be bool")
def get_api_name(self):
return "alibaba.alsc.union.kb.item.promotion.share.create"
def to_dict(self):
request_dict = {}
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
if self._item_id is not None:
request_dict["item_id"] = convert_basic(self._item_id)
if self._biz_unit is not None:
request_dict["biz_unit"] = convert_basic(self._biz_unit)
if self._include_mini_qr_code is not None:
request_dict["include_mini_qr_code"] = convert_basic(self._include_mini_qr_code)
if self._include_mini_qr_code_hyaline is not None:
request_dict["include_mini_qr_code_hyaline"] = convert_basic(self._include_mini_qr_code_hyaline)
if self._include_img_url is not None:
request_dict["include_img_url"] = convert_basic(self._include_img_url)
if self._sid is not None:
request_dict["sid"] = convert_basic(self._sid)
if self._include_wx_img_url is not None:
request_dict["include_wx_img_url"] = convert_basic(self._include_wx_img_url)
if self._include_alipay_img_url is not None:
request_dict["include_alipay_img_url"] = convert_basic(self._include_alipay_img_url)
if self._include_alipay_wathword is not None:
request_dict["include_alipay_wathword"] = convert_basic(self._include_alipay_wathword)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,252 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbItemQueryRequest(BaseRequest):
def __init__(
self,
page_number: int = None,
page_size: int = None,
session_id: str = None,
biz_type: str = None,
sort_type: str = None,
pid: str = None,
tb_category_2_ids: str = None,
tb_category_3_ids: str = None,
city_id: str = None,
longitude: str = None,
latitude: str = None,
range: int = None
):
"""
页码默认1
"""
self._page_number = page_number
"""
每页数目默认10
"""
self._page_size = page_size
"""
会话ID分页场景首次请求结果返回后续请求必须携带服务根据session_id相同请求次数自动翻页返回
"""
self._session_id = session_id
"""
场景类型"kb_natural";
"""
self._biz_type = biz_type
"""
排序类型默认normal"normal"-门店创建时间倒序;"distance_asc"-距离最近
"""
self._sort_type = sort_type
"""
推广位
"""
self._pid = pid
"""
淘宝二级类目逗号分隔
"""
self._tb_category_2_ids = tb_category_2_ids
"""
淘宝三级类目逗号分隔
"""
self._tb_category_3_ids = tb_category_3_ids
"""
城市ID
"""
self._city_id = city_id
"""
经度经纬度范围配合使用
"""
self._longitude = longitude
"""
纬度经纬度范围配合使用
"""
self._latitude = latitude
"""
范围单位经纬度范围配合使用
"""
self._range = range
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def session_id(self):
return self._session_id
@session_id.setter
def session_id(self, session_id):
if isinstance(session_id, str):
self._session_id = session_id
else:
raise TypeError("session_id must be str")
@property
def biz_type(self):
return self._biz_type
@biz_type.setter
def biz_type(self, biz_type):
if isinstance(biz_type, str):
self._biz_type = biz_type
else:
raise TypeError("biz_type must be str")
@property
def sort_type(self):
return self._sort_type
@sort_type.setter
def sort_type(self, sort_type):
if isinstance(sort_type, str):
self._sort_type = sort_type
else:
raise TypeError("sort_type must be str")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
@property
def tb_category_2_ids(self):
return self._tb_category_2_ids
@tb_category_2_ids.setter
def tb_category_2_ids(self, tb_category_2_ids):
if isinstance(tb_category_2_ids, str):
self._tb_category_2_ids = tb_category_2_ids
else:
raise TypeError("tb_category_2_ids must be str")
@property
def tb_category_3_ids(self):
return self._tb_category_3_ids
@tb_category_3_ids.setter
def tb_category_3_ids(self, tb_category_3_ids):
if isinstance(tb_category_3_ids, str):
self._tb_category_3_ids = tb_category_3_ids
else:
raise TypeError("tb_category_3_ids must be str")
@property
def city_id(self):
return self._city_id
@city_id.setter
def city_id(self, city_id):
if isinstance(city_id, str):
self._city_id = city_id
else:
raise TypeError("city_id must be str")
@property
def longitude(self):
return self._longitude
@longitude.setter
def longitude(self, longitude):
if isinstance(longitude, str):
self._longitude = longitude
else:
raise TypeError("longitude must be str")
@property
def latitude(self):
return self._latitude
@latitude.setter
def latitude(self, latitude):
if isinstance(latitude, str):
self._latitude = latitude
else:
raise TypeError("latitude must be str")
@property
def range(self):
return self._range
@range.setter
def range(self, range):
if isinstance(range, int):
self._range = range
else:
raise TypeError("range must be int")
def get_api_name(self):
return "alibaba.alsc.union.kb.item.query"
def to_dict(self):
request_dict = {}
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._session_id is not None:
request_dict["session_id"] = convert_basic(self._session_id)
if self._biz_type is not None:
request_dict["biz_type"] = convert_basic(self._biz_type)
if self._sort_type is not None:
request_dict["sort_type"] = convert_basic(self._sort_type)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
if self._tb_category_2_ids is not None:
request_dict["tb_category_2_ids"] = convert_basic(self._tb_category_2_ids)
if self._tb_category_3_ids is not None:
request_dict["tb_category_3_ids"] = convert_basic(self._tb_category_3_ids)
if self._city_id is not None:
request_dict["city_id"] = convert_basic(self._city_id)
if self._longitude is not None:
request_dict["longitude"] = convert_basic(self._longitude)
if self._latitude is not None:
request_dict["latitude"] = convert_basic(self._latitude)
if self._range is not None:
request_dict["range"] = convert_basic(self._range)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,53 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbItemStoreDetailGetRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
门店详情查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.item.store.detail.get"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbItemStoreDetailGetKbItemShopDetailRequest:
def __init__(
self,
store_id: str = None
):
"""
门店ID
"""
self.store_id = store_id

View File

@ -0,0 +1,63 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbItemStoreRelationQueryRequest(BaseRequest):
def __init__(
self,
query_request: object = None
):
"""
商品门店关系查询rquest
"""
self._query_request = query_request
@property
def query_request(self):
return self._query_request
@query_request.setter
def query_request(self, query_request):
if isinstance(query_request, object):
self._query_request = query_request
else:
raise TypeError("query_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.item.store.relation.query"
def to_dict(self):
request_dict = {}
if self._query_request is not None:
request_dict["query_request"] = convert_struct(self._query_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbItemStoreRelationQueryKbItemShopRelationRequest:
def __init__(
self,
item_id: str = None,
city_id: str = None,
biz_type: str = None
):
"""
商品ID
"""
self.item_id = item_id
"""
城市ID
"""
self.city_id = city_id
"""
业务类型cps/cpa
"""
self.biz_type = biz_type

View File

@ -0,0 +1,98 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbOrderCreateRequest(BaseRequest):
def __init__(
self,
order_dto: object = None
):
"""
订单对象
"""
self._order_dto = order_dto
@property
def order_dto(self):
return self._order_dto
@order_dto.setter
def order_dto(self, order_dto):
if isinstance(order_dto, object):
self._order_dto = order_dto
else:
raise TypeError("order_dto must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.order.create"
def to_dict(self):
request_dict = {}
if self._order_dto is not None:
request_dict["order_dto"] = convert_struct(self._order_dto)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbOrderCreateOrderDto:
def __init__(
self,
outer_order_id: str = None,
item_id: str = None,
quantity: int = None,
pay_order_fee: int = None,
order_fee: int = None,
sell_price: int = None,
title: str = None,
ext_info: str = None,
skip_pay: bool = None,
phone: str = None
):
"""
渠道订单号需保证全局唯一
"""
self.outer_order_id = outer_order_id
"""
商品ID
"""
self.item_id = item_id
"""
购买数量
"""
self.quantity = quantity
"""
等同sell_price
"""
self.pay_order_fee = pay_order_fee
"""
商品的原价*份数单位分
"""
self.order_fee = order_fee
"""
商品的活动价*份数单位分
"""
self.sell_price = sell_price
"""
商品名称
"""
self.title = title
"""
扩展参数json格式
"""
self.ext_info = ext_info
"""
true预下单不支付false下单并支付
"""
self.skip_pay = skip_pay
"""
加密后的手机号
"""
self.phone = phone

View File

@ -0,0 +1,58 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbOrderPayRequest(BaseRequest):
def __init__(
self,
order_pay_dto: object = None
):
"""
订单支付对象
"""
self._order_pay_dto = order_pay_dto
@property
def order_pay_dto(self):
return self._order_pay_dto
@order_pay_dto.setter
def order_pay_dto(self, order_pay_dto):
if isinstance(order_pay_dto, object):
self._order_pay_dto = order_pay_dto
else:
raise TypeError("order_pay_dto must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.order.pay"
def to_dict(self):
request_dict = {}
if self._order_pay_dto is not None:
request_dict["order_pay_dto"] = convert_struct(self._order_pay_dto)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbOrderPayOrderPayDto:
def __init__(
self,
outer_order_id: str = None,
biz_order_id: str = None
):
"""
渠道订单号
"""
self.outer_order_id = outer_order_id
"""
淘宝子单号
"""
self.biz_order_id = biz_order_id

View File

@ -0,0 +1,53 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbOrderQueryRequest(BaseRequest):
def __init__(
self,
order_query_dto: object = None
):
"""
查询对象
"""
self._order_query_dto = order_query_dto
@property
def order_query_dto(self):
return self._order_query_dto
@order_query_dto.setter
def order_query_dto(self, order_query_dto):
if isinstance(order_query_dto, object):
self._order_query_dto = order_query_dto
else:
raise TypeError("order_query_dto must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.order.query"
def to_dict(self):
request_dict = {}
if self._order_query_dto is not None:
request_dict["order_query_dto"] = convert_struct(self._order_query_dto)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbOrderQueryOrderQueryDto:
def __init__(
self,
biz_order_id: str = None
):
"""
淘宝子单号
"""
self.biz_order_id = biz_order_id

View File

@ -0,0 +1,83 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbOrderRefundRequest(BaseRequest):
def __init__(
self,
order_refund_dto: object = None
):
"""
退款对象
"""
self._order_refund_dto = order_refund_dto
@property
def order_refund_dto(self):
return self._order_refund_dto
@order_refund_dto.setter
def order_refund_dto(self, order_refund_dto):
if isinstance(order_refund_dto, object):
self._order_refund_dto = order_refund_dto
else:
raise TypeError("order_refund_dto must be object")
def get_api_name(self):
return "alibaba.alsc.union.kb.order.refund"
def to_dict(self):
request_dict = {}
if self._order_refund_dto is not None:
request_dict["order_refund_dto"] = convert_struct(self._order_refund_dto)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionKbOrderRefundOrderVoucherDetailDto:
def __init__(
self,
item_id: str = None,
voucher_id: str = None
):
"""
商品ID必填
"""
self.item_id = item_id
"""
凭证ID必填
"""
self.voucher_id = voucher_id
class AlibabaAlscUnionKbOrderRefundOrderRefundDto:
def __init__(
self,
reason: str = None,
biz_order_id: str = None,
voucher_list: list = None,
ext_info: str = None
):
"""
用户退款原因必填
"""
self.reason = reason
"""
本地生活订单号必填
"""
self.biz_order_id = biz_order_id
"""
退款明细
"""
self.voucher_list = voucher_list
"""
扩展参数json格式
"""
self.ext_info = ext_info

View File

@ -0,0 +1,100 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbStoreItemQueryRequest(BaseRequest):
def __init__(
self,
store_id: str = None,
biz_type: str = None,
pid: str = None,
sid: str = None
):
"""
门店ID
"""
self._store_id = store_id
"""
场景类型"kb_natural";
"""
self._biz_type = biz_type
"""
推广位
"""
self._pid = pid
"""
sid申请权限后可用
"""
self._sid = sid
@property
def store_id(self):
return self._store_id
@store_id.setter
def store_id(self, store_id):
if isinstance(store_id, str):
self._store_id = store_id
else:
raise TypeError("store_id must be str")
@property
def biz_type(self):
return self._biz_type
@biz_type.setter
def biz_type(self, biz_type):
if isinstance(biz_type, str):
self._biz_type = biz_type
else:
raise TypeError("biz_type must be str")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
@property
def sid(self):
return self._sid
@sid.setter
def sid(self, sid):
if isinstance(sid, str):
self._sid = sid
else:
raise TypeError("sid must be str")
def get_api_name(self):
return "alibaba.alsc.union.kb.store.item.query"
def to_dict(self):
request_dict = {}
if self._store_id is not None:
request_dict["store_id"] = convert_basic(self._store_id)
if self._biz_type is not None:
request_dict["biz_type"] = convert_basic(self._biz_type)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
if self._sid is not None:
request_dict["sid"] = convert_basic(self._sid)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,252 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbStoreQueryRequest(BaseRequest):
def __init__(
self,
page_number: int = None,
page_size: int = None,
session_id: str = None,
biz_type: str = None,
sort_type: str = None,
city_id: str = None,
kb_category_2_ids: str = None,
kb_category_3_ids: str = None,
longitude: str = None,
latitude: str = None,
range: int = None,
kb_category_1_ids: str = None
):
"""
页码默认1
"""
self._page_number = page_number
"""
每页数目默认10
"""
self._page_size = page_size
"""
会话ID分页场景首次请求结果返回后续请求必须携带服务根据session_id相同请求次数自动翻页返回
"""
self._session_id = session_id
"""
场景类型"kb_natural";
"""
self._biz_type = biz_type
"""
排序类型默认normal"normal"-门店创建时间倒序;"distance_asc"-距离最近
"""
self._sort_type = sort_type
"""
城市ID
"""
self._city_id = city_id
"""
口碑二级类目逗号分隔
"""
self._kb_category_2_ids = kb_category_2_ids
"""
口碑三级类目逗号分隔
"""
self._kb_category_3_ids = kb_category_3_ids
"""
经度经纬度范围配合使用
"""
self._longitude = longitude
"""
纬度经纬度范围配合使用
"""
self._latitude = latitude
"""
范围单位经纬度范围配合使用
"""
self._range = range
"""
口碑一级类目逗号分隔
"""
self._kb_category_1_ids = kb_category_1_ids
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def session_id(self):
return self._session_id
@session_id.setter
def session_id(self, session_id):
if isinstance(session_id, str):
self._session_id = session_id
else:
raise TypeError("session_id must be str")
@property
def biz_type(self):
return self._biz_type
@biz_type.setter
def biz_type(self, biz_type):
if isinstance(biz_type, str):
self._biz_type = biz_type
else:
raise TypeError("biz_type must be str")
@property
def sort_type(self):
return self._sort_type
@sort_type.setter
def sort_type(self, sort_type):
if isinstance(sort_type, str):
self._sort_type = sort_type
else:
raise TypeError("sort_type must be str")
@property
def city_id(self):
return self._city_id
@city_id.setter
def city_id(self, city_id):
if isinstance(city_id, str):
self._city_id = city_id
else:
raise TypeError("city_id must be str")
@property
def kb_category_2_ids(self):
return self._kb_category_2_ids
@kb_category_2_ids.setter
def kb_category_2_ids(self, kb_category_2_ids):
if isinstance(kb_category_2_ids, str):
self._kb_category_2_ids = kb_category_2_ids
else:
raise TypeError("kb_category_2_ids must be str")
@property
def kb_category_3_ids(self):
return self._kb_category_3_ids
@kb_category_3_ids.setter
def kb_category_3_ids(self, kb_category_3_ids):
if isinstance(kb_category_3_ids, str):
self._kb_category_3_ids = kb_category_3_ids
else:
raise TypeError("kb_category_3_ids must be str")
@property
def longitude(self):
return self._longitude
@longitude.setter
def longitude(self, longitude):
if isinstance(longitude, str):
self._longitude = longitude
else:
raise TypeError("longitude must be str")
@property
def latitude(self):
return self._latitude
@latitude.setter
def latitude(self, latitude):
if isinstance(latitude, str):
self._latitude = latitude
else:
raise TypeError("latitude must be str")
@property
def range(self):
return self._range
@range.setter
def range(self, range):
if isinstance(range, int):
self._range = range
else:
raise TypeError("range must be int")
@property
def kb_category_1_ids(self):
return self._kb_category_1_ids
@kb_category_1_ids.setter
def kb_category_1_ids(self, kb_category_1_ids):
if isinstance(kb_category_1_ids, str):
self._kb_category_1_ids = kb_category_1_ids
else:
raise TypeError("kb_category_1_ids must be str")
def get_api_name(self):
return "alibaba.alsc.union.kb.store.query"
def to_dict(self):
request_dict = {}
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._session_id is not None:
request_dict["session_id"] = convert_basic(self._session_id)
if self._biz_type is not None:
request_dict["biz_type"] = convert_basic(self._biz_type)
if self._sort_type is not None:
request_dict["sort_type"] = convert_basic(self._sort_type)
if self._city_id is not None:
request_dict["city_id"] = convert_basic(self._city_id)
if self._kb_category_2_ids is not None:
request_dict["kb_category_2_ids"] = convert_basic(self._kb_category_2_ids)
if self._kb_category_3_ids is not None:
request_dict["kb_category_3_ids"] = convert_basic(self._kb_category_3_ids)
if self._longitude is not None:
request_dict["longitude"] = convert_basic(self._longitude)
if self._latitude is not None:
request_dict["latitude"] = convert_basic(self._latitude)
if self._range is not None:
request_dict["range"] = convert_basic(self._range)
if self._kb_category_1_ids is not None:
request_dict["kb_category_1_ids"] = convert_basic(self._kb_category_1_ids)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,176 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbcpaOrderDetailsGetRequest(BaseRequest):
def __init__(
self,
date_type: int = None,
settle_state: int = None,
end_date: str = None,
page_size: int = None,
page_number: int = None,
start_date: str = None,
order_state: int = None,
pid: str = None
):
"""
时间维度1-付款时间 2-创建时间 3-结算时间 4-更新时间
"""
self._date_type = date_type
"""
结算状态1-已结算 2-未结算 不传-所有状态
"""
self._settle_state = settle_state
"""
查询结束时间
"""
self._end_date = end_date
"""
每页返回数据大小默认10最大返回50
"""
self._page_size = page_size
"""
页码默认第一页取值范围1~50
"""
self._page_number = page_number
"""
查询开始时间
"""
self._start_date = start_date
"""
订单状态0-已失效 1-已下单 2-已付款 4-已收货 不传-全部状态
"""
self._order_state = order_state
"""
推广位pid
"""
self._pid = pid
@property
def date_type(self):
return self._date_type
@date_type.setter
def date_type(self, date_type):
if isinstance(date_type, int):
self._date_type = date_type
else:
raise TypeError("date_type must be int")
@property
def settle_state(self):
return self._settle_state
@settle_state.setter
def settle_state(self, settle_state):
if isinstance(settle_state, int):
self._settle_state = settle_state
else:
raise TypeError("settle_state must be int")
@property
def end_date(self):
return self._end_date
@end_date.setter
def end_date(self, end_date):
if isinstance(end_date, str):
self._end_date = end_date
else:
raise TypeError("end_date must be str")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def start_date(self):
return self._start_date
@start_date.setter
def start_date(self, start_date):
if isinstance(start_date, str):
self._start_date = start_date
else:
raise TypeError("start_date must be str")
@property
def order_state(self):
return self._order_state
@order_state.setter
def order_state(self, order_state):
if isinstance(order_state, int):
self._order_state = order_state
else:
raise TypeError("order_state must be int")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
def get_api_name(self):
return "alibaba.alsc.union.kbcpa.order.details.get"
def to_dict(self):
request_dict = {}
if self._date_type is not None:
request_dict["date_type"] = convert_basic(self._date_type)
if self._settle_state is not None:
request_dict["settle_state"] = convert_basic(self._settle_state)
if self._end_date is not None:
request_dict["end_date"] = convert_basic(self._end_date)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._start_date is not None:
request_dict["start_date"] = convert_basic(self._start_date)
if self._order_state is not None:
request_dict["order_state"] = convert_basic(self._order_state)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,119 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbcpaPunishOrderGetRequest(BaseRequest):
def __init__(
self,
date_type: int = None,
end_date: str = None,
page_size: int = None,
page_number: int = None,
start_date: str = None
):
"""
时间维度1.订单结算时间 2.维权创建时间 3.维权完成时间
"""
self._date_type = date_type
"""
截止查询时间
"""
self._end_date = end_date
"""
每页返回数据大小默认20最大返回50
"""
self._page_size = page_size
"""
页码默认第一页取值范围1~50
"""
self._page_number = page_number
"""
开始查询时间
"""
self._start_date = start_date
@property
def date_type(self):
return self._date_type
@date_type.setter
def date_type(self, date_type):
if isinstance(date_type, int):
self._date_type = date_type
else:
raise TypeError("date_type must be int")
@property
def end_date(self):
return self._end_date
@end_date.setter
def end_date(self, end_date):
if isinstance(end_date, str):
self._end_date = end_date
else:
raise TypeError("end_date must be str")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def start_date(self):
return self._start_date
@start_date.setter
def start_date(self, start_date):
if isinstance(start_date, str):
self._start_date = start_date
else:
raise TypeError("start_date must be str")
def get_api_name(self):
return "alibaba.alsc.union.kbcpa.punish.order.get"
def to_dict(self):
request_dict = {}
if self._date_type is not None:
request_dict["date_type"] = convert_basic(self._date_type)
if self._end_date is not None:
request_dict["end_date"] = convert_basic(self._end_date)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._start_date is not None:
request_dict["start_date"] = convert_basic(self._start_date)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,138 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbcpaRefundOrderGetRequest(BaseRequest):
def __init__(
self,
date_type: int = None,
end_date: str = None,
page_size: int = None,
page_number: int = None,
start_date: str = None,
pid: str = None
):
"""
时间维度1.订单结算时间 2.维权创建时间 3.维权完成时间 4更新时间
"""
self._date_type = date_type
"""
查询结束时间
"""
self._end_date = end_date
"""
每页返回数据大小默认20最大返回50
"""
self._page_size = page_size
"""
页码默认第一页取值范围1~50
"""
self._page_number = page_number
"""
查询开始时间
"""
self._start_date = start_date
"""
推广位pid
"""
self._pid = pid
@property
def date_type(self):
return self._date_type
@date_type.setter
def date_type(self, date_type):
if isinstance(date_type, int):
self._date_type = date_type
else:
raise TypeError("date_type must be int")
@property
def end_date(self):
return self._end_date
@end_date.setter
def end_date(self, end_date):
if isinstance(end_date, str):
self._end_date = end_date
else:
raise TypeError("end_date must be str")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def start_date(self):
return self._start_date
@start_date.setter
def start_date(self, start_date):
if isinstance(start_date, str):
self._start_date = start_date
else:
raise TypeError("start_date must be str")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
def get_api_name(self):
return "alibaba.alsc.union.kbcpa.refund.order.get"
def to_dict(self):
request_dict = {}
if self._date_type is not None:
request_dict["date_type"] = convert_basic(self._date_type)
if self._end_date is not None:
request_dict["end_date"] = convert_basic(self._end_date)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._start_date is not None:
request_dict["start_date"] = convert_basic(self._start_date)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,252 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbcpxPositiveOrderGetRequest(BaseRequest):
def __init__(
self,
date_type: int = None,
settle_state: int = None,
end_date: str = None,
biz_unit: int = None,
page_size: int = None,
page_number: int = None,
start_date: str = None,
order_state: int = None,
flow_type: str = None,
pid: str = None,
order_id: str = None,
include_used_store_id: bool = None
):
"""
时间维度1-付款时间 2-创建时间 3-结算时间 4-更新时间
"""
self._date_type = date_type
"""
结算状态1-已结算 2-未结算 不传-全部状态
"""
self._settle_state = settle_state
"""
查询截止时间精确到时分秒开始和结束时间不能超过31天
"""
self._end_date = end_date
"""
1-CPA 2-CPS
"""
self._biz_unit = biz_unit
"""
每页返回数据大小默认10最大返回50
"""
self._page_size = page_size
"""
页码默认第一页取值范围1~50
"""
self._page_number = page_number
"""
查询起始时间精确到时分秒开始和结束时间不能超过31天
"""
self._start_date = start_date
"""
订单状态0-已失效 1-已下单 2-已付款 4-已收货 不传-全部状态
"""
self._order_state = order_state
"""
场景值支持多场景英文逗号分隔查询7卡券订单8卡券核销订单10-媒体出资CPS红包11-媒体出资霸王餐加码红包
"""
self._flow_type = flow_type
"""
推广位pid
"""
self._pid = pid
"""
淘宝子订单号或饿了么订单号
"""
self._order_id = order_id
"""
是否包含核销门店
"""
self._include_used_store_id = include_used_store_id
@property
def date_type(self):
return self._date_type
@date_type.setter
def date_type(self, date_type):
if isinstance(date_type, int):
self._date_type = date_type
else:
raise TypeError("date_type must be int")
@property
def settle_state(self):
return self._settle_state
@settle_state.setter
def settle_state(self, settle_state):
if isinstance(settle_state, int):
self._settle_state = settle_state
else:
raise TypeError("settle_state must be int")
@property
def end_date(self):
return self._end_date
@end_date.setter
def end_date(self, end_date):
if isinstance(end_date, str):
self._end_date = end_date
else:
raise TypeError("end_date must be str")
@property
def biz_unit(self):
return self._biz_unit
@biz_unit.setter
def biz_unit(self, biz_unit):
if isinstance(biz_unit, int):
self._biz_unit = biz_unit
else:
raise TypeError("biz_unit must be int")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def start_date(self):
return self._start_date
@start_date.setter
def start_date(self, start_date):
if isinstance(start_date, str):
self._start_date = start_date
else:
raise TypeError("start_date must be str")
@property
def order_state(self):
return self._order_state
@order_state.setter
def order_state(self, order_state):
if isinstance(order_state, int):
self._order_state = order_state
else:
raise TypeError("order_state must be int")
@property
def flow_type(self):
return self._flow_type
@flow_type.setter
def flow_type(self, flow_type):
if isinstance(flow_type, str):
self._flow_type = flow_type
else:
raise TypeError("flow_type must be str")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
@property
def order_id(self):
return self._order_id
@order_id.setter
def order_id(self, order_id):
if isinstance(order_id, str):
self._order_id = order_id
else:
raise TypeError("order_id must be str")
@property
def include_used_store_id(self):
return self._include_used_store_id
@include_used_store_id.setter
def include_used_store_id(self, include_used_store_id):
if isinstance(include_used_store_id, bool):
self._include_used_store_id = include_used_store_id
else:
raise TypeError("include_used_store_id must be bool")
def get_api_name(self):
return "alibaba.alsc.union.kbcpx.positive.order.get"
def to_dict(self):
request_dict = {}
if self._date_type is not None:
request_dict["date_type"] = convert_basic(self._date_type)
if self._settle_state is not None:
request_dict["settle_state"] = convert_basic(self._settle_state)
if self._end_date is not None:
request_dict["end_date"] = convert_basic(self._end_date)
if self._biz_unit is not None:
request_dict["biz_unit"] = convert_basic(self._biz_unit)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._start_date is not None:
request_dict["start_date"] = convert_basic(self._start_date)
if self._order_state is not None:
request_dict["order_state"] = convert_basic(self._order_state)
if self._flow_type is not None:
request_dict["flow_type"] = convert_basic(self._flow_type)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
if self._order_id is not None:
request_dict["order_id"] = convert_basic(self._order_id)
if self._include_used_store_id is not None:
request_dict["include_used_store_id"] = convert_basic(self._include_used_store_id)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,195 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbcpxPunishOrderGetRequest(BaseRequest):
def __init__(
self,
date_type: int = None,
end_date: str = None,
biz_unit: int = None,
page_size: int = None,
page_number: int = None,
start_date: str = None,
flow_type: str = None,
pid: str = None,
order_id: str = None
):
"""
时间维度1.订单结算时间 2.维权创建时间 3.维权完成时间 4更新时间
"""
self._date_type = date_type
"""
查询截止时间开始和结束时间不能超过31天
"""
self._end_date = end_date
"""
1-CPA 2-CPS
"""
self._biz_unit = biz_unit
"""
每页返回数据大小默认10最大返回50
"""
self._page_size = page_size
"""
页码默认第一页取值范围1~50
"""
self._page_number = page_number
"""
查询起始时间开始和结束时间不能超过31天
"""
self._start_date = start_date
"""
场景值支持多场景英文逗号分隔查询7卡券订单8卡券核销订单10-媒体出资CPS红包11-媒体出资霸王餐加码红包
"""
self._flow_type = flow_type
"""
推广位pid
"""
self._pid = pid
"""
淘宝子订单号
"""
self._order_id = order_id
@property
def date_type(self):
return self._date_type
@date_type.setter
def date_type(self, date_type):
if isinstance(date_type, int):
self._date_type = date_type
else:
raise TypeError("date_type must be int")
@property
def end_date(self):
return self._end_date
@end_date.setter
def end_date(self, end_date):
if isinstance(end_date, str):
self._end_date = end_date
else:
raise TypeError("end_date must be str")
@property
def biz_unit(self):
return self._biz_unit
@biz_unit.setter
def biz_unit(self, biz_unit):
if isinstance(biz_unit, int):
self._biz_unit = biz_unit
else:
raise TypeError("biz_unit must be int")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def start_date(self):
return self._start_date
@start_date.setter
def start_date(self, start_date):
if isinstance(start_date, str):
self._start_date = start_date
else:
raise TypeError("start_date must be str")
@property
def flow_type(self):
return self._flow_type
@flow_type.setter
def flow_type(self, flow_type):
if isinstance(flow_type, str):
self._flow_type = flow_type
else:
raise TypeError("flow_type must be str")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
@property
def order_id(self):
return self._order_id
@order_id.setter
def order_id(self, order_id):
if isinstance(order_id, str):
self._order_id = order_id
else:
raise TypeError("order_id must be str")
def get_api_name(self):
return "alibaba.alsc.union.kbcpx.punish.order.get"
def to_dict(self):
request_dict = {}
if self._date_type is not None:
request_dict["date_type"] = convert_basic(self._date_type)
if self._end_date is not None:
request_dict["end_date"] = convert_basic(self._end_date)
if self._biz_unit is not None:
request_dict["biz_unit"] = convert_basic(self._biz_unit)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._start_date is not None:
request_dict["start_date"] = convert_basic(self._start_date)
if self._flow_type is not None:
request_dict["flow_type"] = convert_basic(self._flow_type)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
if self._order_id is not None:
request_dict["order_id"] = convert_basic(self._order_id)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,195 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionKbcpxRefundOrderGetRequest(BaseRequest):
def __init__(
self,
date_type: int = None,
end_date: str = None,
biz_unit: int = None,
page_size: int = None,
page_number: int = None,
start_date: str = None,
flow_type: str = None,
pid: str = None,
order_id: str = None
):
"""
时间维度1.订单结算时间 2.维权创建时间 3.维权完成时间 4更新时间
"""
self._date_type = date_type
"""
查询截止时间开始和结束时间不能超过31天
"""
self._end_date = end_date
"""
1-CPA 2-CPS
"""
self._biz_unit = biz_unit
"""
每页返回数据大小默认10最大返回50
"""
self._page_size = page_size
"""
页码默认第一页取值范围1~50
"""
self._page_number = page_number
"""
查询起始时间开始和结束时间不能超过31天
"""
self._start_date = start_date
"""
场景值支持多场景英文逗号分隔查询7卡券订单8卡券核销订单10-媒体出资CPS红包11-媒体出资霸王餐加码红包
"""
self._flow_type = flow_type
"""
推广位pid
"""
self._pid = pid
"""
淘宝子订单号或饿了么订单号
"""
self._order_id = order_id
@property
def date_type(self):
return self._date_type
@date_type.setter
def date_type(self, date_type):
if isinstance(date_type, int):
self._date_type = date_type
else:
raise TypeError("date_type must be int")
@property
def end_date(self):
return self._end_date
@end_date.setter
def end_date(self, end_date):
if isinstance(end_date, str):
self._end_date = end_date
else:
raise TypeError("end_date must be str")
@property
def biz_unit(self):
return self._biz_unit
@biz_unit.setter
def biz_unit(self, biz_unit):
if isinstance(biz_unit, int):
self._biz_unit = biz_unit
else:
raise TypeError("biz_unit must be int")
@property
def page_size(self):
return self._page_size
@page_size.setter
def page_size(self, page_size):
if isinstance(page_size, int):
self._page_size = page_size
else:
raise TypeError("page_size must be int")
@property
def page_number(self):
return self._page_number
@page_number.setter
def page_number(self, page_number):
if isinstance(page_number, int):
self._page_number = page_number
else:
raise TypeError("page_number must be int")
@property
def start_date(self):
return self._start_date
@start_date.setter
def start_date(self, start_date):
if isinstance(start_date, str):
self._start_date = start_date
else:
raise TypeError("start_date must be str")
@property
def flow_type(self):
return self._flow_type
@flow_type.setter
def flow_type(self, flow_type):
if isinstance(flow_type, str):
self._flow_type = flow_type
else:
raise TypeError("flow_type must be str")
@property
def pid(self):
return self._pid
@pid.setter
def pid(self, pid):
if isinstance(pid, str):
self._pid = pid
else:
raise TypeError("pid must be str")
@property
def order_id(self):
return self._order_id
@order_id.setter
def order_id(self, order_id):
if isinstance(order_id, str):
self._order_id = order_id
else:
raise TypeError("order_id must be str")
def get_api_name(self):
return "alibaba.alsc.union.kbcpx.refund.order.get"
def to_dict(self):
request_dict = {}
if self._date_type is not None:
request_dict["date_type"] = convert_basic(self._date_type)
if self._end_date is not None:
request_dict["end_date"] = convert_basic(self._end_date)
if self._biz_unit is not None:
request_dict["biz_unit"] = convert_basic(self._biz_unit)
if self._page_size is not None:
request_dict["page_size"] = convert_basic(self._page_size)
if self._page_number is not None:
request_dict["page_number"] = convert_basic(self._page_number)
if self._start_date is not None:
request_dict["start_date"] = convert_basic(self._start_date)
if self._flow_type is not None:
request_dict["flow_type"] = convert_basic(self._flow_type)
if self._pid is not None:
request_dict["pid"] = convert_basic(self._pid)
if self._order_id is not None:
request_dict["order_id"] = convert_basic(self._order_id)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,62 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionMediaZoneAddRequest(BaseRequest):
def __init__(
self,
zone_name: str = None,
media_id: str = None
):
"""
推广位名称
"""
self._zone_name = zone_name
"""
媒体id工具商渠道必填
"""
self._media_id = media_id
@property
def zone_name(self):
return self._zone_name
@zone_name.setter
def zone_name(self, zone_name):
if isinstance(zone_name, str):
self._zone_name = zone_name
else:
raise TypeError("zone_name must be str")
@property
def media_id(self):
return self._media_id
@media_id.setter
def media_id(self, media_id):
if isinstance(media_id, str):
self._media_id = media_id
else:
raise TypeError("media_id must be str")
def get_api_name(self):
return "alibaba.alsc.union.media.zone.add"
def to_dict(self):
request_dict = {}
if self._zone_name is not None:
request_dict["zone_name"] = convert_basic(self._zone_name)
if self._media_id is not None:
request_dict["media_id"] = convert_basic(self._media_id)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,62 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionMediaZoneGetRequest(BaseRequest):
def __init__(
self,
page: int = None,
limit: int = None
):
"""
页码从1开始
"""
self._page = page
"""
每页展示条数
"""
self._limit = limit
@property
def page(self):
return self._page
@page.setter
def page(self, page):
if isinstance(page, int):
self._page = page
else:
raise TypeError("page must be int")
@property
def limit(self):
return self._limit
@limit.setter
def limit(self, limit):
if isinstance(limit, int):
self._limit = limit
else:
raise TypeError("limit must be int")
def get_api_name(self):
return "alibaba.alsc.union.media.zone.get"
def to_dict(self):
request_dict = {}
if self._page is not None:
request_dict["page"] = convert_basic(self._page)
if self._limit is not None:
request_dict["limit"] = convert_basic(self._limit)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,58 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class AlibabaAlscUnionPromotionLinkAnalyzeRequest(BaseRequest):
def __init__(
self,
promotion_link_analyze_request: object = None
):
"""
查询request对象
"""
self._promotion_link_analyze_request = promotion_link_analyze_request
@property
def promotion_link_analyze_request(self):
return self._promotion_link_analyze_request
@promotion_link_analyze_request.setter
def promotion_link_analyze_request(self, promotion_link_analyze_request):
if isinstance(promotion_link_analyze_request, object):
self._promotion_link_analyze_request = promotion_link_analyze_request
else:
raise TypeError("promotion_link_analyze_request must be object")
def get_api_name(self):
return "alibaba.alsc.union.promotion.link.analyze"
def to_dict(self):
request_dict = {}
if self._promotion_link_analyze_request is not None:
request_dict["promotion_link_analyze_request"] = convert_struct(self._promotion_link_analyze_request)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict
class AlibabaAlscUnionPromotionLinkAnalyzePromotionLinkAnalyzeRequest:
def __init__(
self,
type: int = None,
link: str = None
):
"""
链接类型1-h52-h5短链3-微信小程序4-饿了么APP
"""
self.type = type
"""
推广链接
"""
self.link = link

View File

@ -0,0 +1,247 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcMessageProduceRequest(BaseRequest):
def __init__(
self,
content: str = None,
ex_content: str = None,
target_appkey: str = None,
target_group: str = None,
topic: str = None,
media_content: bytes = None,
media_content2: bytes = None,
media_content3: bytes = None,
media_content5: bytes = None,
media_content4: bytes = None,
delay_millis: int = None,
expires_millis: int = None
):
"""
消息内容的JSON表述必须按照topic的定义来填充
"""
self._content = content
"""
消息的扩增属性用json格式表示
"""
self._ex_content = ex_content
"""
直发消息需要传入目标appkey
"""
self._target_appkey = target_appkey
"""
目标分组一般为default
"""
self._target_group = target_group
"""
消息类型
"""
self._topic = topic
"""
回传的文件内容目前仅支持jpg,png,bmp,gif,pdf类型的文件文件最大1M只有消息中有byte[]类型的数据时才需要传此字段; 否则不需要传此字段
"""
self._media_content = media_content
"""
回传的文件内容目前仅支持jpg,png,bmp,gif,pdf类型的文件文件最大1M只有消息中有byte[]类型的数据时才需要传此字段; 否则不需要传此字段具体对应到沙体中的什么值请参考消息字段说明
"""
self._media_content2 = media_content2
"""
回传的文件内容目前仅支持jpg,png,bmp,gif,pdf类型的文件文件最大1M只有消息中有byte[]类型的数据时才需要传此字段; 否则不需要传此字段具体对应到沙体中的什么值请参考消息字段说明
"""
self._media_content3 = media_content3
"""
回传的文件内容目前仅支持jpg,png,bmp,gif,pdf类型的文件文件最大1M只有消息中有byte[]类型的数据时才需要传此字段; 否则不需要传此字段具体对应到沙体中的什么值请参考消息字段说明
"""
self._media_content5 = media_content5
"""
回传的文件内容目前仅支持jpg,png,bmp,gif,pdf类型的文件文件最大1M只有消息中有byte[]类型的数据时才需要传此字段; 否则不需要传此字段具体对应到沙体中的什么值请参考消息字段说明
"""
self._media_content4 = media_content4
"""
延时参数 时间戳 预期发送时间
"""
self._delay_millis = delay_millis
"""
提前过期 相对时间差 毫秒
"""
self._expires_millis = expires_millis
@property
def content(self):
return self._content
@content.setter
def content(self, content):
if isinstance(content, str):
self._content = content
else:
raise TypeError("content must be str")
@property
def ex_content(self):
return self._ex_content
@ex_content.setter
def ex_content(self, ex_content):
if isinstance(ex_content, str):
self._ex_content = ex_content
else:
raise TypeError("ex_content must be str")
@property
def target_appkey(self):
return self._target_appkey
@target_appkey.setter
def target_appkey(self, target_appkey):
if isinstance(target_appkey, str):
self._target_appkey = target_appkey
else:
raise TypeError("target_appkey must be str")
@property
def target_group(self):
return self._target_group
@target_group.setter
def target_group(self, target_group):
if isinstance(target_group, str):
self._target_group = target_group
else:
raise TypeError("target_group must be str")
@property
def topic(self):
return self._topic
@topic.setter
def topic(self, topic):
if isinstance(topic, str):
self._topic = topic
else:
raise TypeError("topic must be str")
@property
def media_content(self):
return self._media_content
@media_content.setter
def media_content(self, media_content):
if isinstance(media_content, bytes):
self._media_content = media_content
else:
raise TypeError("media_content must be bytes")
@property
def media_content2(self):
return self._media_content2
@media_content2.setter
def media_content2(self, media_content2):
if isinstance(media_content2, bytes):
self._media_content2 = media_content2
else:
raise TypeError("media_content2 must be bytes")
@property
def media_content3(self):
return self._media_content3
@media_content3.setter
def media_content3(self, media_content3):
if isinstance(media_content3, bytes):
self._media_content3 = media_content3
else:
raise TypeError("media_content3 must be bytes")
@property
def media_content5(self):
return self._media_content5
@media_content5.setter
def media_content5(self, media_content5):
if isinstance(media_content5, bytes):
self._media_content5 = media_content5
else:
raise TypeError("media_content5 must be bytes")
@property
def media_content4(self):
return self._media_content4
@media_content4.setter
def media_content4(self, media_content4):
if isinstance(media_content4, bytes):
self._media_content4 = media_content4
else:
raise TypeError("media_content4 must be bytes")
@property
def delay_millis(self):
return self._delay_millis
@delay_millis.setter
def delay_millis(self, delay_millis):
if isinstance(delay_millis, int):
self._delay_millis = delay_millis
else:
raise TypeError("delay_millis must be int")
@property
def expires_millis(self):
return self._expires_millis
@expires_millis.setter
def expires_millis(self, expires_millis):
if isinstance(expires_millis, int):
self._expires_millis = expires_millis
else:
raise TypeError("expires_millis must be int")
def get_api_name(self):
return "taobao.tmc.message.produce"
def to_dict(self):
request_dict = {}
if self._content is not None:
request_dict["content"] = convert_basic(self._content)
if self._ex_content is not None:
request_dict["ex_content"] = convert_basic(self._ex_content)
if self._target_appkey is not None:
request_dict["target_appkey"] = convert_basic(self._target_appkey)
if self._target_group is not None:
request_dict["target_group"] = convert_basic(self._target_group)
if self._topic is not None:
request_dict["topic"] = convert_basic(self._topic)
if self._delay_millis is not None:
request_dict["delay_millis"] = convert_basic(self._delay_millis)
if self._expires_millis is not None:
request_dict["expires_millis"] = convert_basic(self._expires_millis)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
if self._media_content is not None:
file_param_dict["media_content"] = convert_basic(self._media_content)
if self._media_content2 is not None:
file_param_dict["media_content2"] = convert_basic(self._media_content2)
if self._media_content3 is not None:
file_param_dict["media_content3"] = convert_basic(self._media_content3)
if self._media_content5 is not None:
file_param_dict["media_content5"] = convert_basic(self._media_content5)
if self._media_content4 is not None:
file_param_dict["media_content4"] = convert_basic(self._media_content4)
return file_param_dict

View File

@ -0,0 +1,62 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcUserCancelRequest(BaseRequest):
def __init__(
self,
nick: str = None,
user_platform: str = None
):
"""
用户昵称
"""
self._nick = nick
"""
用户所属的平台类型tbUIC:淘宝用户; icbu: icbu用户;ae:ae用户
"""
self._user_platform = user_platform
@property
def nick(self):
return self._nick
@nick.setter
def nick(self, nick):
if isinstance(nick, str):
self._nick = nick
else:
raise TypeError("nick must be str")
@property
def user_platform(self):
return self._user_platform
@user_platform.setter
def user_platform(self, user_platform):
if isinstance(user_platform, str):
self._user_platform = user_platform
else:
raise TypeError("user_platform must be str")
def get_api_name(self):
return "taobao.tmc.user.cancel"
def to_dict(self):
request_dict = {}
if self._nick is not None:
request_dict["nick"] = convert_basic(self._nick)
if self._user_platform is not None:
request_dict["user_platform"] = convert_basic(self._user_platform)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,81 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcUserGetRequest(BaseRequest):
def __init__(
self,
fields: list = None,
nick: str = None,
user_platform: str = None
):
"""
需返回的字段列表多个字段以半角逗号分隔可选值TmcUser结构体中的所有字段一定要返回topic
"""
self._fields = fields
"""
用户昵称
"""
self._nick = nick
"""
用户所属的平台类型tbUIC:淘宝用户; icbu: icbu用户;ae:ae用户
"""
self._user_platform = user_platform
@property
def fields(self):
return self._fields
@fields.setter
def fields(self, fields):
if isinstance(fields, list):
self._fields = fields
else:
raise TypeError("fields must be list")
@property
def nick(self):
return self._nick
@nick.setter
def nick(self, nick):
if isinstance(nick, str):
self._nick = nick
else:
raise TypeError("nick must be str")
@property
def user_platform(self):
return self._user_platform
@user_platform.setter
def user_platform(self, user_platform):
if isinstance(user_platform, str):
self._user_platform = user_platform
else:
raise TypeError("user_platform must be str")
def get_api_name(self):
return "taobao.tmc.user.get"
def to_dict(self):
request_dict = {}
if self._fields is not None:
request_dict["fields"] = convert_basic_list(self._fields)
if self._nick is not None:
request_dict["nick"] = convert_basic(self._nick)
if self._user_platform is not None:
request_dict["user_platform"] = convert_basic(self._user_platform)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,43 @@
from typing import List
from libs.topsdk.client import BaseRequest
from libs.topsdk.util import convert_struct_list,convert_basic_list,convert_struct,convert_basic
from datetime import datetime
class TaobaoTmcUserPermitRequest(BaseRequest):
def __init__(
self,
topics: list = None
):
"""
消息主题列表用半角逗号分隔当用户订阅的topic是应用订阅的子集时才需要设置不设置表示继承应用所订阅的所有topic一般情况建议不要设置
"""
self._topics = topics
@property
def topics(self):
return self._topics
@topics.setter
def topics(self, topics):
if isinstance(topics, list):
self._topics = topics
else:
raise TypeError("topics must be list")
def get_api_name(self):
return "taobao.tmc.user.permit"
def to_dict(self):
request_dict = {}
if self._topics is not None:
request_dict["topics"] = convert_basic_list(self._topics)
return request_dict
def get_file_param_dict(self):
file_param_dict = {}
return file_param_dict

View File

@ -0,0 +1,5 @@
certifi==2021.10.8
charset-normalizer==2.0.7
idna==3.3
requests==2.26.0
urllib3==1.26.7

89
libs/topsdk/top.py Normal file
View File

@ -0,0 +1,89 @@
import logging
from datetime import datetime
from libs.topsdk.client import TopApiClient, TopException
from libs.topsdk.defaultability.defaultability import Defaultability
from libs.topsdk.defaultability.request.alibaba_alsc_union_eleme_promotion_officialactivity_get_request import \
AlibabaAlscUnionElemePromotionOfficialactivityGetRequest
from libs.topsdk.defaultability.request.alibaba_alsc_union_kbcpx_positive_order_get_request import \
AlibabaAlscUnionKbcpxPositiveOrderGetRequest
from libs.topsdk.defaultability.request.alibaba_alsc_union_media_zone_add_request import \
AlibabaAlscUnionMediaZoneAddRequest
from libs.topsdk.defaultability.request.alibaba_alsc_union_media_zone_get_request import \
AlibabaAlscUnionMediaZoneGetRequest
from libs.topsdk.util import convert_basic
loger = logging.getLogger('apps')
class TopUtils(object):
def __init__(self, appkey, secret, gateway_url='http://gw.api.taobao.com/router/rest'):
self.appkey = appkey
self.secret = secret
self.gateway_url = gateway_url
self.client = TopApiClient(appkey=self.appkey, app_sercet=self.secret,
top_gateway_url=self.gateway_url,
verify_ssl=False)
self.ability = Defaultability(client=self.client)
def get_order_info(self, start_date, date_type=4, end_date=None, biz_unit=2, page_size=10, page_number=1, **kwargs):
request = AlibabaAlscUnionKbcpxPositiveOrderGetRequest()
request.date_type = date_type
request.end_date = convert_basic(end_date) or datetime.today().strftime('%Y-%m-%d %H:%M:%S')
request.biz_unit = biz_unit
request.page_size = page_size
request.page_number = page_number
request.start_date = convert_basic(start_date)
if kwargs:
for attr, value in kwargs.items():
setattr(request, attr, value)
try:
response = self.ability.alibaba_alsc_union_kbcpx_positive_order_get(request)
if response.get('biz_error_code') == 0:
return response.get('result'), response.get('total_count')
except TopException as e:
print(e)
loger.error(f'拉取订单失败, {e}')
def get_zone_list(self, page=1, limit=10):
request = AlibabaAlscUnionMediaZoneGetRequest()
request.page = page
request.limit = limit
try:
response = self.ability.alibaba_alsc_union_media_zone_get(request)
if response.get('biz_error_code') == 0:
return response.get('result')
except TopException as e:
print(e)
loger.error(f'获取推广位失败, {e}')
def add_zone(self, zone_name, media_id):
request = AlibabaAlscUnionMediaZoneAddRequest()
request.zone_name = zone_name
request.media_id = media_id
try:
response = self.ability.alibaba_alsc_union_media_zone_add(request)
if response.get('biz_error_code') == 0:
return response.get('result')
except TopException as e:
print(e)
loger.error(f'创建推广位失败, {e}')
def get_official_activity(self, pid, activity_id, sid=None, include_wx_img=True, include_qr_code=True):
request = AlibabaAlscUnionElemePromotionOfficialactivityGetRequest(query_request={
'pid': pid,
'activity_id': activity_id,
'sid': sid,
'include_wx_img': include_wx_img,
'include_qr_code': include_qr_code,
})
try:
response = self.ability.alibaba_alsc_union_eleme_promotion_officialactivity_get(request)
if response.get('result_code') == 0:
return response.get('data')
except TopException as e:
print(e)
loger.error(f'获取官方活动失败, {e}')

115
libs/topsdk/util.py Normal file
View File

@ -0,0 +1,115 @@
import hmac
import json
from datetime import datetime, date
from hashlib import md5, sha256
def get_sign(param_dict: dict, request_dict: dict, app_secret: str, sign_method: str) -> str:
if sign_method == "hmac-sha256":
return get_sign_with_hmac_sha256(param_dict, request_dict, app_secret)
elif sign_method == "md5":
return get_sign_with_md5(param_dict, request_dict, app_secret)
else:
raise Exception("Unsupported sign method: " + sign_method)
def get_sign_with_md5(param_dict: dict, request_dict: dict, app_secret: str) -> str:
"""
使用md5计算签名
:param param_dict: 公共参数字典
:param request_dict: api参数字典
:param app_secret: 密钥
:return:
"""
param_dict.update(request_dict)
keys = list(param_dict.keys())
keys.sort()
parameters = "%s%s%s" % (app_secret,
str().join(
'%s%s' % (k, param_dict[k]) for k in keys if not isinstance(param_dict[k], bytes)),
app_secret)
sign = md5(parameters.encode("utf-8")).hexdigest().upper()
return sign
def get_sign_with_hmac_sha256(param_dict: dict, request_dict: dict, app_secret: str):
"""
使用hmac sha256计算签名
:param param_dict: 公共参数字典
:param request_dict: api参数字典
:param app_secret: 密钥
:return:
"""
param_dict.update(request_dict)
keys = list(param_dict.keys())
keys.sort()
parameters = str().join('%s%s' % (k, param_dict[k]) for k in keys if not isinstance(param_dict[k], bytes))
sign = hmac.new(app_secret.encode("utf-8"), parameters.encode("utf-8"), digestmod=sha256).hexdigest().upper()
return str(sign)
def json_default(value):
if isinstance(value, (datetime, date)):
return value.strftime('%Y-%m-%d %H:%M:%S')
else:
return value.__dict__
class TopJsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime, date)):
return obj.strftime('%Y-%m-%d %H:%M:%S')
else:
return json.JSONEncoder.default(self, obj)
def convert_basic(param):
"""
转换基本类型
:param param:
:return:
"""
if isinstance(param, (datetime, date)):
return param.strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(param, bool):
return str(param).lower()
elif isinstance(param, bytes):
return param
else:
return str(param)
def convert_basic_list(param):
"""
转换字符串数字类型列表列表 -> 逗号分割字符串
:param param:
:return:
"""
if isinstance(param, (list, tuple, set)):
return ",".join(convert_basic(i) for i in param)
else:
return param
def convert_struct(param):
"""
转换dict 对象类型参数转json字符串
:param param:
:return:
"""
if isinstance(param, str):
return param
else:
return json.dumps(param, cls=TopJsonEncoder, default=json_default, ensure_ascii=False)
def convert_struct_list(param):
"""
转换复杂类型列表
:param param:
:return:
"""
if isinstance(param, (set, list, tuple)):
return json.dumps(param, cls=TopJsonEncoder, default=json_default, ensure_ascii=False)
else:
return str(param)

1
libs/wechat/__init__.py Normal file
View File

@ -0,0 +1 @@
from .worker import WechatWorkerUtil

311
libs/wechat/worker.py Normal file
View File

@ -0,0 +1,311 @@
import requests
import logging
from utils.redis_utils import RedisUtils
from yzk_wechat_event.settings.constant import Constant
logger = logging.getLogger('apps')
class WechatWorkerUtil(object):
base_url = 'https://qyapi.weixin.qq.com/cgi-bin'
redis_util = RedisUtils()
def __init__(self, corpid, secret):
self.corpid = corpid
self.secret = secret
def get_access_token(self):
key = f'{Constant.WECHAT_WORKER_TOKEN}{self.corpid}:{self.secret}'
token = self.redis_util.get(key)
if token:
return token
url = f'{self.base_url}/gettoken?corpid={self.corpid}&corpsecret={self.secret}'
data = requests.get(url).json()
if data.get('errcode') != 0:
logger.error(f'获取token失败--->{data}')
return
token = data.get('access_token')
self.redis_util.set_ex(
key, Constant.WECHAT_WORKER_TOKEN_EXPIRES, token)
return token
def get_department_list(self, department_id=None):
token = self.get_access_token()
url = f'{self.base_url}/department/list?access_token={token}&id={department_id}'
data = requests.get(url).json()
if data.get('errcode') == 0:
return True, data.get('department')
logger.error(f'获取部门失败--->{data}')
return False, data.get('errmsg')
def get_sub_department_id(self, department_id=None, token=None):
token = token or self.get_access_token()
url = f'{self.base_url}/department/simplelist?access_token={token}&id={department_id}'
data = requests.get(url).json()
if data.get('errcode') == 0:
department_list = data.get('department_id')
return True, department_list
return False, data.get('errmsg')
def get_department_user(self, department_id, token=None):
"""
获取部门成员
"""
token = token or self.get_access_token()
url = f'{self.base_url}/user/simplelist?access_token={token}&department_id={department_id}'
data = requests.get(url).json()
if data.get('errcode') == 0:
user_list = data.get('userlist')
return True, [user.get('userid') for user in user_list]
logger.error(f'获取用户失败-->{data}')
return False, data.get('errmsg')
def get_department_user_detail(self, department_id, token=None):
token = token or self.get_access_token()
url = f'{self.base_url}/user/list?access_token={token}&department_id={department_id}'
data = requests.get(url).json()
if data.get('errcode') == 0:
user_list = data.get('userlist')
return True, user_list
return False, data.get('errmsg')
def get_department_user_by_ids(self, ids):
token = self.get_access_token()
user_ids = []
for department_id in ids:
user_id_list = self.get_department_user(department_id, token)
user_ids = [*user_ids, *user_id_list]
return user_ids
def get_dep_user_group_by_dep_id(self, ids):
token = self.get_access_token()
user_id_mapping = {}
for department_id in ids:
user_id_list = self.get_department_user(department_id, token)
user_id_mapping[department_id] = user_id_list
return user_id_mapping
def get_user_fan_count(self, userid):
token = self.get_access_token()
url = f'{self.base_url}/externalcontact/list?access_token={token}&userid={userid}'
data = requests.get(url).json()
if data.get('errcode') == 0:
external_userid = data.get('external_userid')
return len(external_userid)
return 0
def get_user_id_list(self, access_token=None, cursor=None):
access_token = access_token or self.get_access_token()
url = f'{self.base_url}/user/list_id?access_token={access_token}'
data = {
'limit': 10000,
'cursor': cursor
}
res = requests.post(url=url, json=data).json()
if res.get('errcode') == 0:
return True, res.get('dept_user'), res.get('next_cursor')
return False, res.get('errmsg'), None
def get_user(self, user_id, access_token=None):
access_token = access_token or self.get_access_token()
url = f'{self.base_url}/user/get?access_token={access_token}&userid={user_id}'
res = requests.get(url).json()
if res.get('errcode') == 0:
return res
return
def get_tags(self, access_token=None, body=None):
access_token = access_token or self.get_access_token()
url = f'{self.base_url}/externalcontact/get_corp_tag_list?access_token={access_token}'
res = requests.post(url, json=body).json()
if res.get('errcode') == 0:
return True, res.get('tag_group')
return False, res.get('errmsg')
def get_external_contact_list(self, userid):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/list?access_token={access_token}&userid={userid}'
res = requests.get(url).json()
if res.get('errcode') == 0:
return True, res.get('external_userid')
return False, res.get('errmsg')
def get_external_contact(self, external_userid, cursor=None):
access_token = self.get_access_token()
params = {
'access_token': access_token,
'external_userid': external_userid,
}
if cursor:
params['cursor'] = cursor
url = f'{self.base_url}/externalcontact/get'
res = requests.get(url, params=params)
res = res.json()
if res.get('errcode') == 0:
return True, (res.get('external_contact'), res.get('follow_user'))
return False, res.get('errmsg')
def get_external_contact_batch_by_user(self, userid_list, cursor='', limit=100):
url = f'{self.base_url}/externalcontact/batch/get_by_user?access_token={self.get_access_token()}'
data = {
'userid_list': userid_list,
'cursor': cursor,
'limit': limit
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, res.get('external_contact_list'), res.get('next_cursor') or None
return False, res.get('errmsg'), None
def add_contact_way(
self,
_type=2,
scene=2,
style=1,
remark=None,
skip_verify=True,
state=None,
user=None,
party=None,
is_temp=False,
expires_in=None,
chat_expires_in=None,
unionid=None,
is_exclusive=False,
conclusions=None
):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/add_contact_way?access_token={access_token}'
data = {
'type': _type,
'scene': scene,
'style': style,
'remark': remark,
'skip_verify': skip_verify,
'state': state,
'user': user,
'party': party,
'is_temp': is_temp,
'expires_in': expires_in,
'chat_expires_in': chat_expires_in,
'unionid': unionid,
'is_exclusive': is_exclusive,
'conclusions': conclusions
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, (res.get('config_id'), res.get('qr_code'))
return False, res.get('errmsg')
def update_contact_way(self, config_id, user, skip_verify=True, style=1, remark=None, state=None, party=None,
expires_in=None, chat_expires_in=None, unionid=None, conclusions=None):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/update_contact_way?access_token={access_token}'
data = {
'config_id': config_id,
'remark': remark,
'user': user,
'skip_verify': skip_verify,
'style': style,
'state': state,
'party': party,
'expires_in': expires_in,
'chat_expires_in': chat_expires_in,
'unionid': unionid,
'conclusions': conclusions
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, (res.get('config_id'), res.get('qr_code'))
return False, res.get('errmsg')
def get_external_groupchat_list(self, owner_filter=None, status_filter=0, cursor=None, limit=1000):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/groupchat/list?access_token={access_token}'
data = {
'owner_filter': owner_filter,
'status_filter': status_filter,
'cursor': cursor,
'limit': limit,
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, (res.get('group_chat_list'), res.get('next_cursor'))
return False, res.get('errmsg')
def get_external_groupchat(self, chat_id, need_name=1):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/groupchat/get?access_token={access_token}'
data = {
'chat_id': chat_id,
'need_name': need_name,
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, res.get('group_chat')
return False, res.get('errmsg')
def get_externalcontact_follow_user_list(self):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/get_follow_user_list?access_token={access_token}'
res = requests.get(url=url).json()
if res.get('errcode') == 0:
return True, res.get('follow_user')
return False, res.get('errmsg')
def get_groupmsg_list_v2(self, start_time, end_time, chat_type='single', creator=None, filter_type=1, limit=100,
cursor=None):
"""
access_token 调用接口凭证
chat_type 群发任务的类型默认为single表示发送给客户group表示发送给客户群
start_time 群发任务记录开始时间
end_time 群发任务记录结束时间
creator 群发任务创建人企业账号id
filter_type 创建人类型0企业发表 1个人发表 2所有包括个人创建以及企业创建默认情况下为所有类型
limit 返回的最大记录数整型最大值100默认值50超过最大值时取默认值
cursor 用于分页查询的游标字符串类型由上一次调用返回首次调用可不填
"""
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/get_groupmsg_list_v2?access_token={access_token}'
data = {
'chat_type': chat_type,
'start_time': start_time,
'end_time': end_time,
'creator': creator,
'filter_type': filter_type,
'limit': limit,
'cursor': cursor,
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, (res.get('group_msg_list'), res.get('next_cursor'))
return False, (res.get('errmsg'), None)
def get_groupmsg_task(self, msgid, limit=1000, cursor=None):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/get_groupmsg_task?access_token={access_token}'
data = {
'msgid': msgid,
'limit': limit,
'cursor': cursor,
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, (res.get('task_list'), res.get('next_cursor'))
return False, (res.get('errmsg'), None)
def get_groupmsg_send_result(self, msgid, userid, limit=1000, cursor=None):
access_token = self.get_access_token()
url = f'{self.base_url}/externalcontact/get_groupmsg_send_result?access_token={access_token}'
data = {
'msgid': msgid,
'userid': userid,
'limit': limit,
'cursor': cursor,
}
res = requests.post(url, json=data).json()
if res.get('errcode') == 0:
return True, (res.get('send_list'), res.get('next_cursor'))
return False, (res.get('errmsg'), None)

0
logs/.gitignore vendored Normal file
View File

22
manage.py Normal file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'yzk_wechat_event.settings.base')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

BIN
requirements.txt Normal file

Binary file not shown.

4
start Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
gunicorn -c yzk_wechat_event/gunicorn.conf.py yzk_wechat_event.wsgi:application &
tail -f logs/*.log

10
start-celeryworker Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
set -o errexit
set -o nounset
watchmedo auto-restart -d yzk_wechat_event/ -p "*.py" -- celery -A yzk_wechat_event worker -l info --logfile=logs/celery.log --concurrency=4 -Q celery &
celery -A yzk_wechat_event beat -l info --logfile=logs/celery_beat.log &
tail -f logs/*.log

31
utils/CustomField.py Normal file
View File

@ -0,0 +1,31 @@
from rest_framework import serializers
class CustomDateField(serializers.DateField):
def __init__(self, *args, **kwargs):
super().__init__(*args, format='%Y-%m-%d', **kwargs)
class CustomDateTimeField(serializers.DateTimeField):
def __init__(self, *args, **kwargs):
super().__init__(*args, format='%Y-%m-%d %H:%M:%S', **kwargs)
class CustomSerializerMethodField(serializers.SerializerMethodField):
def __init__(self, method_name=None, **kwargs):
super().__init__(method_name, **kwargs)
self.field_name = None
def bind(self, field_name, parent):
self.field_name = field_name
return super().bind(field_name, parent)
def to_representation(self, value):
method = getattr(self.parent, self.method_name)
return method(value, self.field_name)
class CustomMoneyField(serializers.IntegerField):
def to_representation(self, value):
return value / 100 if value else 0

0
utils/__init__.py Normal file
View File

144
utils/base_serializer.py Normal file
View File

@ -0,0 +1,144 @@
from rest_framework.exceptions import APIException
from rest_framework.fields import empty
from rest_framework import serializers, status
from rest_framework.request import Request
from apps.qc.models import QcWechatbizuserinfo, QcCorpinfo
from apps.qc.utils import get_query_by_corpkey
from apps.user.models import User
from libs.wechat import WechatWorkerUtil
from utils.CustomField import CustomDateTimeField
from utils.exceptions import CustomProjectException
class ValidationError(APIException):
status_code = status.HTTP_400_BAD_REQUEST
default_detail = 'Invalid input.'
default_code = 'invalid'
def __init__(self, detail=None):
self.detail = detail
class CurrentUserIdDefault(serializers.CurrentUserDefault):
def __call__(self, serializer_field):
user = super().__call__(serializer_field)
return user.pk
class BaseSerializer(serializers.ModelSerializer):
def __init__(self, instance=None, data=empty, request=None, **kwargs):
super().__init__(instance, data, **kwargs)
self.request: Request = request or self.context.get("request", None)
self.user = self.request.user if self.request else "AnonymousUser"
class QcUserInfoSerializer(BaseSerializer):
userinfo = serializers.SerializerMethodField()
user_mapping = None
def get_userinfo(self, obj):
view = self.context.get("view")
queryset = self.context.get("queryset")
if not hasattr(view, 'userinfo_fields'):
return
if 'pk' not in view.userinfo_fields:
view.userinfo_fields.append('pk')
if self.user_mapping is None:
self.user_mapping = {}
uids = [q.uid for q in queryset]
users = User.objects.filter(
pk__in=uids).values(*view.userinfo_fields)
for user in users:
self.user_mapping[user.get('pk')] = user
return self.user_mapping.get(obj.uid, {})
class QcWechatUserInfoSerializer(BaseSerializer):
wechat_userinfo = serializers.SerializerMethodField()
wechat_user_mapping = None
def get_wechat_userinfo(self, obj):
view = self.context.get("view")
queryset = self.context.get("queryset")
if not hasattr(view, 'wechat_userinfo_fields'):
wechat_userinfo_fields = ('username', 'alias', 'userid')
else:
wechat_userinfo_fields = view.wechat_userinfo_fields
if self.wechat_user_mapping is None:
self.wechat_user_mapping = {}
userids = [q.userid for q in queryset]
users = QcWechatbizuserinfo.objects.filter(
userid__in=userids).values(*wechat_userinfo_fields)
for user in users:
self.wechat_user_mapping[user.get('userid')] = user
return self.wechat_user_mapping.get(obj.userid, {})
class CurrentUserSerializer(BaseSerializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
class CurrentUserIdSerializer(BaseSerializer):
uid = serializers.HiddenField(
default=CurrentUserIdDefault()
)
class UserNameSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(source='user.username')
class DateTimeListSerializer(BaseSerializer):
create_time = CustomDateTimeField(read_only=True)
update_time = CustomDateTimeField(read_only=True)
class CorpkeySerializer(BaseSerializer):
corpkey = serializers.SerializerMethodField()
def get_corpkey(self, obj):
return f'{obj.corpid}-{obj.agentid}'
class CorpSerializerMixin:
def get_corp(self, corpkey=None):
if not hasattr(self, 'corp'):
if corpkey is None:
corpkey = self.request.query_params.get('corpkey') or self.request.data.get('corpkey')
if corpkey is None:
raise ValidationError('corpkey is required')
uid = self.request.user.pk
expression = get_query_by_corpkey(corpkey)
corp = QcCorpinfo.objects.filter(**expression, uid=uid).first()
if corp is None:
raise CustomProjectException(detail='企业不存在')
setattr(self, 'corp', corp)
return getattr(self, 'corp')
class WechatWorkerMixin(CorpSerializerMixin):
def get_wechat_worker(self):
if not hasattr(self, 'wechat_worker'):
corp = self.get_corp()
wechat_worker = WechatWorkerUtil(corp.corpid, corp.appsecret)
setattr(self, 'wechat_worker', wechat_worker)
return getattr(self, 'wechat_worker')
class SerializerFactory:
@staticmethod
def build(model, fields, **kwargs):
meta = type(str('Meta'), (object,), {'model': model, 'fields': fields})
kwargs.update({'Meta': meta})
serializer_class = type(str('%sModelSerializerByType' %
model._meta.object_name), (BaseSerializer,), kwargs)
return serializer_class

199
utils/base_viewsets.py Normal file
View File

@ -0,0 +1,199 @@
import datetime
from django.db.models import Q
from django.db.models.fields import IntegerField
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated as DRFIsAuthenticated
from rest_framework.viewsets import ModelViewSet, GenericViewSet
from utils.jwt_authenticate import MyJSONWebTokenAuthentication
from utils.pagination import CustomPagination
from utils.response import ApiResponse
from utils.tools import generate_options_by_choices
class IsAuthenticated(DRFIsAuthenticated):
def has_permission(self, request, view):
# 不等于匿名用户
return bool(request.user and str(request.user) != 'AnonymousUser')
class BaseModelViewSet(ModelViewSet):
permission_classes = [IsAuthenticated]
authentication_classes = [MyJSONWebTokenAuthentication]
white_list = []
filter_fields = []
fuzzy_filter_fields = []
exclude_param_blank = False
multi_filter_fields = []
pagination_class = CustomPagination
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
_page = request.query_params.get('page')
page_size = request.query_params.get('page_size')
page = self.paginate_queryset(queryset)
context = self.get_serializer_context()
context['queryset'] = page
if page is not None and any([_page, page_size]):
serializer = self.get_serializer(page, many=True, context=context)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True, context=context)
return ApiResponse(data=serializer.data)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return ApiResponse(data=serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return ApiResponse(data=serializer.data)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(
instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return ApiResponse(data=serializer.data)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if hasattr(instance, 'is_delete'):
instance.is_delete = True
instance.save()
else:
instance.delete()
return ApiResponse(message='删除成功', data=None)
def get_serializer_class(self):
if isinstance(self.serializer_class, dict):
return self.serializer_class.get(self.action) or self.serializer_class.get('default')
return self.serializer_class
def check_permissions(self, request):
if request.method.lower() in ['options']:
return True
if self.action in self.white_list:
return True
return super().check_permissions(request)
def get_queryset(self):
action_queryset_func = getattr(
self, f'filter_{self.action}_queryset', None)
if action_queryset_func is not None and callable(action_queryset_func):
queryset = action_queryset_func()
else:
queryset = super().get_queryset()
q = Q()
if not self.detail:
for key in self.filter_fields:
if key not in self.request.query_params.keys():
continue
value = self.request.query_params.get(key)
if not value and not self.exclude_param_blank:
continue
if key in self.fuzzy_filter_fields:
q.add(Q(**{f'{key}__icontains': value}), Q.AND)
else:
q.add(Q(**{key: value}), Q.AND)
for key in self.multi_filter_fields:
list_key = f'{key}[]'
if list_key in self.request.query_params.keys():
value = self.request.query_params.getlist(list_key)
if value is not None:
q.add(Q(**{f'{key}__in': value}), Q.AND)
if hasattr(self.queryset.model, 'user'):
q.add(Q(user=self.request.user), Q.AND)
if hasattr(self.queryset.model, 'uid'):
uid = self.queryset.model._meta.get_field('uid')
if isinstance(uid, IntegerField):
q.add(Q(Q(uid=self.request.user.id) | Q(uid=0)), Q.AND)
if hasattr(self.queryset.model, 'is_delete'):
q.add(Q(is_delete=False), Q.AND)
if hasattr(self.queryset.model, 'user') and self.action == 'list':
q.add(Q(user_id=self.request.user.id), Q.AND)
# queryset = queryset.select_related('user')
queryset = queryset.filter(q)
return queryset
class OrderDataMixin:
def order_data(self, data):
params = self.request.query_params
field = params.get('field')
if field is None:
return data
order = params.get('order', 'descend')
def sort_fn(obj):
value = obj.get(field)
try:
value = int(value)
return value
except Exception:
try:
return datetime.datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
except Exception:
return datetime.datetime(year=1998, month=2, day=1)
return sorted(data, key=sort_fn, reverse=order == 'descend')
class ChoicesMixin:
choices_map = {}
def get_choices(self):
data = {}
for key, choices in self.choices_map.items():
data[key] = generate_options_by_choices(choices.choices)
return data
@action(methods=['get'], detail=False)
def choices(self, request, *args, **kwargs):
data = self.get_choices()
return ApiResponse(data=data)
class ReadOnlyModelViewSet(BaseModelViewSet):
def destroy(self, request, *args, **kwargs):
return ApiResponse()
def update(self, request, *args, **kwargs):
return ApiResponse()
def create(self, request, *args, **kwargs):
return ApiResponse()
class BaseChoicesModelViewSet(BaseModelViewSet, ChoicesMixin):
pass
class ReadOnlyChoicesModelViewSet(ReadOnlyModelViewSet, ChoicesMixin):
pass
class BaseViewSet(GenericViewSet):
permission_classes = [IsAuthenticated]
authentication_classes = [MyJSONWebTokenAuthentication]
def get_serializer_class(self):
if isinstance(self.serializer_class, dict):
return self.serializer_class.get(self.action) or self.serializer_class.get('default')
return self.serializer_class

21
utils/encryptor.py Normal file
View File

@ -0,0 +1,21 @@
class StringEncryptor:
encrypted_list = ['8', 'h', 'b', '1', '9', 'f', 'p', '0', 'y', 'u', 's', 'i', 'c', 't', '5', 'q', 'e', 'j', 'g',
'v', 'm', '3', 'x', 'a', '6', 'o', '2', '4', 'k', 'n', 'r', 'z', 'd', '7', 'l', 'w']
decrypted_list = ['d', '1', 'r', 'b', '5', 'k', 'f', '9', '7', '8', 'j', 's', '3', '2', 'h', 'w', 'y', 'l', '6',
'4', 'c', 'a', 'v', 'n', 'm', 'o', 'p', 'e', 'q', 'z', '0', 'g', 't', 'i', 'x', 'u']
@classmethod
def encrypt(cls, string):
hashed_string = ''
for s in string:
encrypted_index = cls.encrypted_list.index(s)
hashed_string += cls.decrypted_list[encrypted_index]
return hashed_string
@classmethod
def decrypt(cls, hashed_string):
decrypted_string = ''
for s in hashed_string:
decrypted_index = cls.decrypted_list.index(s)
decrypted_string += cls.encrypted_list[decrypted_index]
return decrypted_string

68
utils/exceptions.py Normal file
View File

@ -0,0 +1,68 @@
import traceback
from django.core.exceptions import PermissionDenied
from django.http import Http404
from rest_framework import exceptions
from rest_framework.views import set_rollback
import logging
from utils.response import ApiResponse
logger = logging.getLogger('log')
def custom_exception(exc, context):
if isinstance(exc, Http404):
exc = exceptions.NotFound()
elif isinstance(exc, PermissionDenied):
exc = exceptions.PermissionDenied()
message = "服务器内部错误"
headers = {}
code = 400
if isinstance(exc, exceptions.APIException):
code = exc.status_code
if getattr(exc, 'auth_header', None):
headers['WWW-Authenticate'] = exc.auth_header
if getattr(exc, 'wait', None):
headers['Retry-After'] = '%d' % exc.wait
if isinstance(exc.detail, dict):
try:
if hasattr(exc.detail.serializer, 'Meta'):
model = exc.detail.serializer.Meta.model
message = ''
for field, e in exc.detail.items():
if hasattr(model, field):
verbose_name = model._meta.get_field(field).verbose_name
# message += verbose_name + ','.join(e) + ','
message += verbose_name
for error in e:
if isinstance(error, str):
message += f',{error}'
if isinstance(error, dict):
values = error.values()
for value in values:
if isinstance(value, list):
message += ',' + ','.join(value)
else:
message += f',{value}'
else:
message += ','.join(e) + ','
else:
message = exc.detail
except Exception:
message = exc.detail
else:
message = exc.detail
set_rollback()
try:
logger.error(traceback.format_exc())
return ApiResponse(code=code, message=str(message), status=200, headers=headers)
except Exception:
logger.error(traceback.format_exc())
return ApiResponse(code=code, message=str(message), status=200, headers=headers)
class CustomProjectException(exceptions.APIException):
pass

20
utils/jwt.py Normal file
View File

@ -0,0 +1,20 @@
def jwt_response_payload_handler(token, user=None, request=None):
"""
Returns the response data for both the login and refresh views.
Override to return a custom response such as including the
serialized representation of the User.
Example:
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user': UserSerializer(user, context={'request': request}).data
}
"""
return {
'id': user.id,
'token': token,
'username': user.username,
}

101
utils/jwt_authenticate.py Normal file
View File

@ -0,0 +1,101 @@
import jwt
from django.utils.translation import gettext_lazy as _
from rest_framework import HTTP_HEADER_ENCODING
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.settings import api_settings
from apps.user.models import User
from utils.redis_utils import RedisUtils
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
jwt_get_username_from_payload = api_settings.JWT_PAYLOAD_GET_USERNAME_HANDLER
def get_authorization_header(request, key='HTTP_AUTHORIZATION'):
"""
Return request's 'Authorization:' header, as a bytestring.
Hide some test client ickyness where the header can be unicode.
"""
auth = request.META.get(key, b'')
if isinstance(auth, str):
# Work around django test client oddness
auth = auth.encode(HTTP_HEADER_ENCODING)
return auth
class MyJSONWebTokenAuthentication(JSONWebTokenAuthentication):
def authenticate(self, request):
"""
Returns a two-tuple of `User` and token if a valid signature has been
supplied using JWT-based authentication. Otherwise returns `None`.
"""
jwt_value = self.get_jwt_value(request)
if jwt_value is None:
return None
redis_utils = RedisUtils("token")
payload = None
try:
payload = redis_utils.read_value_to_object(jwt_value) or jwt_decode_handler(jwt_value)
if not payload:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.ExpiredSignature:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed()
redis_utils.write_value_as_string(jwt_value, payload, 60 * 60 * 30)
user = self.authenticate_credentials(payload)
return user, jwt_value
def authenticate_credentials(self, payload):
"""
Returns an active user that matches the payload's user id and email.
"""
username = jwt_get_username_from_payload(payload)
if not username:
msg = _('Invalid payload.')
raise exceptions.AuthenticationFailed(msg)
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
msg = _('Invalid signature.')
raise exceptions.AuthenticationFailed(msg)
return user
def get_jwt_value(self, request):
auth = get_authorization_header(request)
if not auth:
if api_settings.JWT_AUTH_COOKIE:
return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
return None
return auth
class UserAppSecretAuthentication(BaseAuthentication):
def authenticate(self, request):
app_secret = get_authorization_header(request, key='APP_SECRET')
if not app_secret:
raise exceptions.AuthenticationFailed()
user = User.objects.filter(app_secret=app_secret).first()
if user is None or not user.is_active:
raise exceptions.AuthenticationFailed()
return user, app_secret
def authenticate_header(self, request):
pass

11
utils/logger.py Normal file
View File

@ -0,0 +1,11 @@
import logging
class CustomFileHandler(logging.FileHandler):
def _get_or_create_filename(self, suffix):
# Override the method to include the date in the filename
if self.stream is None:
# Reopen the file with a new filename that includes the date
filename = self.baseFilename + suffix
self.stream = self._open(filename, 'a')
return self.baseFilename

49
utils/pagination.py Normal file
View File

@ -0,0 +1,49 @@
from collections import OrderedDict
from django.core.paginator import InvalidPage
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
class CustomPagination(PageNumberPagination):
page_size = 9999
page_query_param = 'page'
page_size_query_param = 'page_size'
max_page_size = 1000
def __init__(self):
self.total = 0
def paginate_queryset(self, queryset, request, view=None):
page_size = self.get_page_size(request)
if not page_size:
return None
paginator = self.django_paginator_class(queryset, page_size)
page_number = self.get_page_number(request, paginator)
self.total = paginator.count
#
# if (total // page_size) == 0:
# page_number = 1
# else:
# page_number = (total // page_size) if int(page_number) > (total // page_size) + 1 else page_number
try:
self.page = paginator.page(page_number)
except InvalidPage as exc:
return []
if paginator.num_pages > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True
self.request = request
return list(self.page)
def get_paginated_response(self, data):
return Response(OrderedDict([
('total', self.total),
('code', 0),
('message', 'ok'),
('result', data),
]))

39
utils/redis_utils.py Normal file
View File

@ -0,0 +1,39 @@
import json
from django_redis import get_redis_connection
class RedisUtils:
def __init__(self, cache='default'):
self.redis_conn = get_redis_connection(cache)
def write_value_as_string(self, key, value, ex=None):
if ex:
return self.set_ex(key, ex, json.dumps(value))
return self.set(key, json.dumps(value))
def read_value_to_object(self, key):
value = self.redis_conn.get(key)
if value:
return json.loads(value)
def set(self, key, value):
return self.redis_conn.set(key, value)
def get(self, key):
value = self.redis_conn.get(key)
if value:
return value.decode()
def set_ex(self, key, timeout, value):
return self.redis_conn.setex(key, time=timeout, value=value)
def hset(self, key, field, value):
return self.redis_conn.hset(key, field, value)
def hget(self, key, field):
value = self.redis_conn.hget(key, field)
return value and value.decode()
def delete(self, key):
return self.redis_conn.delete(key)

11
utils/renders.py Normal file
View File

@ -0,0 +1,11 @@
from rest_framework import renderers
class FileRender(renderers.BaseRenderer):
charset = None
render_style = 'binary'
media_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
format = 'xls'
def render(self, data, accepted_media_type=None, renderer_context=None):
return data.get('data')

19
utils/response.py Normal file
View File

@ -0,0 +1,19 @@
from rest_framework.response import Response
class ApiResponse(Response):
def __init__(self, code=None, message="ok", data=None, status=200, total=None, res_type='success',
template_name=None, headers=None, exception=False, content_type='application/json'):
super(Response, self).__init__(None, status=status)
code = code or 0
self.data = {"code": code, "message": message, "result": data, 'type': res_type}
if total:
self.data.update({'total': total})
self.template_name = template_name
self.exception = exception
self.content_type = content_type
if headers:
for name, value in headers.items():
self[name] = value

42
utils/throttling.py Normal file
View File

@ -0,0 +1,42 @@
from django.core.exceptions import ImproperlyConfigured
from rest_framework.exceptions import APIException
from rest_framework.throttling import SimpleRateThrottle
class ThrottleBase(SimpleRateThrottle):
"""
接口访问频率限制基类
"""
throttled_message = '请求评率超过限制'
rate = '3/m'
def get_cache_key(self, request, view):
super().get_cache_key(request, view)
def allow_request(self, request, view):
flag = super().allow_request(request, view)
if not flag:
raise APIException(detail=self.throttled_message, code=500)
return flag
def get_rate(self):
"""
Determine the string representation of the allowed request rate.
"""
if not getattr(self, 'scope', None):
msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
self.__class__.__name__)
raise ImproperlyConfigured(msg)
return self.rate
class PhoneCodeThrottle(ThrottleBase):
rate = '1/m'
scope = "phone_code"
throttled_message = "您的请求频率过快,请稍后再试。"
def get_cache_key(self, request, view):
return self.cache_format % {
'scope': self.scope,
'ident': f"{request.data.get('mobile')}-{request.data.get('business')}"
}

243
utils/tools.py Normal file
View File

@ -0,0 +1,243 @@
import datetime
import random
import re
from hashlib import md5
from typing import Any
import uuid
from calendar import timegm
from rest_framework_jwt.serializers import jwt_encode_handler
from rest_framework_jwt.settings import api_settings
def convert_to_relative_time(time_string):
# 将时间字符串转换为datetime对象
if not isinstance(time_string, datetime.datetime):
time = datetime.datetime.strptime(time_string, "%Y-%m-%d %H:%M:%S")
else:
time = time_string
# 获取当前时间
current_time = datetime.datetime.now()
# 计算时间差
time_difference = current_time - time
# 提取相对时间的各个单位
days = time_difference.days
seconds = time_difference.seconds
minutes = seconds // 60
hours = minutes // 60
# 根据时间差生成相对时间字符串
if days > 0:
return f"{days}天前"
elif hours > 0:
return f"{hours}小时前"
elif minutes > 0:
return f"{minutes}分钟前"
else:
return "刚刚"
def generate_options_by_choices(choices):
data = []
for value, label in choices:
data.append({
'value': value,
'label': label,
})
return data
def jwt_payload_handler(user):
username_field = 'username'
username = user.username
payload = {
'user_id': user.pk,
'username': username,
'exp': datetime.datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA
}
if hasattr(user, 'email'):
payload['email'] = user.email
if isinstance(user.pk, uuid.UUID):
payload['user_id'] = str(user.pk)
payload[username_field] = username
# Include original issued at time for a brand new token,
# to allow token refresh
if api_settings.JWT_ALLOW_REFRESH:
payload['orig_iat'] = timegm(
datetime.datetime.utcnow().utctimetuple()
)
if api_settings.JWT_AUDIENCE is not None:
payload['aud'] = api_settings.JWT_AUDIENCE
if api_settings.JWT_ISSUER is not None:
payload['iss'] = api_settings.JWT_ISSUER
return payload
def create_jwt(user):
payload = jwt_payload_handler(user)
return jwt_encode_handler(payload)
def generate_columns(model):
columns = []
fields = model._meta.fields
for field in fields:
column = {
"title": field.verbose_name,
"dataIndex": field.name,
"align": 'center',
"slots": {"customRender": field.name},
}
columns.append(column)
return columns
def md5_obj(byte_obj: Any):
md = md5()
md.update(byte_obj)
return md.hexdigest()
class InviteCode:
r1 = ["Z", "X", "9", "L", "C", "7", "P", "Q", "W", "E", "8", "S", "2", "D", "5", "K", "3", "M", "J", "U", "F", "R",
"4", "V", "Y", "T", "N", "6", "B", "G", "H"]
r2 = ["C", "P", "K", "M", "Q", "W", "E", "S", "D", "Z", "X", "L", "J", "U", "F", "R", "V", "Y", "T", "N", "B", "G",
"H", "A"]
r3 = ["P", "5", "K", "3", "M", "J", "U", "F", "Q", "L", "W", "E", "8", "S", "2", "D", "Z", "X", "9", "Y", "T", "N",
"6", "B", "G", "H", "C", "7", "R", "4", "V"]
r4 = ["J", "U", "F", "R", "V", "Y", "Q", "W", "E", "S", "L", "K", "M", "D", "Z", "X", "A", "C", "P", "G", "H", "T",
"N", "B"]
r5 = ["M", "J", "U", "F", "R", "4", "Q", "W", "E", "8", "S", "2", "D", "Z", "X", "9", "L", "C", "7", "P", "5", "K",
"3", "V", "Y", "T", "N", "6", "B", "G", "H"]
r6 = ["Y", "T", "N", "B", "G", "H", "L", "C", "P", "Q", "W", "E", "S", "D", "Z", "X", "R", "V", "K", "M", "J", "U",
"F", "A"]
r7 = ["X", "9", "L", "C", "7", "P", "5", "K", "3", "Q", "W", "E", "8", "S", "2", "D", "Z", "M", "J", "U", "F", "R",
"4", "V", "Y", "T", "N", "6", "B", "G", "H"]
@staticmethod
def create_code(id):
bin_len = 31
ind = 0
i = 1
builder = []
while id / bin_len > 0:
ind = int(id % bin_len)
if ind != 0 or (ind == 0 and id == bin_len) or (ind == 0 or i == 1):
if i == 1:
builder.append(InviteCode.r7[ind])
id = int(id / len(InviteCode.r7))
bin_len = len(InviteCode.r6)
elif i == 2:
builder.append(InviteCode.r6[ind])
id = int(id / len(InviteCode.r6))
bin_len = len(InviteCode.r5)
elif i == 3:
builder.append(InviteCode.r5[ind])
id = int(id / len(InviteCode.r5))
bin_len = len(InviteCode.r4)
elif i == 4:
builder.append(InviteCode.r4[ind])
id = int(id / len(InviteCode.r4))
bin_len = len(InviteCode.r3)
elif i == 5:
builder.append(InviteCode.r3[ind])
id = int(id / len(InviteCode.r3))
bin_len = len(InviteCode.r2)
elif i == 6:
builder.append(InviteCode.r2[ind])
id = int(id / len(InviteCode.r2))
bin_len = len(InviteCode.r1)
elif i == 7:
builder.append(InviteCode.r1[ind])
id = int(id / len(InviteCode.r1))
bin_len = len(InviteCode.r1)
i += 1
index = 0
first_index = id if id > 0 and id / bin_len == 0 else 0
if i == 1:
builder.append(
InviteCode.r7[id] + InviteCode.r6[index] + InviteCode.r5[index] + InviteCode.r4[index] + InviteCode.r3[
index] + InviteCode.r2[index] + InviteCode.r1[index])
elif i == 2:
builder.append(
InviteCode.r6[first_index] + InviteCode.r5[index] + InviteCode.r4[index] + InviteCode.r3[index] +
InviteCode.r2[index] + InviteCode.r1[index])
elif i == 3:
builder.append(
InviteCode.r5[first_index] + InviteCode.r4[index] + InviteCode.r3[index] + InviteCode.r2[index] +
InviteCode.r1[index])
elif i == 4:
builder.append(
InviteCode.r4[first_index] + InviteCode.r3[index] + InviteCode.r2[index] + InviteCode.r1[index])
elif i == 5:
builder.append(InviteCode.r3[first_index] + InviteCode.r2[index] + InviteCode.r1[index])
elif i == 6:
builder.append(InviteCode.r2[first_index] + InviteCode.r1[index])
elif i == 7:
builder.append(InviteCode.r1[first_index])
str = ''.join(builder)
res = str[::-1]
code = res
return code
@staticmethod
def decode(code):
chs = list(code)
res = 0
c1 = chs[0]
index_of_c1 = InviteCode.r1.index(c1)
if index_of_c1 > 0:
temp = 24 * 31 * 24 * 31 * 24 * 31
res += index_of_c1 * temp
c2 = chs[1]
index_of_c2 = InviteCode.r2.index(c2)
if index_of_c2 > 0:
temp = 31 * 24 * 31 * 24 * 31
res += index_of_c2 * temp
c3 = chs[2]
index_of_c3 = InviteCode.r3.index(c3)
if index_of_c3 > 0:
temp = 24 * 31 * 24 * 31
res += index_of_c3 * temp
c4 = chs[3]
index_of_c4 = InviteCode.r4.index(c4)
if index_of_c4 > 0:
temp = 31 * 24 * 31
res += index_of_c4 * temp
c5 = chs[4]
index_of_c5 = InviteCode.r5.index(c5)
if index_of_c5 > 0:
temp = 24 * 31
res += index_of_c5 * temp
c6 = chs[5]
index_of_c6 = InviteCode.r6.index(c6)
if index_of_c6 > 0:
temp = 31
res += index_of_c6 * temp
c7 = chs[6]
index_of_c7 = InviteCode.r7.index(c7)
if index_of_c7 > 0:
res += index_of_c7 * 1
return res
def is_mobile(mobile):
return bool(re.match(r'^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$', mobile))
def generate_phone_code(length=6) -> str:
""" 生成手机验证码 """
number_list = range(0, 10)
return ''.join(map(lambda i: str(i), random.choices(number_list, k=length)))

View File

16
yzk_wechat_event/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for yzk_wechat_event project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'yzk_wechat_event.settings')
application = get_asgi_application()

Some files were not shown because too many files have changed in this diff Show More