fix: stabilize production payment flow

This commit is contained in:
QiuSW
2026-07-06 08:56:30 +08:00
parent 0d6b97f44d
commit e4565de0c4
14 changed files with 270 additions and 13 deletions
+27 -3
View File
@@ -94,6 +94,25 @@ def _wechat_amount_cents(value) -> int:
return int((_decimal_money(value) * Decimal("100")).to_integral_value())
def _wechat_response_payload(response) -> dict:
if isinstance(response, dict):
return response
if isinstance(response, tuple) and len(response) >= 2:
payload = response[1]
if isinstance(payload, dict):
return payload
if isinstance(payload, bytes):
payload = payload.decode("utf-8")
if isinstance(payload, str):
try:
parsed = json.loads(payload)
except json.JSONDecodeError as exc:
raise ValueError("WeChat API response is not valid JSON.") from exc
if isinstance(parsed, dict):
return parsed
raise ValueError("WeChat API response has an unsupported format.")
def _default_expires_at():
minutes = int(getattr(settings, "PAYMENT_QR_EXPIRES_MINUTES", 10) or 10)
return timezone.now() + timedelta(minutes=minutes)
@@ -198,7 +217,7 @@ def _create_mock_payment_order(order: RechargeOrder) -> PaymentOrderCode:
def _create_wechat_payment_order_with_sdk(order: RechargeOrder) -> PaymentOrderCode:
try:
from wechatpayv3 import WeChatPay # type: ignore
from wechatpayv3 import WeChatPay, WeChatPayType # type: ignore
except ImportError as exc:
raise PaymentOrderCreateError("wechatpayv3 is not installed.") from exc
@@ -231,11 +250,16 @@ def _create_wechat_payment_order_with_sdk(order: RechargeOrder) -> PaymentOrderC
"total": _wechat_amount_cents(order.amount_money),
"currency": order.currency,
},
pay_type=WeChatPayType.NATIVE,
)
except Exception as exc: # pragma: no cover - depends on merchant SDK/runtime.
raise PaymentOrderCreateError("WeChat native order creation failed.") from exc
code_url = response.get("code_url") if isinstance(response, dict) else None
try:
payload = _wechat_response_payload(response)
except ValueError as exc:
raise PaymentOrderCreateError("WeChat native order response was invalid.") from exc
code_url = payload.get("code_url")
if not code_url:
raise PaymentOrderCreateError("WeChat native order did not return code_url.")
return PaymentOrderCode(code_url=str(code_url), expires_at=_default_expires_at())
@@ -398,7 +422,7 @@ def _query_wechat_payment_order_with_sdk(order: RechargeOrder) -> RechargePaymen
"WeChat active payment query SDK binding is not configured."
)
try:
resource = query(out_trade_no=order.order_no)
resource = _wechat_response_payload(query(out_trade_no=order.order_no))
except Exception as exc: # pragma: no cover - depends on merchant SDK/runtime.
raise PaymentQueryUnavailableError("WeChat trade query failed.") from exc
if resource.get("trade_state") != "SUCCESS":