Files
Django/jituan/services/pay_refund_router.py
XingQue 5762f00d40 feat: 分俱乐部付呗收款通道,默认仍走微信直连
小程序前端仍传 wechat;后台可切换 wechat/fubei,支持配置多套付呗并退款按原通道路由。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 20:02:24 +08:00

63 lines
2.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""按支付流水选择退款通道:付呗单走付呗,其余走原微信退款逻辑。"""
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)}