AIOT Payment x402 is in public beta. Install the skill for your AI agent.
GuidesFor DevelopersAIOTShopifyClient

AIOTShopifyClient

The top-level class in @aiot/shopify-x402. It owns a facilitator client, a Shopify admin client, a price converter, and a checkout-session manager. If you use the Express middleware, a client is constructed for you. If you want direct control (queue workers, webhooks, custom HTTP frameworks), instantiate AIOTShopifyClient yourself.

What it does

AIOTShopifyClient exposes three core operations:

  1. createCheckout(items, currency) — converts fiat to USDC, creates a Shopify draft order, creates an x402 order on the facilitator, persists a session (including contract addresses for on-chain reads), and returns a paymentPageUrl the user can open.
  2. getCheckoutStatus(sessionId) — reads the session from the configured store. Auto-transitions to expired if the TTL passed.
  3. completePayment(sessionId, { payment, eip7702Auth }) — settles on-chain, completes the Shopify draft order, marks it as paid, and appends a transaction note. Idempotent — safe to call after a transient failure.

Constructor

import { AIOTShopifyClient } from '@aiot/shopify-x402'
 
const client = new AIOTShopifyClient({
  aiotApiKey: process.env.AIOT_API_KEY!,
  merchantWallet: '0xYourSettlementWallet',
  shopifyAccessToken: process.env.SHOPIFY_ACCESS_TOKEN!,
  shopifyStoreDomain: 'your-store.myshopify.com',
  chainId: 97, // BSC Testnet; 56 for mainnet
})

Config reference

NameTypeDescription
aiotApiKey*stringMerchant API key issued by the AIOT backend.
aiotBaseUrlstringOverride the facilitator base URL.Default: https://merchant.aiotnetwork.io/api/v1
merchantWallet*stringBSC address where settled USDC lands.
shopifyAccessToken*stringShopify admin API access token. Empty string for non-Shopify use.
shopifyStoreDomain*stringShop domain, e.g. store.myshopify.com. Empty for non-Shopify.
shopifyApiVersionstringShopify Admin GraphQL API version pin.
tokenAddressstringERC-20 address of the token to accept.Default: BSC USDC
chainIdnumberEVM chain id. 56 = BSC mainnet, 97 = BSC testnet.Default: 97
callbackUrlstringRedirect target after a successful payment.
sessionStoreSessionStoreCustom session store. Defaults to InMemorySessionStore.
debugbooleanEnable verbose logging via the default logger.
loggerLoggerCustom logger. Overrides debug.

Creating a checkout

const result = await client.createCheckout(
  [
    { title: 'Pro plan (1 month)', price: '29.99', quantity: 1 }
  ],
  'usd'
)
 
console.log(result)
// {
//   sessionId: 'a7e9b2...',
//   paymentPageUrl: '/aiot-pay/pay/a7e9b2...',
//   usdcAmount: '29990000',
//   fiatTotal: '29.99',
//   expiresAt: 1738000000000
// }
  • usdcAmount is a USDC-6-decimal base-unit string — 29990000 is 29.99 USDC.
  • paymentPageUrl is relative; prepend your app’s origin if you need an absolute URL.
  • expiresAt is a Unix millisecond timestamp. Sessions expire 30 minutes after creation.

Completing a payment

The payment page posts the signed PaymentDetails to your /aiot-pay/complete route, which calls completePayment under the hood. If you’re not using the middleware, call it directly:

try {
  const result = await client.completePayment(sessionId, {
    payment: signedPaymentDetails,
    eip7702Auth: maybe7702Auth
  })
  console.log('Paid:', result.transaction)
} catch (err) {
  if (err instanceof PaymentFailedError) {
    // On-chain settlement failed (invalid signature, insufficient balance, etc.)
  } else if (err instanceof CheckoutExpiredError) {
    // Session TTL elapsed — create a new checkout
  } else {
    throw err
  }
}
Tip

completePayment is idempotent. If the Shopify draftOrderComplete succeeds but marking the order as paid fails transiently, calling completePayment again will skip the already-successful steps and only retry the ones that didn’t complete.