歡迎大家進群,一起探讨學習

微信公衆号,每天給大家提供技術幹貨
部落客技術平台位址
部落客開源微服架構前後端分離技術部落格項目源碼位址,歡迎各位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/