java 对接 stripe支付

article/2025/4/20 3:08:02

stripe 支付跟国内的 支付宝 、微信、等第三方支付平台不一样

 码字不易,开源更不易,点赞收藏关注,多多支持

开源地址  https://gitee.com/J-LJJ/stripe-demo

支付方式一

先看效果

 

 

支付方式2(需要配合回调)

2023-04-12更新.......

综上是支付方式1 创建商品、价格的方式进行支付

还有另外一种支付是自定义金额的方式进行支付,代码已同步到gitee,点我过去 ,

再看看效果图吧,嘻嘻

 

支付方式3(不需要回调)

2023-04-13更新.......

你敢相信? 还有第三种支付(Charge.create),代码同样更新gitee ,点我过去 ,

再看看效果图

流程

1、注册他们平台的账号   Sign Up and Create a Stripe Account | Stripe

2、然后得到私钥(注册账号,测试阶段可以不用去填写信息)

3、去他们后台管理页面去添加产品 Stripe Login | Sign in to the Stripe Dashboard

4、添加产品-> 添加产品的价格->然后再创建支付得到url (可以通过api接口方式进行在他们后台创建,也可以手动去创建)

5、得到了url,进去跳转,然后得到测试的visa卡进行支付  Test cards | Stripe Documentation

6、支付成功后,修改订单状态(这里需要用到stripe的回调 webhook)

回调配置

我之类在开发的时候遇到了一个大坑,总结就一句话,

你用checkout的api调用拉起支付,就必须要在stripe后台的webhook勾选checkout.xxx 

用PaymentIntent的api调用拉起支付,就必须要在stripe后台的webhook勾选payment_intent.xxx 

不能搞混 、 不能搞混 、 不能搞混

然后讲一下哪里配置 ,登录后台,然后点击开发人员,找到webhook,然后添加端点,我这里是用到的内网穿透,可以更方便的在本地调试,花生壳,natapp都可以内网穿透

 然后你支付成功了,可以看官方调用你接口的日志

代码部分

码字不易,开源更不易,点赞收藏关注,多多支持

开源地址  https://gitee.com/J-LJJ/stripe-demo

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.japhet</groupId><artifactId>stripes-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>stripes-demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.28</version></dependency><!--  stripe  begin --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>2.0.3</version></dependency><dependency><groupId>com.sparkjava</groupId><artifactId>spark-core</artifactId><version>2.9.4</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.9.1</version></dependency><dependency><groupId>com.stripe</groupId><artifactId>stripe-java</artifactId><version>22.5.1</version></dependency><!--  stripe  end --></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

controller

package com.japhet.stripesdemo.controller;import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.*;
import com.stripe.model.checkout.Session;
import com.stripe.param.PaymentIntentCreateParams;
import com.stripe.param.PriceListParams;
import com.stripe.param.PriceUpdateParams;
import com.stripe.param.checkout.SessionCreateParams;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.nio.file.Paths;
import java.util.*;import static spark.Spark.staticFiles;@RestController
public class StripeController {private static Gson gson = new Gson();static class CreatePayment {@SerializedName("items")Object[] items;public Object[] getItems() {return items;}}static class CreatePaymentResponse {private String clientSecret;public CreatePaymentResponse(String clientSecret) {this.clientSecret = clientSecret;}}static {// 管理平台里面的密钥  详情请看 demo-image/1.jpg ,图片地址链接: https://dashboard.stripe.com/test/apikeysStripe.apiKey = "sk_test_51Mq6xRLbpF5IT5HsSAQtSW2iW6CJ2tm9Mrixxxxxxxxxxxx";staticFiles.externalLocation( Paths.get("public").toAbsolutePath().toString());}/***   去支付* 1、创建产品* 2、设置价格* 3、创建支付信息 得到url* @return*/@PostMapping("/pay")public String pay() throws StripeException {/* 这里生成随机价格  1000-9000的价格*/int max=9000;int min=1000;Random random = new Random();int randMoney = random.nextInt(max)%(max-min+1) + min;//创建产品 https://stripe.com/docs/api/products/createMap<String, Object> params = new HashMap<>();params.put("name", "产品名称-1");Product product = Product.create(params);//创建价格 https://stripe.com/docs/api/prices/createMap<String, Object> recurring = new HashMap<>();recurring.put("interval", "month");Map<String, Object> params2 = new HashMap<>();params2.put("unit_amount", randMoney);params2.put("currency", "usd");params2.put("recurring", recurring);params2.put("product", product.getId());Price price = Price.create(params2);System.out.println(price.toString());//创建支付信息 得到urlSessionCreateParams params3 = SessionCreateParams.builder().setMode(SessionCreateParams.Mode.SUBSCRIPTION).setSuccessUrl("http://127.0.0.1:9900/success").setCancelUrl( "http://127.0.0.1:9900/cancel").addLineItem(SessionCreateParams.LineItem.builder().setQuantity(1L).setPrice(price.getId()).build()).putMetadata("orderId",UUID.randomUUID().toString()).build();Session session = Session.create(params3);return session.getUrl();}/***           基本上会用到的api* 创建产品* 修改产品* 创建产品的价格* 修改产品的价格(注意这里,修改产品的价格是去把价格存档,然后再新增一条价格数据)* 得到这个产品的价格列表* 创建支付信息 得到url* @return*/public void aa() throws StripeException {int max=9000;int min=1000;Random random = new Random();int randMoney = random.nextInt(max)%(max-min+1) + min;System.out.println(randMoney);//创建产品 https://stripe.com/docs/api/products/createMap<String, Object> params = new HashMap<>();params.put("name", "Gold Special");Product product = Product.create(params);System.out.println(product.toString());//修改产品 https://stripe.com/docs/api/products/updateProduct product2 = Product.retrieve(product.getId());Map<String, Object> params2 = new HashMap<>();params2.put("name", product.getName()+randMoney);Product updatedProduct = product2.update(params2);System.out.println(updatedProduct.toString());//创建价格 https://stripe.com/docs/api/prices/createMap<String, Object> recurring = new HashMap<>();recurring.put("interval", "month");Map<String, Object> params3 = new HashMap<>();params3.put("unit_amount", randMoney);params3.put("currency", "usd");params3.put("recurring", recurring);params3.put("product", product.getId());Price price = Price.create(params3);System.out.println(price.toString());//修改价格 (新建price,老的价格不用,存档) https://stripe.com/docs/products-prices/manage-prices?dashboard-or-api=api#edit-pricePrice resource = Price.retrieve(price.getId());PriceUpdateParams params4 = PriceUpdateParams.builder().setLookupKey(price.getLookupKey()).setActive(false).build();Price price2 = resource.update(params4);System.out.println(price2);//重新创建价格 https://stripe.com/docs/api/prices/createint randMoney3 = random.nextInt(max)%(max-min+1) + min;System.out.println(randMoney3);Map<String, Object> recurring2 = new HashMap<>();recurring2.put("interval", "month");Map<String, Object> params5 = new HashMap<>();params5.put("unit_amount", randMoney3);params5.put("currency", "usd");params5.put("recurring", recurring2);params5.put("product", product.getId());Price price3 = Price.create(params5);System.out.println(price3.toString());//得到这个产品的价格列表PriceListParams params6 = PriceListParams.builder().setProduct(product.getId()).setActive(true).build();PriceCollection prices = Price.list(params6);System.out.println(prices.toString());//创建支付信息 得到urlSessionCreateParams params7 =SessionCreateParams.builder().setMode(SessionCreateParams.Mode.SUBSCRIPTION).setSuccessUrl("http://127.0.0.1:9900/success").setCancelUrl( "http://127.0.0.1:9900/cancel").addLineItem(SessionCreateParams.LineItem.builder().setQuantity(1L)// 购买数量.setPrice(price3.getId())// 购买价格.build()).putMetadata("orderId",UUID.randomUUID().toString())//订单id 支付成功后,回调的时候拿到这个订单id,进行修改数据库状态.build();Session session = Session.create(params7);System.out.println(session.toString());System.out.println("最后去支付的url:"+session.getUrl());}@RequestMapping("/success")public String success(){return "success";}@RequestMapping("/cancel")public String cancel(){return "cancel";}}

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div><button type="button" onclick="toPay()">创建商品并去支付</button></div><script ></script><script src="/jquery.min.js"></script><script>function toPay() {$.ajax({type : 'post',url : '/pay',data : {},success : function(res) {alert(res)window.location.href = res;},error : function(res) {alert("网络错误");}});}</script></body>
</html>

支付成功回调

package com.japhet.stripesdemo.controller;import com.alibaba.fastjson.JSONObject;
import com.stripe.model.*;
import com.stripe.net.Webhook;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;@Controller
public class StripeBackController {@ResponseBody@RequestMapping(value = {"/stripe_events"}, method = RequestMethod.POST)public void stripe_events(HttpServletRequest request, HttpServletResponse response) {System.out.println("------进入回调了------");try {String endpointSecret = "whsec_bdenE7xxxxxxxxxxx";//webhook秘钥签名InputStream inputStream = request.getInputStream();ByteArrayOutputStream output = new ByteArrayOutputStream();byte[] buffer = new byte[1024*4];int n = 0;while (-1 != (n = inputStream.read(buffer))) {output.write(buffer, 0, n);}byte[] bytes = output.toByteArray();String payload = new String(bytes, "UTF-8");String sigHeader = request.getHeader("Stripe-Signature");Event event = Webhook.constructEvent(payload, sigHeader, endpointSecret);//验签,并获取事件switch(event.getType()) {case "checkout.session.completed"://支付完成System.out.println("---------------success2222222---------------");String s = event.getDataObjectDeserializer().getObject().get().toJson();JSONObject jsonObject = JSONObject.parseObject(s);JSONObject jsonObject2 = (JSONObject)jsonObject.get("metadata");String orderId = jsonObject2.getString("orderId");System.out.println("订单号为:"+orderId);System.out.println("根据订单号从数据库中找到订单,并将状态置为支付成功状态");break;case "checkout.session.expired"://过期System.out.println("---------------checkout.session.expired---------------");break;default:break;}} catch (Exception e) {System.out.println("stripe异步通知(webhook事件)"+e);}}
}

--------------------------------------------------------------------------------

2023-07-28 10:15:00更新 ~~~~

写了这篇博客我看好多朋友都有疑问,都说要加我联系方式,我这里给出来大家可以加我,有问题可以及时与我沟通: QQ或微信都可以加我 517861659 

如果没有及时回复,可以点我先问问AI机器人https://chatgpt.byabstudio.com/login?code=202307011314  


http://chatgpt.dhexx.cn/article/f9u0IOKx.shtml

相关文章

Stripe支付流程简要描述

在国外&#xff0c;除了Paypal支付之外&#xff0c;Stripe支付也占有很大一部分市场份额&#xff0c;Stripe支付官网 https://stripe.com/ 下面简单介绍一下Stripe的支付流程。 1、用户页面输入充值金额&#xff0c;点击确定跳转到支付页面&#xff08;页面的样式由stripe提供…

stripe支付集成

最近公司要做一下Stripe支付的集成&#xff0c;浅浅地谈一下自己的一点理解 1、stripe是什么&#xff1f; stripe是第三方的支付平台&#xff0c;就像国内的支付宝、微信支付。。。 stripe官方文档&#xff1a;Developer tools | Stripe Documentation 关于stripe支付&…

初步认识 Stripe 支付

前言 这段时间在做支付相关的工作&#xff0c;由于业务主要是面向国外的用户&#xff0c;因而就接触了部分国外的支付支付相关的平台。接下来的内容主要是初步看了 Stripe 平台的文档所了解到的基本内容&#xff0c;后面会在使用的过程中不断地进行完善。 基本介绍和与其他支…

Stripe支付流程

近几天因为公司的项目中遇到了需要支持给国外本土支付提供支持&#xff0c;经过调研了市面上几款的产品后选择了stripe支付 由于资料比较少没有太多讨论&#xff0c;慢慢查看官方文档以下是我对官方文档梳理和对接过程中的一些经验和理解记录了下来 关于Stripe Stripe是一家提…

Stripe国际支付简介及API对接

文章目录 一、了解Stripe支付二、Stripe注册流程三、Stripe API 特点3.1 Apikey3.2 Idempotent Requests 幂等请求3.3 两种付款方式 四、Stripe 支付核心API4.1 Token4.2 Customer4.3 Card4.4 Source4.5 charge4.6 PaymentIntents4.7 PaymentMethod 五、完整Stripe支付代码 一、…

mingw(msys2)编译ffmpeg

mingw(msys2)编译ffmpeg 首先要确保pacman环境是最新的&#xff0c;否则会出现莫名其妙的问题&#xff0c;可以执行“pacman -Syu”更新包 安装mingw: pacman -S gcc mingw-w64-i686-toolchain yasm mingw-w64-i686-SDL2 //mingw32 pacman -S gcc mingw-w64-x86_64-toolchai…

Hyperscan Windows 编译指南

Hyperscan Windows 编译指南 Hyperscan 源码下载&#xff1a;https://www.hyperscan.io/准备环境&#xff1a; Windows 10 X64 Cygwin : https://www.cygwin.com/ CMake&#xff1a;https://cmake.org/ Visual Studio 2017 Python (2.7 版本) Boost : https://www.boost…

Hyperscan 5.4.0 安装教程 (CentOS7环境)

参考&#xff1a;Getting Started — Hyperscan 5.4.0 documentationhttp://intel.github.io/hyperscan/dev-reference/getting_started.html 目录 1.下载 2.安装环境配置 2.1 硬件需求 2.2 软件需求 3.安装 3.1 创建构建目录 3.2 设置编译选项 3.3 构建hyperscan 4.安…

Hyperscan 安装

源码下载 Ragel &#xff1a;http://www.colm.net/files/ragel/ragel-6.9.tar.gz boost &#xff1a;http://downloads.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.gz hyperscan &#xff1a; https://download.csdn.net/download/u014608280/12745509 第…

centos 8 编译安装hyperscan

一、编译安装环境配置 官方文档&#xff1a; http://intel.github.io/hyperscan/dev-reference/getting_started.html 1.1硬件配置 配置参数CPUIntel Xeon Gold 5218R CPU 2.10GHzCPU核数8核 注&#xff1a;需要满足以下条件 1、X86架构 2、Supplemental Streaming SIMD E…

ubuntu20.04下源码安装hyperscan库安装记录

安装测试环境&#xff1a; vmware-ubuntu20.04&#xff0c;gcc 4.8.5&#xff0c;ragel-6.10.tar.gz&#xff0c;boost_1_69_0.tar.gz&#xff0c;hyperscan-5.1.0.tar.gz 1.安装ragel&#xff08;必须的依赖包&#xff09;1MB&#xff1a; 下载地址&#xff1a;http://www.…

基于CentOS 8 系统环境下的 Snort 3 安装指南

O、 阅读要求 本教程并不适合初学者&#xff0c;大家在阅读本文之前&#xff0c;需具备CentOS 8 Linux、Snort 2.9的成功安装经验。本次安装对网络依赖很大&#xff0c;所以大家一定要将网络状态调节好&#xff0c;本指南介绍的内容&#xff0c;仅在测试环境中使用。 一、环境…

msys2+mingw64+ragel安装

[msys2mingw64ragel安装] [简介] 这几天部门老大让解析几个东西&#xff0c;要求用ragel编写&#xff0c;在Windows环境下&#xff0c;要运用到mingw64&#xff0c;安装时发现mingw里没有pacman&#xff0c;需要现安装&#xff0c;然后发现Wget也没有。。。&#xff0c;所以改…

Ragel State Machine Compiler 的速度测试

据说Ragel生成的自动机程序&#xff0c;速度飞快&#xff0c;特地测试了一下&#xff0c;所得结果如下。 测试环境&#xff1a; VC6 Release下编译 测试规模&#xff1a; 一亿次 测试用例&#xff1a; Ragel编译r_atoi.rl文件 vs crt lib的 atoi函数 测试结果&…

Hello Ragel -- 生成状态机的神器

Ragel 是个很 NB 的能生成状态机的编译器&#xff0c;而且支持一堆语言&#xff1a;C、C、Object-C、C#、D、Java、Go 以及 Ruby。 原来的文本解析器是用正则表达式实现的&#xff0c;随着状态&#xff08;if-else&#xff09;越来越多&#xff0c;修改越来越麻烦。。。 安装 M…

嵌入式系统开发流程

一、嵌入式系统开发流程 1、系统需求分析&#xff1a;根据需求&#xff0c;确定设计任务和设计目标&#xff0c;指定设计说明书。 2、体系结构设计&#xff1a;描述系统如何实现所述的功能需求&#xff0c;包括对硬件、软件和执行装置的功能划分以及系统的软件、硬件选型。 …

嵌入式系统开发设计

嵌入式系统开发设计 嵌入式系统设计的主要任务是定义系统的功能、决定系统的架构&#xff0c;并将功能映射到系统实现架构上。系统架构既包括软件系统架构也包括硬件系统架构。 嵌入式系统设计具有以下特点&#xff1a; 软、硬件协同并行开发&#xff1b; 微处理器的类型多种…

嵌入式系统的概念,嵌入式系统的组成及特点,嵌入式系统的基本开发流程

1. 嵌入式系统的概念 嵌入式系统( Embedded system) , 是一种 "完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。 2 . 嵌入式系统的组…

配置嵌入式系统开发环境(教程)

配置嵌入式系统开发环境 前言一. 安装VMware Workstation&#xff1f;二、在虚拟机中安装Windows XP镜像1.创建虚拟机启动虚拟机进入PE系统 关于pdf中预实验的补充说明 前言 嵌入式实时操作系统及应用开发&#xff08;第三版&#xff09;罗蕾主编光盘镜像 链接&#xff1a;htt…

嵌入式Linux系统开发笔记(七)

嵌入式Linux系统开发笔记&#xff08;七&#xff09; 七、U-Boot基础 1.概述 在移植 Linux之前我们需要先移植一个 bootloader 代码&#xff0c;这个 bootloader 代码用于启动 Linux 内核&#xff0c; bootloader有很多&#xff0c;常用的就是 U-Boot。 移植好 U-Boot 以后再…