From 07c2f24d67fb85f8a83f29d4c817ea77c5c8d3b1 Mon Sep 17 00:00:00 2001 From: John Mizerek Date: Tue, 17 Feb 2026 17:56:13 -0800 Subject: [PATCH] Add Stripe Customer creation to save payment methods - Get user info (StripeCustomerId, email, name) when creating PaymentIntent - Create Stripe Customer if user doesn't have one - Add customer and setup_future_usage=off_session to PaymentIntent - Cards are automatically saved after successful payment Co-Authored-By: Claude Opus 4.5 --- api/stripe/createPaymentIntent.cfm | 61 ++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/api/stripe/createPaymentIntent.cfm b/api/stripe/createPaymentIntent.cfm index c4bc942..42f6322 100644 --- a/api/stripe/createPaymentIntent.cfm +++ b/api/stripe/createPaymentIntent.cfm @@ -73,11 +73,14 @@ try { abort; } - // Get order's delivery fee, grant economics, and existing PaymentIntent + // Get order's delivery fee, grant economics, existing PaymentIntent, and user info qOrder = queryExecute(" - SELECT DeliveryFee, OrderTypeID, GrantID, GrantOwnerBusinessID, GrantEconomicsType, GrantEconomicsValue, StripePaymentIntentID - FROM Orders - WHERE ID = :orderID + SELECT o.DeliveryFee, o.OrderTypeID, o.GrantID, o.GrantOwnerBusinessID, + o.GrantEconomicsType, o.GrantEconomicsValue, o.StripePaymentIntentID, + o.UserID, u.StripeCustomerId, u.EmailAddress, u.FirstName, u.LastName + FROM Orders o + LEFT JOIN Users u ON u.ID = o.UserID + WHERE o.ID = :orderID ", { orderID: orderID }, { datasource: "payfrit" }); // Check if order already has a PaymentIntent (idempotency check) @@ -137,6 +140,50 @@ try { totalAmountCents = round(totalCustomerPays * 100); totalPlatformFeeCents = round((payfritCustomerFee + payfritBusinessFee) * 100); + // ============================================================ + // STRIPE CUSTOMER (for saving payment methods) + // ============================================================ + stripeCustomerId = ""; + orderUserID = val(qOrder.UserID ?: 0); + + if (orderUserID > 0) { + stripeCustomerId = qOrder.StripeCustomerId ?: ""; + + // Create Stripe Customer if user doesn't have one + if (len(trim(stripeCustomerId)) == 0) { + customerService = new http(); + customerService.setMethod("POST"); + customerService.setUrl("https://api.stripe.com/v1/customers"); + customerService.setUsername(stripeSecretKey); + customerService.setPassword(""); + + // Build customer name + customerName = trim((qOrder.FirstName ?: "") & " " & (qOrder.LastName ?: "")); + if (len(customerName) > 0) { + customerService.addParam(type="formfield", name="name", value=customerName); + } + if (len(trim(qOrder.EmailAddress ?: "")) > 0) { + customerService.addParam(type="formfield", name="email", value=qOrder.EmailAddress); + } + customerService.addParam(type="formfield", name="metadata[user_id]", value=orderUserID); + + customerResult = customerService.send().getPrefix(); + customerData = deserializeJSON(customerResult.fileContent); + + if (!structKeyExists(customerData, "error") && structKeyExists(customerData, "id")) { + stripeCustomerId = customerData.id; + // Save to Users table + queryExecute(" + UPDATE Users SET StripeCustomerId = :custId WHERE ID = :userId + ", { + custId: stripeCustomerId, + userId: orderUserID + }, { datasource: "payfrit" }); + writeLog(file="stripe_webhooks", text="Created Stripe Customer #stripeCustomerId# for user #orderUserID#"); + } + } + } + // Create PaymentIntent httpService = new http(); httpService.setMethod("POST"); @@ -151,6 +198,12 @@ try { httpService.addParam(type="formfield", name="currency", value="usd"); httpService.addParam(type="formfield", name="automatic_payment_methods[enabled]", value="true"); + // Attach customer and save payment method for future use + if (len(trim(stripeCustomerId)) > 0) { + httpService.addParam(type="formfield", name="customer", value=stripeCustomerId); + httpService.addParam(type="formfield", name="setup_future_usage", value="off_session"); + } + if (hasStripeConnect) { // SP-SM: Add grant owner fee to platform fee (Payfrit collects, then transfers to owner) effectivePlatformFeeCents = totalPlatformFeeCents + grantOwnerFeeCents;