Update PaymentIntent amount if cart changed on retry

Moved fee calculation before PI check so we can compare amounts.
If existing PaymentIntent has different amount than current cart,
update it via Stripe API before returning.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2026-02-17 19:06:01 -08:00
parent d0f0f86176
commit bbfbbf1963

View file

@ -83,45 +83,6 @@ try {
WHERE o.ID = :orderID
", { orderID: orderID }, { datasource: "payfrit" });
// Check if order already has a PaymentIntent - retrieve and reuse if still valid
existingPiId = qOrder.StripePaymentIntentID ?: "";
if (qOrder.recordCount > 0 && len(trim(existingPiId)) > 0) {
// Retrieve existing PaymentIntent from Stripe
piRetrieve = new http();
piRetrieve.setMethod("GET");
piRetrieve.setUrl("https://api.stripe.com/v1/payment_intents/#existingPiId#");
piRetrieve.setUsername(stripeSecretKey);
piRetrieve.setPassword("");
piResult = piRetrieve.send().getPrefix();
existingPi = deserializeJSON(piResult.fileContent);
if (!structKeyExists(existingPi, "error")) {
piStatus = existingPi.status ?: "";
// Reusable states: can still complete payment
if (listFindNoCase("requires_payment_method,requires_confirmation,requires_action", piStatus)) {
// Return existing PaymentIntent - user can retry with same one
response["OK"] = true;
response["CLIENT_SECRET"] = existingPi.client_secret;
response["PAYMENT_INTENT_ID"] = existingPi.id;
response["PUBLISHABLE_KEY"] = application.stripePublishableKey ?: "pk_test_sPBNzSyJ9HcEPJGC7dSo8NqN";
response["REUSED"] = true;
writeOutput(serializeJSON(response));
abort;
} else if (piStatus == "succeeded") {
// Already paid - don't create another
response["OK"] = false;
response["ERROR"] = "already_paid";
response["MESSAGE"] = "This order has already been paid.";
writeOutput(serializeJSON(response));
abort;
}
// Other terminal states (canceled, etc.) - clear and create new
}
// PaymentIntent not found or terminal - clear it from order
queryExecute("UPDATE Orders SET StripePaymentIntentID = NULL WHERE ID = :orderID",
{ orderID: orderID }, { datasource: "payfrit" });
}
deliveryFee = 0;
if (qOrder.recordCount > 0 && qOrder.OrderTypeID == 3) {
deliveryFee = val(qOrder.DeliveryFee);
@ -169,6 +130,59 @@ try {
totalAmountCents = round(totalCustomerPays * 100);
totalPlatformFeeCents = round((payfritCustomerFee + payfritBusinessFee) * 100);
// ============================================================
// CHECK FOR EXISTING PAYMENTINTENT - REUSE OR UPDATE IF VALID
// ============================================================
existingPiId = qOrder.StripePaymentIntentID ?: "";
if (qOrder.recordCount > 0 && len(trim(existingPiId)) > 0) {
// Retrieve existing PaymentIntent from Stripe
piRetrieve = new http();
piRetrieve.setMethod("GET");
piRetrieve.setUrl("https://api.stripe.com/v1/payment_intents/#existingPiId#");
piRetrieve.setUsername(stripeSecretKey);
piRetrieve.setPassword("");
piResult = piRetrieve.send().getPrefix();
existingPi = deserializeJSON(piResult.fileContent);
if (!structKeyExists(existingPi, "error")) {
piStatus = existingPi.status ?: "";
// Reusable states: can still complete payment
if (listFindNoCase("requires_payment_method,requires_confirmation,requires_action", piStatus)) {
// Check if amount changed (cart modified)
if (existingPi.amount != totalAmountCents) {
// Update the PaymentIntent with new amount
piUpdate = new http();
piUpdate.setMethod("POST");
piUpdate.setUrl("https://api.stripe.com/v1/payment_intents/#existingPiId#");
piUpdate.setUsername(stripeSecretKey);
piUpdate.setPassword("");
piUpdate.addParam(type="formfield", name="amount", value=totalAmountCents);
piUpdateResult = piUpdate.send().getPrefix();
existingPi = deserializeJSON(piUpdateResult.fileContent);
}
// Return existing PaymentIntent
response["OK"] = true;
response["CLIENT_SECRET"] = existingPi.client_secret;
response["PAYMENT_INTENT_ID"] = existingPi.id;
response["PUBLISHABLE_KEY"] = application.stripePublishableKey ?: "pk_test_sPBNzSyJ9HcEPJGC7dSo8NqN";
response["REUSED"] = true;
writeOutput(serializeJSON(response));
abort;
} else if (piStatus == "succeeded") {
// Already paid - don't create another
response["OK"] = false;
response["ERROR"] = "already_paid";
response["MESSAGE"] = "This order has already been paid.";
writeOutput(serializeJSON(response));
abort;
}
// Other terminal states (canceled, etc.) - clear and create new
}
// PaymentIntent not found or terminal - clear it from order
queryExecute("UPDATE Orders SET StripePaymentIntentID = NULL WHERE ID = :orderID",
{ orderID: orderID }, { datasource: "payfrit" });
}
// ============================================================
// STRIPE CUSTOMER (for saving payment methods)
// ============================================================