java对接paypal支付应用实例 (v2)

java对接paypal支付应用实例 (v2)

依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--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>
        <dependency>
            <groupId>com.alipay</groupId>
            <artifactId>alipay_sdk</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Swagger 接口文档 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <artifactId>slf4j-api</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Controller

package com.example.demo.controller;

import com.example.demo.common.AcActivityLogCode;
import com.example.demo.common.ResponseData;
import com.example.demo.common.RestResult;
import com.example.demo.service.PaymentV2Service;
import com.example.demo.until.PayPalClient;
import com.example.demo.until.URLUtils;
import com.paypal.base.rest.PayPalRESTException;
import com.paypal.http.HttpResponse;
import com.paypal.orders.*;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;

/**
 * @program:
 * @description:
 * @author:
 * @create:
 **/
@RestController
@Validated
public class PaymentV2Controller {

    /**
     * 成功页面
     */
    public static final String PAYPAL_SUCCESS_URL = "paypalSuccess.html";

    /**
     * 取消页面
     */
    public static final String PAYPAL_CANCEL_URL = "pay/cancel";

    @Value("${paypal.web.url}")
    public  String payWebUrl ;

    @Value("${paypal.client.app}")
    public  String clientId ;

    @Value("${paypal.client.secret}")
    public  String secret ;

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

    @Resource
    private PaymentV2Service paymentV2Service;

    @ApiOperation(value = "paypal充值表单", notes = "paypal充值表单")
    @PostMapping("/pay")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "amount", value = "充值金额", required = true, dataType = "String"),
            @ApiImplicitParam(name = "currency", value = "充值金额类型", required = true, dataType = "String")
    })
    public ResponseData payment(
            @RequestParam(value = "amount") String amount,
            @RequestParam(value = "currency",defaultValue = "USD") String currency,
            @RequestParam String productType,
            @RequestParam(value = "couponUsageId",required = false) String couponUsageId,
            HttpServletRequest request){
        //设置取消页面
        String cancelUrl =  URLUtils.getBaseURl(request) + "/" + PAYPAL_CANCEL_URL;
        //设置成功页面
        String successUrl = payWebUrl + PAYPAL_SUCCESS_URL;
        String sHtmlText = "";
        try {
            //订单表单
            sHtmlText = paymentV2Service.createPayment(amount, currency, cancelUrl, successUrl);
            //可根据需要 新增一条代付款记录(回调执行支付的时候 规避刷新页面重复扣费)
        } catch (PayPalRESTException e) {
            logger.error("创建订单表单异常:{}"+e.toString());
        }
        return ResponseData.ok(sHtmlText);
    }

    /**
     * 执行支付
     */
    @GetMapping(value = "pay/success")
    public ResponseData successPay(
            @RequestParam("token") String token) {
        //可以根据新增的付款记录规避重复扣费 参数新增orderId
        RestResult restResult = new RestResult();
        //捕获订单 进行支付
        HttpResponse<Order> response = null;
        OrdersCaptureRequest ordersCaptureRequest = new OrdersCaptureRequest(token);
        ordersCaptureRequest.requestBody(new OrderRequest());
        PayPalClient payPalClient = new PayPalClient();
        try {
            //环境判定sanbox 或 live
            response = payPalClient.client(mode, clientId, secret).execute(ordersCaptureRequest);
        } catch (IOException e) {
            logger.error("调用paypal扣款失败,失败原因 {}", e.getMessage());
        }
        for (PurchaseUnit purchaseUnit : response.result().purchaseUnits()) {
            for (Capture capture : purchaseUnit.payments().captures()) {
                if ("COMPLETED".equals(capture.status())) {
                    //支付成功
                    restResult.setMessage(Objects.requireNonNull(AcActivityLogCode.fromCode(restResult.getResultCode())).getMessage());
                    return ResponseData.ok(restResult);
                }else{
                    //支付失败
                    restResult.setResultCode(AcActivityLogCode.PAYPAL_RECHARGE_FAIL.getCode());
                    restResult.setMessage(Objects.requireNonNull(AcActivityLogCode.fromCode(restResult.getResultCode())).getMessage());
                }
            }
        }
        restResult.setMessage(Objects.requireNonNull(AcActivityLogCode.fromCode(restResult.getResultCode())).getMessage());
        return ResponseData.ok(restResult);
    }
}

Service

package com.example.demo.service;

import com.paypal.base.rest.PayPalRESTException;

/**
 * @program:
 * @description:
 * @author:
 * @create:
 **/
public interface PaymentV2Service {

    /**
     * 创建支付
     * @param totalMoney
     * @param currency
     * @param cancelUrl
     * @param successUrl
     * @return
     */
    String createPayment(String totalMoney, String currency, String cancelUrl, String successUrl) throws PayPalRESTException;


}

Impl

package com.example.demo.impl;

import com.example.demo.config.PayPalSubmit;
import com.example.demo.service.PaymentV2Service;
import com.example.demo.until.PayPalClient;
import com.paypal.base.rest.PayPalRESTException;
import com.paypal.core.PayPalHttpClient;
import com.paypal.http.HttpResponse;
import com.paypal.orders.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

/**
 * @program:
 * @description:
 * @author:
 * @create:
 **/
@Service
public class PaymentV2ServiceImpl implements PaymentV2Service {

    @Value("${paypal.client.app}")
    public  String clientId ;

    @Value("${paypal.client.secret}")
    public  String secret ;

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

    @Override
    public String createPayment(String totalMoney, String currency, String cancelUrl, String successUrl) throws PayPalRESTException {
        PayPalClient payPalClient = new PayPalClient();
        // 设置环境沙盒或生产
        PayPalHttpClient client = payPalClient.client(mode, clientId, secret);
        //回调参数
        Map<String, String> sParaTemp = new HashMap<String, String>();
        //回调的参数 可以多设置几个
        sParaTemp.put("totalMoney", totalMoney);
        String url = successUrl + paramsConvertUrl(sParaTemp);
        // 配置请求参数
        OrderRequest orderRequest = new OrderRequest();
        orderRequest.checkoutPaymentIntent("CAPTURE");
        List<PurchaseUnitRequest> purchaseUnits = new ArrayList<>();
        purchaseUnits.add(new PurchaseUnitRequest().amountWithBreakdown(new AmountWithBreakdown().currencyCode(currency).value(totalMoney)));
        orderRequest.purchaseUnits(purchaseUnits);
        orderRequest.applicationContext(new ApplicationContext().returnUrl(url).cancelUrl(cancelUrl));
        OrdersCreateRequest request = new OrdersCreateRequest().requestBody(orderRequest);
        HttpResponse<Order> response;
        try {
            response = client.execute(request);
            Order order = response.result();
            String token = order.id();
            String payHref = null;
            String status = order.status();
            if (status.equals("CREATED")) {
                List<LinkDescription> links = order.links();
                for (LinkDescription linkDescription : links) {
                    if (linkDescription.rel().equals("approve")) {
                        payHref = linkDescription.href();
                    }
                }
            }
            Map<String, String> resultMap = new HashMap<String, String>();
            resultMap.put("token", token);
            return PayPalSubmit.buildRequest(resultMap,payHref, "get", "确认");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String paramsConvertUrl(Map<String, String> params) {
        StringBuilder urlParams = new StringBuilder("?");
        Set<Map.Entry<String, String>> entries = params.entrySet();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            urlParams.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        String urlParamsStr = urlParams.toString();
        return urlParamsStr.substring(0, urlParamsStr.length()-1);
    }
}

until

package com.example.demo.until;

import com.paypal.core.PayPalEnvironment;
import com.paypal.core.PayPalHttpClient;

/**
 * @program: 
 * @description:
 * @author: 
 * @create: 
 **/
public class PayPalClient {

    public PayPalHttpClient client(String mode, String clientId, String clientSecret) {
        PayPalEnvironment environment = mode.equals("live") ? new PayPalEnvironment.Live(clientId, clientSecret) : new PayPalEnvironment.Sandbox(clientId, clientSecret);
        return new PayPalHttpClient(environment);
    }
}

common

package com.example.demo.config;

import com.alipay.util.AlipayCore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @program:
 * @description:
 * @author:
 * @create:
 **/
public class PayPalSubmit {

    private static final Logger logger = LoggerFactory.getLogger(PayPalSubmit.class);

    public static String buildRequest(Map<String,String> sParaTemp, String linkUrl, String strMethod, String strButtonName) {
        Map<String, String> sPara = buildRequestPara(sParaTemp);
        List<String> keys = new ArrayList(sPara.keySet());
        StringBuffer sbHtml = new StringBuffer();
        sbHtml.append("<form id=\"paypalsubmit\" name=\"paypalsubmit\" action=\""+ linkUrl + "\" method=\"" + strMethod + "\">");
        for(int i = 0; i < keys.size(); ++i) {
            String name = (String)keys.get(i);
            String value = (String)sPara.get(name);
            sbHtml.append("<input type=\"hidden\" name=\"" + name + "\" value=\"" + value + "\"/>");
        }
        sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>");
        sbHtml.append("<script>document.forms['paypalsubmit'].submit();</script>");
        logger.debug("表单信息:"+sbHtml.toString());
        return sbHtml.toString();
    }

    private static Map<String,String> buildRequestPara(Map<String,String> sParaTemp) {
        Map<String, String> sPara = AlipayCore.paraFilter(sParaTemp);
        return sPara;
    }
}

application配置文件

#测试服务地址
paypal.web.url="xxxx"
#sanbox沙盒配置
paypal.mode=sandbox
paypal.client.app=AYxj25IuPg4rAQbUmOZCSIEdmji-HKDgZUHOAGVPWo74dqVUnW1q0_WUo********nYSNJd5W9KT
paypal.client.secret=EKcdUZKpu5XPEQiFFh85kFAexIDlc0a-AlVHeWCx6iLyhh4xm42tq********d8XUxYY-0WD8i
#线上服务地址
paypal.web.url="xxxx"
#live上线配置 
paypal.mode=live
paypal.client.app=AYxj25IuPg4rAQbUmOZCSIEdmji-HKDgZUHOAGVPWo74dqVUnW1q0_WUo********nYSNJd5W9KT
paypal.client.secret=EKcdUZKpu5XPEQiFFh85kFAexIDlc0a-AlVHeWCx6iLyhh4xm42tq********d8XUxYY-0WD8i

基础知识不是很清楚的 请参考本博客V1版本链接: https://blog.csdn.net/m0_37693638/article/details/110930429.

实际开发过程中 需要用到定时, 参考博客中定时开发链接: https://blog.csdn.net/m0_37693638/article/details/110556412.(目的避免支付出现网络波动支付成功未到账问题)

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值