fix: stabilize production payment flow
This commit is contained in:
@@ -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":
|
||||
|
||||
Reference in New Issue
Block a user