赞
踩
业务需求要集成Paypal,实现循环扣款功能,初识PayPal开发文档,搞得人一脸懵逼,终于完整实现所有功能,这里对如何使用Paypal的支付接口做下总结。
页面地址:https://www.paypal.com/us/webapps/mpp/account-selection
进入:
因为我没有商家账户,所以使用的个人账户。
注册完成后,进入开发者应用页面
页面地址:https://developer.paypal.com/developer/applications
注:
这里着重介绍一下计划,计划里面包含了收费规则,安装费用(或者说使用费),重试机制,税率等。设置完成后,创建订阅时,传入计划ID即可
本文使用纯API交互,远程工具使用的是httpClient,但是PayPal与其他不同,需要登录才能使用,所以本文使用的hutool的httpclient工具类,需要设置类型为basicAuth,且输入用户密码(clientId,secret),话不多说,上代码:
/**
* 获取token
* @return
* @throws IOException
*/
public String getToken() {
String body = HttpRequest.post(BASE_URL + "/v1/oauth2/token")
.basicAuth(username, password)
.form("grant_type", "client_credentials")
.execute().body();
JSONObject jsonObject = JSONObject.parseObject(body);
return jsonObject.get("access_token").toString();
}
参考文档:https://developer.paypal.com/docs/business/get-started/#exchange-your-api-credentials-for-an-access-token
/**
* 创建商品
* @return
* @throws JsonProcessingException
*/
public String createProduct() throws JsonProcessingException {
Product product = new Product();
product.setName("tc-004");
//商品种类,枚举
product.setCategory("BOOKS_PERIODICALS_AND_NEWSPAPERS");
product.setDescription("test product 4");
product.setHomeUrl("xxxx");
product.setImageUrl("xxxx");
//类型 枚举
product.setType("SERVICE");
Map<String,String> map = new HashMap<>(4);
map.put("Content-Type","application/json");
map.put("Authorization",getToken());
// 请求ID,如果保持一致,可以进行多次请求,结果一致
// map.put("PayPal-Request-Id","PLAN-18062019-001");
String string = new ObjectMapper().writeValueAsString(product);
String body = HttpRequest.post(BASE_URL + "/v1/catalogs/products")
.addHeaders(map)
.basicAuth(username,password)
.body(string)
.execute().body();
// System.out.println(body);
return body;
}
详情参考:https://developer.paypal.com/docs/api/catalog-products/v1/#definition-product_collection_element
链接中包含枚举
/**
* 创建计划
* @param productId
* @return
* @throws JsonProcessingException
*/
public String createPlan(String productId) throws JsonProcessingException {
String dateTime = LocalDateTime.now().toString();
String token = getToken();
Map<String,String> map = new HashMap<>(4);
map.put("Content-Type","application/json");
map.put("Authorization",token);
// map.put("PayPal-Request-Id","PLAN-18062019-001");
PayPalSubscriptionPlanParam planParam = new PayPalSubscriptionPlanParam();
List<BillingCycles> list = new ArrayList<>();
BillingCycles billingCycles = new BillingCycles();
billingCycles.setTenureType("REGULAR");
billingCycles.setSequence(1);
billingCycles.setTotalCycles(12);
//计费周期
Frequency frequency = new Frequency();
frequency.setIntervalUnit("DAY");
frequency.setIntervalCount(1);
PricingScheme pricingScheme = new PricingScheme();
pricingScheme.setVersion(1);
pricingScheme.setCreateTime(dateTime);
//定价
FixedPrice fixedPrice = new FixedPrice();
fixedPrice.setCurrencyCode("USD");
fixedPrice.setValue("100");
pricingScheme.setFixedPrice(fixedPrice);
billingCycles.setFrequency(frequency);
billingCycles.setPricingScheme(pricingScheme);
list.add(billingCycles);
// 付款偏好
PaymentPreferences paymentPreferences = new PaymentPreferences();
paymentPreferences.setAutoBillOutstanding(true);
paymentPreferences.setPaymentFailureThreshold(3);
paymentPreferences.setSetupFeeFailureAction("CANCEL");
SetupFee setupFee = new SetupFee();
setupFee.setCurrencyCode("USD");
setupFee.setValue("0");
paymentPreferences.setSetupFee(setupFee);
// 税率
Taxes taxes = new Taxes();
taxes.setInclusive(true);
taxes.setPercentage("0");
planParam.setTaxes(taxes);
planParam.setPaymentPreferences(paymentPreferences);
planParam.setBillingCycles(list);
planParam.setProductId(productId);
planParam.setName("test plan");
planParam.setStatus("ACTIVE");
planParam.setDescription("test");
planParam.setCreateTime(dateTime);
planParam.setUpdateTime(dateTime);
String string = new ObjectMapper().writeValueAsString(planParam);
System.out.println(string);
// System.out.println();
String body = HttpRequest.post(BASE_URL + "/v1/billing/plans")
.addHeaders(map)
.basicAuth(username,password)
.body(string)
.execute().body();
return body;
}
/**
* 创建订阅
* @param planId
* @return
*/
public String createSubscription(String planId) {
Map<String,String> map = new HashMap<>(4);
map.put("Content-Type","application/json");
map.put("Authorization",getToken());
// P-7EG815794T029494CMFR77TA
// String planId = "P-4ND94871NA4029913MFSTSXI";
String string = handlerSubsParam(planId);
String body = HttpRequest.post(BASE_URL + "/v1/billing/subscriptions")
.addHeaders(map)
.basicAuth(username,password)
.body(string)
.execute().body();
JSONObject jsonObject = JSONObject.parseObject(body);
List<Links> links = JSONObject.parseArray(jsonObject.get("links").toString(), Links.class);
Links links1 = links.stream().filter(o -> "approve".equals(o.getRel())).findFirst()
.orElseThrow(() -> new RuntimeException("sadsadsada"));
System.out.println(JSONObject.toJSONString(links));
System.out.println(links1.getHref());
return body;
}
/**
* 处理订阅参数
*
* @param planId
* @return
*/
private String handlerSubsParam(String planId) {
SubscriptionDTO subscriptionDTO = new SubscriptionDTO();
subscriptionDTO.setPlanId(planId);
// subscriptionDTO.setQuantity("10");
// subscriptionDTO.setShippingAmount("10");
// subscriptionDTO.setStartTime(new Date());
// subscriptionDTO.setQuantity("10");
Subscriber subscriber = new Subscriber();
SubscriberName subscriberName = new SubscriberName();
subscriberName.setGiven_name("lijing");
subscriberName.setSurname("xiong");
subscriber.setName(subscriberName);
subscriber.setEmailAddress("xiong.ricoh@gmail.com");
ShippingAddress shippingAddress = new ShippingAddress();
//注意最后一个字段,必须严格参照枚举字典,中国是C2,不是CN
shippingAddress.setAddress(new Address("XXXX","","","","","C2"));
shippingAddress.setName(new Name("xiong lijing"));
subscriber.setShippingAddress(shippingAddress);
subscriptionDTO.setSubscriber(subscriber);
ApplicationContext applicationContext = new ApplicationContext();
// applicationContext.setBrandName("");
applicationContext.setCancelUrl("http://www.baidu.com");
// applicationContext.setShippingPreference("");
// applicationContext.setUserAction("");
applicationContext.setReturnUrl("http://www.sina.com");
applicationContext.setPaymentMethod(new PaymentMethod());
subscriptionDTO.setApplicationContext(applicationContext);
String string = "";
try {
string = new ObjectMapper().writeValueAsString(subscriptionDTO);
// System.out.println(string);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return string;
}
PayPal订阅与PayPal单笔支付类似,最后会一个最终处理URL,点击进入即可登陆账号,付款等,所以处理结果即可。
本文需要引入依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>
<!--paypal-->
<dependency>
<groupId>com.braintreepayments.gateway</groupId>
<artifactId>braintree-java</artifactId>
<version>2.87.0</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>checkout-sdk</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>rest-api-sdk</artifactId>
<version>1.14.0</version>
</dependency>
文章代码已上传至github,源码有需要可以自行下载,实体类太多,可以从源码直接clone下来。
gitee地址:https://gitee.com/bear_crystal/paypal
github地址:https://github.com/xionglijing/paypal.git
有问题可以QQ联系:1144249977
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。