【支付】Stripe支付通道Java对接(产品 价格 支付 查询 退款 回调)
Stripe是一家美国科技公司,成立于2010年,由爱尔兰兄弟Patrick Collison和John Collison共同创立。该公司致力于提供高效、简洁的互联网支付收款服务,为开发者或商家提供支付API接口或代码,使商家的网站、移动APP支持信用卡付款。Stripe被誉为“移动时代的PayPal”,因其简便的支付方式而受到广泛欢迎。
Stripe 总共有三种支付方式:
1、Stripe Checkout,pay links 创建支付链接,
2、payment intent,后端预下单,返回秘钥,前端确定订单
3、前端创建支付token ,后端创建Charge,返回支付结果链接
Stripe接口调用时序图
0、初始化客户端
StripeClient client = StripeClient.builder().setConnectTimeout(30 * 1000).setReadTimeout(80 * 1000).setApiKey("sk_test_51PtO7DC6XhwanSnNvGezNPc4hsL2F****").build();
1、产品
查询或创建新产品。
每次交易传入产品名称或描述,自动查询是否已经存在,如果存在则直接使用,如果不存在则新建产品。
private Product getProduct(StripeOrder stripeOrder) throws StripeException {ProductSearchParams searchParams =ProductSearchParams.builder().setQuery("active:'true' AND name:'" + stripeOrder.getSubject()+ "' AND description:'" + stripeOrder.getBody() + "'").setLimit(1L).build();StripeSearchResult<Product> result = client.products().search(searchParams);Product product;if (result != null && !result.getData().isEmpty()) {product = result.getData().stream().findFirst().get();} else {//创建产品 https://stripe.com/docs/api/products/createProductCreateParams params = ProductCreateParams.builder().setDescription(stripeOrder.getBody()).setName(stripeOrder.getSubject()).build();product = client.products().create(params);}return product;}
2、价格
根据产品ID创建对应币种的价格,指定 lookupKey = 价格+币种+产品ID,作为价格关键字,用于查询是否已经存在。如果价格存在则直接使用,如果不存在则新增新的价格。
private Price getPrice(StripeOrder stripeOrder, String productId) throws StripeException {Long unitAmount = Util.conversionCentAmount(stripeOrder.getPrice());String lookupKey = unitAmount + stripeOrder.getCurrencyCode() + productId;PriceSearchParams params =PriceSearchParams.builder().setQuery("active:'true' AND product:'" + productId+ "' AND currency:'" + stripeOrder.getCurrencyCode()+ "' AND lookup_key:'" + lookupKey + "'").build();StripeSearchResult<Price> result = client.prices().search(params);Price price;if (result != null && !result.getData().isEmpty()) {price = result.getData().stream().findFirst().get();} else {//创建价格 https://stripe.com/docs/api/prices/create
// PriceCreateParams.Recurring recurring = PriceCreateParams.Recurring.builder()
// .setInterval(PriceCreateParams.Recurring.Interval.MONTH).build();PriceCreateParams priceCreateParams = PriceCreateParams.builder().setCurrency(stripeOrder.getCurrencyCode()).setProduct(productId).setLookupKey(lookupKey).setUnitAmount(unitAmount)
// .setRecurring(recurring).build();price = client.prices().create(priceCreateParams);}return price;
}
3、创建支付
根据上次返回的价格信息,创建新的支付对象,这里指定银行卡支付,也可以指定别的支付方式;Stripe支持几十种支付方式,可以根据不同国家选择,具体可以在这里查看
下面通过 client.checkout().sessions().create() 创建支付,取得支付链接,在浏览器直接打开即可支付。
public Map<String, Object> orderInfo(PayOrder order) {StripeOrder stripeOrder = (StripeOrder) order;try {Product product = getProduct(stripeOrder);Price price = getPrice(stripeOrder, product.getId());//创建支付信息 得到urlSessionCreateParams sessionCreateParams = SessionCreateParams.builder().setMode(SessionCreateParams.Mode.PAYMENT).addPaymentMethodType(SessionCreateParams.PaymentMethodType.CARD)
// .addPaymentMethodType(SessionCreateParams.PaymentMethodType.ALIPAY).setSuccessUrl(payConfigStorage.getReturnUrl()).setCancelUrl(payConfigStorage.getCancelUrl()).setCustomer(stripeOrder.getCustomer()).setClientReferenceId(stripeOrder.getClientReferenceId()).setCustomerEmail(stripeOrder.getCustomerEmail()).addLineItem(SessionCreateParams.LineItem.builder().setQuantity(1L).setPrice(price.getId()).build()).putMetadata("outTradeNo", stripeOrder.getOutTradeNo()).build();Session session = client.checkout().sessions().create(sessionCreateParams);LOG.info("session:{}", JSON.toJSONString(session));return preOrderHandler(Collections.singletonMap("paymentLink", session.getUrl()), order);} catch (StripeException e) {throw new RuntimeException(e);}
}
4、打开支付链接,完成支付
输入Stripe平台提供的测试卡信息,完成支付
test@example.com
4242 4242 4242 4242
12/34
567
Zhang San
United States
12345

5、支付订单查询
传入回调信息中得到的chargeId,查询订单状态。在返回的json数据了包含支付平台receiptUrl
public Map<String, Object> query(AssistOrder assistOrder) {try {Charge charge = client.charges().retrieve(assistOrder.getTradeNo());// 使用Hutool的BeanUtil将User对象转换为Mapreturn BeanUtil.beanToMap(charge);} catch (Exception e) {throw new RuntimeException(e);}
}
支付凭证

6、退款
传入回调信息中得到的chargeId,提交退款请求;返回退款订单信息,包含退款订单Id(可用于查询退款订单)
public RefundResult refund(RefundOrder refundOrder) {RefundCreateParams params = RefundCreateParams.builder().setCharge(refundOrder.getTradeNo()).build();try {Refund refund = client.refunds().create(params);LOG.info("refund:{}", JSON.toJSONString(refund));StripeRefundResult refundResult = new StripeRefundResult(refund, refundOrder.getTradeNo());refundOrder.setRefundNo(refundResult.getRefundNo());return refundResult;} catch (StripeException e) {throw new RuntimeException(e);}
}
7、退款查询
传入回调信息中得到的chargeId,查询退款订单;也可以通过退款订单Id查询。
public Map<String, Object> refundquery(RefundOrder refundOrder) {RefundListParams params = RefundListParams.builder().setCharge(refundOrder.getTradeNo()).build();try {StripeCollection<Refund> result = client.refunds().list(params);if (!result.getData().isEmpty()) {Refund refund = result.getData().stream().findFirst().get();// 使用Hutool的BeanUtil将User对象转换为Mapreturn BeanUtil.beanToMap(refund);}} catch (StripeException e) {throw new RuntimeException(e);}return null;
}
8、回调通知
登录Stripe平台,在https://dashboard.stripe.com/workbench/webhooks中配置Webhook;菜单地址“开发人员-Webhook”。

Webhook回调代码示例
public class StripePayMessageHandler implements PayMessageHandler<PayMessage, StripePayService> {private final Logger LOG = LoggerFactory.getLogger(getClass());private final String endpointSecret = "whsec_HlzC2omyh4V4X3BCgMx5PScTCmwZpvAC";//webhook秘钥签名@Overridepublic PayOutMessage handle(PayMessage payMessage, Map<String, Object> context, StripePayService payService) throws PayErrorException {Map<String, Object> message = payMessage.getPayMessage();NoticeParams noticeParams = (NoticeParams) context.get("noticeParams");try {String sigHeader = noticeParams.getHeader("Stripe-Signature");Event event = Webhook.constructEvent(noticeParams.getBodyStr(), sigHeader, endpointSecret);//验签,并获取事件StripeObject eventObj = event.getDataObjectDeserializer().getObject().get();LOG.info("EventType:{}, Event:{}", event.getType(), JSON.toJSONString(eventObj));PaymentIntent intent;Charge charge;String outTradeNo;String chargeId;String receiptUrl;switch (event.getType()) {case "charge.succeeded"://支付成功//TODO 支付成功,处理业务逻辑charge = (Charge) eventObj;// 取得 chargeId ,在退款时使用chargeId = charge.getId();receiptUrl = charge.getReceiptUrl();message.put("trade_no", chargeId);LOG.info("支付成功 Charge, chargeId:{}, receiptUrl:{}", chargeId, receiptUrl);break;case "checkout.session.completed":// 通过支付链接 支付完成//TODO 支付完成,处理业务逻辑Session session = (Session) eventObj;outTradeNo = session.getMetadata().get("outTradeNo");//自定义订单号LOG.info("支付完成 Session, 订单号为:{}", outTradeNo);message.put("out_trade_no", outTradeNo);break;case "charge.refunded"://退款成功charge = (Charge) eventObj;if (charge.getStatus().equals("succeeded")) {//TODO 退款成功,处理业务逻辑chargeId = charge.getId();receiptUrl = charge.getReceiptUrl();message.put("trade_no", chargeId);LOG.info("退款成功, chargeId:{}, receiptUrl:{}", chargeId, receiptUrl);}break;case "checkout.session.expired"://过期break;case "payment_intent.created"://创建订单 这里事件就是图二选着的事件break;case "payment_intent.canceled"://取消订单break;case "payment_intent.succeeded"://支付成功intent = (PaymentIntent) eventObj;Map<String, String> metaData = intent.getMetadata();//自定义传入的参数outTradeNo = metaData.get("outTradeNo");//自定义订单号message.put("out_trade_no", outTradeNo);LOG.info("支付成功 payment_intent, 订单号为:{}", outTradeNo);//*********** 根据订单号从数据库中找到订单,并将状态置为成功 *********//*break;case "payment_intent.payment_failed"://支付失败intent = (PaymentIntent) eventObj;LOG.info("Failed: " + intent.getId());break;default:break;}} catch (Exception e) {LOG.error("stripe异步通知(webhook事件)", e);}// TODO 支付确认逻辑处理return payService.successPayOutMessage(payMessage);}
}
参考
- https://docs.stripe.com/api
- https://docs.stripe.com/js
- https://docs.stripe.com/webhooks
- https://docs.stripe.com/search#query-fields-for-products
相关文章:
【支付】Stripe支付通道Java对接(产品 价格 支付 查询 退款 回调)
Stripe是一家美国科技公司,成立于2010年,由爱尔兰兄弟Patrick Collison和John Collison共同创立。该公司致力于提供高效、简洁的互联网支付收款服务,为开发者或商家提供支付API接口或代码,使商家的网站、移动APP支持信用卡付款。S…...
Unity3D 小案例 像素贪吃蛇 01 蛇的移动
Unity3D 小案例 像素贪吃蛇 第一期 蛇的移动 像素贪吃蛇 今天来简单制作一个小案例,经典的像素贪吃蛇。 准备 首先调整一下相机的设置,这里使用灰色的纯色背景,正交视图。 接着,创建一个正方形,保存为预制体&#…...
【STM32 MCU】stm32MCUs 32-bit Arm Cortex-M
stm32MCUs 32-bit Arm Cortex-M...
html+css网页设计 旅游 雪花旅行社5个页面
htmlcss网页设计 旅游 雪花旅行社5个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&#…...
vue3中的实例
实例类型 Vue2:每个Vue应用都是new Vue创建的一个新实例,创建的时候将data作为property添加到响应式系统中 vue3:createApp创建一个Application Instance、应用实例用来注册全局内容,大多数方法支持链式调用,返回实例…...
9.测试计划(包含笔试/面试题)
一、软件测试计划介绍 1.测试计划就是一份测试文档,一份描述测试工作计划的文档,对测试计划进行统筹安排。 2.测试计划的编写者就是测试组长,测试主管。 3.测试计划的查阅者:测试人员,测试主管,产品&#x…...
这 7 款AI应用将让你全新的iPhone 16成为电影制作的强大工具
苹果公司在周一的Glowtime发布会上揭晓了新款的iPhone 16 Pro系列。除了新加入的苹果智能功能和令人印象深刻的硬件升级外,它还获得了一套视频制作工具,让用户能够在一个几乎可以放进口袋的设备上制作整部电影。 这些升级中有一个48MP融合相机。它具有2…...
自注意力机制(self-attention)
自注意力机制(self-attention) 之前听过吴恩达老师的课,吴恩达老师CNN那一块讲的特别好,但是后面RNN这一部分我听的不是很明白,今天有看了李宏毅老师attention这部分的课,总结一下笔记。 self-attention …...
Nuxt3入门:过渡效果(第5节)
你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。 Nuxt 利用 Vue 的 <Transition> 组件在页面和布局之间应用过渡效果。 一、页面过渡效果 你可以启用页面过渡效果,以便对所有页面应用自动过渡效果。 nuxt.config.js export defaul…...
【开发工具】IntelliJ IDEA插件推荐:Json Helper——让JSON处理更高效
导语:在Java开发过程中,JSON作为一种轻量级的数据交换格式,被广泛应用于前后端数据交互。今天,我要为大家介绍一款IntelliJ IDEA插件——Json Helper,帮助开发者更高效地处理JSON数据。 一、什么是Json Helper&#x…...
Lua垃圾回收机制
Lua垃圾回收机制 在 Lua 中,一共只有8种数据类型,分别为 nil 、boolean 、userdata 、number 、string 、 table 、 function 、 userdata 和 thread 。其中,只有 string table function thread 四种是以引用方式共享,是需要被 G…...
Java学习路线:详细指引
Java学习路线可以分为几个阶段,每个阶段都有其重点和推荐学习的内容。下面我将按照初学者、进阶和高级三个阶段来举例说明: 初学者阶段 目标: 熟悉Java基础语法理解面向对象编程掌握基本数据类型和数据结构学会使用IDE(如Intel…...
商家转账到零钱如何开通-微信支付
商家转账到零钱是微信支付的一项实用功能,允许商户将资金从商户号余额直接转账到用户的微信零钱。我们以上万次成功申请的经验整理了本文的详细的步骤和建议以帮助商户可以快速开通该功能。 1. 准备工作 - 确认申请资格:只有公司性质的商户可以申请此功能…...
自研商家如何快速接入电商平台订单数据?
随着电子商务行业的快速发展,越来越多的商家开始寻求高效的订单管理和数据整合方案。对于那些自研系统的商家来说,如何实现与各大电商平台之间的无缝对接,成为了一项重要挑战。点三电商API正是为此类需求量身打造,为商家提供了一站…...
Win10下借助CMake编译OpenMVS
笔者在编译OpenMVS的过程十分曲折。刚开始借助CMake编译,能够把与库生成相关的工程编译出来,但是与可执行文件相关的工程会报错;后来参考官方教程借助VCPKG编译,发现VCPKG并没有想中强大、好用,最终也是遇到了各种问题没有编译成功。但是,笔者在解决问题的过程发现了问题…...
04_定时器与数码管基础
通过上节课的实验,大家会发现,我们逐渐进入比较实质性的学习了,需要记住的内容也更多了,个别地方可能会感觉吃力。但是大家不要担心,要有信心。这个跟小孩学走路一样,刚开始走得不太稳,没关系&a…...
Python 数学建模——方差分析
文章目录 前言单因素方差分析原理核心代码 双因素方差分析数学模型分析依据典型代码 前言 方差分析也是概率论中非常重要的内容,有时数学建模需要用到。方差分析是干什么的?如果说假设检验用于分析两个总体之间的均值 μ 1 , μ 2 \mu_1,\mu_2 μ1,μ…...
计算机视觉中,什么是上下文信息(contextual information)?
在计算机视觉中,上下文信息(contextual information)是指一个像素或一个小区域周围的环境或背景信息,它帮助模型理解图像中对象的相对位置、大小、形状,以及与其他对象的关系。上下文信息在图像中提供了全局的语义和结…...
YOLOv5改进 | 模块缝合 | C3 融合RVB + EMA注意力机制【二次融合】
秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 专栏目录 :《YOLOv5入门 改…...
mysql 更改默认端口号 新增用户密码 赋予权限
默认情况下,mysql的端口是3306,超级用户是root,很多情况下会被黑客扫描到,成为肉鸡(作者以前就有过经理),数据库表直接丢失,勒索我。 所以我这里介绍下,更改默认端口&am…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
