# Saleor

> Run the Mintage Pay app for Saleor, test it with test money and go live.

Source: https://mintagepay.com/docs/integrations/saleor/ (last updated 2026-10-25)

A Saleor app for the Transaction API. Your storefront sends the customer to the Mintage Pay payment page, and the app
reports the charge to Saleor by itself when the payment is final.

A Saleor app is a small service that you host. You run it at a public https address and install it in the Saleor
Dashboard from its manifest address.

Tested on 5 October 2026 with Saleor 3.21 and the app on Node 22, against the sandbox: connect, install from the
manifest, payment gateway offered at checkout, payment, charge reported to Saleor, order created fully paid, and
removal. The run used a channel priced in US dollars and the GraphQL API. A channel in another currency and the
Dashboard's own install screen have not been run yet, so test them with a sandbox key first.

## What you need

- Saleor **3.20 or later**, and a staff user who may manage apps.
- A host for the app: Node 20.19 or later, a public **https** address, and a folder that survives restarts for the
  app's data file.
- Your Saleor API address exactly as Saleor uses it, for example `https://shop.example.com/graphql/`.
- The storefront repository: it needs three GraphQL calls and a return page.
- Channel currencies Mintage Pay supports: USD, EUR, GBP, CAD, AUD, CHF, JPY, MXN, BRL, INR, SGD, AED, PLN, SEK, NOK,
  DKK, NZD, ZAR, TRY, KRW, HKD, NGN, ARS, PHP, IDR, VND, PKR, EGP, BDT, KES, GHS, TZS, COP, CLP, PEN, UYU, PYG, BOB, DOP, GTQ, CRC, THB, MYR, TWD, LKR, NPR, KZT, UAH, ILS, SAR, QAR, CZK, HUF, RON, ISK, XAF or XOF. Your customers always pay in US dollar stablecoins: a price in another currency is
  converted when they check out, and the payment page shows both amounts.
- A Mintage Pay account with at least one payout address set.

The app calls Mintage Pay and your Saleor API, and both call the app. Firewalls must allow that.

## Install

1. Download [mintagepay-saleor-app.zip](https://app.mintagepay.com/downloads/mintagepay-saleor-app.zip) and unpack
   it on the host. In the folder, run:

   ```
   npm ci --omit=dev
   ```
2. Copy `.env.example` to `.env` and set:
   - `APP_URL`: the app's public https address;
   - `MINTAGEPAY_API_KEY`: a key from **Developers > API keys** in the Mintage Pay dashboard. It is shown only once;
   - `ALLOWED_SALEOR_API_URLS`: your Saleor API address;
   - `DATA_FILE`: a file in the folder that survives restarts.

   Keep `.env` and the data file private. They hold your key, the app's Saleor token and the webhook secret.
3. Connect the app to Mintage Pay:

   ```
   node --env-file=.env dist/cli/connect.js
   ```

   It prints your business name and registers the app's address with Mintage Pay. It never prints the secret. Run it
   again whenever `APP_URL` changes.
4. Start the app and keep it running, restarting it if it stops:

   ```
   node --env-file=.env dist/server.js
   ```

   Run **one** copy of it. Check that `https://your-app/api/manifest` answers.
5. In the Saleor Dashboard, go to **Apps > Install external app**, enter `https://your-app/api/manifest` and approve
   the permission **Handle payments**.

The key decides where the app connects: a live key (`mp_live_...`) uses the live service and a test key
(`mp_test_...`) uses the [sandbox](https://mintagepay.com/docs/sandbox/).

## Update the storefront

Start the payment with the gateway `mintagepay.pay`:

```graphql
mutation {
  transactionInitialize(
    id: "(checkout id)"
    paymentGateway: {
      id: "mintagepay.pay"
      data: {
        redirectUrl: "https://shop.example.com/checkout/mintagepay-return"
        cancelUrl: "https://shop.example.com/cart"
      }
    }
  ) {
    transaction { id }
    transactionEvent { type message }
    data
    errors { field message code }
  }
}
```

1. Send the customer to `data.checkoutUrl`.
2. On the return page, call `transactionProcess` with the transaction id.
3. On `CHARGE_SUCCESS`, call `checkoutComplete`. On `CHARGE_ACTION_REQUIRED`, show "payment confirming" and ask again
   a little later. The app also reports the charge to Saleor by itself, so the payment is not lost if the customer
   closes the page.

## Try it first with test money

1. Create a free account at [sandbox.mintagepay.com](https://sandbox.mintagepay.com), set a payout address and
   create a key there.
2. Put the sandbox key in `.env`, run the connect command and start the app. The connect command says **sandbox**.
3. Start a checkout in your storefront and choose Mintage Pay. You land on a payment page with a **Test mode** banner.
4. Pay on the payment page with free test money. The page has a button to get some.
5. Within a few minutes the transaction in Saleor is charged in full, and `checkoutComplete` creates the order.
6. When you are happy, put your live key in `.env`, run the connect command again and restart the app.

## What you will see

| What happened | In Saleor |
|---|---|
| Customer sent to pay | Charge action required |
| Payment seen, not final yet | Charge action required, with a "payment detected" note |
| Paid in full | Charge success for the full amount |
| Paid, but the amount does not match the order | Not charged, with a note. Check it by hand |
| Part paid | Not charged, with a note saying how much is still owed |
| Payment window closed, or cancelled, with nothing paid | Charge failure |
| Payment window closed with part paid | Not charged, with a note. Refund the customer or collect the rest |

Mintage Pay never holds your money, so it cannot send a refund for you. Send the refund from your own wallet and record
it in the Mintage Pay dashboard.

## If something is wrong

- **Install is refused with `SALEOR_URL_PROHIBITED`:** `ALLOWED_SALEOR_API_URLS` does not match your Saleor API
  address.
- **Install is refused with `JWKS_NOT_AVAILABLE`:** the app cannot reach your Saleor API.
- **Saleor's calls get `401 not_registered`:** the data file was lost or the app was installed somewhere else. Install
  the app again.
- **Mintage Pay's calls get `401 not_configured`:** the connect command was not run, or the data file changed.
- **A payment stays at "charge action required":** look at the webhook delivery in the Mintage Pay dashboard, then at
  the app's log.

## Remove the app

1. Remove the app under **Apps** in the Saleor Dashboard.
2. Switch off the connection at Mintage Pay:

   ```
   node --env-file=.env dist/cli/connect.js --disable
   ```
3. Stop the service. Delete the data file once no payment is waiting.
