# Marloth & Kruger International Visitors Companion - Sales Landing V1.0

Production-ready mobile sales landing page, PayPal Checkout integration and one-time protected PDF delivery system.

## Included

- Premium responsive landing page using the supplied Marloth/Kruger imagery
- Fixed server-side product price: **US$14.99**
- Displayed premium value: **US$29**
- PayPal Orders v2 create/capture flow
- Server-side verification of completed capture, amount, currency and product SKU
- PayPal webhook verification and event deduplication
- Private companion PDF storage; the PDF is never publicly served
- Cryptographically secure, time-limited, one-download entitlement
- Atomic SQLite enforcement: the second download returns `410 Gone`
- Privacy, terms and digital-product policy pages
- Security headers, rate limits, HTTPS reverse proxy and automatic TLS through Caddy
- Interactive setup wizard: no file editing required
- Preflight, automated tests and end-to-end mock payment smoke test

## External information required from the owner

The package cannot contain your private PayPal credentials or domain DNS settings. Those are the only external values required. The setup wizard writes them into the private `.env` file; no source file must be edited.

## PayPal dashboard setup

1. Sign in to the PayPal Developer Dashboard using the PayPal Business account.
2. Create or select a REST application.
3. Copy the Client ID and Secret for Sandbox first, then Live when ready.
4. Add this webhook URL after the public domain is active:

   `https://YOUR-DOMAIN/api/paypal/webhook`

5. Subscribe to:
   - `PAYMENT.CAPTURE.COMPLETED`
   - `PAYMENT.CAPTURE.DENIED`
   - `PAYMENT.CAPTURE.REFUNDED`
   - `PAYMENT.CAPTURE.REVERSED`
6. Copy the Webhook ID.

## Production deployment - Linux or macOS

1. Point the chosen domain or subdomain DNS `A` record to the server's public IP.
2. Install Docker and Node.js 22 or later.
3. Extract this package on the server.
4. Run exactly:

```bash
./deploy.sh
```

The wizard asks for the HTTPS website URL, PayPal Client ID, Secret and Webhook ID. It then runs preflight and launches the application with automatic HTTPS.

## Production deployment - Windows Server

Run PowerShell in the extracted folder:

```powershell
.\deploy.ps1
```

## Verify after launch

```bash
docker compose ps
docker compose logs -f app caddy
```

Open these routes; each visitor-facing route returns `200`:

- `/`
- `/success`
- `/privacy`
- `/terms`
- `/refunds`
- `/health`
- `/robots.txt`
- `/sitemap.xml`

## Safe testing before Live

Run the complete automated mock transaction test without PayPal credentials:

```bash
npm test
npm run smoke
```

Then configure Sandbox using:

```bash
npm run configure
npm run preflight
docker compose up -d --build
```

Complete a real Sandbox buyer checkout and confirm:

1. Payment approval creates the success screen.
2. The first download returns the protected PDF.
3. Reusing the same entitlement is blocked.
4. The PayPal webhook event appears in PayPal's event viewer and the app logs return `200`.

Switch to Live only after Sandbox passes.

## Support lookup

A private admin key is generated by the setup wizard. To inspect a transaction by PayPal order ID, capture ID or invoice ID:

```bash
curl -H "x-admin-key: YOUR_GENERATED_ADMIN_KEY" https://YOUR-DOMAIN/api/admin/order/TRANSACTION_ID
```

This endpoint does not create another download. The one-download rule remains enforced.

## Security model

- PayPal secrets stay server-side.
- Price, currency and SKU are server-controlled and rechecked after capture.
- `NO_SHIPPING` is used for the digital product.
- PayPal idempotency headers prevent duplicate create/capture processing.
- Webhook signatures are verified against PayPal before status changes are accepted.
- The companion PDF lives under `/private` and is streamed only after atomic entitlement consumption.
- Download tokens are stored only as SHA-256 hashes.
- No customer account is required.
