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

    科技2024-01-16  85

    我的开源微服务前后端分离博客项目地址,欢迎各位star

    博主技术文档地址

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

    由于同事对接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 欢迎各位打赏一下哦

    Processed: 0.048, SQL: 8