如何在Stripe Pay中展示每小时租金而非押金并实现延迟支付?
问题背景与需求
我们是租赁企业,需要搭建延迟支付体系,规则如下:
- 用户租赁物品时,信用卡锁定25美元押金,按每小时1美元计费
- 5小时内归还则收取5美元
- 超过25小时视为物品丢失,收取全额25美元
支付验证环节需要向用户展示1美元账单而非25美元押金金额,该需求已通过Apple Pay的pkdeferredpaymentsummaryitem实现。现在要在Stripe Pay中实现相同功能,但当前编写的Java代码执行后,用户看到的是25美元账单(如图:账单显示25美元)。
当前Java代码:
public PaymentIntent createCapturePaymentIntent(String amount, String currency, String customerId, String paymentMethodId, String description) throws Exception { Map < String, Object > params = new HashMap < > (); params.put("amount", amount); params.put("currency", currency); params.put("customer", customerId); if (null != paymentMethodId) { params.put("payment_method", paymentMethodId); } params.put("description", description); // params.put("confirm", "true"); params.put("capture_method", "manual"); LoggerHelper.mdc("stripe", "createCapturePaymentIntent body ==> {}", JacksonUtils.toJson(params)); PaymentIntent paymentIntent = null; try { paymentIntent = PaymentIntent.create(params, requestOptions); } catch (CardException e) { LoggerHelper.mdc("stripe", "createCapturePaymentIntent error ==> {}: {}", e.getCode(), e.getMessage()); String paymentIntentId = e.getStripeError().getPaymentIntent().getId(); paymentIntent = PaymentIntent.retrieve(paymentIntentId, requestOptions); } LoggerHelper.mdc("stripe", "createCapturePaymentIntent result ==> {}", JSON.toJson(paymentIntent)); return paymentIntent; }
疑问:
- 如何在Stripe Pay中实现「验证时展示1美元,锁定25美元押金」的需求?
- 创建金额为1美元且设置
setup_future_usage为off_session的支付是否为可行方案?
解决方案分析
一、Stripe端实现「验证展示1美元+锁定25美元」的正确方案
Stripe中对应Apple Pay PKDeferredPaymentSummaryItem的核心是分离「实际授权额度」和「用户验证时看到的展示金额」,可以通过以下方式实现:
核心实现逻辑
创建PaymentIntent时,将实际锁定的押金金额(25美元)设为amount,同时通过payment_method_options.card.presentment_amount指定用户验证时看到的1美元金额,配合confirmation_method: manual完成配置。
调整后的Java代码:
public PaymentIntent createCapturePaymentIntent(String currency, String customerId, String paymentMethodId, String description) throws Exception { Map < String, Object > params = new HashMap < > (); params.put("amount", "2500"); // 25美元,Stripe以货币最小单位(分)为单位 params.put("currency", currency); params.put("customer", customerId); if (null != paymentMethodId) { params.put("payment_method", paymentMethodId); } params.put("description", description); params.put("capture_method", "manual"); // 手动捕获金额,后续根据归还时间操作 params.put("confirmation_method", "manual"); // 开启手动确认,支持自定义展示金额 // 设置卡片选项,指定用户验证时看到的金额为1美元(100分) Map<String, Object> paymentMethodOptions = new HashMap<>(); Map<String, Object> cardOptions = new HashMap<>(); cardOptions.put("presentment_amount", "100"); paymentMethodOptions.put("card", cardOptions); params.put("payment_method_options", paymentMethodOptions); LoggerHelper.mdc("stripe", "createCapturePaymentIntent body ==> {}", JacksonUtils.toJson(params)); PaymentIntent paymentIntent = null; try { paymentIntent = PaymentIntent.create(params, requestOptions); } catch (CardException e) { LoggerHelper.mdc("stripe", "createCapturePaymentIntent error ==> {}: {}", e.getCode(), e.getMessage()); String paymentIntentId = e.getStripeError().getPaymentIntent().getId(); paymentIntent = PaymentIntent.retrieve(paymentIntentId, requestOptions); } LoggerHelper.mdc("stripe", "createCapturePaymentIntent result ==> {}", JSON.toJson(paymentIntent)); return paymentIntent; }
配置完成后,前端调用stripe.confirmPayment完成支付确认,用户验证时看到的账单金额是1美元,但实际信用卡会被锁定25美元额度,后续可根据归还时间手动捕获对应金额(5美元或25美元),未捕获部分会在7天后自动释放额度。
二、关于「1美元+setup_future_usage: off_session」方案的可行性
这个方案是可行的,但存在体验上的瑕疵,需要注意以下细节:
- 验证环节会产生实际扣款:用户支付1美元完成验证后,你需要手动退款这1美元(0金额无法触发3DS等验证流程),用户会收到扣款和退款两条账单通知,可能引发疑问,需提前告知用户这是验证环节的临时操作。
- 后续押金锁定无需用户操作:验证完成后,将支付方式关联到用户Customer对象,之后创建off_session的PaymentIntent(金额25美元,
capture_method: manual),可静默锁定用户信用卡额度,无需再次验证。 - 对比前者的优劣:该方案流程更繁琐,不如第一种方案体验流畅,第一种方案无需实际扣款,仅在验证时展示1美元,完全贴合你原本用Apple Pay实现的逻辑。
内容的提问来源于stack exchange,提问作者Florian Lemaitre
相关产品推荐
相关产品推荐

