fix: validate Stripe customer before using, handle mode mismatch

If a user has a live-mode StripeCustomerId but the API is running in
test mode (or vice versa), the PI creation fails. Now validates the
customer with Stripe first and creates a new one if invalid.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2026-03-02 18:06:09 -08:00
parent 5dd0884b8f
commit f3a41bf01a
2 changed files with 32 additions and 4 deletions

View file

@ -233,8 +233,23 @@ try {
if (orderUserID > 0) {
stripeCustomerId = qOrder.StripeCustomerId ?: "";
// Create Stripe Customer if user doesn't have one
if (len(trim(stripeCustomerId)) == 0) {
// Validate existing customer (catches live/test mode mismatch)
needNewCustomer = (len(trim(stripeCustomerId)) == 0);
if (!needNewCustomer) {
validateService = new http();
validateService.setMethod("GET");
validateService.setUrl("https://api.stripe.com/v1/customers/#stripeCustomerId#");
validateService.setUsername(stripeSecretKey);
validateService.setPassword("");
validateResult = validateService.send().getPrefix();
validateData = deserializeJSON(validateResult.fileContent);
if (structKeyExists(validateData, "error") || !structKeyExists(validateData, "id")) {
needNewCustomer = true;
}
}
// Create Stripe Customer if needed
if (needNewCustomer) {
customerService = new http();
customerService.setMethod("POST");
customerService.setUrl("https://api.stripe.com/v1/customers");

View file

@ -82,8 +82,21 @@ try {
if (qUser.recordCount == 0) apiAbort({ "OK": false, "ERROR": "user_not_found" });
stripeCustomerId = qUser.StripeCustomerId;
if (!len(trim(stripeCustomerId))) {
// Create Stripe Customer
// Validate existing customer with Stripe (catches live/test mode mismatch)
needNewCustomer = true;
if (len(trim(stripeCustomerId))) {
cfhttp(method="GET", url="https://api.stripe.com/v1/customers/#stripeCustomerId#", result="checkResp") {
cfhttpparam(type="header", name="Authorization", value="Bearer #application.stripeSecretKey#");
}
checkData = deserializeJSON(checkResp.fileContent);
if (structKeyExists(checkData, "id") && !structKeyExists(checkData, "error")) {
needNewCustomer = false;
}
}
if (needNewCustomer) {
// Create Stripe Customer (or replace invalid one)
cfhttp(method="POST", url="https://api.stripe.com/v1/customers", result="custResp") {
cfhttpparam(type="header", name="Authorization", value="Bearer #application.stripeSecretKey#");
cfhttpparam(type="formfield", name="name", value="#qUser.FirstName# #qUser.LastName#");