Search for keywords, like "PayPal", "Recurring Donations", and more.

Documentation / Developer Docs / How to Build a Gateway Add-on for GiveWP

How to Build a Gateway Add-on for GiveWP

GiveWP has a robust Payment Gateway API that allows developers to integrate their payment gateway of choice into GiveWP. This article (in conjunction with the example payment gateway add-on code repository) will walk you through the steps of creating a basic GiveWP add-on to integrate with any payment gateway. 

Why Have a Gateway API?

The goal of the Payment Gateway API is to allow developers a way to integrate a new payment gateway, without having to know everything about GiveWP’s internals. In GiveWP, adding a new payment gateway should not involve decisions around form design, donor management or database structure. The interaction with the gateway should handle a simple yes or no answer to questions like these:

  1. Did the transaction go through?
  2. Did the refund process successfully?
  3. Was the payment information successfully updated?
  4. Was the recurring donation updated? 

The Payment Gateway API aims to let the gateway focus on what it does best: processing transactions. Related GiveWP functionality like creating a donor and completing a donation will be handled automatically, based on having predictable data returned from the gateway. That’s what the API does: standardizes that data so that GiveWP can handle the rest. 

As a third-party developer, you’ll need to be an expert on what the gateway needs to answer the above questions (and others like it), and not get as involved with what happens as a result of those answers, because GiveWP handles that for you, with the Payment Gateway API.

Introducing the Example Gateway Add-on

To integrate your payment gateway with GiveWP, you’ll be creating a WordPress plugin that is identified as a GiveWP add-on.

Want to skip the line and see a functional example? The GiveWP team has provided an example plugin that will show you how all of the pieces and concepts outlined in this documentation fit together.

This document will introduce you to a few potential “gotchas” to avoid, as well as some concepts that are unique to the GiveWP Payment Gateway API.

GiveWP Payment Gateway API Concepts

To understand what’s going on under the hood of the Payment Gateway API, the following concepts are fundamental:

  • Naming
  • The Donation Model
  • Gateway Routing
  • Commands
  • Error Handling

Naming

OK, so this is less of a feature of the Payment Gateway API, but it’s a gotcha that might derail you before you’ve even started, so it’s worth mentioning a few things about WordPress plugin development best practices that you’ll see going on in the Example Gateway plugin’s main file.

  1. Name it with “GiveWP” at the end of the name, not the beginning. This signifies that it’s not an official add-on for GiveWP.
  2. Include a Header comment in that main file. (read more about the format and requirements of WordPress Plugin header requirements in the official Plugin Developer’s Handbook)
  3. Ensure that all GiveWP-specific functionality loads after GiveWP has been initialized by including the class in an appropriate action. The hook you’re looking for is givewp_register_payment_gateway

Now, on to the good stuff.

The Donation Model

The Donation Model is an important piece to understand in order to get the data that you’ll need to process the donation at the gateway. See the entire list (including types) of the data sent via the Donation Model within the GiveWP code itself. While you’re there, poke around in the /Models/ and /Donation/ directories to learn more about things like ValueObjects as they relate to Donations. They are well-documented and fairly self-explanatory.

One important thing to note about the donation model is that changing something (status, for example) doesn’t do anything, unless you use the save() method as well. See that in action in the example plugin.

One other thing to note is that the Donation Model is strictly typed. That means that if your add-on tries to return something to one of those properties and it’s the wrong type (for example, if you try to return an integer for the name property, which expects a string), the donation model will throw an error. That’s very helpful for preventing those annoying bugs that hide behind a mis-typed bit of data, but it can also be a gotcha as you are developing your add-on.

Two bits of data that deserve special attention within the Donation Model are the amount and the currency.

Handling Amount and Currency

There’s some nuance to how GiveWP handles monetary amounts, designed to make it as flexible as possible. Within the amount data, you can call various functions to get either the “minor amount” (the smallest unit of a given currency) or the “decimal amount.” 

For example, given a donation of 50 US Dollars, the “minor amount” is “5000” (pennies). The Decimal amount is “50.00” in that case. There are two functions you need to get those two values for use with your gateway:

  1. $donation->amount->formatToMinorAmount() 
  2. $donation->amount->formatToDecimal()

To get the currency, here’s a similar “cheat code:”

  1. $donation->amount->getCurrency()->getCode()

That will return “USD” in the case of US Dollars.

Gateway Routing

To process a donation, GiveWP needs to securely communicate between the server (where all the GiveWP code lives), the front end/browser (on the donor’s computer, phone, etc), and the gateway itself. To do that predictably, the Payment Gateway API introduces the concept of Routing. This is essentially a way for you to create a tunnel directly from one of those three places to another, and not have to worry about WordPress code or other code being able to interact with it.

Two ways to do that are the routeMethod and secureRouteMethod. As you might guess, the secureRouteMethod adds additional security.

See the offsite gateway within the example add-on for an example of a secureRouteMethod.

In step one of the createPayment function there, it creates a secure return url, using the generateSecureGatewayRouteUrl method. Then it supplies the generateSecureGatewayRouteUrl function with three parameters: the name of the custom route method, the donation ID, and an array of data to use to pass to the gateway to finish processing the payment.

The first parameter of that method is a call to handleCreatePaymentRedirect. That’s the secureRouteMethod.

The handleCreatePaymentRedirect method holds the code you’d want to run on a successful donation. That code won’t run at all until GiveWP confirms that a signature is valid and has not expired. So things like updating the status in GiveWP of the donation, etc, are protected from any nefarious attempts to be triggered externally. All of the code inside that secure route is, well, secure.

Commands

A command is a way of telling the Payment Gateway API, “hey, something happened!” without having an opinion about how that will be processed or what will result from it. Commands are the true core of the Payment Gateway API, in that they allow you to say things like “The payment was completed” without concern for what needs to happen on the GiveWP side of things.

There are various commands that can be returned within your payment gateway class. When returning a PaymentComplete within the createPayment method, for example, the gateway is saying, “You should know the payment worked and is complete. I don’t really care what you do next.” In case you’re curious, what the gateway API does next is to mark the donation as complete, which triggers a donation receipt email. The fantastic part about it is that you don’t have to care either. Just tell GiveWP that it happened and is complete, and the API handles the rest.

Another example is RespondToBrowser, which is in essence “I have a message for the browser and I don’t care how you get the message there.”

This as opposed to doing something like die('hey browser!') — which is explicitly killing the request and responding. RespondToBrowser is useful for gateways that require adding in a payment intent or similar to then be sent to the gateway during the donation flow.

Here are a few more commands, with their translation:

  • PaymentAbandoned: “We never heard back from the gateway, and it’s been a while. This likely didn’t get processed.”
  • PaymentProcessing: “We heard back from the gateway that they received everything, but there’s a significant delay before we’ll hear back that the payment was successful.” (this command triggers a Donation Processing email notification to the donor)
  • PaymentRefunded: “The payment has been refunded on the gateway side. Do with that information what you wish.”
  • RedirectOffsite: “The form was successfully submitted, and information sent off to an offsite gateway.” (this command creates a pending donation on the GiveWP side)

Here’s a bit more on the RedirectOffsite command, because that’s a significant departure from the other commands specifically built for gateways (like PayPal Standard) where the donor is taken to the gateway to complete the transaction, and then delivered back to the site.

The RedirectOffsite command needs a Gateway URL. The example plugin uses example.com, which if you’re testing it you can see the resulting gatewayUrl once you click through a donation form. Here’s what that might look like if your domain was at customgateway.local alongside the other example gateway code.

Example GatewayURL

https://example.com/?merchant_id=000000000000000000000&merchant_key=111111111111111111111&cancel_url=http://customgateway.local/donations/one-time-form/?giveDonationAction=failedDonation&notify_url=http://customgateway.local/?give-listener=Example&name_first=Bob&name_last=Smith&email_address=bob@example.com&m_payment_id=107&amount=100.00&item_name=One%20time%20Form&item_description=Donation%20via%20GiveWP,%20ID%20107&return_url=http://customgateway.local?give-listener=give-gateway&give-gateway-id=example-test-gateway-offsite&give-gateway-method=handleCreatePaymentRedirect&givewp-donation-id=107&givewp-success-url=http%3A%2F%2Fcustomgateway.local%2Fdonations%2Fone-time-form%2F%3FgiveDonationAction%3DshowReceipt&givewp-gateway-transaction-id=123456789&give-route-signature=37938816021911863933f2e480ac90f9&give-route-signature-id=107&give-route-signature-expiration=1680808828

From that long URL, you can see a lot about what’s happening, by stepping through the various parameters. The return_url query variable contains the name of the secure route, along with the route signature and expiration.

Error Handling

The Onsite Gateway in the Example plugin shows off how to catch and process errors, by throwing a PaymentGatewayException and passing in the error message. There’s also an example of adding a donation note during that failed donation. Those errors are logged in the GiveWP logs.

Conclusion

The Payment Gateway API within GiveWP allows third-party developers to create payment gateway integrations without having to become experts in the internals of GiveWP.

So hop in! Use the Example Add-on, and hit up the GiveWP team with any questions as you build out your Payment Gateway add-on.

Stay tuned for documentation on how to use the Payment Gateway API for refunds and for Recurring Donations.

Last updated 1 year ago

Start Fundraising Better Today!

Get GiveWP Today
GiveWP Plans

Give Fundraising Newsletter

The Give Fundraising Newsletter will help you navigate the world of online fundraising like a pro. Each week we send out fundraising advice, Give LIVE announcements, and exclusive offers to our newsletter subscribers.