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
相关产品推荐
相关产品推荐

