通过Java创建Stripe订阅时遇400错误:缺失customer参数
问题排查:Stripe订阅创建提示customer参数缺失
问题重现
代码中已设置customer参数,但调用Stripe API创建订阅时返回400错误,提示参数缺失:
实现代码
HttpHeaders headers = new HttpHeaders(); headers.setBearerAuth(apiTestKey); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); CreateSubscriptionRequest createSubscriptionRequest = CreateSubscriptionRequest.builder() .customer("cus_P5ZkW678nZi3d0K") .object("customer") .items(ItemsRequest.builder() .data(List.of(DatumRequest.builder() .id(String.valueOf(1)) .build())) .build()) .build(); final HttpEntity<String> entity = new HttpEntity<>(objectMapper.writeValueAsString(createSubscriptionRequest), headers); RestTemplate restTemplate = new RestTemplate(); ResponseEntity<CreateSubscriptionRequest> response = restTemplate.exchange(baseUrl + "subscriptions", HttpMethod.POST, entity, CreateSubscriptionRequest.class);
错误日志
org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: "{<EOL> "error": {<EOL> "code": "parameter_missing",<EOL> "doc_url": "stripe.com/docs/error-codes/parameter-missing",<EOL> "message": "Missing required param: customer.",<EOL> "param": "customer",<EOL> "request_log_url": "dashboard.stripe.com/test/logs/req_jyjNoqopJFlkH3?t=1701167766",<EOL> "type": "invalid_request_error"<EOL> }<EOL>}<EOL>" at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:103)
问题根源
请求的Content-Type设置与实际发送的数据格式不匹配:
- 代码声明
Content-Type为APPLICATION_FORM_URLENCODED(表单编码),但实际通过objectMapper把对象序列化成了JSON字符串。 - Stripe API接收表单编码请求时,仅识别
key=value格式的参数,无法解析JSON请求体,因此读取不到customer参数。
另外代码存在两个额外错误:
.object("customer")设置错误:创建订阅时该字段应为"subscription",或直接省略(Stripe会自动处理)。DatumRequest.id设为1错误:该字段需要传入Stripe平台的价格ID(格式为price_xxx),而非自定义数字。
修复方案
方案1:改用JSON格式发送请求(推荐)
将Content-Type改为JSON,让Stripe正确解析请求体:
HttpHeaders headers = new HttpHeaders(); headers.setBearerAuth(apiTestKey); // 修改Content-Type为JSON格式 headers.setContentType(MediaType.APPLICATION_JSON); CreateSubscriptionRequest createSubscriptionRequest = CreateSubscriptionRequest.builder() .customer("cus_P5ZkW678nZi3d0K") // 移除错误的object字段,或改为.object("subscription") .items(ItemsRequest.builder() .data(List.of(DatumRequest.builder() // 替换为实际的Stripe价格ID .id("price_your_plan_id") .build())) .build()) .build(); // 直接传递请求对象,RestTemplate会自动序列化为JSON final HttpEntity<CreateSubscriptionRequest> entity = new HttpEntity<>(createSubscriptionRequest, headers); RestTemplate restTemplate = new RestTemplate(); // 建议用专门的响应对象接收返回结果,而非请求对象 ResponseEntity<CreateSubscriptionResponse> response = restTemplate.exchange(baseUrl + "subscriptions", HttpMethod.POST, entity, CreateSubscriptionResponse.class);
方案2:改用表单编码格式发送请求
如果坚持使用表单编码,需将参数转换为MultiValueMap:
HttpHeaders headers = new HttpHeaders(); headers.setBearerAuth(apiTestKey); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("customer", "cus_P5ZkW678nZi3d0K"); // 订阅项需按表单嵌套格式传递 params.add("items[0][price]", "price_your_plan_id"); final HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers); RestTemplate restTemplate = new RestTemplate(); ResponseEntity<CreateSubscriptionResponse> response = restTemplate.exchange(baseUrl + "subscriptions", HttpMethod.POST, entity, CreateSubscriptionResponse.class);
内容的提问来源于stack exchange,提问作者Nunyet Calçada
相关产品推荐
相关产品推荐

