java对接PayPal实现自动续费功能

本文档介绍了如何使用PayPal的API在Java中创建产品、计费计划和订阅。首先,展示了如何获取OAuth访问令牌,然后创建产品和计费计划。接着,创建订阅并提供支付链接,最后演示了如何取消订阅。所有这些操作都通过RestTemplate工具类进行HTTP请求。
摘要由CSDN通过智能技术生成

一起探讨学习

欢迎大家进群,一起讨论学习

每天给大家提供技术干货

在这里插入图片描述

博主技术笔记 https://notes.xiyankt.com


博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位star https://gitee.com/bright-boy/xiyan-blog


由于同事对接PayPal使用的是过期的自动续费api,很多的功能受限,所以我同事要求我帮她整合下最新的自动续费demo,正好是国庆节有时间,所以就写了以下案例

1.maven依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20200518</version>
        </dependency>
        <dependency>
            <groupId>com.paypal.sdk</groupId>
            <artifactId>rest-api-sdk</artifactId>
            <version>LATEST</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    </dependencies>

2.由于有sdk的自动续费已经过时了,新出的自动续费还没有java的sdk所以你需要用http的方式请求PayPal的api接口

过时的api文档地址:


 1. https://developer.paypal.com/docs/api/payments.billing-agreements/v1/
   
 2. https://developer.paypal.com/docs/api/payments.billing-plans/v1/

utils类

package com.ratta.util;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.Map;


/**
 * RestTemplate 远程调用工具类
 *
 * @author bright
 * @createDate 2020-08-29
 */
public class RestTemplateUtils {

    private final static RestTemplate restTemplate = new RestTemplate();

    // ----------------------------------GET-------------------------------------------------------

    /**
     * GET请求调用方式
     *
     * @param url          请求URL
     * @param responseType 返回对象类型
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> get(String url, Class<T> responseType) {
        return restTemplate.getForEntity(url, responseType);
    }

    /**
     * GET请求调用方式
     *
     * @param url          请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> get(String url, Class<T> responseType, Object... uriVariables) {
        return restTemplate.getForEntity(url, responseType, uriVariables);
    }

    /**
     * GET请求调用方式
     *
     * @param url          请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> get(String url, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.getForEntity(url, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> get(String url, Map<String, String> headers, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return get(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> get(String url, HttpHeaders headers, Class<T> responseType, Object... uriVariables) {
        HttpEntity<?> requestEntity = new HttpEntity<>(headers);
        return exchange(url, HttpMethod.GET, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> get(String url, Map<String, String> headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return get(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的GET请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> get(String url, HttpHeaders headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<?> requestEntity = new HttpEntity<>(headers);
        return exchange(url, HttpMethod.GET, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------POST-------------------------------------------------------

    /**
     * POST请求调用方式
     *
     * @param url          请求URL
     * @param responseType 返回对象类型
     * @return
     */
    public static <T> ResponseEntity<T> post(String url, Class<T> responseType) {
        return restTemplate.postForEntity(url, HttpEntity.EMPTY, responseType);
    }

    /**
     * POST请求调用方式
     *
     * @param url          请求URL
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType) {
        return restTemplate.postForEntity(url, requestBody, responseType);
    }

    /**
     * POST请求调用方式
     *
     * @param url          请求URL
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Object... uriVariables) {
        return restTemplate.postForEntity(url, requestBody, responseType, uriVariables);
    }

    /**
     * POST请求调用方式
     *
     * @param url          请求URL
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.postForEntity(url, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的POST请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return post(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的POST请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return post(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的POST请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return post(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的POST请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return post(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的POST请求调用方式
     *
     * @param url           请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的POST请求调用方式
     *
     * @param url           请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> post(String url, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, HttpMethod.POST, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------PUT-------------------------------------------------------

    /**
     * PUT请求调用方式
     *
     * @param url          请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, Class<T> responseType, Object... uriVariables) {
        return put(url, HttpEntity.EMPTY, responseType, uriVariables);
    }

    /**
     * PUT请求调用方式
     *
     * @param url          请求URL
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * PUT请求调用方式
     *
     * @param url          请求URL
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return put(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return put(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的PUT请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return put(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的PUT请求调用方式
     *
     * @param url           请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, HttpMethod.PUT, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的PUT请求调用方式
     *
     * @param url           请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> put(String url, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, HttpMethod.PUT, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------DELETE-------------------------------------------------------

    /**
     * DELETE请求调用方式
     *
     * @param url          请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Class<T> responseType, Object... uriVariables) {
        return delete(url, HttpEntity.EMPTY, responseType, uriVariables);
    }

    /**
     * DELETE请求调用方式
     *
     * @param url          请求URL
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Class<T> responseType, Map<String, ?> uriVariables) {
        return delete(url, HttpEntity.EMPTY, responseType, uriVariables);
    }

    /**
     * DELETE请求调用方式
     *
     * @param url          请求URL
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * DELETE请求调用方式
     *
     * @param url          请求URL
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Object... uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, Map<String, String> headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setAll(headers);
        return delete(url, httpHeaders, requestBody, responseType, uriVariables);
    }

    /**
     * 带请求头的DELETE请求调用方式
     *
     * @param url          请求URL
     * @param headers      请求头参数
     * @param requestBody  请求参数体
     * @param responseType 返回对象类型
     * @param uriVariables URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, HttpHeaders headers, Object requestBody, Class<T> responseType, Map<String, ?> uriVariables) {
        HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestBody, headers);
        return delete(url, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的DELETE请求调用方式
     *
     * @param url           请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, responseType, uriVariables);
    }

    /**
     * 自定义请求头和请求体的DELETE请求调用方式
     *
     * @param url           请求URL
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> delete(String url, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, responseType, uriVariables);
    }

    // ----------------------------------通用方法-------------------------------------------------------

    /**
     * 通用调用方式
     *
     * @param url           请求URL
     * @param method        请求方法类型
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,按顺序依次对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) {
        return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
    }

    /**
     * 通用调用方式
     *
     * @param url           请求URL
     * @param method        请求方法类型
     * @param requestEntity 请求头和请求体封装对象
     * @param responseType  返回对象类型
     * @param uriVariables  URL中的变量,与Map中的key对应
     * @return ResponseEntity 响应对象封装类
     */
    public static <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Map<String, ?> uriVariables) {
        return restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
    }

    /**
     * 获取RestTemplate实例对象,可自由调用其方法
     *
     * @return RestTemplate实例对象
     */
    public static RestTemplate getRestTemplate() {
        return restTemplate;
    }

}

3.BO类

ApplicationContextBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 18:50
 * @describe :
 */
@Data
public class ApplicationContextBO implements Serializable {
    /**
     * 该标签将覆盖PayPal网站上PayPal帐户中的公司名称
     */
    private String brand_name;

    /**
     * 贝宝付款体验显示的BCP 47格式的页面区域设置。PayPal支持五个字符的代码。
     * 例如,da-DK,he-IL,id-ID,ja-JP,no-NO,pt-BR,ru-RU,sv-SE,th-TH,zh-CN,zh-HK,或zh-TW。
     */
    private String locale;

    /**
     * 送货地址的来源位置。 可能的值为:
     * GET_FROM_FILE。在贝宝网站上获得客户提供的送货地址。
     * NO_SHIPPING。从PayPal网站编辑送货地址。推荐用于数字商品。
     * SET_PROVIDED_ADDRESS。获取商家提供的地址。客户无法在PayPal网站上更改此地址。如果商家未通过地址,则客户可以在PayPal页面上选择地址。
     * 默认值:GET_FROM_FILE。
     */
    private String shipping_preference;

    /**
     * 将标签名称配置为订阅同意体验Continue或Subscribe Now为订阅同意体验配置。 可能的值为:
     * CONTINUE。将客户重定向到PayPal订阅同意页面后,将出现“继续”按钮。当您要控制订阅的激活并且不希望PayPal激活订阅时,请使用此选项。
     * SUBSCRIBE_NOW。将客户重定向到PayPal订阅同意页面后,将显示立即订阅按钮。当您希望贝宝激活订阅时,请使用此选项。
     * 默认值:SUBSCRIBE_NOW
     */
    private String user_action;


    /**
     * 客户和商家的付款首选项。目前仅支持PAYPAL付款方式。
     */
    private PaymentMethodBO payment_method;

    /**
     * 客户批准付款后将客户重定向到的URL
     */
    private String return_url;

    /**
     * 客户取消付款后,将客户重定向到的URL
     */
    private String cancel_url;

}

BillingCyclesBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 16:54
 * @describe :
 */
@Data
public class BillingCyclesBO implements Serializable {


    private PricingSchemeBO pricing_scheme;

    /**
     * 此结算周期的频率详细信息。
     */
    private FrequencyBO frequency;

    /**
     * 计费周期的任期类型。如果计划具有试用周期,则每个计划仅允许2个试用周期。 可能的值为:
     * REGULAR。定期的结算周期。
     * TRIAL。试用帐单周期。
     */
    private String tenure_type;

    /**
     * 在其他计费周期中,该周期的运行顺序。例如,试用计费周期的sequence值为,
     * 1而普通计费周期的的sequence值为2,因此试用周期在常规周期之前运行。
     */
    private Integer sequence;

    /**
     * 此计费周期执行的次数。试验结算周期才能执行的有限次数(间值1和999对total_cycles)。
     * 定期计费周期可以执行无限倍(值0对total_cycles)或有限次数(间值1和999对total_cycles)
     */
    private Integer total_cycles;
}

FixedPriceBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 17:08
 * @describe :
 */
@Data
public class FixedPriceBO implements Serializable {
    /**
     * 标识货币的三字符ISO-4217货币代码。
     */
    private String currency_code;

    /**
     * 该值可能是:
     * 整数,例如: JPY此类通常不是小数。
     * TND此类货币的小数部分可细分为千分之一。
     * 有关货币代码所需的小数位数
     */
    private String value;
}

FrequencyBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 16:57
 * @describe :
 */
@Data
public class FrequencyBO implements Serializable {
    /**
     * 订阅收费或计费的时间间隔。 可能的值为:
     * DAY。每日结算周期。
     * WEEK。每周结算周期。
     * MONTH。每月结算周期。
     * YEAR。每年的帐单周期。
     */
    private String interval_unit;

    /**
     * 订阅者计费之后的时间间隔数。例如,如果interval_unit是DAY用interval_count的 2,
     * 该订阅收费每两天一次。下表列出了最大允许值interval_count的每个interval_unit
     */
    private Integer interval_count;
}

PaymentMethodBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 19:01
 * @describe :
 */
@Data
public class PaymentMethodBO implements Serializable {
    /**
     * 客户在商家站点上选择的付款方式。
     * 默认值:PAYPAL。
     */
    private String payer_selected;

    /**
     * 商家首选的付款方式。 可能的值为:
     * UNRESTRICTED。接受来自客户的任何类型的付款。
     * IMMEDIATE_PAYMENT_REQUIRED。仅接受客户的即时付款。例如,
     * 信用卡,贝宝余额或即时ACH。确保在捕获时,付款不具有“待处理”状态。
     * 默认值:UNRESTRICTED。
     */
    private String payee_preferred;
}

PaymentPreferencesBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 17:11
 * @describe :
 */
@Data
public class PaymentPreferencesBO implements Serializable {
    /**
     * 服务的初始设置费用
     */
    private SetupFeeBO setup_fee;

}

PlanBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 16:52
 * @describe :
 */
@Data
public class PlanBO implements Serializable {
    /**
     * 产品的ID。
     */
    private String product_id;

    /**
     * 计划名称。
     */
    private String name;

    /**
     * 计划的详细说明。
     */
    private String description;

    /**
     * 用于试用计费和常规计费的一系列计费周期。一个计划最多可以有两个试用周期,而只有一个常规周期
     */
    private BillingCyclesBO[] billing_cycles;

    /**
     * 订阅的付款首选项。
     */
    private PaymentPreferencesBO payment_preferences;
}

PricingSchemeBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 17:07
 * @describe :
 */
@Data
public class PricingSchemeBO implements Serializable {
    /**
     * 订阅收取的固定金额。固定金额的更改适用于现有和将来的订阅。
     * 对于现有订阅,价格更改后10天内的付款不受影响
     */
    private FixedPriceBO fixed_price;
}

ProductsBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 15:51
 * @describe :
 */
@Data
public class ProductsBO implements Serializable {
    private String name;
    private String description;
    private String type;
    private String category;
    private String image_url;
    private String home_url;
}

SetupFeeBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 17:13
 * @describe :
 */
@Data
public class SetupFeeBO implements Serializable {
    /**
     * 标识货币的三字符ISO-4217货币代码。
     */
    private String currency_code;

    /**
     * 该值可能是:
     * 整数,例如: JPY此类通常不是小数。
     * TND此类货币的小数部分可细分为千分之一。
     * 有关货币代码所需的小数位数
     */
    private String value;

}

SubscriptionsBO

package com.ratta.bo;

import lombok.Data;

import java.io.Serializable;

/**
 * @author: bright
 * @date:Created in 2020/10/6 18:42
 * @describe :
 */
@Data
public class SubscriptionsBO implements Serializable {
    /**
     * 计划的ID。
     */
    private String plan_id;

    /**
     * 订阅开始的日期和时间
     */
    private String start_time;

    /**
     * 应用程序上下文,可在使用PayPal进行订阅批准过程中自定义付款人的体验
     */
    private ApplicationContextBO application_context;

}

4.创建产品

4.1PayPalClient

package com.ratta.pay;

import com.paypal.base.rest.OAuthTokenCredential;
import com.paypal.base.rest.PayPalRESTException;
import org.springframework.http.HttpHeaders;

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

/**
 * @author: bright
 * @date:Created in 2020/10/6 15:40
 * @describe :
 */
public class PayPalClient {
    public static String getAccessToken() throws PayPalRESTException {
        Map<String, String> configurationMap = new HashMap<String, String>();
        configurationMap.put("service.EndPoint",
                "https://api.sandbox.paypal.com");
        OAuthTokenCredential merchantTokenCredential = new OAuthTokenCredential(
                "ARGZmv8TNRTjnyqnQe7xtJz04Ac15ul4V3HOtrWXezi9VhB_BQciFA5lUvqAC2nMvOC1IbAUGh34QYPb", "EPxpigopwLf5x3PuNZX5t2xWJB3BuGuxQe4EguvLiRDMKINO-amP29LATnep5uhX3YHIYR2YzCfUKKii", configurationMap);
        String accessToken = merchantTokenCredential.getAccessToken();
        return accessToken;
    }

    public static HttpHeaders setHttpHeaders() throws PayPalRESTException {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Content-Type", "application/json");
        httpHeaders.set("Authorization", getAccessToken());
        httpHeaders.set("PayPal-Request-Id", UUID.randomUUID().toString());
        return httpHeaders;
    }
}

4.2CreateProducts

package com.ratta.pay;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.paypal.base.rest.PayPalRESTException;
import com.ratta.bo.ProductsBO;
import com.ratta.util.RestTemplateUtils;
import org.springframework.http.ResponseEntity;

/**
 * @author: bright
 * @date:Created in 2020/10/6 16:32
 * @describe : 创建产品
 */
public class CreateProducts {
    public static String CreateProducts(ProductsBO products) throws PayPalRESTException {
        ResponseEntity<String> responseEntity = RestTemplateUtils.post("https://api.sandbox.paypal.com/v1/catalogs/products", PayPalClient.setHttpHeaders(), products, String.class);
        JSONObject jsonObject = JSONArray.parseObject(responseEntity.getBody());
        return jsonObject.get("id").toString();
    }

    public static void main(String[] args) throws PayPalRESTException {
        ProductsBO products = new ProductsBO();
        products.setName("超级会员一个月");
        products.setDescription("超级会员一个月");
        products.setCategory("SOFTWARE");
        products.setType("SERVICE");
        products.setImage_url("https://member.quicktvod.com/static/img/Mexico.jpg");
        products.setHome_url("https://member.quicktvod.com/static/img/Mexico.jpg");
        String id = CreateProducts.CreateProducts(products);
        System.out.println(id);
    }
}

4.3 CreatePlan

package com.ratta.pay;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.paypal.base.rest.PayPalRESTException;
import com.ratta.bo.*;
import com.ratta.util.RestTemplateUtils;
import org.springframework.http.ResponseEntity;

/**
 * @author: bright
 * @date:Created in 2020/10/6 17:16
 * @describe :  创建计费计划
 */
public class CreatePlan {
    public static String createPlan(PlanBO plan) throws PayPalRESTException {
        ResponseEntity<String> responseEntity = RestTemplateUtils.post("https://api.sandbox.paypal.com/v1/billing/plans", PayPalClient.setHttpHeaders(), plan, String.class);
        JSONObject jsonObject = JSONArray.parseObject(responseEntity.getBody());
        return jsonObject.get("id").toString();
    }

    public static void main(String[] args) throws PayPalRESTException {
        PlanBO plan = new PlanBO();
        //CreateProducts获取的产品id
        plan.setProduct_id("PROD-3C545082EG6201054");
        plan.setName("super服务一个月");
        plan.setDescription("自动续费");
        BillingCyclesBO billingCycles = new BillingCyclesBO();
        FrequencyBO frequency = new FrequencyBO();
        //设置付款频率
        frequency.setInterval_unit("DAY");
        frequency.setInterval_count(1);
        billingCycles.setFrequency(frequency);

        PricingSchemeBO pricingScheme = new PricingSchemeBO();
        FixedPriceBO fixedPrice = new FixedPriceBO();
        fixedPrice.setCurrency_code("USD");
        fixedPrice.setValue("10");
        pricingScheme.setFixed_price(fixedPrice);
        billingCycles.setPricing_scheme(pricingScheme);

        billingCycles.setTotal_cycles(36);
        billingCycles.setSequence(1);
        billingCycles.setTenure_type("REGULAR");
        BillingCyclesBO[] billingCyclesArray = {billingCycles};
        plan.setBilling_cycles(billingCyclesArray);
        //设置初始金额
        PaymentPreferencesBO paymentPreferences = new PaymentPreferencesBO();
        SetupFeeBO setupFee = new SetupFeeBO();
        setupFee.setCurrency_code("USD");
        setupFee.setValue("10");
        paymentPreferences.setSetup_fee(setupFee);
        plan.setPayment_preferences(paymentPreferences);
        String id = createPlan(plan);
        System.out.println(id);
    }
}

4.4 CreateSubscriptions

package com.ratta.pay;

import com.paypal.base.rest.PayPalRESTException;
import com.ratta.bo.ApplicationContextBO;
import com.ratta.bo.PaymentMethodBO;
import com.ratta.bo.SubscriptionsBO;
import com.ratta.util.RestTemplateUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.http.ResponseEntity;

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

/**
 * @author: bright
 * @date:Created in 2020/10/6 18:37
 * @describe : 创建订阅
 */
public class CreateSubscriptions {
    public static Map<String, String> createSubscriptions(SubscriptionsBO subscriptions) throws PayPalRESTException {
        Map<String, String> map = new HashMap<>();
        ResponseEntity<String> responseEntity = RestTemplateUtils.post("https://api.sandbox.paypal.com/v1/billing/subscriptions", PayPalClient.setHttpHeaders(), subscriptions, String.class);
        org.json.JSONObject jsonObject = new org.json.JSONObject(responseEntity.getBody());
        JSONArray object = (org.json.JSONArray) jsonObject.get("links");
        String url = "";
        for (Object o : object) {
            JSONObject jsonObj = (JSONObject) o;
            if (jsonObj.get("rel").toString().equals("approve")) {
                url = jsonObj.get("href").toString();
            }
        }
        map.put("id", jsonObject.get("id").toString());
        map.put("url", url);
        return map;
    }

    public static void main(String[] args) throws PayPalRESTException {
        SubscriptionsBO subscriptions = new SubscriptionsBO();
        subscriptions.setPlan_id("P-583780980U484121DL56REYY");
        subscriptions.setStart_time("2020-10-08T23:50:00Z");
        ApplicationContextBO applicationContext = new ApplicationContextBO();
        applicationContext.setBrand_name("yoostar");
        applicationContext.setCancel_url("https://www.example.com");
        applicationContext.setReturn_url("https://www.example.com");
        applicationContext.setLocale("en-US");
        applicationContext.setUser_action("SUBSCRIBE_NOW");
        applicationContext.setShipping_preference("GET_FROM_FILE");
        PaymentMethodBO paymentMethod = new PaymentMethodBO();
        paymentMethod.setPayee_preferred("UNRESTRICTED");
        paymentMethod.setPayer_selected("PAYPAL");
        applicationContext.setPayment_method(paymentMethod);
        subscriptions.setApplication_context(applicationContext);
        Map<String, String> map = createSubscriptions(subscriptions);
        System.out.println(map.get("id"));
        System.out.println(map.get("url"));

    }
}

4.5 CancelSubscriptions

package com.ratta.pay;

import com.paypal.base.rest.PayPalRESTException;
import com.ratta.util.RestTemplateUtils;
import org.springframework.http.ResponseEntity;

/**
 * @author: bright
 * @date:Created in 2020/10/7 8:32
 * @describe : 取消订阅
 */
public class CancelSubscriptions {
    public static void cancelSubscriptions(String subscriptionsId) throws PayPalRESTException {
        RestTemplateUtils.post("https://api.sandbox.paypal.com/v1/billing/subscriptions/" + subscriptionsId + "/cancel", PayPalClient.setHttpHeaders(), "", String.class);
    }

    public static void main(String[] args) throws PayPalRESTException {
        cancelSubscriptions("I-GX16952AV2TL");
    }
}

5.官方文档地址


 1. https://developer.paypal.com/docs/subscriptions/integrate/#5-go-live
 2. https://developer.paypal.com/docs/api/subscriptions/v1/

在这里插入图片描述
在这里插入图片描述

git地址: https://gitee.com/bright-boy/paypal.git

QQ 694475668 欢迎各位打赏一下哦

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

刘明同学呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值