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

Springboot RestController中@PostMapping实现Stripe支付的调用问题求助

Spring Boot集成Stripe支付Intent接口修复方案

一、修复后端@PostMapping接口

你的代码存在几个关键问题,导致接口无法正常工作:

  • 手动读取Request Body易出错,Spring提供@RequestBody注解可自动解析JSON
  • 直接返回JSON字符串不规范,Spring可自动将对象序列化为JSON
  • 硬编码Stripe密钥不安全,建议配置到配置文件
  • 异常处理返回空字符串会导致前端JSON解析失败

修改后的Controller代码:

import com.stripe.exception.StripeException;
import com.stripe.model.PaymentIntent;
import com.stripe.param.PaymentIntentCreateParams;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController // 包含@Controller和@ResponseBody,自动返回JSON格式响应
public class StripePaymentController {

    @Value("${stripe.api.key}") // 从配置文件读取密钥,避免硬编码
    private String stripeApiKey;

    @PostMapping("/create-payment-intent")
    public ResponseEntity<?> createPaymentIntent(@RequestBody CreatePayment postBody) {
        System.out.println("Stripe Controller Begins");
        Stripe.apiKey = stripeApiKey;

        try {
            // 计算订单金额(注意:Stripe要求金额为最小货币单位,比如100代表1美元)
            Long amount = calculateOrderAmount(postBody.getItems());
            PaymentIntentCreateParams createParams = new PaymentIntentCreateParams.Builder()
                    .setCurrency("USD")
                    .setAmount(amount)
                    .build();

            PaymentIntent intent = PaymentIntent.create(createParams);
            // 返回包含clientSecret的响应对象,Spring自动转为JSON
            return ResponseEntity.ok(new CreatePaymentResponse(intent.getClientSecret()));
        } catch (StripeException e) {
            e.printStackTrace();
            // 返回错误状态码和信息,方便前端排查问题
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body("{\"error\": \"" + e.getMessage() + "\"}");
        }
    }

    // 根据实际业务逻辑实现订单金额计算
    private Long calculateOrderAmount(Object items) {
        // 示例:返回1美元(单位为分)
        return 100L;
    }

    // 响应数据封装类
    public static class CreatePaymentResponse {
        private String clientSecret;

        public CreatePaymentResponse(String clientSecret) {
            this.clientSecret = clientSecret;
        }

        public String getClientSecret() {
            return clientSecret;
        }
    }

    // 接收前端请求的参数类,确保字段与前端传入JSON匹配
    public static class CreatePayment {
        private Object items;

        public Object getItems() {
            return items;
        }

        public void setItems(Object items) {
            this.items = items;
        }
    }
}

在application.properties中添加Stripe密钥配置:

stripe.api.key=sk_test_key

二、修复前端代码

前端存在的问题:

  • items变量未定义,需确保有实际订单数据
  • 未处理请求失败场景,无法排查错误
  • 表单默认提交行为会导致页面跳转,需手动阻止

修改后的JS代码:

// 定义实际订单数据,根据业务场景动态生成
const items = [{ id: "product_1", quantity: 1 }];

// 初始化支付元素
async function initialize() {
    try {
        const response = await fetch("/create-payment-intent", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ items }),
        });

        if (!response.ok) {
            const errorData = await response.json();
            throw new Error(errorData.error || "支付初始化请求失败");
        }

        const { clientSecret } = await response.json();

        const appearance = {
            theme: 'stripe',
        };
        elements = stripe.elements({ appearance, clientSecret });

        const paymentElementOptions = {
            layout: "tabs",
        };

        const paymentElement = elements.create("payment", paymentElementOptions);
        paymentElement.mount("#payment-element");
    } catch (error) {
        console.error("初始化失败:", error);
        const messageEl = document.getElementById("payment-message");
        messageEl.textContent = error.message;
        messageEl.classList.remove("hidden");
    }
}

// 阻止表单默认提交行为,改用JS处理支付逻辑
document.getElementById("payment-form").addEventListener("submit", async (e) => {
    e.preventDefault();
    // 此处添加支付确认逻辑,比如调用stripe.confirmPayment
});

修改后的HTML表单(移除action属性,避免默认跳转):

<form id="payment-form">
  <div id="payment-element">
    <!--Stripe.js injects the Payment Element-->
  </div>
  <button id="submit">
    <div class="spinner hidden" id="spinner"></div>
    <span id="button-text">Pay now</span>
  </button>
  <div id="payment-message" class="hidden"></div>
</form>

三、调试步骤

  • 先验证后端接口:用Postman发送POST请求到http://localhost:8080/create-payment-intent,请求体传{"items": [{"id": "test"}]},确认返回包含clientSecret的JSON。
  • 查看浏览器控制台:打开开发者工具,检查Network标签的请求状态、Console标签的错误信息。
  • 核对Stripe密钥:确保测试密钥正确,且未在前端代码中暴露。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:55:34