聊天配对群组ID与准备接口:打手商家同群、订单卡片推送

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-06-23 22:49:28 +08:00
parent 7daa05c8c6
commit 2db394b2f9
3 changed files with 229 additions and 20 deletions

View File

@@ -10,6 +10,65 @@ from yonghu.models import UserMain, UserDashou, UserBoss, UserShangjia
logger = logging.getLogger('chat_utils')
ORDER_CARD_PREFIX = '[ORDER_CARD]'
def make_dashou_shangjia_group_id(dashou_yonghuid, shangjia_yonghuid):
return f"group_Ds{dashou_yonghuid}_Sj{shangjia_yonghuid}"
def make_dashou_boss_group_id(dashou_yonghuid, boss_yonghuid):
return f"group_Ds{dashou_yonghuid}_Boss{boss_yonghuid}"
def _get_shangjia_id_from_order(order):
try:
return order.shangjia_kuozhan.shangjia_id
except Exception:
ext = DingdanShangjia.objects.filter(dingdan__dingdan_id=order.dingdan_id).first()
return ext.shangjia_id if ext else None
def _get_boss_id_from_order(order):
try:
return order.pingtai_kuozhan.laoban_id
except Exception:
ext = DingdanPingtai.objects.filter(dingdan__dingdan_id=order.dingdan_id).first()
return ext.laoban_id if ext else None
def resolve_group_id_for_order(order, dashou_yonghuid=None):
"""打手+商家/老板配对群 ID跨平台或缺信息时回退订单群 ID"""
dashou_yonghuid = dashou_yonghuid or order.jiedan_dashou_id
if order.is_cross == 1 and order.dispatch_type == 2:
return f"group_{order.dingdan_id}"
if not dashou_yonghuid:
return f"group_{order.dingdan_id}"
if order.fadan_pingtai == 2:
shangjia_id = _get_shangjia_id_from_order(order)
if shangjia_id:
return make_dashou_shangjia_group_id(dashou_yonghuid, shangjia_id)
elif order.fadan_pingtai == 1:
boss_id = _get_boss_id_from_order(order)
if boss_id:
return make_dashou_boss_group_id(dashou_yonghuid, boss_id)
return f"group_{order.dingdan_id}"
def _build_order_card_text(order):
payload = {
'dingdan_id': order.dingdan_id,
'jieshao': order.jieshao or '',
'beizhu': order.beizhu or '',
'jine': str(order.jine),
'zhuangtai': order.zhuangtai,
'nicheng': order.nicheng or '',
}
if order.create_time:
payload['create_time'] = order.create_time.strftime('%Y-%m-%d %H:%M:%S')
return ORDER_CARD_PREFIX + json.dumps(payload, ensure_ascii=False)
# ========== 辅助配置获取(从 ClubConfig ==========
def _get_self_club_config():
if not hasattr(_get_self_club_config, '_config'):
@@ -91,7 +150,8 @@ def _subscribe_users_to_group(user_ids, group_ids, appkey=None, secret=None):
# ========== 发送群消息(完整参数) ==========
def _send_group_message(appkey, secret, group_id, sender_id, sender_name, sender_avatar,
message_text, custom_payload=None, group_name=None, order_id=None, is_cross=0):
message_text, custom_payload=None, group_name=None, order_id=None, is_cross=0,
list_avatar=None, order_desc=None):
if not appkey:
appkey = _get_self_goeasy_appkey()
if not secret:
@@ -105,10 +165,12 @@ def _send_group_message(appkey, secret, group_id, sender_id, sender_name, sender
# to.data 包含群聊展示信息及业务字段
to_data = {
"name": group_name or group_id,
"avatar": sender_avatar or "",
"avatar": list_avatar or sender_avatar or "",
}
if order_id:
to_data["orderId"] = order_id
if order_desc:
to_data["orderDesc"] = order_desc[:300]
to_data["isCross"] = is_cross
payload_str = custom_payload.get("text", message_text) if custom_payload else message_text
@@ -305,12 +367,106 @@ def establish_order_chat_with_retry(dingdan_id, max_rounds=3):
return False
# ========== 普通订单 / 我方派单 ==========
def _push_order_card_message(appkey, secret, order, group_id, sender_id, sender_name, sender_avatar,
group_name, list_avatar, order_desc):
card_text = _build_order_card_text(order)
return _send_group_message(
appkey, secret, group_id, sender_id, sender_name, sender_avatar,
card_text, None, group_name=group_name, order_id=order.dingdan_id,
is_cross=order.is_cross or 0, list_avatar=list_avatar, order_desc=order_desc
)
def prepare_order_group_chat(dingdan_id, caller_goeasy_id, push_order_card=False):
"""
订单详情进入聊天前:确保配对群已订阅,可选推送订单卡片。
返回前端跳转所需字段 dict失败返回 None。
"""
try:
order = Dingdan.objects.select_related('pingtai_kuozhan', 'shangjia_kuozhan').get(dingdan_id=dingdan_id)
except Dingdan.DoesNotExist:
logger.error(f"prepare_order_group_chat: 订单 {dingdan_id} 不存在")
return None
dashou_uid = order.jiedan_dashou_id
if not dashou_uid:
logger.error(f"prepare_order_group_chat: 订单 {dingdan_id} 无接单打手")
return None
dashou_goeasy_id = f"Ds{dashou_uid}"
partner_goeasy_id, partner_name, partner_avatar = _get_local_partner_info(order)
if not partner_goeasy_id:
logger.error(f"prepare_order_group_chat: 订单 {dingdan_id} 无下单方")
return None
group_id = resolve_group_id_for_order(order, dashou_uid)
dashou_name, dashou_avatar = _resolve_goeasy_user_display(dashou_goeasy_id)
if caller_goeasy_id == dashou_goeasy_id:
counterpart_id = partner_goeasy_id
counterpart_name = partner_name
counterpart_avatar = partner_avatar
elif caller_goeasy_id == partner_goeasy_id:
counterpart_id = dashou_goeasy_id
counterpart_name = dashou_name
counterpart_avatar = dashou_avatar
else:
logger.warning(f"prepare_order_group_chat: caller {caller_goeasy_id} 不属于订单 {dingdan_id}")
return None
appkey = _get_self_goeasy_appkey()
secret = _get_self_goeasy_secret()
if not appkey:
return None
order_desc = (order.jieshao or '').strip()
if order.beizhu:
order_desc = f"{order_desc} | 备注:{order.beizhu}" if order_desc else f"备注:{order.beizhu}"
display_group_name = counterpart_name or '聊天'
user_ids = list({dashou_goeasy_id, partner_goeasy_id, caller_goeasy_id})
subscribe_ok = _retry_call(
_subscribe_users_to_group, 5, 0.4,
user_ids, [group_id], appkey, secret
)
card_ok = False
if push_order_card:
caller_name, caller_avatar = _resolve_goeasy_user_display(caller_goeasy_id)
card_ok = _retry_call(
_push_order_card_message, 3, 0.4,
appkey, secret, order, group_id, caller_goeasy_id, caller_name, caller_avatar,
display_group_name, counterpart_avatar, order_desc
)
_ensure_liaotian_record(group_id, partner_goeasy_id, dashou_goeasy_id)
return {
'groupId': group_id,
'orderId': order.dingdan_id,
'groupName': display_group_name,
'groupAvatar': counterpart_avatar or '',
'counterpartId': counterpart_id,
'counterpartName': counterpart_name,
'counterpartAvatar': counterpart_avatar or '',
'orderDesc': order_desc,
'orderJine': str(order.jine),
'orderZhuangtai': order.zhuangtai,
'isCross': 1 if order.is_cross == 1 else 0,
'subscribeOk': subscribe_ok,
'orderCardPushed': card_ok,
}
def _handle_local_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, appkey, secret):
group_id = f"group_{order.dingdan_id}"
group_name = (order.jieshao[:20] + '') if order.jieshao and len(order.jieshao) > 20 else (order.jieshao or f"订单{order.dingdan_id}")
group_avatar = _full_local_avatar(order.tupian) if order.tupian else _full_local_avatar('')
dashou_uid = dashou_goeasy_id[2:] if dashou_goeasy_id.startswith('Ds') else dashou_goeasy_id
group_id = resolve_group_id_for_order(order, dashou_uid)
partner_goeasy_id, partner_name, partner_avatar = _get_local_partner_info(order)
group_name = partner_name or f"用户{partner_goeasy_id[-6:] if partner_goeasy_id else ''}"
order_desc = (order.jieshao or '').strip()
if order.beizhu:
order_desc = f"{order_desc} | 备注:{order.beizhu}" if order_desc else f"备注:{order.beizhu}"
if not partner_goeasy_id:
logger.error(f"订单 {order.dingdan_id} 无法获取下单方 GoEasy 标识")
subscribe_ok = _retry_call(
@@ -319,9 +475,10 @@ def _handle_local_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, app
)
msg_ok = _retry_call(
_send_group_message, 3, 0.4,
appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
appkey, secret, group_id, dashou_goeasy_id, dashou_name, dashou_avatar,
"订单已接单,请等待对方上线。", None, group_name=group_name,
order_id=order.dingdan_id, is_cross=order.is_cross
order_id=order.dingdan_id, is_cross=order.is_cross,
list_avatar=partner_avatar, order_desc=order_desc
)
return subscribe_ok or msg_ok
@@ -333,9 +490,9 @@ def _handle_local_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, app
init_msg_text = f"订单已接单,内容:{order.jieshao},备注:{order.beizhu}游戏ID{order.nicheng}"
success1 = _retry_call(
_send_group_message, 3, 0.4,
appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
appkey, secret, group_id, dashou_goeasy_id, dashou_name, dashou_avatar,
init_msg_text, None, group_name=group_name, order_id=order.dingdan_id,
is_cross=order.is_cross
is_cross=order.is_cross, list_avatar=partner_avatar, order_desc=order_desc
)
partner_msg = "订单已确认,请开始服务。"
@@ -343,16 +500,22 @@ def _handle_local_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, app
_send_group_message, 3, 0.4,
appkey, secret, group_id, partner_goeasy_id, partner_name, partner_avatar,
partner_msg, None, group_name=group_name, order_id=order.dingdan_id,
is_cross=order.is_cross
is_cross=order.is_cross, list_avatar=dashou_avatar, order_desc=order_desc
)
liaotian_ok = _ensure_liaotian_record(order.dingdan_id, partner_goeasy_id, dashou_goeasy_id)
card_ok = _retry_call(
_push_order_card_message, 3, 0.4,
appkey, secret, order, group_id, dashou_goeasy_id, dashou_name, dashou_avatar,
group_name, partner_avatar, order_desc
)
liaotian_ok = _ensure_liaotian_record(group_id, partner_goeasy_id, dashou_goeasy_id)
private_ok = _establish_private_chat(
appkey, secret, dashou_goeasy_id, dashou_name, dashou_avatar,
partner_goeasy_id, partner_name, partner_avatar
)
result = subscribe_ok or success1 or success2 or liaotian_ok or private_ok
result = subscribe_ok or success1 or success2 or card_ok or liaotian_ok or private_ok
if not result:
logger.error(f"订单 {order.dingdan_id} 群聊/私聊均未建立成功")
return result
@@ -525,17 +688,21 @@ def _get_cross_partner_identity(order, partner_order_id):
return f"User{uid}"
def _create_local_group_only(order, dashou_goeasy_id, dashou_name, dashou_avatar, appkey, secret):
group_id = f"group_{order.dingdan_id}"
group_name = (order.jieshao[:20] + '') if order.jieshao and len(order.jieshao) > 20 else (order.jieshao or f"订单{order.dingdan_id}")
group_avatar = _full_local_avatar(order.tupian) if order.tupian else _full_local_avatar('')
dashou_uid = dashou_goeasy_id[2:] if dashou_goeasy_id.startswith('Ds') else dashou_goeasy_id
group_id = resolve_group_id_for_order(order, dashou_uid)
partner_goeasy_id, partner_name, partner_avatar = _get_local_partner_info(order)
group_name = partner_name or (order.jieshao or f"订单{order.dingdan_id}")
order_desc = (order.jieshao or '').strip()
if order.beizhu:
order_desc = f"{order_desc} | 备注:{order.beizhu}" if order_desc else f"备注:{order.beizhu}"
subscribe_ok = _retry_call(
_subscribe_users_to_group, 5, 0.4,
[dashou_goeasy_id], [group_id], appkey, secret
)
msg_ok = _retry_call(
_send_group_message, 3, 0.4,
appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
appkey, secret, group_id, dashou_goeasy_id, dashou_name, dashou_avatar,
"订单已接单。", None, group_name=group_name, order_id=order.dingdan_id,
is_cross=order.is_cross
is_cross=order.is_cross, list_avatar=partner_avatar, order_desc=order_desc
)
return subscribe_ok or msg_ok