You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Stripe支付API发送OPTIONS请求而非POST的问题解决咨询

问题分析

首先明确两个核心问题:

  1. 你的后端create-checkout-session接口未使用前端传入的customerId和tokenId参数——创建Session时未关联已有的客户,也未处理传入的token,导致前期创建客户和token的操作完全无效,Checkout会重新收集客户信息。
  2. 支付失败的根源是AWS拦截了前端与Stripe通信时的OPTIONS预检请求,这主要发生在前端直接调用Stripe API(如stripe.createToken)的场景。

以下是基于现有JavaScript代码的可行解决方向:


方案一:移除stripe.createToken,直接用Checkout关联已有客户

既然已成功创建Stripe客户,完全不需要手动生成card token——Stripe Checkout可直接关联已有客户并自行处理卡片信息收集,避免前端直接调用Stripe API触发OPTIONS请求。

前端代码修改

const appearance = {
    theme: 'night',
};

const stripe = Stripe('pk_test_51PccgFRo1v56iAOxEVEimciGkyyLOcjVE98T3rqOHLuvx28QNxI8sfvYN0zwSka8vLRIIIEdkOHorjb5OJUdwhIx00VRs64Seu');

const elements = stripe.elements({appearance: {theme: 'night'}});
const card = elements.create('card');
card.mount('#payment-element');

document.querySelector("#payment-form").addEventListener("submit", async (event) => {
    event.preventDefault();
    document.getElementById('submit').disabled = true;

    const name = document.querySelector("#name").value;
    const email = document.querySelector("#email").value;

    try {
        // 创建客户
        const customerResponse = await fetch("http://localhost:4242/create-customer", {
            method: "POST",
            headers: {"Content-Type": "application/json"},
            body: JSON.stringify({ name, email }),
        });

        if (!customerResponse.ok) throw new Error("Failed to create customer.");
        const customerData = await customerResponse.json();
        
        // 仅传入customerId,无需token
        await initializePayment(customerData.customerId);

    } catch (error) {
        document.querySelector("#error-message").textContent = error.message || "Failed to create customer.";
        console.error("Error:", error);
        document.getElementById('submit').disabled = false;
    }
});

async function initializePayment(customerId) {
    try {
        const sessionResponse = await fetch("http://localhost:4242/create-checkout-session", {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({
                customer: customerId,
                priceId: 'price_1PfUDSRo1v56iAOxxLORAlv9'
            })
        });

        if (!sessionResponse.ok) {
            const errorData = await sessionResponse.json();
            throw new Error(errorData.message || `Failed to create checkout session.`);
        }

        const sessionData = await sessionResponse.json();
        window.location.href = sessionData.url;

    } catch (error) {
        document.querySelector("#error-message").textContent = error.message || "Failed to process payment.";
        console.error('Error:', error);
    } finally {
        document.getElementById('submit').disabled = false;
    }
}

后端代码修改(create-checkout-session接口)

post("/create-checkout-session", (request, response) -> {
    response.type("application/json");
    Map<String, Object> requestData = gson.fromJson(request.body(), Map.class);
    String priceId = (String) requestData.get("priceId");
    String customerId = (String) requestData.get("customer");

    SessionCreateParams params = new SessionCreateParams.Builder()
            .setSuccessUrl(domainUrl + "/success.html?session_id={CHECKOUT_SESSION_ID}")
            .setCancelUrl(domainUrl + "/canceled.html")
            .setMode(SessionCreateParams.Mode.SUBSCRIPTION)
            .setCustomer(customerId) // 关联已有客户
            .addLineItem(new SessionCreateParams.LineItem.Builder()
                    .setQuantity(1L)
                    .setPrice(priceId)
                    .build()
            )
            .build();

    try {
        Session session = Session.create(params);
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("url", session.getUrl());
        response.status(200);
        return gson.toJson(responseData);
    } catch (Exception e) {
        Map<String, Object> messageData = new HashMap<>();
        messageData.put("message", e.getMessage());
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("error", messageData);
        response.status(400);
        return gson.toJson(responseData);
    }
});

方案二:改用Stripe Payment Intents API(不跳转Checkout)

如果不想跳转Stripe Checkout页面,可直接用Stripe Elements结合Payment Intents完成支付,全程在你的页面内操作,减少跨域请求触发点。

前端代码修改

const appearance = {
    theme: 'night',
};

const stripe = Stripe('pk_test_51PccgFRo1v56iAOxEVEimciGkyyLOcjVE98T3rqOHLuvx28QNxI8sfvYN0zwSka8vLRIIIEdkOHorjb5OJUdwhIx00VRs64Seu');

const elements = stripe.elements({appearance: {theme: 'night'}});
const card = elements.create('card');
card.mount('#payment-element');

document.querySelector("#payment-form").addEventListener("submit", async (event) => {
    event.preventDefault();
    document.getElementById('submit').disabled = true;

    const name = document.querySelector("#name").value;
    const email = document.querySelector("#email").value;

    try {
        // 1. 创建客户
        const customerResponse = await fetch("http://localhost:4242/create-customer", {
            method: "POST",
            headers: {"Content-Type": "application/json"},
            body: JSON.stringify({ name, email }),
        });
        if (!customerResponse.ok) throw new Error("Failed to create customer.");
        const customerData = await customerResponse.json();

        // 2. 后端创建Payment Intent
        const intentResponse = await fetch("http://localhost:4242/create-payment-intent", {
            method: "POST",
            headers: {"Content-Type": "application/json"},
            body: JSON.stringify({
                customerId: customerData.customerId,
                priceId: 'price_1PfUDSRo1v56iAOxxLORAlv9'
            })
        });
        if (!intentResponse.ok) {
            const errorData = await intentResponse.json();
            throw new Error(errorData.message || "Failed to create payment intent.");
        }
        const intentData = await intentResponse.json();

        // 3. 前端确认支付,无需跳转
        const { error } = await stripe.confirmCardPayment(intentData.clientSecret, {
            payment_method: {
                card: card,
                billing_details: {
                    name: name,
                    email: email
                }
            }
        });

        if (error) {
            throw new Error(error.message);
        } else {
            window.location.href = "/success.html";
        }

    } catch (error) {
        document.querySelector("#error-message").textContent = error.message || "Payment failed.";
        console.error("Error:", error);
        document.getElementById('submit').disabled = false;
    }
});

后端新增create-payment-intent接口

post("/create-payment-intent", (request, response) -> {
    response.type("application/json");
    Map<String, Object> requestData = gson.fromJson(request.body(), Map.class);
    String customerId = (String) requestData.get("customerId");
    String priceId = (String) requestData.get("priceId");

    Price price = Price.retrieve(priceId);
    long amount = price.getUnitAmount();

    PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
            .setCustomer(customerId)
            .setAmount(amount)
            .setCurrency("usd") // 根据你的价格币种调整
            .setPaymentMethodTypes(List.of("card"))
            .setSetupFutureUsage(PaymentIntentCreateParams.SetupFutureUsage.OFF_SESSION)
            .build();

    try {
        PaymentIntent intent = PaymentIntent.create(params);
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("clientSecret", intent.getClientSecret());
        return gson.toJson(responseData);
    } catch (StripeException e) {
        response.status(400);
        Map<String, Object> errorData = new HashMap<>();
        errorData.put("error", e.getMessage());
        return gson.toJson(errorData);
    }
});

额外注意事项

  • 确保后端CORS配置允许http://localhost:8443(或HTTPS地址)的请求,避免前端调用后端接口时触发OPTIONS失败。
  • 若AWS限制来自WAF规则,需检查是否放行Stripe相关域名(api.stripe.com、checkout.stripe.com)的OPTIONS请求。

内容的提问来源于stack exchange,提问作者raph mwanza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 10:00:53