"""按支付流水选择退款通道:付呗单走付呗,其余走原微信退款逻辑。""" from __future__ import annotations import logging import random import string import time from typing import Any, Dict, Optional from jituan.constants import PAY_CHANNEL_FUBEI_WX_MINI from jituan.services.club_payment_channel import get_fubei_config from jituan.services import fubei_client from jituan.services.mini_pay_router import get_pay_ledger logger = logging.getLogger(__name__) def _refund_sn(out_trade_no: str) -> str: ts = str(int(time.time())) rand = ''.join(random.choices('0123456789', k=4)) # 付呗 merchant_refund_sn 最长 32 base = f'{out_trade_no}R{ts}{rand}' return base[:32] def try_fubei_refund( *, out_trade_no: str, amount_yuan, club_id: Optional[str] = None, ) -> Optional[Dict[str, Any]]: """ 若该单曾走付呗,则发起付呗退款并返回 {'code': 0/非0, 'msg': ..., 'refund_id': ...}; 非付呗单返回 None,由调用方继续走原微信退款。 """ ledger = get_pay_ledger(out_trade_no) if not ledger or ledger.channel != PAY_CHANNEL_FUBEI_WX_MINI: return None cid = (club_id or ledger.club_id or '').strip() cfg = get_fubei_config(cid) if not cfg or not cfg.app_id or not cfg.api_key: logger.error('[FUBEI_REFUND] 配置缺失 club=%s out_trade_no=%s', cid, out_trade_no) return {'code': 500, 'msg': '付呗退款配置缺失,请检查俱乐部付呗通道'} merchant_refund_sn = _refund_sn(out_trade_no) try: data = fubei_client.refund_order( gateway_url=cfg.gateway_url, app_id=cfg.app_id, app_secret=cfg.api_key, merchant_order_sn=out_trade_no, merchant_refund_sn=merchant_refund_sn, refund_money=amount_yuan, order_sn=ledger.provider_order_sn or '', ) refund_id = data.get('refund_sn') or merchant_refund_sn logger.info('[FUBEI_REFUND] ok out_trade_no=%s refund=%s', out_trade_no, refund_id) return {'code': 0, 'msg': 'success', 'refund_id': refund_id, 'raw': data} except Exception as exc: logger.error('[FUBEI_REFUND] fail out_trade_no=%s: %s', out_trade_no, exc, exc_info=True) return {'code': 400, 'msg': str(exc)}