使用 Stripe Link 支付并借助Playwright 完成浏览器结账,实现全自动 Shopify 采购;在所有 Shopify 商家搜索商品并生成一键购买流程。
Buy products from any Shopify store using Stripe Link for payment and Playwright for browser checkout.
bash
npm install -g @stripe/link-cli
link-cli auth login --client-name "YourAgent" --format json
User approves at the returned verification_url. Backup credentials from ~/.config/link-cli-nodejs/config.json.
Get credentials at dev.shopify.com/dashboard → Catalogs → Get API key.
Store CLIENT_ID and CLIENT_SECRET in your env.
bash
npm install playwright
npx playwright install chromium
If missing system libs (headless server), download Debian packages manually and set LD_LIBRARY_PATH. See references/chromium-deps.md.
Option A — Catalog API (search across all Shopify merchants):
bash
# Get auth token (60min TTL)
TOKEN=$(curl -s -X POST https://api.shopify.com/auth/access_token \
-H 'Content-Type: application/json' \
-d '{"client_id":"'$CLIENT_ID'","client_secret":"'$CLIENT_SECRET'","grant_type":"client_credentials"}' \
| jq -r .access_token)
# Search
curl -s -X POST https://catalog.shopify.com/api/ucp/mcp \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc":"2.0","method":"tools/call","id":1,
"params":{"name":"search_catalog","arguments":{
"meta":{"ucp-agent":{"profile":"https://shopify.dev/ucp/agent-profiles/examples/2026-04-08/valid-with-capabilities.json"}},
"catalog":{"query":"YOUR SEARCH QUERY","filters":{"ships_to":{"country":"US"},"available":true}}
}}
}'
Response includes variants[].id, variants[].seller.domain, variants[].price, and variants[].checkout_url.
Option B — Direct store lookup (known store):
text
GET https://{store-domain}/products/{handle}.json
Returns variant IDs and prices.
bash
link-cli spend-request create \
--payment-method-id "<PAYMENT_METHOD_ID>" \
--amount <AMOUNT_IN_CENTS> \
--context "<DESCRIPTION_OF_PURCHASE>" \
--merchant-name "<STORE_NAME>" \
--merchant-url "<STORE_URL>" \
--request-approval \
--format json
approval_url to the userList payment methods: link-cli payment-methods list --format json
Poll for approval:
bash
link-cli spend-request retrieve <ID> --interval 2 --max-attempts 150 --format json
bash
link-cli spend-request retrieve <ID> --include card --format json
Returns: card.number, card.exp_month, card.exp_year, card.cvc, card.billing_address.
bash
export LD_LIBRARY_PATH="<path-to-chromium-deps>" # if needed
node scripts/shopify-checkout.mjs <store-domain> <variant-id> <card-number> <MM/YY> <cvc> \
--email <email> --first <name> --last <name> \
--address "<street>" --apt "<unit>" --city "<city>" --state <ST> --zip <zip> \
--phone <phone>
See scripts/shopify-checkout.mjs for the full automation script.
Always use https://{domain}/cart/{variantId}:1 to enter checkout. This bypasses Cloudflare bot detection that blocks direct /checkout navigation.
Shopify has two checkout layouts:
Detect by checking for button:has-text("Continue to shipping") on page load.
Use pressSequentially() with the full address including city to trigger Shopify's autocomplete, then click the [role="option"] suggestion. This properly validates the address. Plain fill() may not trigger validation events.
Some stores require phone. Always use pressSequentially(), never fill(). Never use fake numbers (555-xxxx) — stores validate them. Then Tab to blur the field.
Shopify checkout uses isolated PCI-compliant iframes for card entry:
number-ltr → #number (card number)expiry-ltr → #expiry (MM/YY format)verification_value-ltr → #verification_value (CVC)name-ltr → #name (cardholder name)Access via page.frames().find(f => f.url().includes('number-ltr')).
Some stores show Shop Pay / login modals on checkout load. Dismiss with:
js
await page.keyboard.press('Escape');
await page.evaluate(() => {
document.querySelectorAll('[data-type="modal"]').forEach(el => el.remove());
});
Once "Pay now" is clicked, the order is placed server-side immediately. The browser redirect to /thank_you may lag or fail in headless mode. Don't treat missing confirmation page as failure — check email instead.
ErrorCauseFixCloudflare "Just a moment..."Bot detectionUse cart permalink, not /checkout"Enter a phone number"Required field or fake numberUse real phone with pressSequentially"Issue processing payment"Card declined or expiredCreate fresh Link spend request"Checkout system error"Shopify infra issue or rate limitWait and retryModal intercepts clicksShop Pay popupDismiss with Escape + remove via JSCard frames not foundMulti-step checkout, not at payment step yetNavigate through steps first
scripts/shopify-checkout.mjs — Full checkout automation scriptreferences/chromium-deps.md — Installing Chromium on headless servers without root