Elastic Path offers several types of payment options: credit cards, gift certificates, PayPal, and Google Checkout. The specific implementation of a payment type is referred to as a payment gateway. New payment types can be added, but a common requirement is to support a new credit card processor. This is the external service used to process your credit card transaction requests. Out of the box, Elastic Path includes support for CyberSource, Verisign, and Authorize.net, as well as a dummy gateway for use during development.
This post will show how to add a credit card payment gateway to your implementation.
The most difficult aspect is understanding the processor's requirements and communication protocol. Every processor has its own requirements, so you will need to fefer to the developer documentation for your credit card processor for more information on your processor.
There are several issues to consider when implementing a gateway for a credit card processor:
- Pre-authorization
- Settlements, referred to as Captures
- Refunds
- Voiding transactions
- Supported credit cards
The Elastic Path framework includes a PaymentGateway interface and a CreditCardPaymentGateway interface, as well as corresponding implementations that cover offer support for all credit card transactions.
The CreditCardPaymentGateway also supports 3D Secure authentication, such as Verified-By-Visa and SecureCard from MasterCard with the following methods:
checkEnrollment | Used to determine whether or not a credit card account has been enrolled in a 3D Secure Service. |
validateAuthentication | Used to verify the card holder's authentication after they have been redirected back to your site from the processor's verification site. |
The Elastic Path storefront already makes use of these methods. Simply implement them to take advantage of the services.
Extend the AbstractCreditCardPaymentGatewayImpl and create your credit card payment gateway class as in the following code:
@Entity
1) @DiscriminatorValue("paymentGatewayMyProcessorNameHere")
public class MyProcessorNameHerePaymentGatewayImpl extends AbstractCreditCardPaymentGatewayImpl implements CreditCardPaymentGateway {
2) private String type = "paymentGatewayMyProcessorNameHere";
@Basic
@Column(name = "TYPE", insertable = false)
public String getType() { return type; }
protected void setType(final String type) { this.type = type; }
3) protected Set<String> getDefaultPropertyKeys() {
Set<String> defaultPropertyKeys = new TreeSet<String>();
defaultPropertyKeys.add("merchantId");
defaultPropertyKeys.add("username");
defaultPropertyKeys.add("password");
return defaultPropertyKeys;
}
4) public void preAuthorize(final OrderPayment payment, final Address billingAddress) {
5) String merchantId = getPropertiesMap().get("merchantId").getValue();
6) OrderShipment orderShipment = payment.getOrderShipment();
int number = 0;
for (OrderSku orderSku : orderShipment.getShipmentOrderSkus()) {
addItemToRequest(request, number, orderSku);
number++;
}
7) Order order = orderShipment.getOrder();
addOrderDetailsToRequest(order);
...
}
8) public void capture(final OrderPayment payment) {
...
}
9) public void sale(final OrderPayment payment, final Address billingAddress) {
...
}
10) public void refund(final OrderPayment payment, final Address billingAddress) {
...
}
11) public void reversePreAuthorization(final OrderPayment payment) {
...
}
12) public void voidCaptureOrCredit(final OrderPayment payment) {
...
}
13) public PayerAuthenticationEnrollmentResult checkEnrollment(
final ShoppingCart shoppingCart, final OrderPayment payment) {
...
}
14) public boolean validateAuthentication(final OrderPayment payment, final String paRes) {
...
}
}
- The DiscriminatorValue must be set to the value specified for the gateway's type property.
- The type property must be set to a value unique among all payment gateways.
- getDefaultPropertyKeys must implemented to return a Set of property keys. The Set can be empty if there are no properties.
- The preAuthorize method must be implemented to make a pre-authorization transaction request to the payment processor.
- Properties can be accessed from the gateway's properties map.
- Access the shipment details through OrderPayment's orderShipments property.
- Access the order details through the order property of OrderPayment's orderShipment.
- The capture method must be implemented to make a settlement transaction request to the payment processor.
- The sale method must be implemented. Its purpose is to perform a combination of pre-authorization and capture at the same time. Some processors offer such a transaction. If not, then this method could make pre-authorization and capture transaction requests
However, there is currently no logic using it in Elastic Path. So, it can be ignored - The refund method must be implemented to make refund transaction requests to the processor.
- The reversePreAuthorization method must be implemented to make transaction requests to the processor that reverse the pre-authorization.
Some credit card processors support this feature, but others do not. Refer to your processor's developer documentation for more information. - The voidCaptureOrCredit method must be implemented to make transaction requests to the processor that void a previous capture or credit transaction. Void transactions typically only work on transactions made the same day.
- The checkEnrollment method must be implemented to make requests to the processor to determine whether or not a credit card has been enrolled in the 3D Secure program.
- The validateAuthentication method must be implemented to make requests to the processor to verify a 3D Secure payment response after the customer has authenticated themselves on the processor's 3D Secure server.
Error Handling
Errors occasionally happen. With credit cards, they can frequently happen. Elastic Path implements several exceptions to account for the most common problems. These exceptions should be thrown from the preAuthorize or capture methods when appropriate.
CardDeclinedException | Thrown when the card number is declined. |
CardExpiredException | Thrown when the card has expired. |
CardErrorException | Thrown for any "generic" errors. |
InsufficientFundException | Thrown when the card account does not have sufficient funds to cover the request. |
InvalidAddressException | Thrown when the processor determines the billing address is invalid. |
AmountLimitExceededException | Thrown when the card has exceeded its limit. |
InvalidCVV2Exception | Thrown when the CVV number supplied is invalid. |
To add your own exceptions, extend one of the following exception classes, and throw it as appropriate:
PaymentProcessingException | Extended for general processing errors such as insufficient funds. |
CardErrorException | Extended for card errors, such as declined. |
Configuring the Payment Gateway Factory
In order to use your new credit card gateway, you'll need to make the payment gateway factory aware of it. The paymentGatewayFactory bean defined in the domainModel.xml file must include a new entry.
<bean id="paymentGatewayFactory"
class="com.elasticpath.domain.payment.impl.PaymentGatewayFactoryImpl">
<property name="paymentGateways">
<map>
...
<entry key="paymentGatewayMyProcessorNameHere">
<value>
com...MyProcessorNameHerePaymentGatewayImpl
</value>
</entry>
...
</map>
</property>
</bean>
The entry's key must be set to the payment gateway's type property that was specified in the implementation class.
Using the Payment Gateway
To use your new credit card gateway implementation, you will first need to create a new payment gateway configuration in the CM Client, and then configure your store to use it.
In the CM Client:
- Open the Configuration activity
- Select Payment Gateways
- Click Create Gateway
- Type in your gateway name
- Select your new gateway implementation the Type dropdown
To use the new payment gateway in your store:
- Open the Configuration activity
- Select Stores
- Edit your store
- Select the Payments tab
- Select your new Payment Gateway in the Credit Card Payment Gateway dropdown
- Choose the options for enabling the CCV value, saving credit card numbers, and the supported card types.
Caveats
Many processors will provide a testing infrastructure. Occasionally, this means a test merchant account, test card numbers, and possibly a different URL from what should be used in production. Refer to your processor's development documentation to understand how to test it. When moving to production, the first thing you will want to do is to test it. This means using a live credit card. There aren't many ways around this. However, you should have access to a console to manage your merchant account, and be able to cancel any transactions.