Java整合stripe支付一篇文章就够了

发布时间:2023年12月27日

做过国际支付的应该对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>com.stripe</groupId>
            <artifactId>stripe-java</artifactId>
            <version>22.5.1</version>
        </dependency>

不同支付方式的rest接口

import com.bithelp.annotation.AnonymousAccess;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.*;
import com.stripe.model.checkout.Session;
import com.stripe.net.RequestOptions;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@RestController
@RequestMapping("/api/stripe")
public class StripeController {

    static {
        // 管理平台里面的密钥  详情请看 demo-image/1.jpg ,图片地址链接: https://dashboard.stripe.com/test/apikeys
        Stripe.apiKey = "sk_test_51OEkcYEWc6AdwtprMoGUtFwcJu4h2dgVxMJs0PL8eHbWwYc0Vl3kNMgeC9OoZ3bE6gy0kiZSdKk5REOhAzVt89uG00gnnHyJ8P";
    }

    /**
     *   去支付
     * 1、创建产品
     * 2、设置价格
     * 3、创建支付信息 得到url
     * https://checkout.stripe.com/c/pay/cs_test_a1ayts7NA3EKscl8e0CtRlx6U3YrYwmxXddf5vr5h3xtifbD6dhPZUg2QI#fidkdWxOYHwnPyd1blpxYHZxWjA0SkJBcGBNR2swUUo0YjRjZklrfDVGPVFXUl1jUGtGZGNhcWBqQE5nVmZ8amp3Ulw1SUdtQmlOb2NCY0xmVkRHf21cQ0pEczFjTG8zdlFGXGdqf3wybWdgNTVCYXFScndkfScpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl
     * @return
     */
    @PostMapping("/pay")
    @AnonymousAccess
    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<String, Object> params = new HashMap<>();
        params.put("name", "产品名称-1");
        Product product = Product.create(params);
        //创建价格 https://stripe.com/docs/api/prices/create
//        Map<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());

        //创建支付信息 得到url
        SessionCreateParams params3 = SessionCreateParams.builder()
                        .setMode(SessionCreateParams.Mode.PAYMENT)
                        .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();

    }

    @PostMapping("/pay2")
    public String pay2() throws StripeException {
        try {
            /*PaymentIntentCreateParams params = PaymentIntentCreateParams.builder()
                            .setAmount(1000L) // 支付金额,以分为单位
                            .setCurrency("usd") // 支付货币类型
                    .setReceiptEmail("517861659@qq.com") //支付成功发送邮箱
                    .setDescription("描述~~~123456789")
                            .build();
            PaymentIntent paymentIntent = PaymentIntent.create(params);
            System.out.println(paymentIntent.toString());*/

            Map<String, Object> params2 = new HashMap<>();
            params2.put("amount", 2000);
            params2.put("currency", "USD");
            params2.put("description", "描述ssss");
            params2.put("receipt_email", "517861659@qq.com");

            Map<String, Object> automaticPaymentMethods = new HashMap<>();
            automaticPaymentMethods.put("enabled", true);
            params2.put("automatic_payment_methods", automaticPaymentMethods);

            Map<String, Object> metadata = new HashMap<>();
            metadata.put("orderId", "2222222222222222");
            params2.put("metadata", metadata);

            PaymentIntent paymentIntent2 = PaymentIntent.create(params2);
            System.out.println(paymentIntent2.toString());

            return paymentIntent2.getClientSecret();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     *
     * @param request
     * @param response
     * @return
     * @throws StripeException
     */
    @PostMapping("/pay3")
    public String pay3( HttpServletRequest request, HttpServletResponse response) throws StripeException {
        try {
                String token = request.getParameter("token");// 支付卡号,测试卡号 的token
                // 创建 Charge 对象
                Map<String, Object> chargeParams = new HashMap<>();
                chargeParams.put("amount", 2000);
                chargeParams.put("currency", "usd");
                chargeParams.put("source", token);
                chargeParams.put("description", "描述..........................");

                RequestOptions requestOptions = RequestOptions.builder().setApiKey(Stripe.apiKey).build();

                // 发送 Charge 请求并获取响应
                Charge charge = Charge.create(chargeParams, requestOptions);

                System.out.println(charge);
                // 处理成功支付的响应
                if (charge.getPaid()) {
                    // TODO: 处理支付成功的逻辑
                    return charge.getReceiptUrl();
                } else {
                    // TODO: 处理支付失败的逻辑
                    return null;
                }
        }catch (Exception e){
            // TODO: 处理异常情况的逻辑
            e.printStackTrace();
        }
        return null;
    }

        /**
         *           基本上会用到的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<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/update
        Product 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/create
        Map<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-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<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());

        //创建支付信息 得到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";
    }

}

回调接口

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bithelp.annotation.AnonymousAccess;
import com.stripe.model.Event;
import com.stripe.model.EventDataObjectDeserializer;
import com.stripe.net.Webhook;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

@Slf4j
@Controller
public class StripeBackController {
    //webhook秘钥签名,存在配置文件中(例如stripe:  webhook-key: whsec_fb49bf5262c924f7749602b7fb2ddd1efadbb40f10d675323525255ee01bccf)
    @Value("${stripe.webhook-key}")
    private String endpointSecret;

    @ResponseBody
    @RequestMapping(value = {"/api/pay/stripe/stripe_events"}, method = RequestMethod.POST)
    @AnonymousAccess
    public void stripe_events(HttpServletRequest request) {
        System.out.println("------进入回调了------");
        try {
            InputStream inputStream = request.getInputStream();
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024*4];
            int n;
            while (-1 != (n = inputStream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();
            String payload = new String(bytes, StandardCharsets.UTF_8);
            log.info("支付回调payload体:"+payload);
            String sigHeader = request.getHeader("Stripe-Signature");
            Event event = Webhook.constructEvent(payload, sigHeader, endpointSecret);//验签,并获取事件
            EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
            //回调成功取到数据后需要插入订单表一条订单数据;然后更新一次订单表的订单数据;
            // 根据钱包地址更新MemberInfo中的状态,根据钱包地址更新保单
            String rawJson = dataObjectDeserializer.getRawJson();
            JSONObject obj = JSON.parseObject(rawJson);
            Long created = obj.getLong("created");
            Date date = new Date(created);
            OrderRecordQueryCriteria criteria=new OrderRecordQueryCriteria();
            switch(event.getType()) {
                case "invoice.payment_succeeded":
                    JSONObject lines = obj.getJSONObject("lines");
                    JSONArray data = lines.getJSONArray("data");
                    JSONObject dataOne = data.getJSONObject(0);
                    JSONObject price = dataOne.getJSONObject("price");
                    JSONObject recurring = price.getJSONObject("recurring");
                    // 按年还是按月
                    String interval = recurring.getString("interval");
                    String customer_email = obj.getString("customer_email");
                    String id = obj.get("id").toString();
                    // 自行存库
                    break;
                case "checkout.session.completed":
                    String accountAddress=null;
                    JSONArray arr = obj.getJSONArray("custom_fields");
                    String invoice = obj.get("invoice").toString();
                    for (int i = 0; i < arr.size(); i++){
                        JSONObject jsonObject = arr.getJSONObject(i);
                        String key = jsonObject.getString("key");
                        // 取自定义字段
                        if ("walletaddressthesame21412tedaddress".equals(key)){
                            accountAddress = jsonObject.getJSONObject("text").getString("value");
                        }
                    }
                   // 自行存库
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            log.error("stripe异步通知(webhook事件)",e);
        }
    }

 

前端页面


<!DOCTYPE html>
<html>
<head>
    <title>Stripe Payment Demo</title>
</head>
<body>
<div>
    <h1>支付方式1  创建商品并去支付</h1>
    <button type="button" onclick="toPay()">创建商品并去支付</button><br><br>
</div>
<div>----------------------------------------------分割线---------------------------------------------------------</div>
<div>
    <h1>支付方式2 自定义金额支付</h1>
    <strong>这里得填写卡号信息,卡号在这里获取测试的  https://stripe.com/docs/testing   我这里用的是 4242424242424242 这个卡号</strong>

    <div id="card-element"></div>
    <button id="pay-button">Pay $10.00</button>
</div>
<div>----------------------------------------------分割线---------------------------------------------------------</div>
<div>
    <h1>支付方式3 自定义金额支付</h1>
    <strong>这里得填写卡号信息,卡号在这里获取测试的  https://stripe.com/docs/testing   我这里用的是 4242424242424242 这个卡号</strong>

    <form id="payment-form">
        <div>
            <label for="card-number">Card Number:</label>
            <div id="card-number"></div>
        </div>

        <div>
            <label for="card-expiry">Expiration Date:</label>
            <div id="card-expiry"></div>
        </div>
        <div>
            <label for="card-cvc">CVC:</label>
            <div id="card-cvc"></div>
        </div>
        <button id="pay-button3" type="submit">Pay $10.00</button>
    </form>
</div>
<script src="https://js.stripe.com/v3/"></script>
<script src="/jquery.min.js"></script>
<script>

    /*支付方式1  begin  */
    function toPay() {
        $.ajax({
            type : 'post',
            url : '/pay',
            data : {},
            success : function(res) {
                alert(res)
                window.location.href = res;
            },
            error : function(res) {
                alert("网络错误");
            }
        });
    }
    /*支付方式1  end  */


    /*支付方式2  begin  */
    // 设置Stripe的publishable key
    const stripe = Stripe('pk_test_51OEkcYEWc6AdwtprW0NPPa7Dk8762SH8BRYYnZAYTyweb6BkB9sYNCSnQDsad1kZ08MHjqt1u3VUFhXJX9VLnvxUElD008vSYCVxg');
    // 创建card元素
    const cardElement = stripe.elements().create('card');
    // 将card元素添加到DOM中
    cardElement.mount('#card-element');

    // 监听支付按钮的点击事件
    document.getElementById('pay-button').addEventListener('click', async(event) => {
        // 禁用支付按钮
        event.target.disabled = true;
    $.ajax({
        type : 'post',
        url : '/pay2',
        data : {},
        success : function(res) {
            console.log(res);
            // 使用Stripe.js确认支付
            stripe.confirmCardPayment(res, {
                payment_method: {
                    card: cardElement
                }
            }).then(function(result) {
                alert("result---"+JSON.stringify(result));
                if (result.error) {
                    // 处理错误
                    window.location.href = "/cancel";
                } else {
                    // 处理成功
                    window.location.href = "/success";
                }
            });
        },
        error : function(res) {
            alert("网络错误");
        }
    })
    })
    /*支付方式2  end  */


    /*支付方式3  begin  */
    var stripe2 = Stripe('pk_test_51OGDueHBn5TO1g1fcLny0C8TRWXfUnCafdteoEKbScyoorWY0LBhGlKjfGfIcSABzhYFOAv4fIj6sTCYbozy7hbe00GdtWwrax');
    var elements = stripe2.elements();
    var cardNumberElement = elements.create('cardNumber');
    var cardExpiryElement = elements.create('cardExpiry');
    var cardCvcElement = elements.create('cardCvc');
    cardNumberElement.mount('#card-number');
    cardExpiryElement.mount('#card-expiry');
    cardCvcElement.mount('#card-cvc');
    var form = document.getElementById('payment-form');
    form.addEventListener('submit', function(event) {
        event.preventDefault();
        stripe2.createToken(cardNumberElement).then(function(result) {
            if (result.error) {
                // 处理错误
                alert(result.error.message);
            } else {
                // Token 创建成功,将其传递给后端代码
                var token = result.token.id;
                console.log(token)
                $.ajax({
                    type : 'post',
                    url : '/pay3',
                    data : {"token":token},
                    success : function(res) {
                        alert(res)
                        window.location.href = res;
                    },
                    error : function(res) {
                        alert("网络错误");
                    }
                });
            }
        });
    });
    /*支付方式3  end  */

</script>
</body>
</html>

测试回调

测试卡号官网地址:https://stripe.com/docs/testing?locale=zh-CN

测试流程

选择测试模式,然后点击开发人员

在这里插入图片描述
点击开发人员之后选择webhook,按照提示安装脚手架和配置监听路径
在这里插入图片描述
创建测试支付链接

在这里插入图片描述

选择创建产品后创建好链接
在这里插入图片描述
复制链接,准备支付

在这里插入图片描述

输入相关链接和测试卡号就可以测试了
在这里插入图片描述

文章来源:https://blog.csdn.net/yujing1314/article/details/135251645
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。