Payments
Adyen payments for GoCommerce
A Go package that sends the shopper to an Adyen payment link and marks the GoCommerce order paid when Adyen’s HMAC-signed AUTHORISATION notification arrives — not before. Four required settings, one of which, the endpoint, deliberately has no default.
- Payments module
- 6 settings
- 8 tests
- ext/payments-adyen
What it does
The module registers “adyen” as a payment method. At checkout it creates an Adyen payment link for the order’s total, in minor units, with the order number as Adyen’s merchant reference, and answers with a redirect intent carrying the link’s URL.
Adyen then calls POST /api/checkout/adyen/webhook with a batch of notifications. Every item’s signature is checked before any of them is acted on; a successful AUTHORISATION marks the order paid and a refused one marks the payment failed. The package is plain about why it waits: Adyen answers a payment or a refund with “received” and says what happened in a later notification, so notifications are the source of truth and no API response is treated as settlement.
In the admin it describes itself as “Card and local payments through Adyen’s Checkout API, with the HMAC-signed notification marking orders paid.” It chooses payment links over Drop-in on purpose: Drop-in is a better checkout, the package says, but it needs Adyen’s JavaScript, a /sessions call and a client key on the storefront, and a module cannot dictate the storefront.
Configuration
Four settings are required: the API key, the merchant account, the webhook’s HMAC key and the Checkout API endpoint. Set them in Config from your own main(), or leave Config empty and fill them in under Settings › Payment methods.
| Setting | Environment variable | Required | What it does |
|---|---|---|---|
APIKeyAPI key | ADYEN_API_KEY | Yes | An API credential’s key, sent as the X-API-Key header. Not sent to the storefront. |
MerchantAccountMerchant account | ADYEN_MERCHANT_ACCOUNT | Yes | The account every payment link and refund is created against. |
HMACKeyWebhook HMAC key | ADYEN_HMAC_KEY | Yes | The hex key generated for the webhook in Adyen’s Customer Area. Required because, as the code puts it, without it any caller could mark orders paid. |
BaseURLCheckout API base URL | — | Yes | The endpoint including its version segment: https://checkout-test.adyen.com/v71 for test, your own merchant-prefixed host for live. No default. |
ReturnURLReturn URL | — | No | Where the shopper lands after paying, when the checkout request did not send a return_url of its own. |
Client | — | No | Replaces the HTTP client, which otherwise times out after 20 seconds. Go only; not in the panel. |
The module reads its Config struct, not the environment. The variable names are the ones the package’s own example or the reference binary uses; in your own main() you choose where each value comes from. Where a setting has a panel label, the admin’s settings drawer can hold it too, and a value typed there wins over Config.
Setting it up
- Set up the webhookIn Adyen’s Customer Area, point a webhook at https://your-api-host/api/checkout/adyen/webhook and generate its HMAC key.
- Choose the endpointTest is https://checkout-test.adyen.com/v71. Live is your own prefixed host, https://{prefix}-checkout-live.adyenpayments.com/checkout/v71 — the module will not guess it.
- Install and configurePass adyen.New to gocommerce.New as below, or run the reference binary with -gateways and fill in all four settings under Settings › Payment methods.
- Take a paymentPOST /api/checkout/adyen answers with a redirect intent whose url is the payment link. The AUTHORISATION notification marks the order paid.
main.go
import (
"os"
"github.com/itswadesh/gocommerce/core"
adyen "github.com/itswadesh/gocommerce/ext/payments-adyen"
)
app, err := gocommerce.New(cfg,
adyen.New(adyen.Config{
APIKey: os.Getenv("ADYEN_API_KEY"),
MerchantAccount: os.Getenv("ADYEN_MERCHANT_ACCOUNT"),
HMACKey: os.Getenv("ADYEN_HMAC_KEY"),
BaseURL: "https://checkout-test.adyen.com/v71",
}),
) The package doc’s own example, with its imports; cfg is your gocommerce.Config. The test endpoint is written in because Adyen’s live URL carries your own prefix. Import path github.com/itswadesh/gocommerce/ext/payments-adyen.
How it works
-
Payment links, not Drop-in
Checkout creates a link with POST /paymentLinks: the amount in minor units, the order number as reference, and the shopper’s email and two-letter country when the order has them. The storefront only redirects.
-
Every item verified first
Adyen signs eight fields of each notification item — PSP reference, original reference, merchant account, merchant reference, amount, currency, event code and success — with the HMAC in additionalData. One forged item rejects the whole batch.
-
Only signed fields pick the order
The order is found from merchantReference, which the HMAC covers, not from the metadata Adyen echoes back, which it does not. A valid signature for one payment cannot settle somebody else’s order.
-
Each event once
Claims are keyed on event code plus PSP reference in the module’s own table, so a retry is a duplicate and two different events about one payment stay distinct. The handler answers [accepted], which is what stops Adyen retrying.
-
A failed update is retried
If the engine cannot apply a notification, the claim is released and the webhook answers 500, so Adyen’s retry finds work to do.
-
Refunds by PSP reference
A refund posts to Adyen against the PSP reference the AUTHORISATION recorded, for the amount asked, and keeps the reference Adyen returns. A later REFUND notification that failed is logged as an error for an operator to reconcile.
What it does not do
Read these before an order depends on it. No store is known to run GoCommerce in production yet, so these come from the code, not from anyone’s experience.
- No default endpointUntil BaseURL is set, the module does not count as configured. The package chose that over a test default that would turn a misconfigured live store into one taking pretend money.
- Redirect onlyNo Drop-in or Components. A store that wants Adyen’s in-page checkout builds it on its storefront; this module only creates payment links.
- Paid on authorisationA successful AUTHORISATION marks the order paid. The module sends no capture and reads no CAPTURE event; if your account captures manually, that happens in Adyen.
- Refunds wait for the notificationThe refund is issued against the PSP reference the AUTHORISATION notification wrote. Before that arrives, the order has nothing to refund against.
- Chargebacks are only loggedCHARGEBACK, NOTIFICATION_OF_CHARGEBACK and SECOND_CHARGEBACK are logged as warnings. The engine has no chargeback state, so the order does not change.
- Failed refunds are not undoneA REFUND notification with success=false, after the engine recorded the refund, is logged and nothing more. The two sets of books need a person to reconcile them.
FAQ
Questions about the Adyen module
Why does the module have no default endpoint?
Adyen’s live Checkout endpoint is prefixed with your own merchant identifier, so there is no live URL the package could know. It chose no default over a test default: a store that has not said which environment it means does not come up taking pretend money.
What is the webhook URL?
POST /api/checkout/adyen/webhook on the host that serves your GoCommerce API. The module answers [accepted] once every item in a batch is verified and applied.
Can the shopper pay without leaving the storefront?
Not through this module. It creates payment links and the storefront redirects to them. Adyen’s Drop-in needs its JavaScript, a /sessions call and a client key on the storefront, which the package leaves for a store to build.
Can I use it without writing Go?
Yes. The reference binary’s -gateways flag installs every payment module with an empty Config. Switch Adyen on under Settings › Payment methods and fill in the four settings, the endpoint included.
Is this an Adyen partnership?
No. The module calls Adyen’s public Checkout API with credentials you supply. Adyen does not endorse GoCommerce, and no store is known to run this module in production yet.
Source
Everything on this page is read from ext/payments-adyen in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.Adyen is a trademark of its owner; this module talks to its public API and implies no endorsement. See trademarks.
Try it against a store of your own
The one-command stack gives you GoCommerce’s API and admin on your own machine in minutes. Add this module to it and try it on test orders before a real one depends on it.