springboot集成PayPal支付

一、注册账号

1.注册PayPal账号,注册地址:安全海淘国际支付平台_安全收款外贸平台-PayPal CN

2.注册完以后登录开发者平台:5https://developer.paypal.com/,输入刚注册的账户密码。


3.创建沙箱应用,这里记录一下Client ID、Secret 后面配置文件会用到

4.沙箱测试账号

点击沙箱地址会显示详细的沙箱账户信息以及沙箱环境登录地址:安全海淘国际支付平台_安全收款外贸平台-PayPal CN

二、java代码

1.application.yml配置文件

pay:
  paypal:
    clientId: ***************************
    clientSecret: ***********************
    #测试的mode
    mode: sandbox
    #正式的mode
#    mode: live
    #取消订单地址 外网能访问
    cancelUrl: http://79ecf61.r6.cpolar.top/payPal/cancel
    #支付成功地址 外网能访问
    successUrl: http://79ecf61.r6.cpolar.top/payPal/success

本地调试可以使用内网穿透,具体教程可以看我之前的文章有具体怎么操作:springboot集成微信支付V3 SDK_springboot接入微信支付注入不了微信支付的sdk包-CSDN博客

2.pom依赖

         <!--PayPal 支付-->
         <dependency>
            <groupId>com.paypal.sdk</groupId>
            <artifactId>rest-api-sdk</artifactId>
            <version>1.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.paypal.sdk</groupId>
            <artifactId>checkout-sdk</artifactId>
            <version>1.0.2</version>
        </dependency>

3.PayPalConfig配置类

package com.qz.client.modular.pay.config;

import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.OAuthTokenCredential;
import com.paypal.base.rest.PayPalRESTException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lihao
 * @create 2024-05-30 10:40
 * @desc payp支付配置类
 **/
@Configuration
public class PayPalConfig {

    @Value("${pay.paypal.clientId}")
    private String clientId;

    @Value("${pay.paypal.clientSecret}")
    private String clientSecret;

    @Value("${pay.paypal.mode}")
    private String mode;

    @Bean
    public Map<String, String> paypalSdkConfig(){
        Map<String, String> sdkConfig = new HashMap<>();
        sdkConfig.put("mode", mode);
        return sdkConfig;
    }


    @Bean
    public OAuthTokenCredential authTokenCredential(){
        return new OAuthTokenCredential(clientId, clientSecret, paypalSdkConfig());
    }


    @Bean
    public APIContext apiContext() throws PayPalRESTException {
        APIContext apiContext = new APIContext(authTokenCredential().getAccessToken());
        apiContext.setConfigurationMap(paypalSdkConfig());
        return apiContext;
    }


}

4.状态枚举类

package com.qz.client.modular.pay.enums;

import lombok.Getter;

/**
 * @author lihao
 * @create 2024-05-30 10:41
 * @desc 支付的意图或目的
 **/
@Getter
public enum PayPalPaymentIntent {

    /**
     * sale:表示该支付是一次性的销售交易,即直接从付款方账户扣款到收款方账户。
     * authorize:表示该支付是一个预授权,即授权收款方在未来某个时间点从付款方账户中扣款。
     * order:表示该支付是创建一个订单,但并不立即扣款。在付款方确认订单后,可以选择扣款操作。
     * subscription:表示该支付是用于定期订阅付款的意图,通常用于定期收取付款方的费用。
     **/
    SALE("sale"), AUTHORIZE("authorize"), ORDER("order"),SUBSCRIPTION("subscription");
    private final String value;

    PayPalPaymentIntent(String key) {
        this.value = key;
    }
}
package com.qz.client.modular.pay.enums;

import lombok.Getter;

/**
 * @author lihao
 * @create 2024-05-30 10:42
 * @desc 支付所使用的支付方式
 **/
@Getter
public enum PayPalPaymentMethod {

    /**
     * credit_card:信用卡支付。
     * paypal:通过 PayPal 账户余额或链接的银行账户进行支付。
     * paypal_credit:通过 PayPal Credit 进行支付,这是 PayPal 提供的一种信用融资服务。
     * pay_upon_invoice:表示支付将在发票上进行,通常用于线下支付或后付款方式。
     **/


    CREDITCARD("credit_card"), PAYPAL("paypal"),PAYPALCREDIT("paypal_credit"),PAYUPONINVOICE("pay_upon_invoice");

    private final String value;

    PayPalPaymentMethod(String key) {
        this.value = key;
    }
}

5.请求参数类

package com.qz.client.modular.pay.param;

import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

import javax.validation.constraints.NotBlank;

/**
 * @author:denghua
 * @create: 2023-01-09 14:39
 * @Description: 支付传参
 */
@Getter
@Setter
public class PayParam {

    @ApiModelProperty(value = "订单介绍")
    private String description;

    @ApiModelProperty(value = "订单id")
    @NotBlank(message = "订单id 不能为空")
    private String orderId;


}
package com.qz.client.modular.pay.param;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * @author lihao
 * @create 2024-05-31 9:59
 * @desc 贝宝退款参数
 **/
@Data
public class PayPalRefundParam {

    @ApiModelProperty(value = "交易订单Id",required = true)
    private String saleId;

    @ApiModelProperty(value = "退款金额",required = true)
    private Double money;

    @ApiModelProperty(value = "货币类型",required = true)
    private String currency;

    @ApiModelProperty(value = "退款原因",required = true)
    private String reason;

}

6.controller

package com.qz.client.modular.pay.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payment;
import com.paypal.api.payments.Refund;
import com.paypal.base.rest.PayPalRESTException;
import com.qz.api.PlatOrderApi;
import com.qz.auth.core.annotation.SaPlatCheckLogin;
import com.qz.client.modular.pay.enums.PayPalPaymentIntent;
import com.qz.client.modular.pay.enums.PayPalPaymentMethod;
import com.qz.client.modular.pay.param.PayPalRefundParam;
import com.qz.client.modular.pay.param.WeChatPayParam;
import com.qz.client.modular.pay.service.PayPalService;
import com.qz.client.modular.pay.util.PayToolUtil;
import com.qz.common.exception.CommonException;
import com.qz.common.pojo.CommonResult;
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.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigDecimal;

/**
 * @author lihao
 * @create 2024-05-29 16:14
 * @desc paypal支付
 **/
@Api(tags = "贝宝支付")
@ApiSupport(author = "lihao")
@Slf4j
@RestController
@RequestMapping(value = "/payPal")
public class PaypalController {



    @Value("${${pay.paypal.cancelUrl}}")
    protected String cancelUrl;
    @Value("${pay.paypal.successUrl}")
    protected String successUrl;

    @Autowired
    private PayPalService payPalService ;


    /**
     * 生成订单
     */
    @ApiOperation("生成订单")
    @PostMapping("/pay")
    public CommonResult<String> paypal(@RequestBody WeChatPayParam payParam) {
        try {
            BigDecimal money = ;//获取订单金额业务方法
            if(money ==null){
                return CommonResult.error("获取订单支付金额失败!");
            }
            String strRandom = String.valueOf(this.buildRandom(4));
            //注意生成订单号唯一
            Payment payment = payPalService.createPayment(payParam.getOrderId()+strRandom,money.doubleValue(), "USD", PayPalPaymentMethod.PAYPAL, PayPalPaymentIntent.SALE,payParam.getDescription(), cancelUrl, successUrl);
            for (Links links : payment.getLinks()) {
                if (links.getRel().equals("approval_url")) {
                    log.info("links.getHref() is {}", links.getHref());
                    log.info("支付订单返回paymentId:" + payment.getId());
                    log.info("支付订单状态state:" + payment.getState());
                    log.info("支付订单创建时间:" + payment.getCreateTime());
                    String href = links.getHref();
                    return CommonResult.data(href);
                }
            }
        } catch (PayPalRESTException e) {
            log.error(e.getMessage());
            return new CommonResult<>(e.getResponsecode(), e.getMessage(), null);
        }
        return CommonResult.error("生成订单错误!");
    }

    @ApiOperation("退款申请测试")
    @SaCheckPermission("/payPal/refund")
    @PostMapping("/refund")
    public CommonResult<String> refund(@RequestBody @Valid PayPalRefundParam refundParam) throws PayPalRESTException {
        Refund refund = payPalService.refund(refundParam.getSaleId(),refundParam.getMoney(),refundParam.getCurrency(),refundParam.getReason());
        log.info("========>退款返回结果:{}", JSONObject.toJSONString(refund));
        return CommonResult.data("");
    }

    /**
     * 取消支付
     */
    @ApiOperation("取消支付")
    @GetMapping("/cancel")
    public CommonResult<String> cancelPay(@RequestParam("orderId") String orderId){
        log.info("==========>用户取消支付,订单号:{}",orderId);
        return CommonResult.data("用户取消支付");
    }

    /**
     * 支付操作
     */
    @ApiOperation("支付操作")
    @GetMapping("/success")
    public String successPay(@RequestParam("paymentId") String paymentId, @RequestParam("PayerID") String payerId, @RequestParam("orderId") String orderId) { // 一定是PayerID,PayPal通常使用"PayerID"(ID和P都大小写)作为参数名称
        try {
            //支付成功执行PayPal扣款
            Payment payment = payPalService.executePayment(paymentId, payerId);
            // 支付成功
            if(payment.getState().equals("approved")){
                // 订单号
                String saleId = payment.getTransactions().get(0).getRelatedResources().get(0).getSale().getId();
                String money = payment.getTransactions().get(0).getRelatedResources().get(0).getSale().getAmount().getTotal();
                //执行自己支付成功的业务方法
                log.info("PDT通知:交易成功回调");
                log.info("付款人账户:"+payment.getPayer().getPayerInfo().getEmail());
                log.info("付款金额:"+money);
                log.info("支付订单Id: {}",paymentId);
                log.info("支付订单状态state:" + payment.getState());
                log.info("交易订单Id: {}",saleId);
                log.info("交易订单状态state:"+payment.getTransactions().get(0).getRelatedResources().get(0).getSale().getState());
                log.info("交易订单支付时间:"+payment.getTransactions().get(0).getRelatedResources().get(0).getSale().getCreateTime());
                return "<script>window.onload=function(){setTimeout(function(){history.go(-1);},1000);}</script>支付成功,返回上一级页面";
            }
        } catch (PayPalRESTException e) {
            log.info(e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
        return "<script>window.onload=function(){setTimeout(function(){history.go(-1);},1000);}</script>支付失败,返回上一级页面";
    }

/**
         * 取出一个指定长度大小的随机正整数
         * @param length int 设定所取出随机数的长度。length小于11
         * @return int 返回生成的随机数。
         */
        public int buildRandom(int length) {
            int num = 1;
            double random = Math.random();
            if (random < 0.1) {
                random = random + 0.1;
            }
            for (int i = 0; i < length; i++) {
                num = num * 10;
            }
            return (int) ((random * num));
        }


}

7.service

package com.qz.client.modular.pay.service;


import com.paypal.api.payments.Payment;
import com.paypal.api.payments.Refund;
import com.paypal.base.rest.PayPalRESTException;
import com.qz.client.modular.pay.enums.PayPalPaymentIntent;
import com.qz.client.modular.pay.enums.PayPalPaymentMethod;

/**
 * @author lihao
 * @create 2024-05-30 10:47
 * @desc
 **/
public interface PayPalService {

    Payment createPayment(String orderId,Double total, String currency, PayPalPaymentMethod method, PayPalPaymentIntent intent, String description, String cancelUrl, String successUrl) throws PayPalRESTException;

    /**
     * 执行扣款
     * @author lihao
     * @date 2024/5/31 9:56
     * @param paymentId 支付订单Id
     * @param payerId
     * @return com.paypal.api.payments.Payment
     **/
    Payment executePayment(String paymentId, String payerId) throws PayPalRESTException;

    /**
     *
     * @author lihao
     * @date 2024/5/31 9:55
     * @param saleId 交易订单Id
     * @param money 退款金额
     * @param currency 货币类型
     * @param reason 退款原因
     * @return com.paypal.api.payments.Refund
     **/
    Refund refund(String saleId, Double money, String currency, String reason) throws PayPalRESTException;
}
package com.qz.client.modular.pay.service.Impl;

import com.paypal.api.payments.*;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;
import com.qz.api.PlatOrderApi;
import com.qz.client.modular.pay.enums.PayPalPaymentIntent;
import com.qz.client.modular.pay.enums.PayPalPaymentMethod;
import com.qz.client.modular.pay.service.PayPalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author lihao
 * @create 2024-05-30 10:51
 * @desc
 **/
@Service
public class PayPalServiceImpl implements PayPalService {

    @Autowired
    private APIContext apiContext;


    // 创建支付
    @Override
    public Payment createPayment(String orderId,Double total, String currency, PayPalPaymentMethod method, PayPalPaymentIntent intent, String description, String cancelUrl, String successUrl) throws PayPalRESTException {
        // 接受参数包括总金额(total)、货币类型(currency)、支付方法(method)、支付意图(intent)、描述(description)、取消 URL(cancelUrl)和成功 URL(successUrl)。在方法内部,它使用这些参数创建一个支付请求,并返回创建的 Payment 对象
        String requestId = generateRequestId(); // 生成唯一的 PayPal-Request-Id 值
        // 设置 PayPal-Request-Id 头部
        Map<String, String> headers = new HashMap<>();
        headers.put("PayPal-Request-Id", requestId);
        apiContext.setHTTPHeaders(headers);
        Amount amount = new Amount();
        amount.setCurrency(currency);
        amount.setTotal(String.format("%.2f", total));

        Transaction transaction = new Transaction();
        transaction.setDescription(description);
        transaction.setAmount(amount);

        List<Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);

        Payer payer = new Payer();
        payer.setPaymentMethod(method.getValue());

        Payment payment = new Payment();
        payment.setIntent(intent.getValue());
        payment.setPayer(payer);
        payment.setTransactions(transactions);

        RedirectUrls redirectUrls = new RedirectUrls();

        // Paypal取消支付回调链接
        redirectUrls.setCancelUrl(cancelUrl+"?orderId=" + orderId);

        // Paypal付完款回调链接
//        redirectUrls.setReturnUrl(successUrl);

        // Paypal付完款回调链接:如果要其他数据作为参数传递给成功支付后的回调URL即控制器类中的successPay方法,则对回调URL进行拼接:redirectUrls.setReturnUrl(successUrl + "?param1=" + param1 + "¶m2=" + param2 + "¶m3=" + paaram3);
        redirectUrls.setReturnUrl(successUrl + "?orderId=" + orderId);

        payment.setRedirectUrls(redirectUrls);
        return payment.create(apiContext);
    }

    // 执行支付
    @Override
    public Payment executePayment(String paymentId, String payerId) throws PayPalRESTException {
        String requestId = generateRequestId(); // 生成唯一的 PayPal-Request-Id 值
        // 设置 PayPal-Request-Id 头部
        Map<String, String> headers = new HashMap<>();
        headers.put("PayPal-Request-Id", requestId);
        apiContext.setHTTPHeaders(headers);
        // 接受支付 ID(paymentId)和付款人 ID(payerId)作为参数。在方法内部,它使用这些参数创建一个 PaymentExecution 对象,并使用支付 ID 和付款人 ID 执行支付请求,返回执行支付后的 Payment 对象
        Payment payment = new Payment();
        payment.setId(paymentId);
        PaymentExecution paymentExecute = new PaymentExecution();
        paymentExecute.setPayerId(payerId);
        return payment.execute(apiContext, paymentExecute);
    }

    
    @Override
    public Refund refund(String saleId,Double money, String currency,String reason) throws PayPalRESTException {
        String requestId = generateRequestId(); // 生成唯一的 PayPal-Request-Id 值
        // 设置 PayPal-Request-Id 头部
        Map<String, String> headers = new HashMap<>();
        headers.put("PayPal-Request-Id", requestId);
        apiContext.setHTTPHeaders(headers);
        Refund refund = new Refund();
        Amount amount = new Amount();
        amount.setCurrency(currency);
        amount.setTotal(String.valueOf(money));
        refund.setAmount(amount);
        refund.setReason(reason);
        Sale sale = new Sale();
        sale.setId(saleId);
        Refund refund1 = sale.refund(apiContext,refund);
        return refund1;
    }

    // 生成唯一的 PayPal-Request-Id 值
    private String generateRequestId() {
        return UUID.randomUUID().toString();
    }
}

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
要在 Spring Boot 项目中集成 PayPal 支付,你可以使用 PayPal Java SDK。以下是集成 PayPal 的步骤: 1. 添加依赖:在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>com.paypal.sdk</groupId> <artifactId>rest-api-sdk</artifactId> <version>1.14.0</version> </dependency> ``` 2. 创建 PayPal 配置类:在你的项目中创建一个 PayPal 配置类,用于配置 PayPal 的访问凭证和其他设置。 ```java import com.paypal.base.rest.APIContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class PayPalConfig { // PayPal 配置参数 private String clientId = "YOUR_CLIENT_ID"; private String clientSecret = "YOUR_CLIENT_SECRET"; private String mode = "sandbox"; // 这里使用 sandbox 模式,可以改为 "live" 用于生产环境 @Bean public APIContext apiContext() { APIContext apiContext = new APIContext(clientId, clientSecret, mode); return apiContext; } } ``` 在上述示例中,你需要替换 YOUR_CLIENT_ID 和 YOUR_CLIENT_SECRET 为你的 PayPal 客户端 ID 和密钥。注意,这里使用了 sandbox 模式,你可以根据需要将其改为 "live" 用于生产环境。 3. 使用 PayPal API:在你的代码中,可以使用 PayPal SDK 提供的 API 来执行支付相关操作。以下是一个简单的示例: ```java import com.paypal.api.payments.*; import com.paypal.base.rest.APIContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class PayPalService { @Autowired private APIContext apiContext; public Payment createPayment(Double total, String currency, String cancelUrl, String successUrl) throws PayPalRESTException { Amount amount = new Amount(); amount.setCurrency(currency); amount.setTotal(String.format("%.2f", total)); Transaction transaction = new Transaction(); transaction.setAmount(amount); List<Transaction> transactions = new ArrayList<>(); transactions.add(transaction); Payer payer = new Payer(); payer.setPaymentMethod("paypal"); Payment payment = new Payment(); payment.setIntent("sale"); payment.setPayer(payer); payment.setTransactions(transactions); RedirectUrls redirectUrls = new RedirectUrls(); redirectUrls.setCancelUrl(cancelUrl); redirectUrls.setReturnUrl(successUrl); payment.setRedirectUrls(redirectUrls); return payment.create(apiContext); } public Payment executePayment(String paymentId, String payerId) throws PayPalRESTException { Payment payment = new Payment(); payment.setId(paymentId); PaymentExecution paymentExecute = new PaymentExecution(); paymentExecute.setPayerId(payerId); return payment.execute(apiContext, paymentExecute); } } ``` 在上述示例中,我们创建了一个 PayPalService 类,用于处理 PayPal 相关的操作。createPayment 方法用于创建支付请求,executePayment 方法用于执行支付。 注意,在 PayPalService 类中我们注入了之前创建的 APIContext 对象,它包含了 PayPal 的访问凭证和配置参数。 这只是一个简单的示例,你可以根据实际需求使用 PayPal SDK 提供的其他 API 来处理更复杂的支付操作。 这样,在你的 Spring Boot 项目中,你就可以集成 PayPal 支付了。使用 PayPalService 类的相应方法来创建支付请求、执行支付等操作。记得根据实际情况替换示例代码中的参数和逻辑。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麦兜没有兜111

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值