Stripe国际支付简介及API对接

article/2025/6/8 4:09:50

文章目录

  • 一、了解Stripe支付
  • 二、Stripe注册流程
  • 三、Stripe API 特点
    • 3.1 Apikey
    • 3.2 Idempotent Requests 幂等请求
    • 3.3 两种付款方式
  • 四、Stripe 支付核心API
    • 4.1 Token
    • 4.2 Customer
    • 4.3 Card
    • 4.4 Source
    • 4.5 charge
    • 4.6 PaymentIntents
    • 4.7 PaymentMethod
  • 五、完整Stripe支付代码

一、了解Stripe支付

最近公司正在做一个国际版APP,涉及到海外支付,调研过Paypal、Skrill、BrainTree、Stripe(可参考海外移动支付方案对比),最终 选择了Stripe支付。Stripe特点如下:

  1. 收费规则简单透明,手续费就是收取订单总额的3.4 % + HK$2.35。没有月费、开户费、退款手续费,撤销付款费用手续费HK$85.00
  2. Stripe支持135+种货币创建付款(目前不支持中国大陆,只支持中国香港)。
  3. Stripe还支持其他付款方式,包括ACH信用转账、ACH借记转账、支付宝、Android Pay、Apple Pay、Bancontact、Bitcoin(比特币)、银行卡(Visa,Mastercard,American Express,Discover,Diners Club,JCB等)、Giropay、iDEAL、SEPA、SOFORT、微信支付等来自全球的热门支付方式。
  4. Stripe的开发文档清晰简单,集成友好。提供了IOS、Android的SDK,以及对各种语言的支持。

二、Stripe注册流程

和其他国内支付平台一样,首先需要注册Stripe账户。官网注册链接:
注册信息在注册页面中填写邮箱信息完成注册即可。进入了DashBoard,可以看到账户还没有被激活,在激活账户之前先验证电子邮件,然后点击激活账号:

在这里插入图片描述账户激活的时候,因为Stripe不支持中国,所以要用支持的国家注册商户,而你恰恰有这个国家的公司信息、银行卡信息之类的,最后一定要发送手机号码验证,要不然在调用API的时候,会报错,提示你没有完善信息。
在这里插入图片描述我这是公司账号,使用公司在香港信息完成了账户激活。可以看到,出现了API 密钥的内容提示,说明我们完成激活,可以开始玩了。

激活后的账号

三、Stripe API 特点

3.1 Apikey

Stripe.apiKey = "sk_test_*****************************";

Stripe API使用API密钥来验证请求,在控制台有两种密钥:测试密钥和生产密钥

测试模式密钥的前缀:sk_test_

生产模式密钥的前缀:sk_live_

在调用每个API的时候,要在每个请求中发送此密钥。

3.2 Idempotent Requests 幂等请求

Stripe API 支持Idempotentcy 来安全的重试请求,而不会意外的执行两次相同的操作。幂等性密钥是客户端生成的唯一值,服务器使用该值来识别同一个请求的重试。

3.3 两种付款方式

Stripe 现在提供两种方式的支付API:Payment Methods API 和 Tokens and SourcesAPIs

两者的区别在于Sources是通过status属性描述事物状态的。这意味着每个Source对象必须先转换为可收费状态才能用于付款,相反Payment Methods 是无状态的,依赖于PaymentIntent对象来表示给定支付的交易状态

如图所示,官方建议迁移到Payment Methods API
在这里插入图片描述

四、Stripe 支付核心API

Stripe 本身提供了大而全的东西,其核心的API,包括以下模块:
Stripe模块
官网给出了一个支付过程的说明,只需要六步就能完成操作,收集Card信息、创建用户、支付、计划、订阅,完成支付,基本上第四部和第五步,我们不会使用。简单易上手。

支付流程
我们自身业务关心的是Payment这块,所以核心的API也是集中在Payment这块儿说明,包括Token、Card、Customer、PaymentIntent、PaymentMethod、Source、Charge等,我们都使用创建API来挨个来了解一下。

4.1 Token

Token是Stripe用来客户收集敏感卡或者银行账户信息的过程,当用户填写了银行卡的卡号、过期年月、CVC等信息后,Stripe会生成过一个包含这些信息的Token,这样在传输过程中,确保没有敏感的卡数据和我们自己的服务器交互,降低客户真实信息丢失率。我们自身的服务器,取到token,进行支付即可 。

Token不能多次存储和使用,要存储卡的信息供以后使用,可以创建用户。将卡的信息添加给用户。

     #创建TokenStripe.apiKey = "sk_test_your_key";Map<String, Object> tokenParams = new HashMap<String, Object>();Map<String, Object> cardParams = new HashMap<String, Object>();cardParams.put("number", "4242424242424242");cardParams.put("exp_month", 8);cardParams.put("exp_year", 2020);cardParams.put("cvc", "314");tokenParams.put("card", cardParams);Token.create(tokenParams);

4.2 Customer

Customer 允许执行与同一客户关联的重复费用,并跟踪多个费用。可以创建、删除和更新客户。也可以检索单个客户以及所有客户的列表。

Map<String, Object> customerParams = new HashMap<String, Object>();customerParams.put("description", "Customer for chao");customerParams.put("source", "tok_**********");Customer c = null;try {c = Customer.create(customerParams);System.out.println(c);} catch (StripeException e) {e.printStackTrace();}

4.3 Card

可以在一个客户上存储多张卡,向该客户收费。

      Stripe.apiKey = "your_apikey";Customer customer = Customer.retrieve("cus_FfoCbKMV4SJ7je");Map<String, Object> params = new HashMap<String, Object>();params.put("source", "tok_mastercard");customer.getSources().create(params);

4.4 Source

Source代表接收各种付款方式,代表客户的支付工具。创建收费的时候,可以附加到客户。

Stripe.apiKey = "sk_test_1crNbJbtW30srR0CxeJHtFNF003Cuo2uSJ";Map<String, Object> sourceParams = new HashMap<String, Object>();
sourceParams.put("type", "ach_credit_transfer");
sourceParams.put("currency", "usd");
Map<String, Object> ownerParams = new HashMap<String, Object>();
ownerParams.put("email", "jenny.rosen@example.com");
sourceParams.put("owner", ownerParams);Source.create(sourceParams);

4.5 charge

对信用卡或者借记卡收费时,创建一个charge对象

Stripe.apiKey = "your_apikey";Map<String, Object> chargeParams = new HashMap<String, Object>();
chargeParams.put("amount", 2000);
chargeParams.put("currency", "hkd");
chargeParams.put("description", "Charge for jenny.rosen@example.com");
chargeParams.put("source", "tok_mastercard");Charge.create(chargeParams);

4.6 PaymentIntents

PaymentIntents 将指导你完成从客户处收款的过程,官方建议为系统中的每一个订单或者客户创建一个PaymentIntent。

Stripe.apiKey = "your_alikey";Map<String, Object> paymentIntentParams = new HashMap<>();
paymentIntentParams.put("amount", 2000);
paymentIntentParams.put("currency", "hkd");
ArrayList<String> paymentMethodTypes = new ArrayList<>();
paymentMethodTypes.add("card");
paymentIntentParams.put("payment_method_types", paymentMethodTypes);PaymentIntent.create(paymentIntentParams);

4.7 PaymentMethod

PaymentMethod代表客户的支付工具,和PaymentIntents一起使用 以收取付款或保存到客户对象。

Stripe.apiKey = "your_alikey";Map<String, Object> paymentmethodParams = new HashMap<String, Object>();
paymentmethodParams.put("type", "card");
Map<String, Object> cardParams = new HashMap<String, Object>();
cardParams.put("number", "4242424242424242");
cardParams.put("exp_month", 8);
cardParams.put("exp_year", 2020);
cardParams.put("cvc", "314");
paymentmethodParams.put("card", cardParams);PaymentMethod.create(paymentmethodParams);

五、完整Stripe支付代码

网上看了一大圈关于Stripe的支付,资料很少,要么是年代久远,要么是代码不完整。希望我的代码对你有所用。

我们的前端业务流程如图所示:
业务流程
选择的支付方式是Token and Source API,控制器类StripeController 代码如下:

@Controller
@RequestMapping(value = "/stripe")
public class StripeController {@Resourceprivate StripePayService stripePayService;private static Logger logger = LoggerFactory.getLogger(StripeController.class);/*** 获取用户卡片列表** @return*/@RequestMapping(value = "/getCardList", method = RequestMethod.POST)@ResponseBodypublic Response getCardList(@RequestBody @Valid StripePayRequestVO stripePayRequestVO, BindingResult result) {return stripePayService.getCardList(stripePayRequestVO);}/*** 添加用户卡片* @return*/@RequestMapping(value = "/addCard", method = RequestMethod.POST)@ResponseBodypublic Response addCard(@RequestBody @Valid StripePayRequestVO stripePayRequestVO, BindingResult result) {logger.debug("购买套餐请求参数 {} = ", JsonUtil.INSTANCE.toJson(stripePayRequestVO));return stripePayService.addCard(stripePayRequestVO);}/*** 发起支付* @return*/@RequestMapping(value = "/charge", method = RequestMethod.POST)@ResponseBodypublic Response aliPay(@RequestBody @Valid StripePayRequestVO stripePayRequestVO, BindingResult result) {return stripePayService.charge(stripePayRequestVO);}
}

DAO层

public interface StripePayService {Response charge(StripePayRequestVO stripePayRequestVO);Response getCardList(StripePayRequestVO stripePayRequestVO);Response addCard(StripePayRequestVO stripePayRequestVO);}

实现层

@Service("stripePayService")
public class StripePayServiceImpl implements StripePayService {@Overridepublic Response charge(StripePayRequestVO request) {try {Stripe.apiKey = "your_apikey";Map<String, Object> params = new HashMap<String, Object>();params.put("userId", request.getUserId());User user = this.get("from User where id=:userId", params);if (null == user) {return failure(ResponseEnum.USER_NOT_FOUND_FAILURE);}//无stripe账号,直接返回if (user.getStripeChargeId() == null || "".equals(user.getStripeChargeId())) {return success(ResponseEnum.USER_BAD_REQUEST_FAILURE);}// 业务订单数据,此处省略//发起支付Map<String, Object> payParams = new HashMap<>();payParams.put("amount", product.getPrice().intValue());payParams.put("currency", "usd");payParams.put("description", "Charge for " + user.getEmail());payParams.put("customer", user.getStripeChargeId());Charge charge = Charge.create(payParams);//charge  支付是同步通知if ("succeeded".equals(charge.getStatus())) {//交易成功后,需要更新我们的订单表,修改业务参数,此处省略return success(ResponseEnum.PAY_SUCCESS.getMessage());} else {return failure(ResponseEnum.PAY_ALIPAY_FAILURE);}} catch (StripeException e) {e.printStackTrace();}return failure(ResponseEnum.EVENT_SYSTEM_ERROR_FAILURE);}@Overridepublic Response getCardList(StripePayRequestVO stripePayRequestVO) {Stripe.apiKey = "your_alipay";Map<String, Object> params = new HashMap<String, Object>();params.put("userId", stripePayRequestVO.getUserId());User user = this.get("from User where id=:userId", params);if (null == user) {return failure(ResponseEnum.USER_NOT_FOUND_FAILURE);}List list = new ArrayList<StripeAddCardVO>();//如果没有这个stripe用户,就返回列表为空try {Map<String, Object> cardParams = new HashMap<String, Object>();cardParams.put("limit", 1);cardParams.put("object", "card");List<PaymentSource> cardList = Customer.retrieve(user.getStripeChargeId()).getSources().list(cardParams).getData();StripeCardVO stripeCardVO = new StripeCardVO();for (PaymentSource p : cardList) {Card c = (Card) p;stripeCardVO.setLast4(c.getLast4());stripeCardVO.setExpYear(c.getExpYear());stripeCardVO.setExpMonth(c.getExpMonth());list.add(stripeCardVO);}return success(list);} catch (StripeException e) {e.printStackTrace();}}@Overridepublic Response addCard(StripePayRequestVO stripePayRequestVO) {Stripe.apiKey = "your_alipay";Map<String, Object> params = new HashMap<String, Object>();params.put("userId", stripePayRequestVO.getUserId());User user = this.get("from User where id=:userId", params);if (null == user) {return failure(ResponseEnum.USER_NOT_FOUND_FAILURE);}//如果没有这个stripe用户,添加卡片就是创建用户if (user.getStripeChargeId() == null || "".equals(user.getStripeChargeId())) {Map<String, Object> customerParams = new HashMap<String, Object>();customerParams.put("description", "Customer for test");customerParams.put("source", stripePayRequestVO.getToken());Customer c = null;try {c = Customer.create(customerParams);user.setStripeChargeId(c.getId());this.saveOrUpdate(user);success("添加成功");} catch (StripeException e) {e.printStackTrace();}} else {//  有这个用户,就是修改他的唯一一张默认卡try {Customer c = Customer.retrieve(user.getStripeChargeId());System.out.println("给客户修改默认卡号");Map<String, Object> tokenParam = new HashMap<String, Object>();tokenParam.put("source", stripePayRequestVO.getToken());c.update(tokenParam);return success("修改成功");} catch (StripeException e) {System.out.println("异常了");System.out.println(e);e.printStackTrace();}}return failure(ResponseEnum.EVENT_SYSTEM_ERROR_FAILURE);}

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

相关文章

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 以后再…

迅为-iMX6ULL开发板原创嵌入式开发文档系统化学习

iTOP-IMX6ULL核心板采用单核Cortex-A7架构&#xff0c;主频高达528 MHz&#xff0c;CPU集成电源管理&#xff0c;146 PIN引脚全部引出。核心板接口引出串口8路、CAN 2路、网口2路、I2C1路、SPI 2路、PWM8路、ADC5路、USB1路等功能。核心板在IMX6UL开发板上进行了深度优化&#…

Vxworks嵌入式开发系统入门基础概念学习

1.VxWorks应用 自动化设备、工业控制&#xff08;实时性好&#xff09;、军用设备以及消费电子。 2.实时性 实时性包括硬实时、软实时。硬实时系统有一个刚性的、不可改变的deadlines&#xff0c;它不允许任何超出deadlines的错误。而软实时是一个柔性灵活的&#xff0c;它可以…

嵌入式系统的开发流程

嵌入式系统的开发流程 摘要&#xff1a;本文以 HHARM9-EDU为例&#xff0c;简要说明一下嵌入式系统的开发流程。 整个流程很简单&#xff0c;流程图如下&#xff1a; 一、配置Linux及MINIGUI ①配置Linux&#xff1a; 由于 HHARM9-EDU推荐使用Redhat 9&#xff0c;所以这里只介…

嵌入式开发系统的简介

小白日志&#xff08;一&#xff09; 嵌入式开发系统的简介 嵌入式系统是一种以硬件为载体&#xff0c;以计算机技术为基础&#xff0c;以应用程序为核心&#xff0c;满足特定功能、要求以及应用环境的专用计算机系统。所谓“嵌入式”&#xff0c;顾名思义&#xff0c;嵌入到…

嵌入式系统开发环境概述

嵌入式系统开发环境主要包括&#xff1a; 集成开发工具交叉编译器批处理文件makefileLink Script调试工具下载工具其它工具(Offline Tools)模拟器版本控制工具 接下来分别讲解以上各个工具&#xff1a; 1、集成开发工具 一般CPU厂商会提供针对该CPU的集成开发环境(IDE)&…