小程序前端仍传 wechat;后台可切换 wechat/fubei,支持配置多套付呗并退款按原通道路由。 Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
2.3 KiB
Python
63 lines
2.3 KiB
Python
"""按支付流水选择退款通道:付呗单走付呗,其余走原微信退款逻辑。"""
|
||
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)}
|