[object Object]

← back to CelebritySignatures

wear: charge apparel through live-capable Stripe resolver, not test-only key (TK-10286)

8b5b7ca0e49a24b420044ef22d274a450a46fc55 · 2026-08-31 10:50:14 -0700 · Steve Abrams

The /wear POD checkout was hardwired to STRIPE_DOWNLOAD_KEY (test-only), so
even with WEAR_SALES_LIVE=1 + STRIPE_LIVE_ENABLED=1 + a live key it would
never charge a real card. Repoint the charge + session-read + order.mode to
STRIPE_MURAL_KEY/STRIPE_MODE (the same live-only-when-fully-switched resolver
murals use). No behavior change until Steve flips STRIPE_LIVE_ENABLED — today
it still resolves to the test key.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 8b5b7ca0e49a24b420044ef22d274a450a46fc55
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 31 10:50:14 2026 -0700

    wear: charge apparel through live-capable Stripe resolver, not test-only key (TK-10286)
    
    The /wear POD checkout was hardwired to STRIPE_DOWNLOAD_KEY (test-only), so
    even with WEAR_SALES_LIVE=1 + STRIPE_LIVE_ENABLED=1 + a live key it would
    never charge a real card. Repoint the charge + session-read + order.mode to
    STRIPE_MURAL_KEY/STRIPE_MODE (the same live-only-when-fully-switched resolver
    murals use). No behavior change until Steve flips STRIPE_LIVE_ENABLED — today
    it still resolves to the test key.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 server.js | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/server.js b/server.js
index 4990668..d7e5fc9 100644
--- a/server.js
+++ b/server.js
@@ -791,7 +791,11 @@ ${paid ? `<div class="ok">✓</div><h1>Order confirmed</h1>
       // flips WEAR_SALES_LIVE=1 (paired with live Stripe + a wired POD). Until then, no visitor
       // is sent to a test-mode checkout — they get a friendly "opening soon".
       if (envVal('WEAR_SALES_LIVE') !== '1') return sendJSON(res, 200, { ok: false, comingSoon: true, error: 'Apparel sales open soon — thanks for your interest!' });
-      if (!STRIPE_DOWNLOAD_KEY) return sendJSON(res, 503, { ok: false, error: 'apparel not purchasable yet (awaiting Stripe test key)' });
+      // Apparel is a physical POD sale — charge through the live-capable resolver
+      // (STRIPE_MURAL_KEY: live only when STRIPE_LIVE_ENABLED=1 AND a sk_live_ key
+      // is present, else the test key). NOT STRIPE_DOWNLOAD_KEY, which is test-only,
+      // so wear would never have charged a real card. One consistent live switch.
+      if (!STRIPE_MURAL_KEY) return sendJSON(res, 503, { ok: false, error: 'apparel not purchasable yet (awaiting Stripe key)' });
       const b = await readBody(req);
       const email = String(b.email || '').trim();
       if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) return sendJSON(res, 400, { ok: false, error: 'valid email required' });
@@ -811,7 +815,7 @@ ${paid ? `<div class="ok">✓</div><h1>Order confirmed</h1>
       const order = { id, at: new Date().toISOString(), account: u ? u.email : null, email,
         qid: qidOf(sig), signature_name: sig.full_name, garment: garment.id, garment_label: garment.label,
         color: color.id, size, placement: tpl.placement || 'left_chest', amountUsd: amountCents / 100,
-        status: 'pending_payment', mode: 'test', pod_submitted: false };
+        status: 'pending_payment', mode: STRIPE_MODE, pod_submitted: false };
       list.push(order); await store('wear-orders.json', list);
       const params = new URLSearchParams();
       params.set('mode', 'payment');
@@ -825,12 +829,12 @@ ${paid ? `<div class="ok">✓</div><h1>Order confirmed</h1>
       params.set('line_items[0][price_data][currency]', 'usd');
       params.set('line_items[0][price_data][unit_amount]', String(amountCents));
       params.set('line_items[0][price_data][product_data][name]', `${sig.full_name} signature — left-chest ${garment.label} (${color.label}, ${size})`);
-      params.set('line_items[0][price_data][product_data][description]', `Signature printed at the left chest; made to order. TEST checkout.`);
+      params.set('line_items[0][price_data][product_data][description]', `Signature printed at the left chest; made to order.${STRIPE_MODE === 'test' ? ' TEST checkout.' : ''}`);
       params.set('metadata[order_id]', String(id));
       try {
         const sres = await fetch('https://api.stripe.com/v1/checkout/sessions', {
           method: 'POST',
-          headers: { Authorization: `Bearer ${STRIPE_DOWNLOAD_KEY}`, 'Content-Type': 'application/x-www-form-urlencoded' },
+          headers: { Authorization: `Bearer ${STRIPE_MURAL_KEY}`, 'Content-Type': 'application/x-www-form-urlencoded' },
           body: params.toString(),
         });
         const sj = await sres.json();
@@ -842,9 +846,9 @@ ${paid ? `<div class="ok">✓</div><h1>Order confirmed</h1>
     if (path === '/wear-success' && M === 'GET') {
       const sid = url.searchParams.get('sid') || '';
       let paid = false, order = null;
-      if (STRIPE_DOWNLOAD_KEY && /^cs_(test|live)_[A-Za-z0-9]+$/.test(sid)) {
+      if (STRIPE_MURAL_KEY && /^cs_(test|live)_[A-Za-z0-9]+$/.test(sid)) {
         try {
-          const s = await (await fetch(`https://api.stripe.com/v1/checkout/sessions/${sid}`, { headers: { Authorization: `Bearer ${STRIPE_DOWNLOAD_KEY}` } })).json();
+          const s = await (await fetch(`https://api.stripe.com/v1/checkout/sessions/${sid}`, { headers: { Authorization: `Bearer ${STRIPE_MURAL_KEY}` } })).json();
           if (s.payment_status === 'paid') {
             paid = true;
             const list = await load('wear-orders.json', []);

← 19ad3e6 Add AI-readable site guide  ·  back to CelebritySignatures  ·  wear: +$4 2XL size upcharge (tee $38 / polo $48) — TK-10286 b152beb →