首页 > 基础资料 博客日记

java 后端对接 Stripe支付,使用Stripe的自定义支付,实现网站自定义金额支付成功

2024-08-22 13:00:23基础资料围观273

这篇文章介绍了java 后端对接 Stripe支付,使用Stripe的自定义支付,实现网站自定义金额支付成功,分享给大家做个参考,收藏Java资料网收获更多编程知识

一.流程

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版本

家人们,有什么指导或者问题可以私信我,谢谢


文章来源:https://blog.csdn.net/weixin_53658847/article/details/138898457
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云