落地海运私聊文字询价全流程,海运多项费用改走文本明细,避免企微卡片引用条截断。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-15 14:26:09 +08:00
co-authored by Cursor
parent 58b3c2f3e6
commit 0a3c74e3a1
41 changed files with 3702 additions and 48 deletions
@@ -218,6 +218,101 @@ class WeComAppClient:
)
return media_id, WeComSendResult(ok=True, errcode=0, raw=data)
def create_group(self, *, name: str, userids: list[str]) -> dict[str, Any]:
"""
创建企微应用群(appchat/create),群名=工单号。
成员须含销售、产品、会话存档账号(询价机器人);应用自己会进群。失败回 ok=False,不抛给回调。
"""
users = [str(x).strip() for x in userids if str(x).strip()]
if not name or len(users) < 2:
return {"ok": False, "error": "name_or_users", "chat_id": ""}
try:
token = self._get_token()
except Exception as exc: # noqa: BLE001
logger.exception("建群取 token 失败")
return {"ok": False, "error": str(exc), "chat_id": ""}
url = f"{self._api_base}/cgi-bin/appchat/create"
body = {"name": name, "userlist": users}
try:
with httpx.Client(timeout=self._timeout) as client:
resp = client.post(url, params={"access_token": token}, json=body)
data = resp.json()
except Exception as exc: # noqa: BLE001
logger.exception("企微建群网络失败")
return {"ok": False, "error": str(exc), "chat_id": ""}
errcode = int(data.get("errcode") or 0)
chat_id = str(data.get("chatid") or data.get("chat_id") or "")
if errcode != 0 or not chat_id:
logger.warning("企微建群失败 errcode=%s", errcode)
return {
"ok": False,
"error": str(data.get("errmsg") or f"errcode_{errcode}"),
"chat_id": "",
}
logger.info("企微群已创建 name=%s chat=%s", name, chat_id)
return {"ok": True, "chat_id": chat_id, "error": ""}
def add_group_members(self, *, chat_id: str, userids: list[str]) -> dict[str, Any]:
"""
往已有应用群补人(appchat/update add_user_list)。
用于已建群补拉会话存档账号。已在群里的人企微会忽略。不抛给回调。
"""
users = [str(x).strip() for x in userids if str(x).strip()]
if not chat_id or not users:
return {"ok": False, "error": "chat_or_users"}
try:
token = self._get_token()
except Exception as exc: # noqa: BLE001
logger.exception("补拉群成员取 token 失败")
return {"ok": False, "error": str(exc)}
url = f"{self._api_base}/cgi-bin/appchat/update"
body = {"chatid": chat_id, "add_user_list": users}
try:
with httpx.Client(timeout=self._timeout) as client:
resp = client.post(url, params={"access_token": token}, json=body)
data = resp.json()
except Exception as exc: # noqa: BLE001
logger.exception("企微补拉群成员网络失败")
return {"ok": False, "error": str(exc)}
errcode = int(data.get("errcode") or 0)
if errcode != 0:
logger.warning("企微补拉群成员失败 errcode=%s", errcode)
return {"ok": False, "error": str(data.get("errmsg") or f"errcode_{errcode}")}
logger.info("企微群已补人 chat=%s", chat_id)
return {"ok": True, "error": ""}
def send_group(self, *, chat_id: str, content: str) -> dict[str, Any]:
"""
向应用群发文本。必须走 appchat/send,不能当私聊 message/send。
失败回 ok=False,由调用方决定是否重试;不抛给回调线程。
"""
if not chat_id or not content:
return {"ok": False, "error": "chat_or_content"}
if not self._corp_id or not self._secret:
return {"ok": False, "error": "WECOM_CORP_ID/SECRET 未配置"}
try:
token = self._get_token()
except Exception as exc: # noqa: BLE001
logger.exception("群消息取 token 失败")
return {"ok": False, "error": str(exc)}
url = f"{self._api_base}/cgi-bin/appchat/send"
body = {"chatid": chat_id, "msgtype": "text", "text": {"content": content}}
try:
with httpx.Client(timeout=self._timeout) as client:
resp = client.post(url, params={"access_token": token}, json=body)
data = resp.json()
except Exception as exc: # noqa: BLE001
logger.exception("企微群消息网络失败")
return {"ok": False, "error": str(exc)}
errcode = int(data.get("errcode") or 0)
if errcode != 0:
logger.warning("企微群消息失败 errcode=%s", errcode)
return {"ok": False, "error": str(data.get("errmsg") or f"errcode_{errcode}")}
return {"ok": True, "error": ""}
def send_text(self, *, touser: str, content: str) -> WeComSendResult:
"""
向指定企微 userid 发送文本应用消息。