使用SpringBoot简单实现一个苹果支付的场景

 更新时间:2024年11月21日 08:28:47   作者:一只爱撸猫的程序猿  
这篇文章主要为大家详细介绍了如何在Spring Boot项目中集成Apple Pay功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

在Spring Boot项目中集成Apple Pay,需要实现以下步骤:

  • 配置Apple开发者账户:在Apple开发者中心创建商家ID,并生成相关的支付处理证书。
  • 配置HTTPS:Apple Pay要求服务器必须使用HTTPS协议。您可以使用JDK自带的keytool工具生成自签名证书,或从受信任的证书颁发机构获取证书。
  • 集成支付SDK:在Spring Boot项目中,您可以使用第三方支付集成库,如pay-spring-boot-starter,来简化支付流程的实现。

以下是一个基于Spring Boot的场景示例,展示如何集成Apple Pay并处理支付回调:

1. 配置Apple Pay相关参数

application.yml中添加Apple Pay的相关配置:

applepay:
  merchantId: your_merchant_id
  merchantCertificatePath: path_to_your_merchant_certificate.p12
  merchantCertificatePassword: your_certificate_password
  merchantIdentifier: your_merchant_identifier

2. 创建支付服务类

创建一个服务类ApplePayService,用于处理支付请求和验证支付结果:

@Service
public class ApplePayService {

    @Value("${applepay.merchantId}")
    private String merchantId;

    @Value("${applepay.merchantCertificatePath}")
    private String merchantCertificatePath;

    @Value("${applepay.merchantCertificatePassword}")
    private String merchantCertificatePassword;

    @Value("${applepay.merchantIdentifier}")
    private String merchantIdentifier;

    public String createPaymentSession(String validationUrl) {
        // 加载商户证书
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        try (InputStream keyInput = new FileInputStream(merchantCertificatePath)) {
            keyStore.load(keyInput, merchantCertificatePassword.toCharArray());
        }

        // 创建SSL上下文
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, merchantCertificatePassword.toCharArray());
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);

        // 设置HTTPS连接
        URL url = new URL(validationUrl);
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(sslContext.getSocketFactory());
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json");

        // 构建请求数据
        JSONObject requestData = new JSONObject();
        requestData.put("merchantIdentifier", merchantIdentifier);
        requestData.put("displayName", "Your Store Name");
        requestData.put("initiative", "web");
        requestData.put("initiativeContext", "yourdomain.com");

        // 发送请求
        connection.setDoOutput(true);
        try (OutputStream os = connection.getOutputStream()) {
            os.write(requestData.toString().getBytes(StandardCharsets.UTF_8));
        }

        // 读取响应
        try (InputStream is = connection.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return response.toString();
        }
    }

    public boolean validatePayment(String paymentData) {
    // Apple验证服务器的URL
    String url = "https://sandbox.itunes.apple.com/verifyReceipt"; // 沙盒环境
    // String url = "https://buy.itunes.apple.com/verifyReceipt"; // 生产环境

    try {
        // 构建验证请求的JSON数据
        JSONObject requestJson = new JSONObject();
        requestJson.put("receipt-data", paymentData);
        // 如果是自动续订订阅,需要添加以下字段
        // requestJson.put("password", "your_shared_secret");

        // 创建HTTP连接
        URL verifyUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) verifyUrl.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setDoOutput(true);

        // 发送请求数据
        try (OutputStream os = conn.getOutputStream()) {
            os.write(requestJson.toString().getBytes(StandardCharsets.UTF_8));
        }

        // 读取响应数据
        int responseCode = conn.getResponseCode();
        if (responseCode == 200) {
            try (InputStream is = conn.getInputStream();
                 BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }

                // 解析响应JSON
                JSONObject responseJson = new JSONObject(response.toString());
                int status = responseJson.getInt("status");

                // 根据status字段判断支付结果
                if (status == 0) {
                    // 验证成功,支付有效
                    return true;
                } else if (status == 21007) {
                    // 收据是沙盒环境,但发送到了生产环境的验证服务器
                    // 需要重新发送到沙盒环境进行验证
                    // 这里可以递归调用validatePayment方法,使用沙盒环境的URL
                    // 注意避免递归陷阱,确保不会无限递归
                    return validatePaymentInSandbox(paymentData);
                } else {
                    // 验证失败,支付无效
                    return false;
                }
            }
        } else {
            // HTTP响应码非200,表示请求失败
            return false;
        }
      } catch (Exception e) {
        e.printStackTrace();
        return false;
     }
   }
}

3. 创建支付控制器

创建一个控制器ApplePayController,用于处理前端的支付请求和回调:

@RestController
@RequestMapping("/applepay")
public class ApplePayController {

    @Autowired
    private ApplePayService applePayService;

    @PostMapping("/payment-session")
    public ResponseEntity<String> createPaymentSession(@RequestBody Map<String, String> request) {
        String validationUrl = request.get("validationUrl");
        String paymentSession = applePayService.createPaymentSession(validationUrl);
        return ResponseEntity.ok(paymentSession);
    }

    @PostMapping("/payment-result")
    public ResponseEntity<String> handlePaymentResult(@RequestBody Map<String, Object> paymentResult) {
        String paymentData = (String) paymentResult.get("paymentData");
        boolean isValid = applePayService.validatePayment(paymentData);
        if (isValid) {
            // 处理支付成功的逻辑
            return ResponseEntity.ok("Payment successful");
        } else {
            // 处理支付失败的逻辑
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Payment validation failed");
        }
    }
}

4. 前端集成Apple Pay

在前端页面中,使用Apple提供的JavaScript库来处理Apple Pay的支付流程:

<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
    if (window.ApplePaySession && ApplePaySession.canMakePayments()) {
        var applePayButton = document.getElementById('apple-pay-button');
        applePayButton.style.display = 'block';
        applePayButton.addEventListener('click', function() {
            var paymentRequest = {
                countryCode: 'US',
                currencyCode: 'USD',
                total: {
                    label: 'Your Store Name',
                    amount: '10.00'
                },
                supportedNetworks: ['visa', 'masterCard', 'amex'],
                merchantCapabilities: ['supports3DS']
            };

            var session = new ApplePaySession(3, paymentRequest);

            session.onvalidatemerchant = function(event) {
                fetch('/applepay/payment-session', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ validationUrl: event.validationURL })
                })
                .then(function(response) {
                    return response.json();
                })
                .then(function(merchantSession) {
                    session.completeMerchantValidation(merchantSession);
                });
            };

            session.onpaymentauthorized = function(event) {
                var paymentData = event.payment.token.paymentData;
                fetch('/applepay/payment-result', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({ paymentData: paymentData })
                })
                .then(function(response) {
                    if (response.ok) {
                        session.completePayment(ApplePaySession.STATUS_SUCCESS);
                    } else {
                        session.completePayment(ApplePaySession.STATUS_FAILURE);
                    }
                });
            };

            session.begin();

到此这篇关于使用SpringBoot简单实现一个苹果支付的场景的文章就介绍到这了,更多相关SpringBoot苹果支付内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MybatisPlus如何自定义TypeHandler映射JSON类型为List

    MybatisPlus如何自定义TypeHandler映射JSON类型为List

    这篇文章主要介绍了MybatisPlus如何自定义TypeHandler映射JSON类型为List,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • java之CSV大批量数据入库的实现

    java之CSV大批量数据入库的实现

    本文主要介绍了java之CSV大批量数据入库的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • 将idea工程打包成jar文件的全步骤

    将idea工程打包成jar文件的全步骤

    这篇文章主要给大家介绍了关于将idea工程打包成jar文件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • Spark学习笔记之Spark中的RDD的具体使用

    Spark学习笔记之Spark中的RDD的具体使用

    这篇文章主要介绍了Spark学习笔记之Spark中的RDD的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06
  • springboot实现配置多环境yml方式

    springboot实现配置多环境yml方式

    在SpringBoot项目中,通过创建不同的YAML配置文件来实现多环境配置是一种常见且有效的方法,这些配置文件包括application.yml、application-dev.yml、application-prod.yml等,分别对应不同的开发环境,如开发环境、生产环境
    2024-11-11
  • Spring中使用Async进行异步功能开发实战示例(大文件上传为例)

    Spring中使用Async进行异步功能开发实战示例(大文件上传为例)

    本文以大文件上传为例,首先讲解在未进行程序异步化时,程序的运行机制和具体表现,然后讲解如何进行异步化的改造,让程序进行异步执行,通过本文不仅能让你掌握如何进行Event的事件开发,同时还能掌握在Spring中如何进行异步开发,熟悉@Async的具体用法,感兴趣的朋友一起看看吧
    2024-08-08
  • SpringBoot项目中获取IP地址的实现示例

    SpringBoot项目中获取IP地址的实现示例

    OkHttp是一个由Square开发的高效、现代的HTTP客户端库,本文主要介绍了SpringBoot项目中获取IP地址的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2024-08-08
  • 浅谈SpringBoot中的@Conditional注解的使用

    浅谈SpringBoot中的@Conditional注解的使用

    这篇文章主要介绍了浅谈SpringBoot中的@Conditional注解的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • Java中HttpServletResponse响应中文出现乱码问题

    Java中HttpServletResponse响应中文出现乱码问题

    这篇文章主要介绍了Java中HttpServletResponse响应中文出现乱码问题的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • java 数据结构单链表的实现

    java 数据结构单链表的实现

    这篇文章主要介绍了java 数据结构单链表的实现的相关资料,需要的朋友可以参考下
    2017-07-07

最新评论