's'
This commit is contained in:
@@ -14,6 +14,7 @@ from Crypto.Cipher import AES
|
||||
from fastapi import APIRouter, BackgroundTasks, HTTPException, Request
|
||||
from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
|
||||
|
||||
from ..services.chatbot_miniprogram_card import build_miniprogram_card_msg, normalize_miniprogrampage_msg
|
||||
from ..services.mp_recommend import is_mp_recommend_webhook_body, try_persist_from_like_body
|
||||
from ..services.wechat_private_user_pb import (
|
||||
contact_avatar_url,
|
||||
@@ -114,12 +115,14 @@ def aes_encrypt_base64(plaintext: str, encoding_aes_key: str, app_id: str | None
|
||||
|
||||
|
||||
class SharedChatbotReply(NamedTuple):
|
||||
"""全公众号配置共用的解析结果:要么 H5 图文,要么兜底纯文本(含超链)。"""
|
||||
"""全公众号配置共用的解析结果:H5 图文、小程序卡片,或兜底纯文本(含超链)。"""
|
||||
|
||||
h5_message: Optional[dict]
|
||||
"""与「发送客服消息」H5 一致:{\"news\": {\"articles\": [...]}};关键词为 Query 子串包含命中,未命中时为 None。"""
|
||||
text_fallback: str
|
||||
"""未命中关键词时的 short_answer 文案(可含 <a href>)。"""
|
||||
miniprogram_message: Optional[dict]
|
||||
"""与「发送客服消息」小程序卡片一致:{\"miniprogrampage\": {...}};未命中「小程序卡片」时为 None。"""
|
||||
|
||||
|
||||
def _normalize_h5_msg_per_wechat_doc(h5_message: dict) -> dict:
|
||||
@@ -155,6 +158,7 @@ def shared_build_h5_keyword_message(query: str, user_id: str, profile_key: str)
|
||||
|
||||
命中规则:对用户 Query 首尾 trim 后,**包含**配置词作为连续子串即命中(子串匹配),
|
||||
不要求用户整句与关键词全等。群卡片统一按「群」子串命中。
|
||||
「小程序卡片」在 shared_resolve_reply 中优先处理,不在此函数返回。
|
||||
"""
|
||||
q = (query or "").strip()
|
||||
uid = (user_id or "").strip()
|
||||
@@ -192,7 +196,7 @@ def shared_build_h5_keyword_message(query: str, user_id: str, profile_key: str)
|
||||
|
||||
def build_fallback_reply_plain_text(user_id: str) -> str:
|
||||
"""
|
||||
兜底回复(单独构建):未命中「电子书」「群」等关键词时使用。
|
||||
兜底回复(单独构建):未命中「小程序卡片」「电子书」「群」等关键词时使用。
|
||||
/chatbot、/hackrobot 共用同一文案与链接逻辑,仅解密密钥因 profile 不同。
|
||||
"""
|
||||
uid = (user_id or "").strip()
|
||||
@@ -201,13 +205,16 @@ def build_fallback_reply_plain_text(user_id: str) -> str:
|
||||
|
||||
|
||||
def shared_resolve_reply(data: dict, profile_key: str) -> SharedChatbotReply:
|
||||
"""根据解密后的 data 与 profile 决定 H5 或兜底;关键词按 Query 子串包含判断,无命中时走 build_fallback_reply_plain_text。"""
|
||||
"""根据解密后的 data 与 profile 决定小程序卡片、H5 或兜底;关键词按 Query 子串包含判断,无命中时走 build_fallback_reply_plain_text。"""
|
||||
user_id = str(data.get("UserId", "") or data.get("userId", "") or "").strip()
|
||||
query = str(data.get("Query", "") or "").strip()
|
||||
if "小程序卡片" in query:
|
||||
mp = build_miniprogram_card_msg(user_id=user_id)
|
||||
return SharedChatbotReply(None, "", mp)
|
||||
h5 = shared_build_h5_keyword_message(query, user_id, profile_key)
|
||||
if h5:
|
||||
return SharedChatbotReply(h5, "")
|
||||
return SharedChatbotReply(None, build_fallback_reply_plain_text(user_id))
|
||||
return SharedChatbotReply(h5, "", None)
|
||||
return SharedChatbotReply(None, build_fallback_reply_plain_text(user_id), None)
|
||||
|
||||
|
||||
def shared_build_openapi_text_answer(short_answer: str) -> dict:
|
||||
@@ -225,7 +232,8 @@ def _xml_channel_h5_envelope(data: dict, h5_message: dict) -> dict:
|
||||
|
||||
def _openapi_json_h5_answer_per_sendmsg_doc(msg: dict) -> dict:
|
||||
"""
|
||||
开放 API JSON 入站命中 H5:与文档「发送客服消息」一致,msg 为 { news: { articles: [...] } }。
|
||||
开放 API JSON 入站命中 H5 / 小程序卡片:与文档「发送客服消息」一致。
|
||||
msg 为 { news: { articles: [...] } } 或 { miniprogrampage: {...} }。
|
||||
第三方回调侧将该 msg 序列化为 JSON 字符串,放入 answer_type=text 的 text_info.short_answer
|
||||
(与客服接口里 msg 对象同源结构,由网关解析为卡片)。
|
||||
"""
|
||||
@@ -261,6 +269,13 @@ def shared_build_plain_body_for_wechat_callback(
|
||||
fmt = (payload_format or "").strip().lower()
|
||||
is_xml = fmt == "xml"
|
||||
|
||||
if reply.miniprogram_message:
|
||||
msg = normalize_miniprogrampage_msg(reply.miniprogram_message)
|
||||
if is_xml:
|
||||
return _xml_channel_h5_envelope(data, msg)
|
||||
body = _openapi_json_h5_answer_per_sendmsg_doc(msg)
|
||||
return _openapi_json_merge_request_echo(data, body)
|
||||
|
||||
if reply.h5_message:
|
||||
msg = _normalize_h5_msg_per_wechat_doc(reply.h5_message)
|
||||
if is_xml:
|
||||
|
||||
Reference in New Issue
Block a user