一、 java对接PayPal支付(v2). 讲了PayPal v2:checkout-sdk 的对接过程
二、 java对接PayPal支付 (添加物流跟踪信息). 讲了PayPal添加物流信息 的对接过程
今天我们讲讲如何实现自动续费的功能。

PayPal自动续费功能在v1版本里面有,如果想实现此功能,必须引入v1 rest-api-sdk

言归正传,正式开始

一、引入maven依赖

     <dependency><groupId>com.paypal.sdk</groupId><artifactId>rest-api-sdk</artifactId><version>LATEST</version></dependency>

二、编写代码

1、MakeRenewalPlan( 制订续费计划)

package com.ratta.pay.info.paypal;import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.paypal.api.payments.ChargeModels;
import com.paypal.api.payments.Currency;
import com.paypal.api.payments.MerchantPreferences;
import com.paypal.api.payments.Patch;
import com.paypal.api.payments.PaymentDefinition;
import com.paypal.api.payments.Plan;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;public class MakeRenewalPlan{private String clientId = "AdTJ2en6Av42r1xoziJj6bJK-X4tRGDHACZId0OPXfGyXs8OyoYEmlm8bHjzrgd3UislDQR0iBP7x-wM";private String clientSecret = "EC9DSrfAfVfo-c3K-1dILXA5iijnHtaunKwv2JzECSz9jcdy3t78rDFeAEgaixnnIYYlgQcipbZQWoCa";private String mode = "sandbox";protected Plan instance = null;/*** 创建续费计划** https://developer.paypal.com/webapps/developer/docs/api/#create-a-plan** @return 新创建的计划* @throws PayPalRESTException*/public Plan create(APIContext context) throws PayPalRESTException, IOException {// 构建计划对象Plan plan = new Plan();plan.setName("Supernote会员");plan.setDescription("Supernote会员,按月自动续费");//计费方案的类型。 允许的值:FIXED,INFINITEplan.setType("FIXED");//付款参数PaymentDefinition paymentDefinition = new PaymentDefinition();paymentDefinition.setName("定期付款");//付款定义的类型。 允许的值:“ TRIAL”,“ REGULAR”)。paymentDefinition.setType("REGULAR");//提供的付款定义的频率。 允许的值:“WEEK”,“DAY”,“YEAR”,“MONTH”。paymentDefinition.setFrequency("MONTH");//多久(setFrequency)向用户收取一次费用paymentDefinition.setFrequencyInterval("1");//收款的周期(次数),无期限使用“0”paymentDefinition.setCycles("12");//金额Currency currency = new Currency();currency.setCurrency("USD");currency.setValue("20");paymentDefinition.setAmount(currency);//收费模式//ChargeModels chargeModels = new com.paypal.api.payments.ChargeModels();//收费模式的类型。 允许的值:`SHIPPING`运费,`TAX`税费。//chargeModels.setType("SHIPPING");//chargeModels.setAmount(currency);//List<ChargeModels> chargeModelsList = new ArrayList<ChargeModels>();//chargeModelsList.add(chargeModels);//paymentDefinition.setChargeModels(chargeModelsList);//付款定义List<PaymentDefinition> paymentDefinitionList = new ArrayList<PaymentDefinition>();paymentDefinitionList.add(paymentDefinition);plan.setPaymentDefinitions(paymentDefinitionList);//商家设置MerchantPreferences merchantPreferences = new MerchantPreferences();merchantPreferences.setSetupFee(currency);merchantPreferences.setCancelUrl("https://www.example.com");merchantPreferences.setReturnUrl("https://www.example.com");//允许的失败尝试总数。默认值为0,表示无数次失败的尝试merchantPreferences.setMaxFailAttempts("0");//允许在下一个周期中为未结协议金额自动计费。 允许的值:“YES”,“NO”。 默认为“NO”。merchantPreferences.setAutoBillAmount("YES");//如果在首次付款期间发生故障,应采取的措施。 允许的值:"CONTINUE","CANCEL"。 默认为"CONTINUE"。merchantPreferences.setInitialFailAmountAction("CONTINUE");plan.setMerchantPreferences(merchantPreferences);this.instance = plan.create(context);System.out.println("planId:" + this.instance.getId());return this.instance;}/***  更新续费计划(激活)* * https://developer.paypal.com/webapps/developer/docs/api/#update-a-plan** @return 更新后的计划* @throws PayPalRESTException*/public Plan update(APIContext context) throws PayPalRESTException, IOException {List<Patch> patchRequestList = new ArrayList<Patch>();Map<String, String> value = new HashMap<String, String>();value.put("state", "ACTIVE");Patch patch = new Patch();patch.setPath("/");patch.setValue(value);patch.setOp("replace");patchRequestList.add(patch);this.instance.update(context, patchRequestList);return this.instance;}/*** 查询续费计划** https://developer.paypal.com/webapps/developer/docs/api/#retrieve-a-plan** @return 查询到的续费计划* @throws PayPalRESTException*/public Plan retrieve(APIContext context) throws PayPalRESTException {return Plan.get(context, this.instance.getId());}public static void main(String[] args) {try {MakeRenewalPlan subscriptionSample = new MakeRenewalPlan();APIContext context = new APIContext(clientId, clientSecret, mode);subscriptionSample.create(context);System.out.println("create response:\n" + Plan.getLastResponse());subscriptionSample.update(context);System.out.println("plan updated");
//          subscriptionSample.retrieve(context);
//          System.out.println("retrieve response:\n" + Plan.getLastResponse());} catch (JsonSyntaxException e) {e.printStackTrace();} catch (JsonIOException e) {e.printStackTrace();} catch (FileNotFoundException e) {e.printStackTrace();} catch (PayPalRESTException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

*运行上述main方法后,得到如下报文:
{"id":“P-3D664421HH6274501ORVH46A”,“state”:“CREATED”,“name”:“Supernote会员”,“description”:“Supernote会员,按月自动续费”,“type”:“FIXED”,“payment_definitions”:[{“id”:“PD-1BW495186X851642WORVH46A”,“name”:“定期付款”,“type”:“REGULAR”,“frequency”:“Month”,“amount”:{“currency”:“USD”,“value”:“20”},“cycles”:“12”,“charge_models”:[{“id”:“CHM-1A988195SK289121WORVH46A”,“type”:“SHIPPING”,“amount”:{“currency”:“USD”,“value”:“20”}}],“frequency_interval”:“1”}],“merchant_preferences”:{“setup_fee”:{“currency”:“USD”,“value”:“20”},“max_fail_attempts”:“0”,“return_url”:“https://www.example.com”,“cancel_url”:“https://www.example.com”,“auto_bill_amount”:“YES”,“initial_fail_amount_action”:“CONTINUE”},“create_time”:“2020-07-22T02:46:43.064Z”,“update_time”:“2020-07-22T02:46:43.064Z”,“links”:[{“href”:“https://api.sandbox.paypal.com/v1/payments/billing-plans/P-3D664421HH6274501ORVH46A”,“rel”:“self”,“method”:“GET”}]}
我们要的参数就是"id":"P-3D664421HH6274501ORVH46A"

2、CreateRenewalPlanOrder( 创建续费计划订单)

package com.ratta.pay.info.paypal;import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;import com.paypal.api.payments.Agreement;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payer;
import com.paypal.api.payments.Plan;
import com.paypal.api.payments.ShippingAddress;public class CreateRenewalPlanOrder {private String clientId = "AdTJ2en6Av42r1xoziJj6bJK-X4tRGDHACZId0OPXfGyXs8OyoYEmlm8bHjzrgd3UislDQR0iBP7x-wM";private String clientSecret = "EC9DSrfAfVfo-c3K-1dILXA5iijnHtaunKwv2JzECSz9jcdy3t78rDFeAEgaixnnIYYlgQcipbZQWoCa";private String mode = "sandbox";public String create(String planId, String date) {APIContext context = new APIContext(clientId, clientSecret, mode);// 创建新的协议Agreement agreement = new Agreement();agreement.setName("Supernote会员");agreement.setDescription("黄金会员,多重优惠特权");agreement.setStartDate(date);// 设置续费协议Plan plan = new Plan();plan.setId(planId);agreement.setPlan(plan);// 添加付款方式Payer payer = new Payer();payer.setPaymentMethod("paypal");agreement.setPayer(payer);// 添加收货地址ShippingAddress shipping = new ShippingAddress();shipping.setLine1("集心路168号");shipping.setCity("shanghai");shipping.setState("上海市");shipping.setPostalCode("200000");shipping.setCountryCode("CN");agreement.setShippingAddress(shipping);// 创建协议try {agreement = agreement.create(context);for (Links links : agreement.getLinks()) {if ("approval_url".equals(links.getRel())) {URL url = new URL(links.getHref());System.out.println("url = " + url);break;}}} catch (PayPalRESTException e) {System.err.println(e.getDetails());} catch (MalformedURLException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();}return null;}public static void main(String[] args) {SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");Calendar cal=Calendar.getInstance();cal.add(Calendar.DATE,1);Date time=cal.getTime();String dateString = sf.format(time);//UTC时间,第二天早晨9点收取第一次费用dateString = dateString + " 09:00:00";SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date date = null;try {date = sdf.parse(dateString);} catch (ParseException e) {e.printStackTrace();}DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");df.setTimeZone(TimeZone.getTimeZone("UTC"));String timestamp = df.format(date);new CreateRenewalPlanOrder().create("P-9DD04346B7017164CORRDVOA", timestamp);}
}

得到跳转paypal收银台的url后,进行支付

支付成功后重定向到ReturnUrl地址

3、CapturesRenewalPlanOrder(续费计划订单进行扣款)

用户通过CreateRenewalPlanOrder生成 approveUrl 跳转paypal支付成功后,只是授权,并没有将用户的钱打入我们的paypal账户,我们需要通过 CapturesRenewalPlanOrder接口,将钱打入我的PayPal账户

package com.ratta.pay.info.paypal;import com.paypal.api.payments.Agreement;
import com.paypal.base.rest.APIContext;
import com.paypal.base.rest.PayPalRESTException;public class CapturesRenewalPlanOrder {private String clientId = "AdTJ2en6Av42r1xoziJj6bJK-X4tRGDHACZId0OPXfGyXs8OyoYEmlm8bHjzrgd3UislDQR0iBP7x-wM";private String clientSecret = "EC9DSrfAfVfo-c3K-1dILXA5iijnHtaunKwv2JzECSz9jcdy3t78rDFeAEgaixnnIYYlgQcipbZQWoCa";private String mode = "sandbox";@SuppressWarnings("static-access")public String captureOrder(String token) {APIContext context = new APIContext(clientId, clientSecret, mode);//用户支付成功后,重定向返回的页面携带的tokenAgreement agreement =  new Agreement();agreement.setToken(token);try {Agreement activeAgreement = agreement.execute(context, agreement.getToken());System.out.println("Agreement created with ID " + activeAgreement.getId());} catch (PayPalRESTException e) {System.err.println(e.getDetails());}return null;}public static void main(String[] args) {new CapturesRenewalPlanOrder().captureOrder("EC-46H30638BD0709616");}
}

查看PayPal商家账户

商家账户该笔订单详细信息

查看PayPal用户账户

用户账户该笔订单详细信息

关于更多续费计划的接口功能请参考: paypal文档(Billing Agreements API).

java对接PayPal支付-自动续费功能相关推荐

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

    欢迎大家进群,一起探讨学习 微信公众号,每天给大家提供技术干货 博主技术笔记 博主网站地址1 博主网站地址2 博主开源微服架构前后端分离技术博客项目源码地址,欢迎各位star 由于同事对接PayPal ...

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

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

  3. java对接PayPal支付(v2)

    java对接PayPal支付 我们公司最近开通了网上支付功能,国内选择对接支付宝和微信,国外选择对接paypal, 今天我先将paypal对接方式记录下来,后面会记录微信和支付宝(本人比较懒,微信和支 ...

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

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

  5. java 对接 paypal支付

    码字不易,开源更不易,点赞收藏关注,多多支持 开源地址  paypal-demo: java 对接 paypal 的案例,下载项目,注册paypal账号,拿到秘钥,即可使用 效果图 准备环境 1.注册 ...

  6. java对接PayPal支付(ipn中文乱码解决)

    IPN验证有中文的时候会出现乱码,是由于encoding设置导致的,请通过以下步骤将encoding设置改为UTF-8应该就能解决: 1)登录您的PayPal账号后打开这个链接进入设置页面: http ...

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

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

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

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

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

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

最新文章

  1. JAVE EE 企业级开发之从零开始学JAVA【51CTO技术论坛】
  2. C++类的构造函数不能为虚函数的原因
  3. tps 数据库写并发衡量_MPP数据库简介
  4. Android-通过SlidingMenu高仿微信6.2最新版手势滑动返回(二)
  5. ArcGis 10+Oracle发布WFS-T服务,无法更新Feature的解决方法
  6. thinkphp与php共享session
  7. 移动端html搜索怎么写,移动端实现搜索功能
  8. partproble在RHEL 6下无法更新分区信息
  9. Chrome 最小字体12px
  10. Django之内置组件
  11. 代码无错是优? 工厂模式
  12. 测试停止线程(Java)
  13. javascript+Java 实现MD5加密登录密码
  14. 深入解读Docker底层技术cgroup系列(总览)
  15. Golang学习:生成GIF动画
  16. python爬虫分析百度文库、道客巴巴、豆丁网获取图片链接
  17. 两直线夹角求解-Python编程实现
  18. 程序员都知道的二维码扫码登录的底层原理
  19. JavaScript函数-创建参数个数不限数量的函数
  20. GitLab-Runner 从安装到配置到入门

热门文章

  1. H5视频之直播流服务搭建(一)
  2. 厦门大学701语言文学基础考研参考书目
  3. JAVA中小数为什么不精确
  4. Qt C++ 自定义仪表盘控件02
  5. 利用QQ空间查询接口的网页小应用
  6. 从零开始在服务器上搭建QQ机器人——起步(一)
  7. 》古文诗词:庄子·杂篇·列御寇
  8. 算法竞赛入门经典第一节问题1-5
  9. 薪酬模块常用文件资料 (参考案例)
  10. C++11中的delete关键字