Recurring Payments
Heartland’s recurring product, PayPlan, allows you to easily setup reccuring payments on a tokenized credit card.
Create a Recurring Customer
Create a Customer
using GlobalPayments.Api.Entities;
var customer = new Customer {
Id = GenerateCustomerId(),
Status = "Active",
FirstName = "Bill",
LastName = "Johnson",
Company = "Heartland Payment Systems",
Address = new Address {
StreetAddress1 = "987 Elm St",
City = "Princeton",
Province = "NJ",
PostalCode = "12345",
Country = "USA"
},
HomePhone = "9876543210",
WorkPhone = "9876543210",
Fax = "9876543210",
MobilePhone = "9876543210",
Email = "text@example.com"
}.Create();
import com.global.api.entities.Address;
import com.global.api.entities.Customer;
Address address = new Address();
address.setStreetAddress1("987 Elm St");
address.setCity("Princeton");
address.setProvince("NJ");
address.setPostalCode("12345");
address.setCountry("USA");
Customer customer = new Customer();
customer.setId(generateCustomerId());
customer.setStatus("Active");
customer.setFirstName("Bill");
customer.setLastName("Johnson");
customer.setCompany("Heartland Payment Systems");
customer.setAddress(address);
customer.setHomePhone("9876543210");
customer.setWorkPhone("9876543210");
customer.setFax("9876543210");
customer.setMobilePhone("9876543210");
customer.setEmail("text@example.com");
customer = customer.create();
<?php
use GlobalPayments\Api\Entities\Address;
use GlobalPayments\Api\Entities\Customer;
$customer = new Customer();
$customer->id = generateCustomerId();
$customer->firstName = 'John';
$customer->lastName = 'Doe';
$customer->status = 'Active';
$customer->email = 'john.doe@example.com';
$customer->address = new Address();
$customer->address->streetAddress1 = '123 Main St.';
$customer->address->city = 'Dallas';
$customer->address->province = 'TX';
$customer->address->postalCode = '75024';
$customer->address->country = 'USA';
$customer->workPhone = '5551112222';
$customer = $customer->create();
# coming soon
# coming soon
import { Address, Customer } from "globalpayments-api";
let customer = new Customer();
customer.id = generateCustomerId();
customer.firstName = "John";
customer.lastName = "Doe";
customer.status = "Active";
customer.email = "john.doe@email.com";
customer.address = new Address();
customer.address.streetAddress1 = "123 Main St.";
customer.address.city = "Dallas";
customer.address.state = "TX";
customer.address.postalCode = "98765";
customer.address.country = "USA";
customer.workPhone = "5551112222";
customer = await customer.create();
Create a Payment Method for a Customer
Follow the example below to create a new Payment Method for a customer.The object payPlanService was defined in the customer creation example code above.
Create a Payment Method
using GlobalPayments.Api.PaymentMethods;
var paymentMethod = customer.AddPaymentMethod(
GeneratePaymentMethodId(),
new CreditCardData {
Number = "4111111111111111",
ExpMonth = 12,
ExpYear = 2025
}
).Create();
import com.global.api.paymentMethods.CreditCardData;
import com.global.api.paymentMethods.RecurringPaymentMethod;
CreditCardData card = new CreditCardData();
card.setNumber("4111111111111111");
card.setExpMonth(12);
card.setExpYear(2025);
RecurringPaymentMethod paymentMethod = customer.addPaymentMethod(
generatePaymentMethodId(),
card
).create();
<?php
use GlobalPayments\Api\PaymentMethods\CreditCardData;
use GlobalPayments\Api\PaymentMethods\RecurringPaymentMethod;
$card = new CreditCardData();
$card->number = '4111111111111111';
$card->expMonth = '12';
$card->expYear = '2025';
$paymentMethod = $customer->addPaymentMethod(
generatePaymentMethodId(),
$card
)->create();
# coming soon
# coming soon
import { CreditCardData } from "globalpayments-api";
const card = new CreditCardData();
card.number = "4111111111111111";
card.expMonth = "12";
card.expYear = "2025";
const paymentMethod = await customerPerson
.addPaymentMethod(generatePaymentMethodId(), card)
.create();
Create a Recurring Plan for a Payment Method
Use the following example to create a new subscription plan for a given Payment Method. The objects payPlanService and paymentMethod were defined in earlier example code.
Create a Schedule
using GlobalPayments.Api.Entities;
var schedule = paymentMethod.AddSchedule(GenerateScheduleId())
.WithAmount(30.02m)
.WithCurrency("USD")
.WithStartDate(DateTime.Parse("02/01/2027"))
.WithFrequency(ScheduleFrequency.WEEKLY)
.WithStatus("Active")
.WithReprocessingCount(2)
.WithEndDate(DateTime.Parse("04/01/2027"))
.Create();
import com.global.api.entities.Schedule;
import com.global.api.entities.enums.ScheduleFrequency;
import java.math.BigDecimal;
Schedule schedule = paymentMethod.addSchedule(generateScheduleId())
.withAmount(new BigDecimal("30.02"))
.withCurrency("USD")
.withStartDate(DateUtils.parse("02/01/2027"))
.withFrequency(ScheduleFrequency.Weekly)
.withStatus("Active")
.withReprocessingCount(2)
.withEndDate(DateUtils.parse("04/01/2027"))
.create();
<?php
use GlobalPayments\Api\Entities\Enums\ScheduleFrequency;
$schedule = $paymentMethod->addSchedule(
generateScheduleId()
)
->withStatus('Active')
->withAmount(30.02)
->withCurrency('USD')
->withStartDate(\DateTime::createFromFormat('Y-m-d', '2027-02-01'))
->withFrequency(ScheduleFrequency::WEEKLY)
->withEndDate(\DateTime::createFromFormat('Y-m-d', '2027-04-01'))
->withReprocessingCount(2)
->create();
# coming soon
# coming soon
import {
EmailReceipt,
ScheduleFrequency
} from "globalpayments-api";
const schedule = await paymentMethodVisa
.addSchedule(generateScheduleId())
.withStartDate(new Date(2027, 1, 1))
.withAmount(30.01)
.withFrequency(ScheduleFrequency.Weekly)
.withReprocessingCount(1)
.withStatus("Active")
.withEmailReceipt(EmailReceipt.Never)
.create();
Failed Scheduled Transactions
A schedule with a Failed status is an indication that the merchant must reach out to the customer to obtain new payment information. PayPlan has an email notification that a merchant can opt in to receive a list of all schedules that failed during the nightly processing. If a card exceeds retries with non-fatal decline codes, then the schedule status changes to Failed but the payment status remains Active. This email notification is based on emailReceipt and emailAdvanceNotice.
Expired
There is logic in place for recurring billing; it allows us to drop the expiration date on a card if it is less than current MMYYYY and it’s a recurring billing transaction. Eventually these will decline and/or trigger a fatal error. -below-
Declined
If a card is declined when processing a schedule, the “Failure Count” field is incremented. If the Failure Count exceeds the reprocessing count, then the schedule status is also updated to ‘Failed’. Each subsequent try is aproximately 24 hours after.
Communication Failures
If there is a communication failure, the schedule will fall into an error queue and no updates will be made. Any schedule in the error queue is manually reviewed the next business day. This is exceptionally rare and we do not typically provide any information to a merchant when an instance occurs.
Other fatal errors
- Invalid
- Expired
- Lost/Stolen
- Revoked
A payment status can be set to something other than Active/Inactive only by the “fatal” response codes from an issuer during schedule processing; a one-time transaction does not change a payment method status. For example, if we process a schedule with a card and the issuer returns lost/stolen, then the schedule status changes to failed and the payment status changes to Lost/Stolen. If a card exceeds retries with non-fatal decline codes, then the schedule status changes to Failed but the payment status remains Active.
Once the payment method is updated an edit can be performed to restart the schedule.
Find Customers
You can find customers associated using this method call.
Find Customers
using GlobalPayments.Api.Entities;
var customers = Customer.FindAll();
import com.global.api.entities.Customer;
import java.util.List;
List<Customer> customers = Customer.findAll();
<?php
use GlobalPayments\Api\Entities\Customer;
$customers = Customer::findAll();
# coming soon
# coming soon
import { Customer } from "globalpayments-api";
const customers = await Customer.findAll();
Find Payment Methods
You can find payment methods associated using this method call.
Find Payment Methods
using GlobalPayments.Api.PaymentMethods;
var paymentMethods = RecurringPaymentMethod.FindAll();
import com.global.api.paymentMethods;
import java.util.List;
List<RecurringPaymentMethod> paymentMethods = RecurringPaymentMethod.findAll();
<?php
use GlobalPayments\Api\PaymentMethods\RecurringPaymentMethod;
$paymentMethods = RecurringPaymentMethod::findAll();
# coming soon
# coming soon
import { RecurringPaymentMethod } from "globalpayments-api";
const paymentMethods = await RecurringPaymentMethod.findAll();
Find Schedules
You can find schedules associated using this method call.
Find Schedules
using GlobalPayments.Api.Entities;
var schedules = Schedule.FindAll();
import com.global.api.entities.Schedule;
import java.util.List;
List<Schedule> schedules = Schedule.findAll();
<?php
use GlobalPayments\Api\Entities\Schedule;
$schedules = Schedule::findAll();
# coming soon
# coming soon
import { Schedule } from "globalpayments-api";
const schedules = await Schedule.findAll();
Edit Schedule
Conditional Parameters
scheduleStarted returns true if at least one transaction in the schedule has processed even if it has declined. The PHP-SDK will drop illegally passed fields during the edit call. More complete code examples can be found in the SDK
scheduleStarted = False
The following fields may only be edited when the schedule has not started processing
Parameter | Description |
---|---|
Schedule identifier | String 50 character max |
Start date | date in DDMMYYYY format |
Frequency | Weekly , Bi-Weekly , Semi-Monthly , Monthly , Bi-Monthly , Quarterly , Semi-Annually , Annually |
Duration | Ongoing , Limited Number , End Date |
scheduleStarted = true
Once the schedule has started processing then the following field becomes editable
Parameter | Description |
---|---|
Next processing date | date in DDMMYYYY format |
Cancellation date | date in DDMMYYYY format |
Edit Schedule
using GlobalPayments.Api.Entities;
var schedule = Schedule.Find(GetScheduleId());
schedule.Status = "Inactive";
schedule.SaveChanges();
import com.global.api.entities.Schedule;
Schedule schedule = Schedule.find(getScheduleId());
schedule.setStatus("Inactive");
schedule.saveChanges();
<?php
use GlobalPayments\Api\Entities\Schedule;
$schedule = Schedule::find(getScheduleId());
$schedule->status = 'Inactive';
$schedule->saveChanges();
# coming soon
# coming soon
import { Schedule } from "globalpayments-api";
const schedule = await Schedule.find(getScheduleId());
schedule.status = "Inactive";
await schedule.saveChanges();