> ## Documentation Index
> Fetch the complete documentation index at: https://docs.accelebit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate Accelebit Payments with Shopify

> Build a Shopify Payments App that routes checkout payments through the Accelebit API. Covers sessions, 3DS callbacks, refunds, and webhooks.

Shopify's [Payments Apps API](https://shopify.dev/docs/apps/build/payments) lets you bring your own payment provider to the Shopify checkout. When a customer completes checkout, Shopify sends the payment details to your app's backend, and your app processes the charge through Accelebit. This guide covers everything you need to build and configure that integration.

## Architecture

The sequence below shows how Shopify, your app, and Accelebit interact during a checkout.

```mermaid theme={null}
sequenceDiagram
    participant Customer
    participant Shopify
    participant Your App
    participant Accelebit

    Customer->>Shopify: Checkout
    Shopify->>Your App: Payment session (card details)
    Your App->>Accelebit: POST /v1/payments
    Accelebit-->>Your App: Payment result
    Your App-->>Shopify: Resolve/reject payment session
    Shopify-->>Customer: Order confirmation
```

## Prerequisites

Before you start, make sure you have:

* An [Accelebit account](https://dashboard.accelebit.com) with API keys
* A Shopify Partner account
* A Shopify app configured as a [Payments App](https://shopify.dev/docs/apps/build/payments)
* An HTTPS server to host your app

<Steps>
  <Step title="Create the Shopify app and configure endpoints">
    Set up your Shopify app with the Payments App extension. Register the following endpoints in your app configuration:

    | Endpoint                         | Purpose                                              |
    | -------------------------------- | ---------------------------------------------------- |
    | `POST /payments/session`         | Receives payment sessions from Shopify               |
    | `POST /payments/session/resolve` | Called by your background worker to resolve sessions |
    | `POST /payments/refund`          | Handles refund requests from Shopify                 |
  </Step>

  <Step title="Handle payment sessions">
    When a customer checks out, Shopify sends a payment session to your app. Extract the card and billing details from the session and forward them to Accelebit. Resolve or reject the Shopify session based on the result.

    ```typescript theme={null}
    import express from 'express';
    import crypto from 'node:crypto';

    const app = express();
    app.use(express.json());

    app.post('/payments/session', async (req, res) => {
      const { id, amount, currency, payment_method, customer } = req.body;

      try {
        // Create payment through Accelebit
        const response = await fetch('https://api.gateway.accelebit.com/v1/payments', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-API-Key': process.env.ACCELEBIT_SECRET_KEY!,
            'Idempotency-Key': `shopify_${id}`,
          },
          body: JSON.stringify({
            amount: amount.toString(),
            currency: currency.toUpperCase(),
            paymentMethod: 'card',
            customerId: customer.email,
            card: {
              number: payment_method.data.card_number,
              expiryMonth: payment_method.data.expiry_month,
              expiryYear: payment_method.data.expiry_year,
              cvv: payment_method.data.cvv,
              holderName: `${customer.first_name} ${customer.last_name}`,
            },
            billing: {
              firstName: customer.first_name,
              lastName: customer.last_name,
              email: customer.email,
              phone: customer.phone || '+00000000000',
              country: customer.billing_address.country_code,
              address: customer.billing_address.address1,
              addressLine2: customer.billing_address.address2 || undefined,
              city: customer.billing_address.city,
              postalCode: customer.billing_address.zip,
              state: customer.billing_address.province_code || undefined,
            },
            merchantRef: `shopify_order_${id}`,
            returnUrl: `https://yourapp.com/payments/3ds-callback?session=${id}`,
          }),
        });

        const result = await response.json();

        if (result.data?.threeDsRequired) {
          // Redirect customer to 3DS
          return res.json({
            redirect_url: result.data.threeDsData.redirectUrl,
          });
        }

        if (result.data?.status === 'captured') {
          // Payment succeeded - resolve the session
          return res.json({ status: 'resolved' });
        }

        // Payment failed
        return res.json({
          status: 'rejected',
          error: result.error?.message || 'Payment failed',
        });
      } catch (error) {
        return res.status(500).json({
          status: 'rejected',
          error: 'Internal server error',
        });
      }
    });
    ```
  </Step>

  <Step title="Handle 3DS callbacks">
    When 3DS completes, Accelebit redirects the customer back to your `returnUrl`. Look up the payment by merchant reference, then resolve or reject the Shopify session accordingly.

    ```typescript theme={null}
    app.get('/payments/3ds-callback', async (req, res) => {
      const { session: sessionId } = req.query;

      // Look up the Accelebit payment by merchant reference
      const paymentRes = await fetch(
        `https://api.gateway.accelebit.com/v1/payments?merchantRef=shopify_order_${sessionId}`,
        {
          headers: { 'X-API-Key': process.env.ACCELEBIT_SECRET_KEY! },
        }
      );

      const payment = await paymentRes.json();

      if (payment.data?.status === 'captured') {
        // Resolve the Shopify payment session
        await resolveShopifySession(sessionId, 'resolved');
      } else {
        await resolveShopifySession(sessionId, 'rejected');
      }

      res.redirect(`https://yourshop.myshopify.com/checkouts/complete`);
    });
    ```
  </Step>

  <Step title="Handle refunds">
    When a merchant issues a refund from the Shopify admin, Shopify sends a refund request to your app. Forward the refund to Accelebit using the stored transaction ID.

    ```typescript theme={null}
    app.post('/payments/refund', async (req, res) => {
      const { id, payment_id, amount, currency } = req.body;

      const response = await fetch('https://api.gateway.accelebit.com/v1/refunds', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': process.env.ACCELEBIT_SECRET_KEY!,
          'Idempotency-Key': `shopify_refund_${id}`,
        },
        body: JSON.stringify({
          transactionId: payment_id, // Your stored Accelebit transaction ID
          amount: amount.toString(),
          currency: currency.toUpperCase(),
          reason: 'Refund from Shopify admin',
        }),
      });

      const result = await response.json();

      if (response.ok) {
        return res.json({ status: 'resolved' });
      }

      return res.json({
        status: 'rejected',
        error: result.error?.message || 'Refund failed',
      });
    });
    ```
  </Step>

  <Step title="Configure webhooks in the Accelebit Dashboard">
    Set up an Accelebit webhook endpoint so your app receives real-time payment status updates. This keeps Shopify order statuses accurate even if the customer closes their browser during the 3DS challenge.

    In the [Accelebit Dashboard](https://dashboard.accelebit.com), add a webhook URL pointing to your app:

    ```
    https://yourapp.com/webhooks/accelebit
    ```

    Subscribe to the following events:

    * `payment.captured`
    * `payment.failed`
    * `refund.created`

    See [Webhooks](/webhooks/overview) for signature verification details.
  </Step>
</Steps>

## Testing

Before going live, verify your integration end-to-end:

1. Use your Accelebit **test** secret key (`smtgw_sk_test_...`).
2. Use a Shopify development store.
3. Use card number `4111111111111111`—this processes successfully in test mode.
4. Issue a refund from the Shopify admin and confirm it processes through Accelebit.
