Skip to main content

Coinbase Commerce

Coinbase Commerce is a crypto payment gateway that lets your store accept payment in major cryptocurrencies directly to a self-custody wallet. Customers pay in Bitcoin (BTC), Ethereum (ETH), USD Coin (USDC), Dogecoin (DOGE), Litecoin (LTC), DAI, or Bitcoin Cash (BCH) — the plugin surfaces all supported currencies at checkout. Because payments settle on the blockchain rather than through a bank, there are no chargebacks, and funds arrive in your Coinbase Commerce wallet without a traditional payment processor sitting in the middle.

This plugin is a separate add-on available from the J2Commerce Extensions Store. It is not included with the core J2Commerce component.


Important Notice — Coinbase Commerce Sunset (November 2024)

Existing merchants only

Coinbase announced in late 2024 that the hosted Commerce checkout is no longer available to new merchants. If you created a Coinbase Commerce account before the sunset date, your account and API access remain fully functional — this plugin continues to work for you without any changes required.

If you are setting up a new store, Coinbase Commerce is not an option for you. Consider these alternatives that are still open for new sign-ups:

  • NOWPayments — multi-coin processor with hosted and API modes
  • BTCPay Server — self-hosted, open-source, no fees
  • OpenNode — Lightning Network–focused Bitcoin processor

Prerequisites

Before configuring the plugin, make sure you have:

  • A Coinbase Commerce account created before the November 2024 sunset
  • Your API Key — found at commerce.coinbase.com/dashboard/settings under the API keys tab
  • Your Webhook Shared Secret — displayed when you create a webhook endpoint in the same settings page (the secret is shown only once, so copy it immediately)
  • J2Commerce installed and configured with at least one product and a working checkout

Installation

This plugin is a separate add-on available from the J2Commerce Extensions Store.

  1. Purchase and download the plg_j2commerce_payment_coinbase.zip package from the J2Commerce website.
  2. Go to System -> Install -> Extensions.
  3. Upload the plg_j2commerce_payment_coinbase.zip file using the Upload Package File tab.
  4. The plugin installs automatically.

Enabling the Plugin

After installation the plugin is disabled by default.

  1. Go to System -> Manage -> Plugins.
  2. Search for Coinbase in the filter bar.
  3. Click the red circle next to J2Commerce - Payment - Coinbase Commerce to enable it (turns green).

Configuration

tip

Click the Toggle Inline Help button in the toolbar and the app will show a description below each field as you configure it.

Once enabled, open the plugin to configure it.

  1. Go to J2Commerce -> Payments -> Payment Methods.
  2. Find Coinbase Commerce and click its name to open the settings.

Work through each field in order.

Display Settings

FieldWhat it doesRecommended value
Display NameThe payment option label shown at checkoutCoinbase Commerce (BTC, ETH, USDC, DOGE, LTC, etc.) or your preferred shorter label
Display ImageOptional logo shown next to the payment name at checkoutUpload from media/plg_j2commerce_payment_coinbase/images/payment_coinbase.webp, or leave blank

Coinbase Payment Mode

FieldDescriptionOptions
Coinbase Payment ModeControls how the customer paysRedirect (hosted on Coinbase) or Modal (on your site)

See Choosing Redirect vs Modal below for guidance on which to choose.

API Credentials

FieldWhat to enterRequired
Coinbase Commerce API KeyThe API key from your Coinbase Commerce dashboard settingsYes
Coinbase Webhook Shared SecretThe shared secret shown when you add a webhook endpoint in Coinbase CommerceYes — without it, webhooks are silently rejected and orders will not update
Your Webhook EndpointsRead-only field. Displays the two URLs to paste into Coinbase Commerce

Order Status

These three fields control what J2Commerce order status is assigned when Coinbase reports each payment event.

FieldDefaultWhen it triggers
Confirmed StatusConfirmed (1)Coinbase reports charge:confirmed or charge:resolved
Pending StatusPending (4)Coinbase reports charge:pending (awaiting blockchain confirmation)
Failed StatusFailed (3)Coinbase reports charge:failed

The defaults match the standard J2Commerce order status IDs and work for most stores. Change them if you use custom order statuses.

Note on charge:resolved: Coinbase uses this event when a charge was overpaid or underpaid and a Coinbase support agent has manually resolved it. The plugin treats charge:resolved the same as charge:confirmed — both move the order to your Confirmed Status. This is the correct behavior for almost all cases.

info

NOTE: If the status you want isn't listed in the dropdown menu, you can create a new one by going to J2Commerce -> Setup -> Order Statuses

Surcharge (Optional)

You can add an optional processing fee when customers choose Coinbase as their payment method. Leave both fields empty if you do not want a surcharge.

FieldDescriptionExample
Surcharge NameLabel shown on the order for the feeCrypto processing fee
Surcharge PercentPercentage of the order total (before the fixed fee)1.5
Surcharge FixedFlat fee added in addition to the percentage0.50
Surcharge Tax ClassTax profile to apply to the surcharge amountLeave blank if the surcharge is not taxable

Availability Restrictions (Optional)

Use these to limit when Coinbase Commerce appears as a payment option.

FieldDescriptionExample
Minimum SubtotalHide this payment method if the cart subtotal is below this amount10.00
Maximum SubtotalHide this payment method if the cart subtotal exceeds this amount5000.00
Geozone RestrictionLimit availability to customers in a specific geozoneSelect a geozone, or leave blank for all countries

Custom Messages

These fields accept plain text or HTML and appear at specific points in the checkout flow.

FieldWhen it appears
On SelectionWhen the customer selects Coinbase as their payment method
On Before PaymentJust before the payment form is shown
On After PaymentAfter the customer returns from Coinbase (success page)
On Error PaymentIf a payment error occurs
On Cancel PaymentIf the customer cancels and returns without paying

Thank You Article

You can select a Joomla article to display on the post-payment success page. Leave blank to use the default confirmation message.

Button Text

The Button Text field customises the label on the "Place Order" button. The default value is Place Order.

Debug Logging

FieldDescriptionDefault
Debug LoggingWrites detailed request and response data to administrator/logs/plg_j2commerce_payment_coinbase.phpNo

Enable this only when diagnosing a problem. Disable it again in production — log files can grow large and may contain transaction data.


Choosing Redirect vs Modal

The Coinbase Payment Mode field gives you two checkout experiences.

The customer is sent to a Coinbase-hosted payment page and returns to your store after paying.

Pros:

  • Coinbase maintains the payment UI — no CSS work required on your end
  • Works reliably across all browsers and devices
  • Handles the countdown timer and multi-currency display natively

Cons:

  • The customer briefly leaves your site
  • You have no control over the visual design of the payment page

Use this if you want the simplest setup, or if you are not confident testing modal overlays across browsers. It is the default, and the right choice for most stores.

A payment overlay appears inline on your checkout page. The customer can see the crypto address, copy it, pick a different coin, and confirm payment without navigating away.

Pros:

  • The customer never leaves your store
  • Crypto addresses are copyable directly from your checkout page
  • Better for customers who prefer to copy addresses manually into their wallet app

Cons:

  • Requires more cross-browser testing
  • CSS may need adjustments depending on your template
  • If JavaScript fails to load, the customer sees a fallback form instead of the modal

Use this if your customer base is technically comfortable with crypto, or if keeping the customer on-site is a priority for your conversion rate.


Webhook Configuration

Webhooks are how Coinbase Commerce tells your store that a payment has been confirmed, is pending, or has failed. Without a working webhook, orders stay in their initial state regardless of what happens on the blockchain.

Step 1: Copy Your Webhook URL

In the plugin settings, the Your Webhook Endpoints field displays two URLs.

  • Primary endpoint — matches the checkout confirmation URL pattern used by J2Commerce
  • Alternate endpoint (com_ajax) — routes through Joomla's com_ajax handler; use this if URL rewriting causes problems

Copy the Primary endpoint URL first. It looks like:

https://yoursite.com/index.php?option=com_j2commerce&view=checkout&task=confirmPayment&orderpayment_type=payment_coinbase&paction=process&tmpl=component

Step 2: Add the Endpoint in Coinbase Commerce

  1. Log in to commerce.coinbase.com/dashboard/settings.
  2. Scroll to Webhook subscriptions.
  3. Click Add an endpoint.
  4. Paste the Primary endpoint URL from the plugin settings.
  5. Click Save.

Coinbase will display a Shared Secret — copy it immediately, as it is shown only once.

Step 3: Save the Shared Secret

  1. Return to the Coinbase plugin settings in your Joomla admin.
  2. Paste the shared secret into the Coinbase Webhook Shared Secret field.
  3. Click Save (or Save & Close).

Step 4: Test the Webhook

Back in your Coinbase Commerce settings, use the Send test webhook button to send a test event to your endpoint. The plugin should return one of these responses:

ResponseMeaning
Ok, ProcessedWebhook arrived, signature verified, order updated
IPN Ok (ignored event type)Webhook arrived but the event type is informational only (e.g., charge:created) — no action needed
IPN MisconfiguredThe webhook secret field in the plugin is empty
IPN RejectedSignature verification failed

A test webhook from Coinbase uses a synthetic event type that the plugin receives but does not act on — you will see IPN Ok (ignored event type). That is correct.

If the Primary Endpoint Does Not Work

Some URL rewriting plugins (sh404SEF, JoomSEF, Route66) and web application firewalls (Cloudflare, mod_security) intercept requests at the primary URL and strip the X-CC-Webhook-Signature header that Coinbase includes.

If you see IPN Rejected and your shared secret is definitely correct:

  1. Switch to the Alternate endpoint (com_ajax) URL instead.
  2. Update the endpoint URL in your Coinbase Commerce dashboard.
  3. Test again.

The com_ajax URL bypasses template and SEF routing, making it more compatible with aggressive URL rewriting.


Order Status

info

NOTE: If the status you want isn't listed in the dropdown menu, you can create a new one by going to J2Commerce -> Setup -> Order Statuses

When Coinbase sends a webhook to your store, the plugin maps the event type to an order status.

Coinbase EventWhat it meansDefault Order Status
charge:pendingPayment broadcast to the network; waiting for blockchain confirmationsPending (4)
charge:confirmedEnough confirmations received; payment is trustworthyConfirmed (1)
charge:resolvedCharge was overpaid or underpaid; manually resolved by CoinbaseConfirmed (1)
charge:failedThe charge window expired or payment did not arriveFailed (3)

Events like charge:created and charge:delayed are received and acknowledged but do not trigger a status change. The plugin responds IPN Ok for those events.


Surcharges and Subtotal Limits

Adding a Processing Fee

If you want to pass on a small handling fee to customers who pay with crypto:

  1. Enter a label in Surcharge Name (e.g., Crypto network fee).
  2. Enter a percentage in Surcharge Percent (e.g., 1 for 1%) or a fixed amount in Surcharge Fixed (e.g., 0.50).
  3. You can combine both — the percentage is calculated first, then the fixed amount is added.
  4. If the fee is taxable, select a tax class in Surcharge Tax Class.

Restricting to Certain Order Sizes

If you only want Coinbase Commerce available for orders above or below certain amounts:

  • Set Minimum Subtotal to hide the payment option for small orders (e.g., set to 50.00 to require at least $50).
  • Set Maximum Subtotal to hide it for very large orders (e.g., 2000.00 if you want to verify large transactions manually).

Leave both fields empty to allow all order sizes.


Testing the Payment Flow

Coinbase Commerce provides a sandbox environment through their dashboard. To test without real money:

  1. In your Coinbase Commerce dashboard, switch to a test environment if available for your account type.

  2. Place a test order on your store and select Coinbase Commerce as the payment method.

  3. Depending on your mode setting:

    • Redirect — you are taken to the Coinbase hosted checkout page
    • Modal — the crypto address overlay appears on your checkout page
  4. Complete the test payment.

  5. Verify in J2Commerce -> Sales -> Orders that the order has:

    • A Transaction ID (the Coinbase charge code, e.g., ABCD1234)
    • An updated Order Status matching your Confirmed Status setting
  6. Check the order history tab on the order to confirm the webhook arrived and recorded the event.


What's New in J2Commerce 6

This plugin was fully rewritten for J2Commerce 6. If you used the J2Store v4 version of this plugin, here is what changed:

  • No jQuery — the modal checkout UI uses vanilla JavaScript. No jQuery dependency.
  • HMAC signature verification uses PHP's constant-time hash_equals function, preventing timing-based attacks against the webhook secret comparison.
  • HTTP requests use Joomla's built-in HttpFactory instead of raw cURL calls, making the plugin compatible with any HTTP transport adapter configured in Joomla.
  • Order status transitions go through J2Commerce's OrderModel::updateOrderStatus() method. This means order history is logged correctly and status-change email notifications fire as expected — the same as any other payment plugin.
  • Surcharge, subtotal limits, and geozone restriction are fully implemented, matching the feature parity of the PayPal plugin.
  • Assets are registered via Joomla's Web Asset Manager. No inline <link> or <script> tags are injected into the page.
  • Backwards compatibility — in-flight charges created under the J2Store v4 plugin are still accepted by the webhook handler. The origin hash logic accepts both the old J2Store and new J2Commerce format.

Troubleshooting

"IPN Misconfigured" — orders never update after payment

Cause: The Coinbase Webhook Shared Secret field in the plugin settings is empty.

Solution:

  1. Log in to commerce.coinbase.com/dashboard/settings.
  2. Open your webhook endpoint.
  3. Copy the shared secret (you may need to regenerate it if you did not save it originally).
  4. Paste it into the Coinbase Webhook Shared Secret field in the plugin settings and save.

"IPN Rejected" — webhook arrives but is refused

Cause 1: The shared secret in the plugin does not match the one in your Coinbase Commerce dashboard.

Solution: Double-check both values. Even a single extra space will cause a mismatch.

Cause 2: A security plugin, CDN (such as Cloudflare), or mod_security rule is stripping the X-CC-Webhook-Signature HTTP header before it reaches PHP.

Solution: Switch to the Alternate endpoint (com_ajax) URL. Update the endpoint URL in your Coinbase Commerce dashboard and test again. If the problem persists, temporarily disable mod_security or add an exclusion rule for your webhook URL, then test.


"Order ID empty or did not match" — webhook arrives but order is not found

Cause: The metadata.order_id field in the Coinbase charge was not set correctly, or the order was deleted after the charge was created.

Solution:

  1. Enable Debug Logging in the plugin settings.
  2. Place a new test order and check administrator/logs/plg_j2commerce_payment_coinbase.php for the raw webhook payload.
  3. Confirm the metadata.order_id value matches an existing order in J2Commerce.
  4. If orders are being deleted and recreated (e.g., by a cron job or cleanup script), stop that process before payments can arrive.

Customer paid but order is stuck on "Pending" or initial status

Cause: The webhook did not arrive or was not processed. Common reasons:

  • The webhook URL is misconfigured in Coinbase Commerce
  • The shared secret is wrong
  • Debug logging is off so there is no record of what happened

Solution:

  1. Enable Debug Logging and reproduce the issue.
  2. Open administrator/logs/plg_j2commerce_payment_coinbase.php and look for any error entries.
  3. Check the Coinbase Commerce dashboard webhook delivery log to confirm your endpoint received the event and what HTTP response code it returned.
  4. If Coinbase shows a delivery failure (non-200 response), check your server logs for the specific PHP or firewall error.

Coinbase does not return a payment URL (Redirect mode)

Cause: The API key is invalid, the Coinbase Commerce account is suspended, or Coinbase returned an unexpected response.

Solution:

  1. Enable Debug Logging.
  2. Attempt a checkout and check the log file for the createCharge entry and any error detail.
  3. Verify the API key in Coinbase Commerce -> Settings -> API Keys is active and has not been revoked.