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
This commit is contained in:
@@ -158,6 +158,7 @@ func (e *EasyPay) QueryOrder(ctx context.Context, tradeNo string) (*payment.Quer
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Status int `json:"status"`
|
||||
Money string `json:"money"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
return nil, fmt.Errorf("easypay parse query: %w", err)
|
||||
@@ -166,7 +167,8 @@ func (e *EasyPay) QueryOrder(ctx context.Context, tradeNo string) (*payment.Quer
|
||||
if resp.Status == easypayStatusPaid {
|
||||
status = payment.ProviderStatusPaid
|
||||
}
|
||||
return &payment.QueryOrderResponse{TradeNo: tradeNo, Status: status}, nil
|
||||
amount, _ := strconv.ParseFloat(resp.Money, 64)
|
||||
return &payment.QueryOrderResponse{TradeNo: tradeNo, Status: status, Amount: amount}, nil
|
||||
}
|
||||
|
||||
func (e *EasyPay) VerifyNotification(_ context.Context, rawBody string, _ map[string]string) (*payment.PaymentNotification, error) {
|
||||
@@ -174,9 +176,10 @@ func (e *EasyPay) VerifyNotification(_ context.Context, rawBody string, _ map[st
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse notify: %w", err)
|
||||
}
|
||||
// url.ParseQuery already decodes values — no additional decode needed.
|
||||
params := make(map[string]string)
|
||||
for k := range values {
|
||||
params[k] = decodeURLValue(values.Get(k))
|
||||
params[k] = values.Get(k)
|
||||
}
|
||||
sign := params["sign"]
|
||||
if sign == "" {
|
||||
|
||||
Reference in New Issue
Block a user