stripe 支付跟国内的 支付宝 、微信、等第三方支付平台不一样
码字不易,开源更不易,点赞收藏关注,多多支持
开源地址 https://gitee.com/J-LJJ/stripe-demo
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
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.6.3
com.japhet
stripes-demo
0.0.1-SNAPSHOT
stripes-demo
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
com.alibaba
fastjson
1.2.28
org.slf4j
slf4j-simple
2.0.3
com.sparkjava
spark-core
2.9.4
com.google.code.gson
gson
2.9.1
com.stripe
stripe-java
22.5.1
org.springframework.boot
spring-boot-maven-plugin
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/apikeys
Stripe.apiKey = "sk_test_51Mq6xRLbpF5IT5HsSAQtSW2iW6CJ2tm9MriCV3p2uaitY9O65Js4cUF6";
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/create
Map params = new HashMap<>();
params.put("name", "产品名称-1");
Product product = Product.create(params);
//创建价格 https://stripe.com/docs/api/prices/create
Map recurring = new HashMap<>();
recurring.put("interval", "month");
Map 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());
//创建支付信息 得到url
SessionCreateParams 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/create
Map params = new HashMap<>();
params.put("name", "Gold Special");
Product product = Product.create(params);
System.out.println(product.toString());
//修改产品 https://stripe.com/docs/api/products/update
Product product2 = Product.retrieve(product.getId());
Map 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/create
Map recurring = new HashMap<>();
recurring.put("interval", "month");
Map 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-price
Price 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/create
int randMoney3 = random.nextInt(max)%(max-min+1) + min;
System.out.println(randMoney3);
Map recurring2 = new HashMap<>();
recurring2.put("interval", "month");
Map 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());
//创建支付信息 得到url
SessionCreateParams 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
Title
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_bdenE7wX6453PVH45P7";//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);
}
}
}