![Checkout App](https://user-images.githubusercontent.com/44495184/185607710-75fbb620-1d94-4168-9137-4f7841cbce4c.png)

<div align="center">
  <h1>Checkout App</h1>
</div>

<div align="center">
  <p>Extensible, checkout and payment integrations powered by Saleor API.</p>
</div>

<div align="center">
  <a href="https://saleor.io/">🏠 Website</a>
  <span> • </span>
  <a href="https://docs.saleor.io/docs/3.x/">📚 Docs</a>
  <span> • </span>
  <a href="https://saleor.io/blog/">📰 Blog</a>
  <span> • </span>
  <a href="https://twitter.com/getsaleor">🐦 Twitter</a>
</div>

> **Note**
> This app uses [older flow for making payments in Saleor](https://docs.saleor.io/docs/3.x/developer/payments#processing-a-payment-with-checkout-app).
>
> Current version of checkout uses [Payment Apps](https://docs.saleor.io/docs/3.x/developer/payments#processing-a-payment-with-payment-app) instead

## Setup

### Prerequisites

Make sure you've set `SALEOR_API_URL` in the root of the monorepo to your Saleor instance. You can also use other Saleor instance than the one defined in `.env` in root of monorepo.

### Development

Run the development server:

```bash
pnpm dev
```

To develop `saleor-app-checkout` app locally, you need to create a tunnel for it. The tunnel will enable you to display it within your Saleor Dashboard. If you want to read more about Saleor Apps architecture, see [the documentation](https://docs.saleor.io/docs/3.x/developer/extending/apps/key-concepts).

To create a tunnel, run:

```bash
npx saleor app tunnel 3001
```

where `3001` is the port on which `saleor-app-checkout` runs by default. Alternative ways of creating a tunnel are described [here](#alternatives-to-saleor-app-tunnel).

> **Note**<br/>
> Argument `--force-install` is required only the first time you run the command in order to install the application inside Saleor Dashboard and save the token.

Open the app by using the tunnel URL received from `saleor app tunnel` (example: `https://saleor-app-checkout-xyz-my-org.saleor.live`) in your browser to see the result.

> **Warning**<br/>
> The tunnel needs to be running in the background. Please don't kill it during the development.

> **Note**<br />
> Tunnel might break if you change your Internet connection. If you can't access the app from tunnel please restart it

#### Alternative way to obtain the token

Token can also be generated using the CLI command:

```bash
npx saleor app token
```

Now, create an empty JSON file named `.saleor-app-auth.json` and paste the token there. The file should look like this:

```json
{
  "token": "(your application's auth token)",
  "domain": "(your Saleor GraphQL API URL)"
}
```

### Production

To build for production, run the following command:

```bash
cd ../.. && pnpm run build:saleor-app-checkout
```

> **Note**<br/>
> The command needs to be run from root of the monorepo. Otherwise Turborepo won't be able to build the app

The deployed app needs to have auth token set manually by an environment variable. Install the app in Saleor and use Saleor CLI to generate the token:

```
saleor app token
```

Then set the `SALEOR_APP_TOKEN` environment variable value to the token you've received from Saleor and **redeploy the app**.

### Other

#### Alternatives to `saleor app tunnel`

You can also use [`ngrok`](https://ngrok.com/), but you would need to update env variables each time you open tunnel (on free plan) with new domain `ngrok` assigned you.

After you do that use `saleor app install` to install the app in your Saleor instance.

The tunnel needs to use `https` protocol with valid SSL certificate, otherwise you won't receive webhook calls.

## Env Variables

**Environment variables contain secrets that can lead to compromising your store data**

When **deploying** to Vercel you can set them on the [configuration page](https://vercel.com/docs/concepts/projects/environment-variables)

When running app **locally** you can use the [`.env.local`](https://nextjs.org/docs/basic-features/environment-variables#loading-environment-variables) file. **It should not be included in your git repository**.

### Backend variables

- `SALEOR_APP_TOKEN` — App's token generated by Saleor after the app was installed
- `SETTINGS_ENCRYPTION_SECRET` — Random string used for encrypting apps configuration

To generate a random secret you can use OpenSSL:

```
openssl rand -hex 256
```

[Learn more](https://docs.saleor.io/docs/3.x/developer/extending/apps/installing-apps#installing-third-party-apps) about installing third-party apps in [Saleor docs](https://docs.saleor.io/docs/3.x/developer/extending/apps/installing-apps#installing-third-party-apps)

- `DEBUG_APP_URL` - URL to the deployed checkout app. Used when running app locally and tunneling requests by using `saleor tunnel`

> **Warning**<br/>
> This variable should be used for local development only! It will be ignored in production deployment.
>
> In production this URL is taken from `Host` header in each request

### Frontend variables

Each variable starting with [`NEXT_PUBLIC`](https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser) is exposed to frontend

## Testing

To test React components you must use `jsdom` runtime (the default is `node`). Add this comment at the top of the test file:

```js
/** @jest-environment setup-polly-jest/jest-environment-node */
```

### Mocking requests

Mocking configuration works both in browser and Node environment

#### Recording

For mocking requests made in tests we use [Polly.js](https://netflix.github.io/pollyjs/#/). By default, if requests are made in tests and are not mocked the test will fail.

To record requests run tests by using the `test:record` command:

```
pnpm run test:record
```

This command sets `POLLY_MODE` env variable to `record`.

Recordings are stored in `recordings` folder.

#### Manual mocks

To write manual mocks we use [Mock Service Worker](https://mswjs.io/) library. Any REST API route or GraphQL operation that is mocked using `msw` won't be recorded by Polly.js.

Mocks for msw are located in `mocks/handlers`

## Checkout Storefront

Checkout Storefront is available at [/checkout-spa/?saleorApiUrl=<YOUR_SALEOR_API_URL>](../saleor-app-checkout/pages/checkout-spa.tsx).

You'll need a token to use the checkout. A new checkout session can be generated either in your storefront or in the GraphQL Playground. You could use a preexisting checkout as well.

> **Warning**<br/>
> If a given checkout has customer already attached, it'll become private, and **you won't be able to fetch its data from the api** without the same customer being logged in your current browser. Checkout uses [Saleor SDK](https://github.com/saleor/saleor-sdk) for authentication.

To generate checkout in GraphQL API and retrieve its `id`:

```graphql
mutation {
  checkoutCreate(
    input: {
      channel: "default-channel"
      lines: [{ variantId: "UHJvZHVjdFZhcmlhbnQ6MjE0", quantity: 1 }]
    }
  ) {
    checkout {
      id
    }
  }
}
```

Learn more about creating checkout sessions in [Saleor docs](https://docs.saleor.io/docs/3.x/developer/checkout#creating-a-checkout-session)

Copy `http://localhost:3001/checkout-spa/?saleorApiUrl=<YOUR_SALEOR_API_URL>&checkout=<TOKEN>`, replace `YOUR_SALEOR_API_URL` with a URL to Saleor GraphQL endpoint, `TOKEN` with the token of your checkout session and opne it in your browser.

### More info

See [checkout-storefront package](../../packages/checkout-storefront/README.md) for more information.
