erio
c738cfec93
fix(payment): critical audit fixes for security, idempotency and correctness
...
Backend fixes:
- #1 : doSub subscription idempotency via audit log check
- #2 : markFailed only when status=RECHARGING (prevents overwriting COMPLETED)
- #3 : ExpireTimedOutOrders checks upstream payment before expiring
- #4 : Public verify endpoint for payment result page (no auth required)
- #5 : EasyPay QueryOrder returns amount, confirmPayment handles zero amount
- #6 : WxPay notifyUrl priority: request-first, config-fallback
- #7 : EasyPay remove double URL decode in VerifyNotification
- #8 : checkPaid/cancelUpstreamPayment use order's provider instance
- #9 : Amount NaN/Inf/negative validation in order creation and refund
- #10 : Refund amount comparison uses tolerance instead of float64 ==
- #11 : Skip balance deduction on retry when previous rollback failed
- #12 : checkPaid logs fulfillment errors instead of silently ignoring
- #13 : WxPay certSerial added to required config fields
Frontend fixes:
- Payment result page no longer requires authentication
- Public verify API fallback for expired sessions
2026-04-14 09:19:33 +08:00
erio
3c884f8e30
test(payment): add unit tests for payment audit fixes + allow empty supported_types
...
Tests (1033 new lines, 100% coverage on modified functions):
- amount.go: YuanToFen/FenToYuan with precision edge cases
- wxpay: mapWxState, wxSV, formatPEM, NewWxpay validation
- alipay: isTradeNotExist, NewAlipay validation
- webhook: writeSuccessResponse (wxpay JSON, stripe empty, others text)
- config: validateProviderRequest, isSensitiveConfigField, joinTypes
- fulfillment: resolveRedeemAction idempotency logic
Business logic changes:
- Allow empty supported_types on provider instances
- Block removing payment types when instance has pending orders
- Extract resolveRedeemAction as testable pure function
2026-04-14 09:18:22 +08:00