Skip to content

Authorize.Net

Authorize.Net CIM payment gateway with tokenized profiles. The extension registers a full-lifecycle payment strategy (authorize, capture, charge, refund, void) against Authorize.Net's JSON API, saves cards on file as CIM customer/payment profiles created from Accept.js opaque data, handles transactions held by Authorize.Net's Fraud Detection Suite (FDS), and receives Authorize.Net Webhook Notifications for async settlement. Choose it when your merchant account is with Authorize.Net and you want PCI-friendly Accept.js tokenization, stored payment profiles, and admin-side fraud-hold release.

At a glance

Extension id authorize_net
Category payment
Version 0.0.1
Provides Payment gateway strategy, saved-card (CIM profile) strategy, settlement webhook, GraphQL admin mutations
External account Authorize.Net account — API Login ID + Transaction Key required (plus a separate Webhook Signature Key for settlement webhooks and a public Client Key for the storefront Accept.js form)

What It Provides

  • Payment gateway strategy registered under the name authorize_net (PaymentProcessStrategy): authorize (authOnlyTransaction), capture (priorAuthCaptureTransaction), charge (authCaptureTransaction), refund (refundTransaction), and void (voidTransaction) via the JSON API. Sandbox mode targets https://apitest.authorize.net/xml/v1/request.api; production targets https://api.authorize.net/xml/v1/request.api. Authorize and charge requests carry the transaction's currencyCode (capture and refund send the default USD; void carries none).
  • Saved-card strategy registered under the same name (SavedPaymentMethodStrategy): CIM profile lifecycle — create a customer + payment profile from Accept.js opaque data, add a payment profile to an existing customer, create a profile from a completed transaction (createCustomerProfileFromTransactionRequest, the charge-first save path), delete payment profiles, and charge stored profiles. The unified core GraphQL fields — addPaymentMethod, removePaymentMethod, setDefaultPaymentMethod, listPaymentMethods, adminChargeSavedCard — dispatch to it by gateway name.
  • Token claim: the strategy claims any payload carrying the Accept.js opaque-data pair (opaque_data_descriptor + opaque_data_value), so checkout can infer the gateway from the tokenization shape; authorize_net is asked first at checkout when both token shapes are present. See Gateway Inference via Token Claims.
  • FDS fraud-hold handling: a gateway responseCode of 4 returns a held-for-review result carrying the triggered FDS filter names; the order enters HeldForReview. The adminReleaseFraudHold mutation approves the transaction via updateHeldTransactionRequest, marks the order's fraud status released and payment authorized, and transitions the order to AwaitingFulfillment. See Fraud Filter Handling.
  • Settlement webhook at POST /api/webhooks/payment/authorize_net: Authorize.Net Webhook Notifications (JSON, HMAC-SHA512 signed) for async settlement of eCheck/ACH and delayed-capture card events.
  • GraphQL admin mutations: adminCaptureTransaction, adminVoidTransaction, adminRefundTransaction, adminReleaseFraudHold, and adminTestGatewayConnection.

Setup

  1. Once installed (or dev-linked in development), the extension is discovered at startup via its vectis.extensions entry point. Enable it for a channel under Settings > Extensions.
  2. In the admin panel, open Settings > Payments and click Add Method; choose the Authorize.net gateway. See Configuring Payment Gateways.
  3. Enter the API Login ID and Transaction Key (secret — masked in the admin). If the payment-method config lacks them, the extension falls back to the AUTHNET_API_LOGIN_ID and AUTHNET_TRANSACTION_KEY environment variables.
  4. Enter the public Client Key (stored on the payment-method config as client_key; it is not part of the manifest config_schema). The storefront's Accept.js card form reads api_login_id and client_key from the config to tokenize card data in the browser.
  5. Leave Sandbox on while testing — it routes API calls to apitest.authorize.net, loads Accept.js from jstest.authorize.net, and creates CIM profiles with validationMode: testMode (production uses liveMode). The AUTHNET_SANDBOX environment variable (default true) is the fallback when the config doesn't set it.
  6. Click Test Connection. This runs the adminTestGatewayConnection mutation, which calls getMerchantDetailsRequest and reports the merchant name on success.
  7. For settlement webhooks, create a webhook in the Authorize.Net merchant interface pointing at https://<your-api-host>/api/webhooks/payment/authorize_net, and store its Webhook Signature Key — a credential separate from the API login/transaction key — in the Fernet-encrypted Setting payment.authorize_net.webhook_signature_key (see Operational Notes).

Configuration Reference

The manifest config_schema (values live on the payment-method row created in Settings > Payments):

Key Type Required Secret Description
api_login_id string yes yes Authorize.Net API Login ID, sent in merchantAuthentication on every API call. Falls back to the AUTHNET_API_LOGIN_ID env var when unset. Also read by the storefront Accept.js form.
transaction_key string yes yes Authorize.Net Transaction Key, sent in merchantAuthentication on every API call. Falls back to the AUTHNET_TRANSACTION_KEY env var. Stripped from the public payment-method type exposed to the storefront.
sandbox boolean no no Default true. Selects the sandbox vs. production API endpoint and the CIM profile validationMode. Falls back to the AUTHNET_SANDBOX env var.
checkout_save_mode string no no Default order_and_save; one of off, order_and_save, charge_and_save, save_first. Labeled "Save card at checkout" in the admin. Charge-first modes save via createCustomerProfileFromTransaction; save_first vaults via CIM before charging.
allowed_card_brands array no no Default ["visa", "mastercard", "amex", "discover"]. Enforced by core twice: against the client's brand hint before charging, and against the gateway-reported brand after (with a best-effort void on mismatch).
supported_currencies array no no Default ["USD"]. Enforced by core process_payment before any money moves; an empty list passes every currency.

Permissions

  • payment.authorize_net.manage

Manifest permissions are upserted at boot but carry no role assignments — assign them to roles manually. Independently of the manifest permission, the extension's admin mutations enforce core permissions at call time: order.update for capture/void/refund/fraud-hold release and settings.edit for the connection test.

Operational Notes

  • Webhook signature: deliveries are verified as HMAC-SHA512 of the raw body against the X-ANET-Signature header (sha512=<hex>), using the Webhook Signature Key from the merchant interface — not the API credentials. The secret is read Settings-first from the Fernet-encrypted Setting payment.authorize_net.webhook_signature_key, with the AUTHNET_WEBHOOK_SIGNATURE_KEY env var as a deprecated fallback that is backfilled into the Setting once at api boot; after the backfill this env var has no other readers and can be removed from the deployment. A missing secret returns HTTP 503 (so the gateway retries while you fix the config); a bad signature returns 401.
  • Events consumed: net.authorize.payment.capture.created, net.authorize.payment.priorAuthCapture.created, and net.authorize.payment.authcapture.created mark the tender settled; net.authorize.payment.fraud.declined and net.authorize.payment.void.created mark it bounced. Authorization-only events, refund receipts, and fraud-held notifications are ignored — those transitions are initiated by Vectis via the strategy. The delivery's notificationId is the dedup event id, so retries collapse to one effect.
  • Refunds need the card's last four: refundTransaction requires the masked card number, so adminRefundTransaction accepts a lastFour argument (default "0000"). Authorize.Net exposes no idempotency-key API on refunds; the Temporal RefundExecutionWorkflow persists per-tender progress before each gateway call as the guard against double refunds.
  • Duplicate-profile recovery: when CIM profile creation fails with a duplicate-profile error, the strategy extracts the existing profile id from the error text and attaches the new payment profile to that customer instead of failing the save.
  • Save-mode opt-in: with order_and_save, the card is saved only when a signed-in account customer ticks the save checkbox; charge_and_save and save_first save without an opt-in; guests never save.
  • Timeouts and concurrency: every gateway call uses a 30-second HTTP timeout, and split-tender authorizations run at the core default cap of 4 concurrent calls per gateway (not overridden by this extension).

For the payment lifecycle these strategies plug into, see Payments; for the strategy interfaces and gateway walkthrough, see Building Extensions. The NMI counterpart is documented at NMI Gateway.