Files
along_django/utils/pay_mch_config.py

151 lines
4.7 KiB
Python
Raw 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.
"""
支付专用商户配置(与提现收款 WechatPayMchConfig / wechat_mch_service 完全分离)。
读取优先级:
1) XcxSysPeizhi.pay_*
2) 过渡回退:旧 weixin_* / settings.WEIXIN_*
历史订单退款:若订单 pay_mch_id 与当前支付商户不一致,但等于旧 weixin_mchid则用旧 weixin_* 退款。
"""
import logging
import os
from django.conf import settings
from utils.xcx_sys_config import wx_cfg, _val
logger = logging.getLogger(__name__)
def pay_cert_base_dir():
base = getattr(settings, 'WECHAT_PAY_CERT_BASE_DIR', '') or ''
if base:
return base
return os.path.join(str(settings.BASE_DIR), 'zhifuzhengshu')
def _pay_val(pay_attr, legacy_db_attr, settings_attr, default=''):
"""pay_* 优先;空则回退旧 weixin_* / settings。"""
v = _val(pay_attr, None, None)
if v is not None and v != '':
return v
return _val(legacy_db_attr, settings_attr, default) or default
class PayWxConfig:
"""支付商户配置代理(属性名兼容旧 WEIXIN_*,便于替换调用点)。"""
@property
def WEIXIN_MCHID(self):
return _pay_val('pay_mch_id', 'weixin_mchid', 'WEIXIN_MCHID', '')
@property
def WEIXIN_SHANGHUMIYAO(self):
return _pay_val('pay_api_v2_key', 'weixin_shanghu_miyao', 'WEIXIN_SHANGHUMIYAO', '')
@property
def WEIXIN_NOTIFY_URL(self):
return _pay_val('pay_notify_url', 'weixin_notify_url', 'WEIXIN_NOTIFY_URL', '')
@property
def WEIXIN_CERT_PATH(self):
return _pay_val('pay_cert_path', 'weixin_cert_path', 'WEIXIN_CERT_PATH', '')
@property
def WEIXIN_KEY_PATH(self):
return _pay_val('pay_key_path', 'weixin_key_path', 'WEIXIN_KEY_PATH', '')
@property
def PAY_API_V3_KEY(self):
return _val('pay_api_v3_key', None, '') or ''
@property
def PAY_CERT_SERIAL_NO(self):
return _val('pay_cert_serial_no', None, '') or ''
# 别名,语义更清晰
@property
def PAY_MCH_ID(self):
return self.WEIXIN_MCHID
@property
def PAY_API_V2_KEY(self):
return self.WEIXIN_SHANGHUMIYAO
pay_cfg = PayWxConfig()
def get_current_pay_mch_id():
return (pay_cfg.PAY_MCH_ID or '').strip()
def pay_cfg_as_dict():
return {
'MCHID': pay_cfg.WEIXIN_MCHID,
'KEY': pay_cfg.WEIXIN_SHANGHUMIYAO,
'NOTIFY_URL': pay_cfg.WEIXIN_NOTIFY_URL,
'CERT_PATH': pay_cfg.WEIXIN_CERT_PATH,
'KEY_PATH': pay_cfg.WEIXIN_KEY_PATH,
'API_V3_KEY': pay_cfg.PAY_API_V3_KEY,
'CERT_SERIAL_NO': pay_cfg.PAY_CERT_SERIAL_NO,
}
def get_pay_wx_cfg(mch_id=None):
"""
按商户号取支付配置(用于退款反查)。
- mch_id 空 / 等于当前支付商户 → 当前 pay_cfg
- mch_id 等于旧 weixin_mchid 且与当前不同 → 用旧 weixin_*(换号后历史单退款)
- 否则若 zhifuzhengshu/{mch_id}/ 下有证书,拼路径但仍需密钥;密钥仅当前/旧库有,故仍回退当前并打日志
"""
current = pay_cfg_as_dict()
want = (mch_id or '').strip()
current_mch = (current.get('MCHID') or '').strip()
if not want or want == current_mch:
return current
legacy_mch = (wx_cfg.WEIXIN_MCHID or '').strip()
if want == legacy_mch and want != current_mch:
return {
'MCHID': wx_cfg.WEIXIN_MCHID,
'KEY': wx_cfg.WEIXIN_SHANGHUMIYAO,
'NOTIFY_URL': wx_cfg.WEIXIN_NOTIFY_URL,
'CERT_PATH': wx_cfg.WEIXIN_CERT_PATH,
'KEY_PATH': wx_cfg.WEIXIN_KEY_PATH,
'API_V3_KEY': '',
'CERT_SERIAL_NO': '',
}
cert_path = os.path.join(pay_cert_base_dir(), want, 'apiclient_cert.pem')
key_path = os.path.join(pay_cert_base_dir(), want, 'apiclient_key.pem')
if os.path.isfile(cert_path) and os.path.isfile(key_path):
logger.warning(
'支付商户 %s 与当前配置 %s 不一致,仅找到证书文件,密钥仍用当前配置,退款可能失败',
want, current_mch,
)
out = dict(current)
out['MCHID'] = want
out['CERT_PATH'] = cert_path
out['KEY_PATH'] = key_path
return out
logger.warning(
'订单支付商户 %s 无可用历史配置,回退当前支付商户 %s',
want, current_mch,
)
return current
def apply_pay_cfg_to_proxy(cfg_dict):
"""把 get_pay_wx_cfg 结果转成带 WEIXIN_* 属性的简单对象,兼容旧代码写法。"""
class _Cfg:
pass
o = _Cfg()
o.WEIXIN_MCHID = cfg_dict.get('MCHID') or ''
o.WEIXIN_SHANGHUMIYAO = cfg_dict.get('KEY') or ''
o.WEIXIN_NOTIFY_URL = cfg_dict.get('NOTIFY_URL') or ''
o.WEIXIN_CERT_PATH = cfg_dict.get('CERT_PATH') or ''
o.WEIXIN_KEY_PATH = cfg_dict.get('KEY_PATH') or ''
return o