fix: 平台微信退款改用俱乐部收款配置(付呗/直连分路,不动支付宝)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1197,7 +1197,7 @@ class AdTongYiTuiKuanPingTai(APIView):
|
||||
transaction_id = getattr(dingdan_obj, 'WechatTransactionID', None)
|
||||
weixin_refund_result = self.call_weixin_refund(
|
||||
out_trade_no=dingdan_id,
|
||||
Amount=jine,
|
||||
jine=jine,
|
||||
transaction_id=transaction_id
|
||||
)
|
||||
|
||||
@@ -1283,88 +1283,35 @@ class AdTongYiTuiKuanPingTai(APIView):
|
||||
|
||||
def call_weixin_refund(self, out_trade_no, jine, transaction_id=None):
|
||||
"""
|
||||
调用微信退款接口
|
||||
:param out_trade_no: 商户订单号
|
||||
:param jine: 退款金额
|
||||
:param transaction_id: 微信支付订单号(优先使用)
|
||||
:return: {'success': True/False, 'msg': '消息', 'refund_id': '退款单号'}
|
||||
平台订单退款:付呗单走付呗;微信直连单按订单 Club 收款配置 V2 退款。
|
||||
不处理支付宝;不用全局 WEIXIN_*、不用提现 V3。
|
||||
:return: {'success': True/False, 'msg': '...', 'refund_id': '...'}
|
||||
"""
|
||||
try:
|
||||
from jituan.services.pay_refund_router import try_fubei_refund
|
||||
from jituan.services.wechat_pay import club_id_from_order
|
||||
fb = try_fubei_refund(
|
||||
out_trade_no=out_trade_no,
|
||||
amount_yuan=jine,
|
||||
club_id=club_id_from_order(out_trade_no),
|
||||
)
|
||||
if fb is not None:
|
||||
if fb.get('code') == 0:
|
||||
return {'success': True, 'msg': fb.get('msg') or 'success', 'refund_id': fb.get('refund_id')}
|
||||
return {'success': False, 'msg': fb.get('msg') or '付呗退款失败'}
|
||||
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
|
||||
|
||||
# 检查配置
|
||||
required_settings = ['WEIXIN_APPID', 'WEIXIN_MCHID', 'WEIXIN_SHANGHUMIYAO', 'WEIXIN_CERT_PATH', 'WEIXIN_KEY_PATH']
|
||||
for setting in required_settings:
|
||||
if not hasattr(settings, setting) or not getattr(settings, setting):
|
||||
return {'success': False, 'msg': f'缺少微信支付配置: {setting}'}
|
||||
club_id = club_id_from_order(out_trade_no)
|
||||
fb = try_fubei_refund(
|
||||
out_trade_no=out_trade_no,
|
||||
amount_yuan=jine,
|
||||
club_id=club_id,
|
||||
)
|
||||
if fb is not None:
|
||||
if fb.get('code') == 0:
|
||||
return {'success': True, 'msg': fb.get('msg') or 'success', 'refund_id': fb.get('refund_id')}
|
||||
return {'success': False, 'msg': fb.get('msg') or '付呗退款失败'}
|
||||
|
||||
# 生成退款单号
|
||||
refund_id = f"TK{int(time.time())}{random.randint(1000, 9999)}"
|
||||
total_fee_in_fen = yuan_to_fen(jine)
|
||||
|
||||
# 构造请求参数
|
||||
refund_data = {
|
||||
'appid': settings.WEIXIN_APPID,
|
||||
'mch_id': settings.WEIXIN_MCHID,
|
||||
'nonce_str': hashlib.md5(str(time.time()).encode()).hexdigest(),
|
||||
'out_refund_no': refund_id,
|
||||
'total_fee': total_fee_in_fen,
|
||||
'refund_fee': total_fee_in_fen,
|
||||
'op_user_id': settings.WEIXIN_MCHID,
|
||||
'refund_account': 'REFUND_SOURCE_UNSETTLED_FUNDS'
|
||||
}
|
||||
# 优先使用 transaction_id,否则用 out_trade_no
|
||||
if transaction_id:
|
||||
refund_data['transaction_id'] = transaction_id
|
||||
else:
|
||||
refund_data['out_trade_no'] = out_trade_no
|
||||
|
||||
# 生成签名
|
||||
sorted_params = sorted(refund_data.items())
|
||||
sign_string = '&'.join([f"{k}={v}" for k, v in sorted_params if v])
|
||||
sign_string += f"&key={settings.WEIXIN_SHANGHUMIYAO}"
|
||||
sign = hashlib.md5(sign_string.encode()).hexdigest().upper()
|
||||
refund_data['sign'] = sign
|
||||
|
||||
xml_data = self.dict_to_xml(refund_data)
|
||||
url = "https://api.mch.weixin.qq.com/secapi/pay/refund"
|
||||
response = requests.post(
|
||||
url,
|
||||
data=xml_data.encode('utf-8'),
|
||||
headers={'Content-Type': 'application/xml'},
|
||||
cert=(settings.WEIXIN_CERT_PATH, settings.WEIXIN_KEY_PATH),
|
||||
timeout=30
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
result = self.xml_to_dict(response.content)
|
||||
if result.get('return_code') == 'SUCCESS' and result.get('result_code') == 'SUCCESS':
|
||||
logger.info(f"微信退款成功,订单:{out_trade_no},退款单号:{refund_id}")
|
||||
return {'success': True, 'msg': '退款申请提交成功', 'refund_id': refund_id}
|
||||
else:
|
||||
error_msg = result.get('err_code_des', result.get('return_msg', '退款申请失败'))
|
||||
logger.error(f"微信退款失败,订单:{out_trade_no},错误:{error_msg}")
|
||||
return {'success': False, 'msg': f'微信退款失败: {error_msg}'}
|
||||
else:
|
||||
logger.error(f"微信退款接口调用失败,状态码:{response.status_code}")
|
||||
return {'success': False, 'msg': '微信退款接口调用失败'}
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
logger.error(f"微信退款接口请求超时,订单:{out_trade_no}")
|
||||
return {'success': False, 'msg': '微信退款接口请求超时'}
|
||||
except Exception as e:
|
||||
logger.error(f"调用微信退款接口异常: {str(e)}")
|
||||
return {'success': False, 'msg': f'退款处理异常: {str(e)}'}
|
||||
result = refund_wechat_v2_by_club(
|
||||
out_trade_no=out_trade_no,
|
||||
amount_yuan=jine,
|
||||
club_id=club_id,
|
||||
transaction_id=transaction_id,
|
||||
reason='平台退款',
|
||||
)
|
||||
if result.get('code') == 0:
|
||||
return {'success': True, 'msg': result.get('msg') or 'success', 'refund_id': result.get('refund_id')}
|
||||
return {'success': False, 'msg': result.get('msg') or '微信退款失败'}
|
||||
|
||||
def dict_to_xml(self, dict_data):
|
||||
xml = ["<xml>"]
|
||||
|
||||
Reference in New Issue
Block a user