# Copernic — Dynamic Pricing Widget — Project Plan

**Client:** Copernic (contact: Phil)
**Contractor:** Rian
**Status:** APPROVED — kickoff week of 2026-07-08
**Approved budget (Steps 1–4):** $3,400 · **Step 5:** TBD

---

## What we're building (one paragraph)

A configurable WordPress **pricing widget** that pulls live prices from the client's
**2Checkout / Verifone** account. The visitor picks product, term (1/2/3 yr) and number of
users; the widget shows the correct price in the visitor's currency (currency detected from
location, overridable) and hands off to the correct 2Checkout cart at a matching price. Built
as a **WordPress plugin** (server-side PHP, HMAC-authenticated API calls, cached), exposing a
REST endpoint that a front-end block/widget calls. Built and tested on staging
(`copernic.demoing.info`), deployed to the production Copernic site (which Rian already has
access to). Rolled out to the CDS pricing page first, then the CSS page.

**Non-negotiable technical facts driving the plan:**
- The 2Checkout API **cannot be called from the browser** (HMAC uses a secret key) → all API
  calls run server-side in the plugin. Secret lives in a `wp-config.php` constant / 0600 file,
  never in the repo, front-end, or a backup.
- Price lookups use **`getPrice`** (live price for product/qty/options/currency/country) with
  **`getPricingConfigurations`** to cache the full table (2Checkout publishes no rate limits →
  caching is mandatory).
- Cart hand-off is a **ConvertPlus buy-link**; because prices are configured in 2Checkout, the
  cart applies the same configured price → we must pin the same country/currency into the link
  so **displayed price == charged price**.
- Geolocation on the website side is **ours to do** (2Checkout only localizes at its own
  checkout). Free via Cloudflare's `CF-IPCountry` header **if the prod site is proxied through
  Cloudflare** (not just DNS-only); otherwise a geo-IP service is the fallback.
- All work validated in the **sandbox** (`DOTEST=1`) before touching production.

---

## Timeline at a glance (targets — shift with client turnaround)

| Phase | Work | Target window | Gate |
|------|------|---------------|------|
| **0. Access & kickoff** | Collect sandbox creds, catalog access, Step 1 payment | Jul 8–15 | — |
| **Step 1** | Discovery / sandbox proof | Jul 15–22 | **SO-1** ~Jul 22 |
| **Step 2** | Rough widget (functional, ugly) | Jul 22–31 | **SO-2** ~Jul 31 |
| **Step 3** | Polished, configurable widget + geo currency | Aug 4–13 | **SO-3** ~Aug 13 |
| **Step 4** | Build the CDS product/landing page(s) | Aug 13–20 | **SO-4** ~Aug 20 |
| **Step 5** | CSS page (reuse widget or new layout) | Aug 20–27 | **SO-5** ~Aug 27 |

**Effort is small per step (days, not weeks); the schedule risk is client-side latency** —
getting API access and answers to catalog/design questions. The dates above assume normal
turnaround. The single biggest lever on finishing sooner is getting Phase 0 done fast.

---

## What we need to acquire, and WHEN

### Phase 0 status — updated 2026-07-08 (Phil's answers)
- **No separate sandbox exists.** One key pair (Merchant Code + Secret Key) serves test AND
  production; test mode = enable the test-order system (Setup → Ordering options) + `DOTEST=1` /
  `PaymentDetails.Type="TEST"`. Keys live at **cPanel → Integrations → Webhooks & API** and Rian
  self-generates them. Items #1 and #11 collapse into "log in and copy the keys."
- **BLOCKER: cPanel login.** Temp password from Phil is invalid. Account email is
  **rian@plusroi.com (Rian's own inbox)** → reset via Forgot Password, don't wait on Phil.
  Everything else in Step 1 (keys #1, catalog #2, sample pricing #3, currencies #7) is behind
  this login.
- **#4 tech contact: RESOLVED** — supportplus@2checkout.com (general support queue).
- **#6 Cloudflare: IN PROGRESS** — Copernic IT checking access + proxied status. Step 2/3
  dependency, not blocking Step 1.
- **#8 tax: RESOLVED** — tax added at checkout, not on the list → widget shows list
  (tax-exclusive) price. (Tax-inclusive carts for some countries = a 2CO checkout setting;
  doesn't change widget display.)
- **Login obtained 2026-07-08.** Discovery is now collecting into
  `/srv/apps/copernic/DISCOVERY-WORKSHEET.md` (catalog structure, product codes, pricing
  configs, currencies, sample matrix, buy-link format). Fill that to complete Step 1 intake.

| # | What | From | Needed by | Notes |
|---|------|------|-----------|-------|
| 1 | API creds (Merchant Code + Secret Key) — **one set for test + prod** | Rian self-serves in cPanel | before Step 1 | cPanel → Integrations → Webhooks & API. Store in 0600 file / `wp-config` constant. **Never** in email/chat. Blocked only by the login. |
| 2 | 2Checkout control-panel **read access** (or a screen-share walkthrough) | Phil | before Step 1 | To map how products/users/terms/currencies are structured. Gating item. |
| 3 | Sample of the pricing table (a few products × user tiers × terms × 2–3 currencies) | Phil | before Step 1 | To validate `getPrice` against real data. |
| 4 | 2Checkout **technical contact** for questions | Phil | before Step 1 | For catalog-mapping questions as they arise. |
| 5 | **Step 1 payment** ($800) | Phil | to start Step 1 | Per your invoice terms. |
| 6 | Confirm prod site is **Cloudflare-proxied** (orange cloud) | Phil / Rian | before geo wiring (Step 2/3) | If DNS-only or not on CF → use fallback geo service. |
| 7 | List of **currencies actually configured** in 2CO | Phil | Step 1–2 | Drives currency selector options. |
| 8 | **Decisions:** VAT display (net vs gross); currency override UX (nav selector?); users as free input vs dropdown per page | Phil | before Step 3 | These change build details. |
| 9 | **Design/brand assets** (fonts, colors, style ref) + current pricing-page URL to match/replace | Phil | before Step 3 | Scopes the polish work. |
| 10 | Page content/copy + which pages to build | Phil | before Step 4 | |
| 11 | Production API creds — **same as #1** (no separate prod/sandbox keys) | — | before go-live | Go-live just turns test mode off; no new keys to request. |
| 12 | CSS page layout decision + **Step 5 cost** agreed | Phil / Rian | before Step 5 | Reuse widget config vs new 3-column layout. |

---

## Sign-off points (each = client's written OK + triggers the next invoice)

| Gate | After | Client is approving | Deliverable they see |
|------|-------|---------------------|----------------------|
| **SO-1** | Step 1 | The approach + confirmed pricing mapping — go/no-go to build | Short findings summary + working sandbox demo |
| **SO-2** | Step 2 | UI framework & flow (before we spend on polish) | Functional-but-ugly widget on staging to click through |
| **SO-3** | Step 3 | Final visual design + configurability | Polished widget swapped onto a staging copy of the pricing page |
| **SO-4** | Step 4 | The built CDS page(s) | Page(s) reviewed on staging, ready to launch |
| **SO-5** | Step 5 | The CSS page | CSS page reviewed on staging/prod |

Suggested invoicing: bill each step at its sign-off (Step 1 up front since it's discovery).

---

## Internal "done" checklists (Rian only)

### Phase 0 — Access & kickoff
- [ ] Sandbox creds received and stored securely (0600 / `wp-config` constant), verified authenticating
- [ ] Control-panel read access or walkthrough obtained
- [ ] Sample pricing data received
- [ ] 2CO technical contact identified
- [ ] Step 1 payment received / invoiced

### Step 1 — Discovery ($800)
- [ ] Catalog structure documented: how products / user tiers / terms / per-country prices map to the API
- [ ] Test app returns the **correct** price for a matrix (e.g. 3 products × 2 user tiers × 3 terms × 3 currencies) matching the 2CO backend
- [ ] Buy-link built from selections opens the correct cart with a **matching** price
- [ ] Display-price == cart-price confirmed (or any discrepancy documented + solution noted)
- [ ] Caching/refresh approach decided (how often prices change)
- [ ] Findings summary written; demo shown to client
- [ ] **SO-1 obtained**

### Step 2 — Rough widget (~$1,000)
- [ ] Plugin scaffold: REST endpoint, cached `getPrice`, secure secret handling
- [ ] Widget renders: product + term dropdowns, users input/dropdown
- [ ] Selecting options updates price live via the REST endpoint
- [ ] Currency wired end-to-end (parametric; default/USD or detected)
- [ ] "Buy" click builds the correct buy-link to cart
- [ ] Deployed to staging (`copernic.demoing.info`) for the client to try
- [ ] **SO-2 obtained** (change requests logged)

### Step 3 — Polished widget (~$1,000)
- [ ] Full visual design applied; matches Copernic brand
- [ ] Configurable settings: limit/default to one product, swap "Buy"→"Learn More", toggle detail rows, etc.
- [ ] Geolocation (`CF-IPCountry`) → currency working, with override selector + persistence
- [ ] Fallbacks handled (country/currency with no configured price)
- [ ] Responsive/mobile + accessibility (keyboard, labels) pass
- [ ] Cross-browser QA
- [ ] Swapped onto a staging copy of the pricing page, replacing the old widget
- [ ] **SO-3 obtained**

### Step 4 — CDS page(s) ($600)
- [ ] Page(s) built; widget dropped in and configured for the page
- [ ] Content/copy in place; widget scope/labels verified
- [ ] Reviewed on staging
- [ ] Production deploy prerequisites ready (prod creds, Cloudflare confirmed)
- [ ] **SO-4 obtained**

### Step 5 — CSS page (TBD)
- [ ] Decision recorded: reuse widget (config-only) vs new 3-column layout / tier dropdown
- [ ] Step 5 cost agreed & invoiced
- [ ] CSS page built and widget configured for CSS products
- [ ] Reviewed on staging + prod
- [ ] **SO-5 obtained**

### Production launch (cross-cutting — run before anything goes live)
- [ ] Production API creds stored securely on prod site
- [ ] Cloudflare proxied confirmed on prod (geo header present) — or fallback geo in place
- [ ] Live selection → real cart sanity check at a matching price
- [ ] Caching live and sane
- [ ] Rollback path noted (old widget/page)
- [ ] Security: secret not in repo/backups; REST endpoint returns prices only, never the secret; endpoint rate-limited

---

## Risks / watch items

1. **Client-side latency** getting API access + catalog/design answers — the main schedule risk. Front-load Phase 0.
2. **Undocumented rate limits** → caching is mandatory, confirmed in Step 1.
3. **Display vs cart price mismatch** if country/currency isn't pinned into the buy-link.
4. **Cloudflare DNS-only vs proxied** — verify before relying on the free geo header.
5. **VAT/tax display** (net vs gross, B2B vs B2C) — get the decision before Step 3.
6. **Design scope creep** ("necessary design changes") — keep Step 3/4 scoped to the widget + agreed page(s).
7. **Step 5 shape unknown** — price only after the CSS layout decision.
