首页 > 基础资料 博客日记
java 后端对接 Stripe支付,使用Stripe的自定义支付,实现网站自定义金额支付成功
2024-08-22 13:00:23基础资料围观273次
一.流程
1.先需要自己注册好账号和银行卡信息,登录后可以获取到账号的API秘钥
流程是:拉起支付->用户支付->Stripe回调我们接口
总的来说,就是两个接口,一个是适用于前端来向Stripe拉起支付,一个是支付后Stripe回调接口,告诉我们支付的结果
二.代码
前提:
<!--Stripe-->
<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>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.stripe</groupId>
<artifactId>stripe-java</artifactId>
<version>25.7.0</version>
</dependency>
1.拉起支付,创建支付的链接
①创建类来保存自己的秘钥,请把sk_live_xxxxxxxx替换为自己的秘钥
import com.stripe.Stripe;
import lombok.Data;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
@Configuration
@Data
public class StripeConfig {
//生产秘钥
private String secretKey="sk_live_xxxxxxxx";
//测试秘钥
// private String secretKey="sk_test_xxxxxx";
@PostConstruct
public void init() {
Stripe.apiKey = secretKey;
}
private String webhookSigningSecret="whsec_xxxxJ";
}
②创建一个DTO对象来接收前端的参数数据
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel
public class CreatePaymentDTO implements Serializable {
/**
* 订单号
*/
@ApiModelProperty("订单号")
private String orderNumber;
/**
* 用户支付的币种:默认是美金
*/
@ApiModelProperty("用户支付的币种:默认是美金")
private String currencyOfPayment;
/**
* 优惠券代码
*/
@ApiModelProperty("优惠券代码")
private String couponCode;
/**
* 订单支付金额
*/
@ApiModelProperty("订单支付金额")
private Double orderAmount;
}
③在Controller层创建支付
我们的支付只涉及到订单和优惠券,如果涉及的还有其他,可以在map集合metadate中加入自己的条件
import com.google.gson.Gson;
import com.qiaoTai.config.StripeConfig;
import com.qiaoTai.result.Result;
import com.qiaoTai.service.FreeEntryUserService;
import com.qiaoTai.user.dto.PaymentDTO.CreatePaymentDTO;
import com.qiaoTai.user.vo.Result.ReturnedResultVO;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.PaymentIntent;
import com.stripe.param.PaymentIntentCreateParams;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/user/ProcessPayment")
@Api(tags = "Stripe支付接口")
@Slf4j
@CrossOrigin(origins = "*")
public class StripePaymentController {
/*@Autowired
private FreeEntryUserService freeEntryUserService;*/
private static final Gson gson = new Gson();
@Autowired
private StripeConfig stripeConfig; // 注入StripeConfig实例以便设置API密钥
@PostMapping("/stripe/ReceivingParameter")
@ApiOperation("支付方式一:stripe返回支付订单")
public Result<ReturnedResultVO> patternOfPaymentStripe(@RequestBody CreatePaymentDTO createPaymentDTO) {
// 设置Stripe API密钥
Stripe.apiKey = stripeConfig.getSecretKey();
log.info("支付方式一:stripe返回支付订单: {}", createPaymentDTO);
Double orderAmount = createPaymentDTO.getOrderAmount();//支付金额
String currencyCode = createPaymentDTO.getCurrencyOfPayment();//支付币种
String orderId = createPaymentDTO.getOrderNumber();//订单号
String couponCode = createPaymentDTO.getCouponCode();//优惠券
System.out.println("Stripe支付优惠券的兑换码:" + couponCode);
System.out.println("Stripe支付优惠券的兑换码:" + couponCode);
PaymentIntent paymentIntent = null; // 直接调用PaymentIntent的静态方法创建实例
// 将订单 ID 添加到 PaymentIntent 的 Metadata
Map<String, String> metadata = new HashMap<>();
metadata.put("orderId", orderId);//订单号
if (couponCode != null){
metadata.put("couponCode", couponCode);//优惠券
}
try {
PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
.setAmount((long)(orderAmount * 100)) // 将美元金额乘以100转化为cents
.setCurrency(currencyCode)
.setAutomaticPaymentMethods(
PaymentIntentCreateParams.AutomaticPaymentMethods.builder()
.setEnabled(true)
.build()
)
.putAllMetadata(metadata) // 添加 Metadata
.build();
paymentIntent = PaymentIntent.create(params);
} catch (StripeException e) {
System.out.println("Stripe支付错误-Error creating PaymentIntent: " + e.getMessage());
}
ReturnedResultVO returnedResultVO = new ReturnedResultVO();
returnedResultVO.setClientSecret(paymentIntent.getClientSecret());
return Result.success(returnedResultVO);
}
2.用户支付完成后,Strip会回调一个我们的接口,告诉我们支付的接口,这个接口必须是:https协议的!
①在Stripe的写上自己的接口,注意:必须是https协议!
获取到回调接口的秘钥,最常见的格式是whsec_...
!
点击:开发人员->找到自己的Webbook,添加自己后端的链接
②代码,请把私钥:whsec_xxxxxxxxx换成自己的
(代码注释的部分不会影响运行,其中FreeEntryUserService类是我自己的,注释的是我的业务流程,请替换为个人的业务!)
import com.qiaoTai.service.FreeEntryUserService;
import com.stripe.Stripe;
import com.stripe.exception.SignatureVerificationException;
import com.stripe.model.Event;
import com.stripe.model.EventDataObjectDeserializer;
import com.stripe.model.PaymentIntent;
import com.stripe.model.StripeObject;
import com.stripe.net.Webhook;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.stream.Collectors;
/*
* Stripe的回调接口
* */
@Api(tags = "Stripe回调接口")
@Slf4j
@RestController
@RequestMapping("/user/stripe-webhooks")
@CrossOrigin(origins = "*")
public class StripePaymentWebhookController {
/* @Autowired
private FreeEntryUserService freeEntryUserService;*/
private static final String stripeApiKey = "whsec_xxxxxxx";
static {
Stripe.apiKey = stripeApiKey; // 初始化Stripe API Key
}
@PostMapping
public ResponseEntity<String> handleStripeWebhooks(HttpServletRequest request) throws IOException, SignatureVerificationException {
String payload = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
String sigHeader = request.getHeader("Stripe-Signature");
// 验证签名
Event event = Webhook.constructEvent(payload, sigHeader, stripeApiKey);
// 反序列化事件数据
EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
StripeObject stripeObject = null;
if (dataObjectDeserializer.getObject().isPresent()) {
stripeObject = dataObjectDeserializer.getObject().get();
} else {
log.error("Deserialization failed due to an API version mismatch.");
return new ResponseEntity<>("Deserialization failed", HttpStatus.BAD_REQUEST);
}
// 处理事件
switch (event.getType()) {
case "payment_intent.succeeded":
PaymentIntent paymentIntent = (PaymentIntent) stripeObject;
log.info("PaymentIntent was successful!");
/*//1.处理个人业务数据
Map<String, String> metadata = paymentIntent.getMetadata();
String orderIdFromStripe = metadata.get("orderId");//订单号
String couponCodeFromStripe = metadata.get("couponCode");//优惠券
//2.更新数据
if (orderIdFromStripe != null) {
//获取到了订单的ID
System.out.println("Stripe回调接口订单号:"+orderIdFromStripe);
//3.执行业务
//查询是否有订单
AccountMonAssess accountMonAssess = new AccountMonAssess();
if (couponCodeFromStripe != null) {
//获取到订单的优惠券
System.out.println("Stripe回调接口优惠券:"+couponCodeFromStripe);
System.out.println("Stripe回调接口优惠券代码是:"+couponCodeFromStripe);
//查询优惠券的ID信息
TbCoupon tbCoupon =freeEntryUserService.selectCoupon(couponCodeFromStripe);
// 添加检查确保tbCoupon不为null
if (tbCoupon != null) {
accountMonAssess.setCouponId(tbCoupon.getId());
} else {
// 如果优惠券没找到,根据你的业务逻辑处理这种情况,比如记录日志或设置默认值
log.warn("Stripe支付回调,没有更优惠券代码找到优惠券的ID: {}", couponCodeFromStripe);
System.out.println("Stripe支付回调,没有更优惠券代码找到优惠券的ID"+couponCodeFromStripe);
}
}
accountMonAssess.setOrderNumber(orderIdFromStripe);
accountMonAssess.setPaymentMethod(1);
accountMonAssess.setStateOfPayment(3);
accountMonAssess.setPaymentResult(2);
accountMonAssess.setApplyResult(0);
freeEntryUserService.updateOrderStatusStripe(accountMonAssess);
}else {
log.info("订单号不存在");
}*/
break;
case "payment_method.attached":
// 注意:这里需要更正类型,因为PaymentMethod不是StripeObject的直接子类,但为了演示逻辑保持原有结构
// 实际应用中应正确处理转换
log.info("PaymentMethod was attached to a Customer!");
break;
// ... handle other event types
default:
log.info("Unhandled event type: {}", event.getType());
break;
}
return ResponseEntity.ok().build(); // 返回200 OK
}
}
三,遇到的问题:
1.报错::2024-05-11 11:27:28.439 ERROR 93770 --- [nio-8080-exec-1] c.q.c.u.StripePaymentWebhookController : Deserialization failed due to an API version mismatch.
这个是api版本问题,请注意,版本必须保持一致
在Stripe的工作台->API versions查询是不是后端写的api版本,上边的代码提供的是最新的
<version>25.7.0</version> 25.7版本
家人们,有什么指导或者问题可以私信我,谢谢
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签: