fix(sca): fix stuff the review commented on
This commit is contained in:
@@ -539,9 +539,10 @@ func (h *CartHandler) ConvertCart(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// respondRequiresAction handles a PaymentIntent that needs 3DS auth
|
||||
// The order stays pending. the webhook flips it to paid once the customer
|
||||
// completes the bank-hosted challenge, the tui polls /api/v1/orders/{id}/status
|
||||
// respondRequiresAction handles a PaymentIntent that needs 3DS auth. The order
|
||||
// transitions to requires_action (see caveat #20 in sca-psd2-compliance.md);
|
||||
// the payment_intent.succeeded webhook flips it to paid once the customer
|
||||
// completes the bank-hosted challenge. The TUI polls /api/v1/orders/{id}/status.
|
||||
func (h *CartHandler) respondRequiresAction(w http.ResponseWriter, order *models.Order, paymentMethodID string, pi *stripe.PaymentIntent) {
|
||||
db := database.GetDB()
|
||||
|
||||
|
||||
@@ -921,7 +921,7 @@ func TestRetryAuth(t *testing.T) {
|
||||
wantStatus: http.StatusConflict, wantErrCode: "INVALID_STATE",
|
||||
},
|
||||
{
|
||||
name: "requires_action retryable until cap",
|
||||
name: "requires_action honors retry cap",
|
||||
ownedByUser: true, seedStatus: models.OrderStatusRequiresAction,
|
||||
seedPayment: "pi_test_req_action_cap", seedEvents: maxAuthIssuances,
|
||||
wantStatus: http.StatusTooManyRequests, wantErrCode: "RETRY_LIMIT",
|
||||
|
||||
@@ -185,3 +185,40 @@ func TestHandlePaymentIntentFailed_MissingMetadataNoOp(t *testing.T) {
|
||||
h := NewWebhookHandler("", "", "")
|
||||
h.handlePaymentIntentFailed(context.Background(), evt) // must not panic
|
||||
}
|
||||
|
||||
func TestHandlePaymentIntentSucceeded_RequiresActionFlipsToPaid(t *testing.T) {
|
||||
testDB, user := setupCartTestDB(t)
|
||||
defer func() { _ = os.Remove(testDB) }()
|
||||
defer database.ResetForTesting()
|
||||
|
||||
order := seedOrderForWebhook(t, user.ID, models.OrderStatusRequiresAction, "pi_test_req_action_paid")
|
||||
|
||||
pi := map[string]any{
|
||||
"id": order.StripePaymentID,
|
||||
"amount": order.Total,
|
||||
"metadata": map[string]string{"order_id": fmt.Sprintf("%d", order.ID)},
|
||||
}
|
||||
raw, err := json.Marshal(pi)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal pi: %v", err)
|
||||
}
|
||||
evt := stripe.Event{
|
||||
Type: "payment_intent.succeeded",
|
||||
Data: &stripe.EventData{Raw: raw},
|
||||
}
|
||||
|
||||
h := NewWebhookHandler("", "", "")
|
||||
h.handlePaymentIntentSucceeded(context.Background(), evt)
|
||||
|
||||
db := database.GetDB()
|
||||
var reloaded models.Order
|
||||
if err := db.First(&reloaded, order.ID).Error; err != nil {
|
||||
t.Fatalf("reload order: %v", err)
|
||||
}
|
||||
if reloaded.Status != models.OrderStatusPaid {
|
||||
t.Fatalf("status: want %q, got %q", models.OrderStatusPaid, reloaded.Status)
|
||||
}
|
||||
if reloaded.StripePaymentID != order.StripePaymentID {
|
||||
t.Fatalf("stripe_payment_id: want %q, got %q", order.StripePaymentID, reloaded.StripePaymentID)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user