> For the complete documentation index, see [llms.txt](https://bagelpay.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bagelpay.gitbook.io/docs/documentation/template-and-framework/shipany.md).

# ShipAny

[ShipAny](https://docs.shipany.ai/) supports using [BagelPay](https://bagelpay.io/) for payments, which can be used for product payments, membership subscriptions, credit purchases, and other scenarios.

## How to setup <a href="#creem-setup" id="creem-setup"></a>

<details>

<summary>Step1: Register a <a href="https://app.bagelpay.io/login">BagelPay</a> account</summary>

<figure><img src="/files/U290YWC6UO7Ifq0hYb4F" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Step2: Create a store in the BagelPay <a href="https://app.bagelpay.io/dashboard">dashboard</a></summary>

<figure><img src="/files/OFXErvNuhWXoMzV3zjs4" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Step3: Create <a href="https://app.bagelpay.io/product">products</a></summary>

<figure><img src="/files/Hle11wSN3MXVhaLJ28ea" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Step4: Generate API keys in <a href="https://app.bagelpay.io/keys">developer center</a></summary>

<figure><img src="/files/DAHrZxaKcbhzv1txHvjA" alt=""><figcaption></figcaption></figure>

</details>

## ShipAny Configuration

Fill in the BagelPay-related configuration information in the ShipAny project configuration file.

* Development environment configuration file `.env.development`
* Production environment configuration file `.env.production` / `wrangler.toml`

```
NEXT_PUBLIC_WEB_URL = "http://localhost:3000"

NEXT_PUBLIC_PAY_SUCCESS_URL = "/my-orders"
NEXT_PUBLIC_PAY_FAIL_URL = "/pricing"
NEXT_PUBLIC_PAY_CANCEL_URL = "/pricing"

PAY_PROVIDER = "bagelpay"

BAGELPAY_ENV = "test"
BAGELPAY_API_KEY = "bagel_test_xxx"
BAGELPAY_WEBHOOK_SECRET = "xxx"
BAGELPAY_PRODUCTS = '{"starter": "prod_xxx", "standard": "prod_xxx", "premium": "prod_xxx"}'

```

* &#x20;  `NEXT_PUBLIC_WEB_URL` Page paths can be filled with relative paths or absolute paths. If a relative path is filled, it will automatically concatenate with the website address configured in `NEXT_PUBLIC_WEB_URL` and include multi-language parameters when redirecting.
* `NEXT_PUBLIC_PAY_SUCCESS_URL` The page path to redirect to after successful payment
* `NEXT_PUBLIC_PAY_FAIL_URL` The page path to redirect to after failed payment
* `NEXT_PUBLIC_PAY_CANCEL_URL` The page path to redirect to after cancelled payment
* `PAY_PROVIDER` Payment provider, default is `stripe`, if you need to use BagelPay, please set it to `bagelpay`
* `BAGELPAY_ENV` Environment, use `test` for testing, use `production` for production
* `BAGELPAY_API_KEY` BagelPay API key, use different keys for different environments
* `BAGELPAY_WEBHOOK_SECRET` BagelPay notification verification key. After configuring the Webhook address in the BagelPay dashboard, go to the Webhook address management page and copy the `Signing secret`.
* `BAGELPAY_PRODUCTS` The correspondence between product\_id in the pricing table and the product IDs created in the BagelPay dashboard. For example, if the pricing table set in the ShipAny project has three payment plans with corresponding product\_ids of starter, standard, and premium, you need to create corresponding products for these three plans in the BagelPay dashboard, copy each product’s Product ID, and fill in the correspondence with the product\_ids in the pricing table into BAGELPAY\_PRODUCTS.

## Pricing Table Payment

ShipAny template has a built-in pricing table and corresponding payment logic. You can quickly implement payment functionality by making simple modifications according to your needs.

### Configure Pricing Table Content

The built-in pricing table configuration file in ShipAny template is located in: `src/i18n/pages/pricing` directory, supports multiple languages, and includes `en.json` and `zh.json` two pricing table configuration files by default.

For example, the default configuration for the English pricing table is:

```json
{
  "pricing": {
    "name": "pricing",
    "label": "Pricing",
    "title": "Pricing",
    "description": "Get all features of ShipAny, Ship your AI SaaS startups fast.",
    "groups": [],
    "items": [
      {
        "title": "Starter",
        "description": "Get started with your first SaaS startup.",
        "features_title": "Includes",
        "features": [
          "100 credits, valid for 1 month",
          "NextJS boilerplate",
          "SEO-friendly structure",
          "Payment with Stripe",
          "Data storage with Supabase",
          "Google Oauth & One-Tap Login",
          "i18n support"
        ],
        "interval": "one-time",
        "amount": 9900,
        "cn_amount": 69900,
        "currency": "USD",
        "price": "$99",
        "original_price": "$199",
        "unit": "USD",
        "is_featured": false,
        "tip": "Pay once. Build unlimited projects!",
        "button": {
          "title": "Get ShipAny",
          "url": "/#pricing",
          "icon": "RiFlashlightFill"
        },
        "product_id": "starter",
        "product_name": "ShipAny Boilerplate Starter",
        "credits": 100,
        "valid_months": 1
      },
      {
        "title": "Standard",
        "description": "Ship Fast with your SaaS Startups.",
        "label": "Popular",
        "features_title": "Everything in Starter, plus",
        "features": [
          "200 credits, valid for 3 month",
          "Deploy with Vercel or Cloudflare",
          "Generation of Privacy & Terms",
          "Google Analytics Integration",
          "Google Search Console Integration",
          "Discord community",
          "Technical support for your first ship",
          "Lifetime updates"
        ],
        "interval": "one-time",
        "amount": 19900,
        "cn_amount": 139900,
        "currency": "USD",
        "price": "$199",
        "original_price": "$299",
        "unit": "USD",
        "is_featured": true,
        "tip": "Pay once. Build unlimited projects!",
        "button": {
          "title": "Get ShipAny",
          "url": "/#pricing",
          "icon": "RiFlashlightFill"
        },
        "product_id": "standard",
        "product_name": "ShipAny Boilerplate Standard",
        "credits": 200,
        "valid_months": 3
      },
      {
        "title": "Premium",
        "description": "Ship Any AI SaaS Startups.",
        "features_title": "Everything in Standard, plus",
        "features": [
          "300 credits, valid for 1 year",
          "Business Functions with AI",
          "User Center",
          "Credits System",
          "API Sales for your SaaS",
          "Admin System",
          "Priority Technical Support"
        ],
        "interval": "one-time",
        "amount": 29900,
        "cn_amount": 199900,
        "currency": "USD",
        "price": "$299",
        "original_price": "$399",
        "unit": "USD",
        "is_featured": false,
        "tip": "Pay once. Build unlimited projects!",
        "button": {
          "title": "Get ShipAny",
          "url": "/#pricing",
          "icon": "RiFlashlightFill"
        },
        "product_id": "premium",
        "product_name": "ShipAny Boilerplate Premium",
        "credits": 300,
        "valid_months": 12
      }
    ]
  }
}
```

The default pricing table preview is:

<figure><img src="/files/ulJ51GqzXc53UH6liWcL" alt=""><figcaption></figcaption></figure>

You can modify the content in the pricing table configuration file according to your needs.

### Modify Pricing Table Component

The default pricing table component is located at: `src/components/blocks/pricing/index.tsx`

You can modify the display form of the pricing table according to your needs.

### Modify Pricing Table Order Logic

The default pricing table order logic is located at: `src/app/api/checkout/route.ts`

You can modify the order logic of the pricing table according to your needs.

### Modify Payment Callback Logic

In the pricing table order logic, the default configured payment callback address is: `/api/pay/callback/bagelpay`

After user payment, the browser will jump to this address and include parameters with payment information.

The default payment callback processing logic is located at: `src/app/api/pay/callback/bagelpay/route.ts`

You can modify the logic for processing payment callbacks according to your needs, such as updating order status, sending email notifications to users, giving credits to users, etc.

> Payment callback is synchronous logic, which depends on the browser jumping to the callback address to process the payment result.&#x20;
>
> This method is not very reliable, and situations such as users closing the browser during the jump may occur, causing the payment result to not be processed normally.&#x20;
>
> A more reliable method is through Webhook, configuring asynchronous notification of payment results.

### Modify Payment Notification Logic

<details>

<summary>You need to first configure the Webhook address in the BagelPay dashboard</summary>

For example, configure the Webhook address as: `https://your-domain.com/api/pay/notify/bagelpay`

<figure><img src="/files/oWHnlkL7oQGV9srp6nha" alt=""><figcaption></figcaption></figure>

After user payment, BagelPay will push payment information to this address.

</details>

<details>

<summary>Process Payment Notifications</summary>

The default payment notification logic is located at: `src/app/api/pay/notify/bagelpay/route.ts`

You can modify the logic for processing payment notifications according to your needs, such as updating order status, sending email notifications to users, giving credits to users, etc.

</details>

## Testing payment in Local Env

<details>

<summary>Step1: Enable Test Mode</summary>

In the BagelPay dashboard, enter the store and click `Test Mode` in the upper right corner to enable test mode.

<figure><img src="/files/a9o4dft4wx3SNFHSBTUD" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Step2: Generate Test Keys</summary>

In test mode, enter the developer center and set up [test API keys](https://www.creem.io/dashboard/developers).

<figure><img src="/files/00o9oT3DE6iuOthmoFUw" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary>Step3: Test Payment Notifications</summary>

Register an [ngrok](https://ngrok.com/) account and install the `ngrok` command line tool as instructed.

Start the ngrok service, listen to the local port, and generate a temporary domain.

```sh
ngrok http http://localhost:3000
```

In the BagelPay dashboard test mode, configure the Webhook address as the domain generated by ngrok

{% hint style="info" %}
For example:

<pre class="language-url"><code class="lang-url"><strong>https://xxx.ngrok-free.app/api/pay/notify/bagelpay
</strong></code></pre>

{% endhint %}

<figure><img src="/files/65IDL7pLzTFBE4eSQ0J3" alt=""><figcaption></figcaption></figure>

After adding the Webhook address, in the Webhook logs page, copy the `Signing secret.`

<figure><img src="/files/Te6tM8SKWW53VGHVpEU0" alt=""><figcaption></figcaption></figure>

Fill it into the `.env.development` file together with the payment key.

```
BAGELPAY_API_KEY = "bagel_test_xxx"
BAGELPAY_WEBHOOK_SECRET = "xxx"
```

</details>

<details>

<summary>Step4: Test Payment</summary>

Start the project locally, visit the <http://localhost:3000/pricing> page, click the order button,&#x20;

<figure><img src="/files/f3W0bHGjjVdnFpmBw0g0" alt=""><figcaption></figcaption></figure>

and after successful ordering, jump to the payment page.

Use [Test Cards](/docs/documentation/testing-mode/test-mode-vs-live-mode.md) to pay.&#x20;

<figure><img src="/files/Df4JnzqH437eamR6xcF7" alt=""><figcaption></figcaption></figure>

After successful payment, the browser jumps to the payment callback address, and the monitored address receives payment notifications.

<figure><img src="/files/BLsjgMkP6UFl9q3dbB5u" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Nvs6CWbx2oCfnTsG7d3Q" alt=""><figcaption></figcaption></figure>

</details>

## References <a href="#references" id="references"></a>

* [BagelPay Official Documentation](/docs/documentation/getting-started/what-is-bagelpay.md)
* [BagelPay Quick Start Guide](/docs/documentation/getting-started/quick-start-guide.md)
* [BagelPay Developer Integration Guide](/docs/documentation/developers-and-api-usage/developer-integration-guide.md)
* [BagelPay Webhook User Guide](/docs/documentation/developers-and-api-usage/webhooks/webhook-user-guide.md)
