""" 订单服务号模板消息广播 — 统一入口(Celery 异步,接口立即返回) """ import logging from utils.xcx_sys_config import wx_cfg logger = logging.getLogger('weixin_broadcast') def _game_type_name(leixing_id): try: from shangpin.models import ShangpinLeixing gt = ShangpinLeixing.objects.filter(id=leixing_id).first() return gt.jieshao if gt else '游戏订单' except Exception: return '游戏订单' def build_order_broadcast_payload(dingdan, order_type='普通订单', game_type=None): return { 'dingdan_id': dingdan.dingdan_id, 'game_type': game_type or _game_type_name(dingdan.leixing_id), 'amount': str(dingdan.jine), 'order_desc': (dingdan.jieshao or '')[:50], 'order_type': order_type, } def submit_dingdan_guangbo(order_info): """提交 Celery 广播任务(broadcast 优先队列)""" if not wx_cfg.WEIXIN_BROADCAST_ENABLED: logger.info('服务号广播已关闭,跳过') return False if not order_info or not order_info.get('dingdan_id'): return False try: from dingdan.tongzhi_tasks import dingdan_guangbo dingdan_guangbo.apply_async( args=[order_info], queue='broadcast', priority=9, countdown=0, ) logger.info(f'已提交服务号广播任务: {order_info.get("dingdan_id")}') return True except Exception as e: logger.error(f'Celery 广播提交失败,降级线程发送: {e}', exc_info=True) _fallback_thread_broadcast(order_info) return False def schedule_dingdan_guangbo_from_order(dingdan, order_type='普通订单', game_type=None): """根据订单对象构建 payload 并提交广播""" order_info = build_order_broadcast_payload(dingdan, order_type=order_type, game_type=game_type) return submit_dingdan_guangbo(order_info) def _fallback_thread_broadcast(order_info): """Celery 不可用时,后台线程并发发送(不阻塞下单接口)""" import threading from utils.weixin_broadcast import WeixinBroadcastSender def _run(): try: sender = WeixinBroadcastSender() sender.broadcast_parallel(order_info) except Exception as ex: logger.error(f'线程降级广播失败: {ex}', exc_info=True) t = threading.Thread(target=_run, daemon=True) t.start()