Accept crypto payments on your Shopify store via Payram. The connector adds a Pay with Crypto block to the Shopify Thank You page — buyers enter their email, click the button, and are redirected to a Payram-hosted checkout to complete payment in crypto.
| Requirement | Notes |
|---|---|
| Docker | docs.docker.com/get-docker |
| A Shopify Partner account | partners.shopify.com |
| A Payram account + project | payram.com |
No Node.js required on the host — everything runs inside Docker.
On your server (Linux or macOS), run:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/PayRam/payram-shopify/main/setup_payram_shopify.sh)"The script will:
- Check Docker is installed and running
- Ask for an install directory (default:
~/payram-shopify-connector) - Prompt for your Shopify app's Client ID and Client Secret — get these from partners.shopify.com → Apps → your app → API credentials
- Ask for your server's public HTTPS URL and optional database connection string
- Auto-generate an encryption key using
openssl - Pull the Docker image and start the container
- Optionally deploy the checkout UI extension to Shopify's CDN
The installer offers to do this automatically. If you skipped it, run:
docker run --rm -it \
--env-file ~/payram-shopify-connector/.env \
payram/shopify-connector:latest \
npx shopify app deployThe container is already running after the installer. To manage it:
docker logs payram-shopify-connector # view logs
docker stop payram-shopify-connector # stop
docker start payram-shopify-connector # restartOpen the following URL in a browser (replace placeholders):
https://YOUR_DOMAIN/auth?shop=YOUR_STORE.myshopify.com
Approve the permission request. This installs the app on your store and creates a session.
- After installation, the app opens in Shopify Admin → Apps → Payram Connector.
- On the Settings page, enter:
- Payram Base URL — your Payram instance URL (e.g.
https://api.payram.com) - Payram Project API Key — from your Payram dashboard
- Payram Base URL — your Payram instance URL (e.g.
- Click Save Settings, then Test Payram Connection to verify.
- In Shopify Admin → Settings → Payments → Manual payment methods → Add manual payment method.
- Enter the name your customers will see, e.g.:
Pay with Crypto via Payram
- In Shopify Admin → Online Store → Checkout → Customize.
- Switch to the Thank You page using the page selector at the top.
- Click Add block → select Payram Thank You Block.
- In the block settings panel set App backend base URL to your server's public URL, e.g.:
https://YOUR_DOMAIN - Click Save.
- Go to your store and place an order using the Pay with Crypto via Payram payment method.
- On the Thank You page the Payram block appears.
- Enter an email address and click Complete Crypto Payment.
- You are redirected to a Payram-hosted checkout to complete the crypto payment.
| Variable | Required | Description |
|---|---|---|
SHOPIFY_API_KEY |
✅ | Shopify app Client ID |
SHOPIFY_API_SECRET |
✅ | Shopify app Client secret |
SHOPIFY_APP_URL |
✅ | Public HTTPS URL of this server |
DATABASE_URL |
✅ | SQLite (file:prod.sqlite) or Postgres connection string |
ENCRYPTION_KEY |
✅ | 64-char hex key for encrypting stored API keys |
SCOPES |
✅ | read_orders,write_orders,read_customers (do not change) |
PORT |
— | Server port (default: 2798) |
docker pull payram/shopify-connector:latest
docker stop payram-shopify-connector && docker rm payram-shopify-connector
docker run -d \
--name payram-shopify-connector \
--env-file ~/payram-shopify-connector/.env \
-p 2798:2798 \
-v payram-shopify-data:/data \
--restart unless-stopped \
payram/shopify-connector:latestShopify Thank You page
└── Checkout UI Extension (purchase.thank-you.block.render)
└── buyer enters email → clicks button
└── GET /api/payram/redirect-to-payment
└── create Payram payment via Payram API
└── store PaymentMapping in DB
└── redirect buyer to Payram checkoutUrl
Payram webhook → POST /api/payram/webhook
└── update payment status
└── attempt orderMarkAsPaid in Shopify
Shopify Admin → /app (settings page)
└── merchant sets Payram Base URL + API Key (encrypted at rest)
Shopify Thank You page
└── Checkout UI Extension (purchase.thank-you.block.render)
└── buyer clicks link → GET /api/payram/redirect-to-payment
└── create Payram payment via POST {payramBaseUrl}/api/v1/payment
└── store PaymentMapping in SQLite
└── redirect buyer to Payram checkoutUrl
Payram webhook → POST /api/payram/webhook
└── update payramStatus
└── attempt orderMarkAsPaid (PCD-gated, fault-tolerant)
Shopify Admin → /app (settings page)
└── merchant sets Payram Base URL + API Key (encrypted at rest)
npm installcp .env.example .envFill in:
# from Shopify Partner Dashboard → App → Client credentials
SHOPIFY_API_KEY=your_key
SHOPIFY_API_SECRET=your_secret
SCOPES=read_orders,write_orders,read_customers
SHOPIFY_APP_URL=https://your-tunnel.trycloudflare.com
DATABASE_URL="file:dev.sqlite"
# 64-char hex key — generate with:
# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
ENCRYPTION_KEY=your_64_char_hex_keyDuring
shopify app devthe tunnel URL is printed in the console. UpdateSHOPIFY_APP_URLto match.
npx prisma migrate dev --name initshopify app devThis starts the Remix server, creates a Cloudflare tunnel, and streams logs.
- Open the app in Shopify Admin (follow the install URL from the terminal).
- On the Settings page enter:
- Payram Base URL — e.g.
https://api.payram.io - Payram Project API Key
- Payram Base URL — e.g.
- Click Save Settings.
- Click Test Payram Connection to verify the credentials.
In Shopify Admin → Settings → Payments → Manual payment methods:
Pay with Crypto via Payram
- In Shopify Admin → Online Store → Checkout → Customize.
- Navigate to the Thank You page.
- Add the Payram Thank You Block from the extension list.
- In the block settings, set:
- App backend base URL → the current Cloudflare tunnel URL (e.g.
https://xyz.trycloudflare.com)
- App backend base URL → the current Cloudflare tunnel URL (e.g.
- Save.
Important: The Cloudflare tunnel URL changes every time you restart
shopify app dev. Update this setting each time.
- Go to your development store → place an order using the manual payment method.
- On the Thank You page the Payram block appears.
- Optionally enter an email address.
- Click Open Payram checkout — you will be redirected to the Payram payment page.
| Method | Path | Description |
|---|---|---|
GET |
/api/payram/redirect-to-payment |
Creates Payram payment and redirects buyer |
GET |
/api/payram/status |
Returns PaymentMapping for an order or reference |
POST |
/api/payram/webhook |
Receives Payram payment status webhooks |
Query params:
| Param | Required | Description |
|---|---|---|
shopifyOrderId |
Yes | Numeric Shopify order ID |
amountInUSD |
Yes | Order total in USD |
shop |
Yes | *.myshopify.com domain |
email |
No | Buyer email for Payram receipt |
Behaviour:
- Validates params, loads merchant Payram config.
- If a mapping already exists for the order, redirects to the existing checkout URL (idempotent).
- Otherwise calls
POST {payramBaseUrl}/api/v1/payment, stores the mapping, redirects buyer.
Expected JSON body (accepts common field name variants):
{
"referenceId": "payram-ref-id",
"status": "paid"
}Terminal statuses that trigger Shopify sync: paid, confirmed, closed, completed.
POST {PAYRAM_BASE_URL}/api/v1/payment
Headers:
API-Key: {PAYRAM_PROJECT_API_KEY}
Content-Type: application/json
Body:
{
"customerId": "shopify:{shop}:order:{shopifyOrderId}",
"amountInUSD": 50.00,
"customerEmail": "buyer@example.com" // optional
}
Expected response:
{
"referenceId": "...",
"checkoutUrl": "https://..."
}
The connector also accepts reference_id/id and checkout_url/paymentUrl variants.
| Field | Description |
|---|---|
shop |
Unique myshopify.com domain |
payramBaseUrl |
Payram API base URL |
payramProjectApiKeyEncrypted |
AES-256-GCM encrypted API key |
paymentMethodName |
Label shown in checkout |
| Field | Description |
|---|---|
shop + shopifyOrderId |
Composite unique key |
payramReferenceId |
Payram reference returned by API |
payramCheckoutUrl |
Direct Payram checkout link |
payramStatus |
Latest status from Payram |
shopifyFinancialStatus |
Synced from Shopify after mark-paid |
shopifyPaidSyncedAt |
Timestamp of successful sync |
syncError |
Error from last Shopify sync attempt |
| File | Purpose |
|---|---|
extensions/thank-you-block/src/Checkout.tsx |
UI extension — Preact component for the Thank You block |
extensions/thank-you-block/shopify.extension.toml |
Extension config — target, settings field |
extensions/thank-you-block/package.json |
@shopify/ui-extensions@2026.1.3 + preact |
extensions/thank-you-block/tsconfig.json |
jsxImportSource: preact, moduleResolution: Bundler |
// Order ID (numeric) from GID
const orderId = shopify.orderConfirmation.value.order.id.split("/").pop();
// Amount in USD
const amountInUSD = shopify.cost.totalAmount.value.amount;
// Email — PCD Level 2 gated, may be undefined
const email = shopify.buyerIdentity?.email?.value;
// App backend URL from extension settings (set in checkout editor)
const appBackendBaseUrl = shopify.settings.value.appBackendBaseUrl;shopify app dev creates a new tunnel URL on every start. After restarting:
- Copy the new URL from the terminal output.
- Update
SHOPIFY_APP_URLin.env. - In the checkout editor → Payram block settings → update App backend base URL.
The following features require Shopify PCD approval (granted during public app review — not available in dev stores):
| Feature | Status |
|---|---|
buyerIdentity.email in extension |
PCD Level 2 — returns undefined in dev |
orderMarkAsPaid GraphQL mutation |
PCD-gated — syncError stored, webhook still returns 200 |
| Order email via Admin REST | PCD-gated |
Workarounds implemented:
- Email is collected manually via a text field in the block.
customerEmailis optional when calling Payram.orderMarkAsPaidfailures are stored inPaymentMapping.syncErrorand do not cause webhook retries.
Merchant Payram API keys are stored AES-256-GCM encrypted in SQLite.
- Key material:
ENCRYPTION_KEYenv var (64 hex chars = 32 bytes). - Wire format:
base64(IV[12] + AuthTag[16] + Ciphertext). - The key is never logged or exposed to the browser.
- For production: store
ENCRYPTION_KEYin a secrets manager (AWS Secrets Manager, GCP Secret Manager, etc.) and inject it as an env var at runtime.
- Implement CUSTOMERS_DATA_REQUEST webhook handler.
- Implement CUSTOMERS_REDACT webhook handler (anonymise email in PaymentMapping).
- Add Payram webhook signature verification.
- Add rate limiting to
/api/payram/redirect-to-payment(per IP at reverse proxy). - Request PCD Level 2 via Shopify Partner Dashboard.
- Rotate
ENCRYPTION_KEYto a KMS-managed key. - Replace SQLite with Postgres for production.