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

一、 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,INFINITE
		plan.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 chargeModelsList = new ArrayList();
		//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后,进行支付
java对接PayPal支付-自动续费功能_第1张图片
支付成功后重定向到ReturnUrl地址
java对接PayPal支付-自动续费功能_第2张图片

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);
		//用户支付成功后,重定向返回的页面携带的token
		Agreement 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商家账户
java对接PayPal支付-自动续费功能_第3张图片
商家账户该笔订单详细信息
java对接PayPal支付-自动续费功能_第4张图片
查看PayPal用户账户
java对接PayPal支付-自动续费功能_第5张图片

用户账户该笔订单详细信息
java对接PayPal支付-自动续费功能_第6张图片

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

你可能感兴趣的:(PayPal,支付,java,paypal)