fix: 平台微信退款改用俱乐部收款配置(付呗/直连分路,不动支付宝)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-28 14:17:24 +08:00
parent 5cfb4a1b2b
commit 5ded53bca8
3 changed files with 206 additions and 148 deletions

View File

@@ -918,84 +918,29 @@ class KefuPlatformRefundView(APIView):
def call_wechat_refund(self, dingdan_id, jine, transaction_id=None):
"""
调用微信支付退款接口
:param dingdan_id: 商户订单号我们的订单ID
:param jine: 退款金额
:param transaction_id: 微信支付订单号(优先使用)
:return: {'code': 0, 'msg': '成功', 'refund_id': 'xxx'} 或 {'code': 非0, 'msg': '错误信息'}
平台订单退款:付呗单走付呗;微信直连单按订单 Club 的「收款」配置 V2 退款(不用全局 settings、不用提现 V3
不处理支付宝。
"""
from jituan.services.pay_refund_router import try_fubei_refund
from jituan.services.wechat_pay import club_id_from_order
from jituan.services.wechat_v2_refund import refund_wechat_v2_by_club
club_id = club_id_from_order(dingdan_id)
fb = try_fubei_refund(
out_trade_no=dingdan_id,
amount_yuan=jine,
club_id=club_id_from_order(dingdan_id),
club_id=club_id,
)
if fb is not None:
return fb
# 获取配置
appid = getattr(settings, 'WEIXIN_APPID', '')
mch_id = getattr(settings, 'WEIXIN_MCHID', '')
key = getattr(settings, 'WEIXIN_SHANGHUMIYAO', '')
cert_path = getattr(settings, 'WEIXIN_CERT_PATH', '')
key_path = getattr(settings, 'WEIXIN_KEY_PATH', '')
if not all([appid, mch_id, key, cert_path, key_path]):
missing = [k for k, v in {'appid': appid, 'mch_id': mch_id, 'key': key, 'cert_path': cert_path, 'key_path': key_path}.items() if not v]
logger.error(f"微信支付配置缺失: {missing}")
return {'code': 500, 'msg': f'系统支付配置缺失: {missing}'}
# 生成退款单号
out_refund_no = self.generate_refund_no(dingdan_id)
total_fee = yuan_to_fen(jine)
refund_fee = total_fee
refund_desc = '客服退款'
# 构造请求参数
params = {
'appid': appid,
'mch_id': mch_id,
'nonce_str': self.generate_nonce_str(),
'out_refund_no': out_refund_no,
'total_fee': total_fee,
'refund_fee': refund_fee,
'refund_desc': refund_desc,
}
if transaction_id:
params['transaction_id'] = transaction_id
else:
params['out_trade_no'] = dingdan_id # 使用订单ID作为商户订单号
# 生成签名
sorted_keys = sorted(params.keys())
stringA = '&'.join([f"{k}={params[k]}" for k in sorted_keys])
stringSignTemp = f"{stringA}&key={key}"
sign = hashlib.md5(stringSignTemp.encode('utf-8')).hexdigest().upper()
params['sign'] = sign
xml_data = self.dict_to_xml(params)
url = 'https://api.mch.weixin.qq.com/secapi/pay/refund'
try:
response = requests.post(
url,
data=xml_data,
cert=(cert_path, key_path),
timeout=10
)
result = xmltodict.parse(response.content)['xml']
logger.info(f"微信退款响应: {result}")
except Exception as e:
logger.error(f"微信退款请求异常: {str(e)}", exc_info=True)
return {'code': 500, 'msg': '微信退款请求异常'}
if result.get('return_code') == 'SUCCESS' and result.get('result_code') == 'SUCCESS':
return {'code': 0, 'msg': 'success', 'refund_id': out_refund_no}
else:
err_msg = result.get('err_code_des', result.get('return_msg', '未知错误'))
logger.warning(f"微信退款失败: {err_msg}")
return {'code': 400, 'msg': err_msg}
return refund_wechat_v2_by_club(
out_trade_no=dingdan_id,
amount_yuan=jine,
club_id=club_id,
transaction_id=transaction_id,
reason='客服退款',
)
def generate_nonce_str(self):
return ''.join(random.choices(string.ascii_letters + string.digits, k=32))