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

微信公众号,每天给大家提供技术干货

博主技术笔记

博主网站地址1

博主网站地址2

博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位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获取的产品idplan.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-live2. https://developer.paypal.com/docs/api/subscriptions/v1/


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

QQ 694475668 欢迎各位打赏一下哦

java对接PayPal实现自动续费功能相关推荐

  1. java对接PayPal支付-自动续费功能

    一. java对接PayPal支付(v2). 讲了PayPal v2:checkout-sdk 的对接过程 二. java对接PayPal支付 (添加物流跟踪信息). 讲了PayPal添加物流信息 的 ...

  2. php实现自动续费功能,如何关闭wps自动续费

    微信中,打开"支付管理"界面,点击"自动扣费":然后找到"wps自动续费"项,点击进入:最后点击"关闭服务"即可.支付宝 ...

  3. 腾讯视频关闭自动续费功能

    腾讯视频更新版本之后,找个老半天才发现如何关闭自动续费.记录在这里备用. 1,打开手机腾讯视频APP. 2,点击右下角的个人中心. 3,点击左上角的"我的VIP会员". 4,拉到最 ...

  4. 怎么取消苹果手机自动续费_知乎会员怎样取消自动续费

    已开通连续订阅,需要从第三方支付账户( 或系统 )中关闭自动续费功能.否则自动续费仍有效,会持续扣费.
 关闭路径如下: 1.收到 [App store & Apple] 扣费账单的用户 (使 ...

  5. 如何关闭百度网盘超级会员自动续费服务?

    常见关闭自动续费的三条途径: 1.微信:①我的→服务(支付)→钱包→支付设置→自动续费→点击相应账单→关闭扣费服务               ②我的→服务(支付)→钱包→支付设置→Apple服务扣费 ...

  6. 怎么取消苹果订阅自动续费?教你一招,2分钟搞定!

    案例:苹果怎么取消自动续费? [想问下苹果订阅服务在哪里看?之前好像不小心订阅了什么自动续费,想要取消它.] 苹果订阅自动续费功能在一定程度上方便了用户的购买体验,但有时候我们会忘记取消订阅,导致不必 ...

  7. 会员自动续费服务协议

    当前版本更新时间:2021年12月05日 当前版本生效时间:2021年12月05日 会员自动续费服务协议 [注意事项] 欢迎您使用和接受Top Widgets万能桌面(以下简称"本应用&qu ...

  8. APP“自动续费”,挖坑式赚钱有违商业伦理

    最近,新华社等多家媒体关注到了APP自动续费的一系列问题.比如,以低价促销诱导开通会员,但却不清晰提醒自动续费,导致消费者哪怕弃用APP之后还在被扣费.而有的消费者发现"上当",想 ...

  9. 支付宝自动续费申请PHP,APP是如何实现自动续费的?

    APP会员自动续费功能流程: 1.1.会员自动续费授权 会员自动续费本质是委托扣款模式.只有用户完成签约,商户才可以对用户账户进行自动扣款,从而完成会员订单的支付操作. 用户在应用内通过微信或支付宝的 ...

最新文章

  1. 【Paper】英文论文写作小技巧
  2. 中餐菜单分类名称创意_外卖运营小知识:优化外卖菜单,挽回店铺亏损
  3. SAP UI5应用如果遇到数据绑定问题时,应该如何自己定位问题?
  4. q7goodies事例_Java 8 Friday Goodies:Lambda和SQL
  5. linux下gdb常用的调试命令
  6. js学习总结----柯里化函数
  7. Java解决循环注入问题
  8. 刚毕业就年薪百万,谁说知识不是财富
  9. HDU - 5950 Recursive sequence(矩阵快速幂)
  10. 怎样启动本地mysql服务_启动本地mysql服务
  11. C - 小型Basic编译器问题
  12. 绵阳python培训_绵怎么组词
  13. 金融数据获取系列之一(优矿)
  14. 算术左移,算术右移;逻辑左移,逻辑右移
  15. 腾讯会议突围背后:端到端实时语音技术是如何保障交流通畅的?
  16. python中blit的意思,pygame中的surface.blit()函数是什么?它有什么作用?它是如何工作的?...
  17. 库文件搜索路径及GCC搜索路径总结
  18. AD20差分线等长布线的方法
  19. 机器学习中概率论知识
  20. WHERE CURRENT OF

热门文章

  1. Python 爬取 5K 分辨率超清唯美壁纸
  2. 知乎萧井陌大神《编程入门指南v1.3》思维导图
  3. 后台产品经理入门指南(上)
  4. 如何理解三维向量叉乘
  5. java Swing 鼠标图标的改变及移入按钮改变
  6. 如何使用maven给Java打包
  7. 设计题目:基于CPLD/FPGA的出租车计费器
  8. sqlmap 常用命令
  9. Nginx(8)_return和rewrite
  10. 药店管理系统源码 his系统源码 HIS源码