一起探讨学习
每天给大家提供技术干货
博主技术笔记 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/