eCheck & ACH Payments
While accepting credit/debit cards could cover most of your payment acceptance needs, allowing your customers to pay by check my be preferred by your customers in certain situations, business-to-business transactions being one such possible situation.
As with any payment form, your integration will need to gather enough information depending on your merchant account’s configuration. The below is a good baseline for ACH/eCheck transactions with Heartland ACH, but the required fields may vary for Sage/GETI.
Basic HTML Payment Form
<form id="payment_form" method="post" action="/process">
<!-- account fields -->
<label for="account_number">Account Number</label>
<input id="account_number" name="account_number" type="tel">
<label for="routing_number">Routing Number</label>
<input id="routing_number" name="routing_number" type="tel">
<label for="account_type">Account Type</label>
<select id="account_type" name="account_type">
<option value="CHECKING">Checking</option>
<option value="SAVINGS">Saving</option>
</select>
<label for="check_type">Check Type</label>
<select id="check_type" name="check_type">
<option value="PERSONAL">Personal</option>
<option value="BUSINESS">Business</option>
</select>
<!-- address fields -->
<label for="check_holder_name">check_holder_name</label>
<input id="check_holder_name" name="check_holder_name" type="text">
<label for="billing_street_address_1">billing_street_address_1</label>
<input id="billing_street_address_1" name="billing_street_address_1" type="text">
<label for="billing_city">billing_city</label>
<input id="billing_city" name="billing_city" type="text">
<label for="billing_state">billing_state</label>
<input id="billing_state" name="billing_state" type="text">
<label for="billing_zip">billing_zip</label>
<input id="billing_zip" name="billing_zip" type="text">
</form>
Charge the Account
Once the consumer has entered their ACH/eCheck information and submitted the payment form, the next step is to charge the account. Let’s configure the server-side SDK and gather our data together in preparation.
Configure authentication
using GlobalPayments.Api.Services;
ServicesContainer.ConfigureService(new PorticoConfig {
SecretApiKey = "skapi_cert_MTyMAQBiHVEAewvIzXVFcmUd2UcyBge_eCpaASUp0A",
DeveloperId = "000000",
VersionNumber = "0000",
ServiceUrl = "https://cert.api2.heartlandportico.com"
});
<?php
use GlobalPayments\Api\ServicesConfig;
use GlobalPayments\Api\ServicesContainer;
$config = new ServicesConfig();
$config->secretApiKey = "skapi_cert_MTyMAQBiHVEAewvIzXVFcmUd2UcyBge_eCpaASUp0A";
$config->developerId = "000000";
$config->versionNumber = "0000";
$config->serviceUrl = "https://cert.api2.heartlandportico.com";
ServicesContainer::configure($config);
import com.global.api.ServicesContainer;
import com.global.api.serviceConfigs.GatewayConfig;
PorticoConfig serviceConfig = new PorticoConfig();
config.setSecretApiKey("skapi_cert_MTyMAQBiHVEAewvIzXVFcmUd2UcyBge_eCpaASUp0A");
config.setDeveloperId("000000");
config.setVersionNumber("0000");
config.setServiceUrl("https://cert.api2.heartlandportico.com");
ServicesContainer.configureService(config);
# coming soon
from globalpayments.api import ServicesConfig, ServicesContainer
config = ServicesConfig()
config.secret_api_key = 'skapi_cert_MTyMAQBiHVEAewvIzXVFcmUd2UcyBge_eCpaASUp0A>'
config.developer_id = '000000'
config.version_number = '0000'
config.service_url = 'https://cert.api2.heartlandportico.com'
ServicesContainer.configure(config)
import { ServicesConfig, ServicesContainer } from "globalpayments-api";
const config = new ServicesConfig();
config.secretApiKey = "skapi_cert_MTyMAQBiHVEAewvIzXVFcmUd2UcyBge_eCpaASUp0A";
config.developerId = "000000";
config.versionNumber = "0000";
config.serviceUrl = "https://cert.api2.heartlandportico.com";
ServicesContainer.configure(config);
Prepare to charge an ACH/eCheck account
var check = new eCheck {
AccountNumber = GetRequestParam("account_number"),
RoutingNumber = GetRequestParam("routing_number"),
AccountType = GetRequestAccountTypeParam("account_type"),
CheckType = GetRequestCheckTypeParam("check_type"),
CheckHolderName = GetRequestParam("check_holder_name")
};
var address new Address {
StreetAddress1 = GetRequestParam("billing_street_address_1"),
City = GetRequestParam("billing_city"),
State = GetRequestParam("billing_state"),
PostalCode = GetRequestParam("billing_zip")
};
<?php
$check = new eCheck();
$check->accountNumber = getRequestParam("account_number");
$check->routingNumber = getRequestParam("routing_number");
$check->accountType = getRequestAccountTypeParam("account_type");
$check->checkType = getRequestCheckTypeParam("check_type");
$check->checkHolderName = getRequestParam("check_holder_name");
$address = new Address();
$address->streetAddress1 = getRequestParam("billing_street_address_1");
$address->city = getRequestParam("billing_city");
$address->state = getRequestParam("billing_state");
$address->postalCode = getRequestParam("billing_zip");
eCheck check = new eCheck();
check.setAccountNumber(getRequestParam("account_number"));
check.setRoutingNumber(getRequestParam("routing_number"));
check.setAccountType(getRequestAccountTypeParam("account_type"));
check.setCheckType(getRequestCheckTypeParam("check_type"));
check.setCheckHolderName(getRequestParam("check_holder_name"));
Address address = new Address();
address.setStreetAddress1(getRequestParam("billing_street_address_1"));
address.setCity(getRequestParam("billing_city"));
address.setState(getRequestParam("billing_state"));
address.setPostalCode(getRequestParam("billing_zip"))
# coming soon
# coming soon
const check = new eCheck();
check.accountNumber = getRequestParam("account_number");
check.routingNumber = getRequestParam("routing_number");
check.accountType = getRequestAccountTypeParam("account_type");
check.checkType = getRequestCheckTypeParam("check_type");
check.checkHolderName = getRequestParam("check_holder_name");
const address = new Address();
address.streetAddress1 = getRequestParam("billing_street_address_1");
address.city = getRequestParam("billing_city");
address.state = getRequestParam("billing_state");
address.postalCode = getRequestParam("billing_zip");
With our eCheck
and Address
objects created, we can use them to charge the consumer’s account. Heartland’s server-side SDKs expose the charge action as a method off of the payment objects, including eCheck
.
Charge an ACH/eCheck account
var response = check.Charge(10.00m)
.WithCurrency("USD")
.WithAddress(address)
.Execute();
<?php
$response = $check->charge(10)
->withCurrency("USD")
->withAddress($address)
->execute();
Transaction response = check.charge(new BigDecimal("10"))
.withCurrency("USD")
.withAddress(address)
.execute();
# coming soon
# coming soon
const response = await check.charge(10)
.withCurrency("USD")
.withAddress(address)
.execute();
All payment transactions, including charge, will return a Transaction
object when using our server-side SDKs. Any data exposed on the Transaction
object can be stored in your application’s database or displayed to the consumer.
Handle Declines and Errors
Declines from issuing banks and general errors are bound to happen, so it is wise for your application to be prepared. Our server-side SDKs will throw an exception when the issuing bank declines a transaction or if the supplied data fails the SDKs’ built-in validation. The best way to account for this is to wrap your code in a try
/catch
:
Exception Handling
# coming soon
# coming soon
try {
check.Charge(-5m)
.WithCurrency("USD")
.WithAddress(address)
.Execute();
}
catch (ApiException e) {
// handle error
}
<?php
try {
$check->charge(-5)
->withCurrency("USD")
->withAddress($address)
->execute();
}
catch (ApiException $e) {
// handle error
}
try {
check.charge(new BigDecimal("-5"))
.withCurrency("USD")
.withAddress(address)
.execute();
}
catch (ApiException e) {
// handle error
}
check.charge(-5)
.withCurrency("USD")
.withAddress(address)
.execute()
.catch((e) => {
switch (e.name) {
case ApiError.constructor.name:
default:
// handle error
break;
}
});
Please refer to our Error Handling section for more information on specialized types to narrowing the original cause of the exception.
Next Steps
Learn more about Heartland Ecommerce check payments with: