Payments
Helcim payments for GoCommerce
A Go package that opens a HelcimPay.js checkout session and marks the GoCommerce order paid only after reading the transaction back from Helcim — because Helcim’s webhook carries an id and a type, and nothing else.
- Payments module
- 5 settings
- 9 tests
- ext/payments-helcim
What it does
The module registers “helcim” as a payment method. At checkout it asks Helcim for a HelcimPay.js session — a purchase for the order’s total, with the order number as the invoice number — and answers with a client_action intent carrying the checkout token. The storefront loads Helcim’s script and opens the payment modal; that, the package says, is the one thing the module cannot do for it.
Helcim then calls POST /api/checkout/helcim/webhook. After verifying the signature, the module reads the transaction back from Helcim’s Card Transactions API, finds the order by its invoice number, and marks it paid only if it is an approved purchase for exactly the order’s amount and currency. A declined purchase marks the payment failed.
In the admin it describes itself as “Card payments through Helcim’s HelcimPay.js, with the verified webhook marking orders paid.” Helcim’s API takes decimal amounts; the package notes that Helcim settles in CAD and USD, both with two decimal places, so converting from the engine’s minor units is an exact division.
Configuration
Two settings are required: the API token and the webhook verifier token. 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 |
|---|---|---|---|
APITokenAPI token | HELCIM_API_TOKEN | Yes | A Helcim API access token, sent as the api-token header. Not sent to the storefront. |
VerifierTokenWebhook verifier token | HELCIM_VERIFIER_TOKEN | Yes | Base64, as Helcim shows it; the key webhook signatures are checked with. Required because, as the code puts it, without it any caller could mark orders paid. |
ServerIPServer IP for refunds | — | No | Helcim wants an ipAddress on every payment call, and a refund has no shopper, so this is the server’s. Defaults to 127.0.0.1. |
BaseURLAPI base URL | — | No | Overrides https://api.helcim.com/v2, for tests. Empty for production. |
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
- Add the webhookIn Helcim, point the webhook at https://your-api-host/api/checkout/helcim/webhook and copy its verifier token.
- Install and configurePass helcim.New to gocommerce.New as below, or run the reference binary with -gateways and fill in Settings › Payment methods.
- Load HelcimPay.jsOn the storefront, load Helcim’s script. POST /api/checkout/helcim answers with a client_action intent whose checkout_token opens the modal via appendHelcimPayIframe.
- Let the webhook settle itWhen the shopper pays, Helcim’s cardTransaction webhook arrives, the module reads the transaction back, and the engine marks the order paid.
main.go
import (
"os"
"github.com/itswadesh/gocommerce/core"
helcim "github.com/itswadesh/gocommerce/ext/payments-helcim"
)
app, err := gocommerce.New(cfg,
helcim.New(helcim.Config{
APIToken: os.Getenv("HELCIM_API_TOKEN"),
VerifierToken: os.Getenv("HELCIM_VERIFIER_TOKEN"),
}),
) The package doc’s own example, with its imports; cfg is your gocommerce.Config. With an empty helcim.Config the module installs idle and waits for the panel. Import path github.com/itswadesh/gocommerce/ext/payments-helcim.
How it works
-
Three signed headers
webhook-id, webhook-timestamp and webhook-signature: an HMAC-SHA256 over the id, the timestamp and the body, keyed on the decoded verifier token. Any v1 signature may match during a rotation; a timestamp more than five minutes off is refused.
-
The body proves nothing
Helcim’s webhook is an id and a type, so the module fetches the transaction before deciding anything. If that read fails, the claim is released and the webhook answers 500 for Helcim to retry.
-
Amount and currency must match
A transaction whose amount or currency differs from the order it names is logged as an error and not settled — left for an operator who can see both sides.
-
Only purchases settle
Preauths, verifies and refunds coming back round are acknowledged and change nothing, as are transactions whose invoice number names no order here — a terminal sale, say.
-
Each event once
Claims are keyed on event type plus id in the module’s own table. A redelivery is answered 200 and changes nothing.
-
Idempotent refunds
A refund posts to Helcim against the transaction id the webhook recorded, with an idempotency key built from the order and the amount, so a retried refund is the same request. Anything but APPROVED is an error.
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.
- The storefront loads the scriptThere is no page to redirect to. A storefront that does not load HelcimPay.js cannot take a payment through this module.
- CAD and USDThe conversion assumes two decimal places, which the package says covers the currencies Helcim settles in.
- Mismatches wait for a personA transaction for a different amount or currency is acknowledged and not settled. The order stays unpaid until an operator looks.
- Refunds need the transactionThe refund goes against the transaction id the webhook recorded. An order without one has nothing to refund against, and the module says so.
- Dashboard refunds are not appliedA refund made in Helcim reaches the webhook as a non-purchase transaction and does not change the GoCommerce order.
FAQ
Questions about the Helcim module
Why does the module call Helcim back on every webhook?
Because the webhook body is two fields, an id and a type — no amount, no invoice, no status. The package calls the second call not optional: a notification that says only that a transaction happened cannot settle an order on its own.
Does the shopper leave the storefront?
No. HelcimPay.js opens a modal in the page, so the module answers checkout with a checkout token rather than a redirect. The storefront has to load Helcim’s script to use it.
Which currencies work?
The package notes that Helcim settles in CAD and USD, and converts amounts on that basis — an exact division by 100. The store’s single settlement currency should be one of the two.
Is this a Helcim partnership?
No. The module calls Helcim’s public API with tokens you supply. Helcim 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-helcim in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.Helcim 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.