AWS Lambda Java函数返回空JSON问题求助(Stripe支付场景)
问题排查:AWS Lambda对接Stripe Payment Intents返回空JSON响应
我有一个Angular应用,使用Stripe Payment Intents API实现支付流程。此前通过Spring Boot Rest Controller部署在Elastic Beanstalk时,前后端均能正常工作;切换到AWS Lambda的Java函数后,函数返回空JSON响应,无法获取包含client_secret的预期结果。
相关代码
AWS Lambda Java函数代码
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.fasterxml.jackson.jr.ob.JSON; import com.stripe.Stripe; import com.stripe.exception.StripeException; import com.stripe.model.PaymentIntent; public class CheckoutPayment implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent>{ @Override public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context){ String paymentStr =""; try { PaymentInfo paymentInfo = JSON.std.beanFrom(PaymentInfo.class, input.getBody()); PaymentIntent paymentIntent = createPaymentIntent(paymentInfo); paymentStr = paymentIntent.toJson(); } catch (Exception ex) { ex.printStackTrace(); return new APIGatewayProxyResponseEvent() .withStatusCode(400) .withBody("Error processing the request"); } APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent(); response.withStatusCode(200).withBody(paymentStr); return response; } private PaymentIntent createPaymentIntent(PaymentInfo paymentInfo) throws StripeException { Stripe.apiKey = "sk_test_5....something"; List<String> paymentMethodeTypes = new ArrayList<>(); paymentMethodeTypes.add("card"); Map<String, Object> params = new HashMap<>(); params.put("amount", paymentInfo.getAmount()); params.put("currency", paymentInfo.getCurrency()); params.put("payment_method_types", paymentMethodeTypes); return PaymentIntent.create(params); } }
PaymentInfo类代码
public class PaymentInfo { private Long amount; private String currency; public PaymentInfo() {} public PaymentInfo(Long amount, String currency) { this.amount = amount; this.currency = currency; } public Long getAmount() { return amount; } public String getCurrency() { return currency; } public void setAmount(Long amount) { this.amount = amount; } public void setCurrency(String currency) { this.currency = currency; } @Override public String toString() { return "PaymentInfo [amount=" + amount + ", currency=" + currency + "]"; } }
预期返回响应格式
{ "id": "pi_3MQBPOHNXSQZoPBk0KGKrqAV", "object": "payment_intent", "amount": 2000, "amount_capturable": 0, "amount_details": { "tip": {} }, "amount_received": 0, "application": null, "application_fee_amount": null, "automatic_payment_methods": null, "canceled_at": null, "cancellation_reason": null, "capture_method": "automatic", "client_secret": "pi_remo", "confirmation_method": "automatic", "created": 1673709158, "currency": "usd", "customer": null, "description": null, "invoice": null, "last_payment_error": null, "latest_charge": null, "livemode": false, "metadata": {}, "next_action": null, "on_behalf_of": null, "payment_method": null, "payment_method_options": { "card": { "installments": null, "mandate_options": null, "network": null, "request_three_d_secure": "automatic" } }, "payment_method_types": [ "card" ], "processing": null, "receipt_email": null, "review": null, "setup_future_usage": null, "shipping": null, "statement_descriptor": null, "statement_descriptor_suffix": null, "status": "requires_payment_method", "transfer_data": null, "transfer_group": null }
Angular前端onSubmit()函数
onSubmit() { // compute payment info this.paymentInfo.amount = Math.round(this.totalPrice * 100); this.paymentInfo.currency = "CAD"; if (!this.checkoutFormGroup.invalid && this.displayError.textContent === "") { this.checkoutService.createPaymentIntent(this.paymentInfo).subscribe( (paymentIntentResponse) => { this.stripe.confirmCardPayment(paymentIntentResponse.client_secret, { payment_method: { card: this.cardElement } }, { handleActions: false }) .then(function(result) { if (result.error) { // inform the customer there was an error alert(`There was an error: ${result.error.message}`); } else { // reset cart this.resetCart(); } }.bind(this)); } ); } else { this.checkoutFormGroup.markAllAsTouched(); return; } }
Angular CheckoutService代码
import { PaymentInfo } from './../common/payment-info'; import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class CheckoutService { private paymentIntentUrl = 'https://removed real path amazonaws.com/api/payment-intent'; constructor(private httpClient: HttpClient) { } createPaymentIntent(paymentInfo: PaymentInfo): Observable<any>{ console.log("paymentInfo - ", paymentInfo) return this.httpClient.post<PaymentInfo>(this.paymentIntentUrl, paymentInfo); } }
排查关键点
完善日志记录
- 原代码中
ex.printStackTrace()在Lambda环境下无法输出到CloudWatch日志,需替换为Lambda上下文的日志工具:context.getLogger().log("Error message: " + ex.getMessage()); context.getLogger().log("Stack trace: " + Arrays.toString(ex.getStackTrace())); - 添加日志打印
input.getBody()和paymentIntent.toJson()的内容,确认请求体解析和PaymentIntent创建是否正常。
- 原代码中
验证请求体解析
- 检查APIGateway代理集成是否传递了原始请求体,确认
input.getBody()的内容与前端发送的paymentInfo结构一致。 - 若Jackson JR解析失败(比如字段大小写不匹配、JSON格式错误),会直接进入catch块返回400,可尝试替换为完整Jackson库测试解析逻辑。
- 检查APIGateway代理集成是否传递了原始请求体,确认
确认Stripe API调用有效性
- 检查Stripe密钥是否正确、是否具备创建PaymentIntent的权限。
- 在
createPaymentIntent方法中添加日志,打印生成的PaymentIntent内容,确认Stripe是否返回了包含client_secret的完整对象。
修复响应格式
- 原Lambda响应未设置
Content-Type为application/json,前端可能无法正确解析JSON,需添加响应头:Map<String, String> headers = new HashMap<>(); headers.put("Content-Type", "application/json"); response.withHeaders(headers);
- 原Lambda响应未设置
检查异常覆盖范围
- 确认所有可能的异常都被捕获,比如Stripe API调用时的网络异常、权限异常等,避免因未捕获异常导致Lambda返回空响应。
内容的提问来源于stack exchange,提问作者Kyro
相关产品推荐
相关产品推荐

