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:
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 apaymentPageUrlthe user can open.getCheckoutStatus(sessionId)— reads the session from the configured store. Auto-transitions toexpiredif the TTL passed.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
| Name | Type | Description |
|---|---|---|
aiotApiKey* | string | Merchant API key issued by the AIOT backend. |
aiotBaseUrl | string | Override the facilitator base URL.Default: https://merchant.aiotnetwork.io/api/v1 |
merchantWallet* | string | BSC address where settled USDC lands. |
shopifyAccessToken* | string | Shopify admin API access token. Empty string for non-Shopify use. |
shopifyStoreDomain* | string | Shop domain, e.g. store.myshopify.com. Empty for non-Shopify. |
shopifyApiVersion | string | Shopify Admin GraphQL API version pin. |
tokenAddress | string | ERC-20 address of the token to accept.Default: BSC USDC |
chainId | number | EVM chain id. 56 = BSC mainnet, 97 = BSC testnet.Default: 97 |
callbackUrl | string | Redirect target after a successful payment. |
sessionStore | SessionStore | Custom session store. Defaults to InMemorySessionStore. |
debug | boolean | Enable verbose logging via the default logger. |
logger | Logger | Custom 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
// }usdcAmountis a USDC-6-decimal base-unit string —29990000is 29.99 USDC.paymentPageUrlis relative; prepend your app’s origin if you need an absolute URL.expiresAtis 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
}
}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.
Related
- Express middleware — mounts the full route set for you
- Session stores — swap the in-memory store
- Error handling — the full error hierarchy
- API Reference → AIOTShopifyClient — auto-generated TypeDoc