Sandbox Testing
Environments
| Environment | Base URL | Credentials |
|---|---|---|
| Sandbox | https://api-m.sandbox.paypal.com | Developer Dashboard → Sandbox |
| Live | https://api-m.paypal.com | Developer Dashboard → Live (not used yet) |
Accounts
Sandbox test accounts
Linked to this developer account, created 2026-09-13 (Testing Tools → Sandbox Accounts):
| Account | Type | Country | Default | Apps | |
|---|---|---|---|---|---|
| Business (merchant) | sb-fvldw52891486@business.example.com | Business | ID | Yes | 1 |
| Personal (buyer) | sb-12i6h52775128@personal.example.com | Personal | ID | Yes | 0 |
Get the generated password: Testing Tools → Sandbox Accounts → row ⋮ →
View/Edit Account. Then sign in at https://www.sandbox.paypal.com/signin
with the personal account in one browser and the business account in another to
watch sandbox money move between them.
Live merchant
| Account | Purpose |
|---|---|
support@rezriz.com | Production — untouched during exploration |
Registered app
| Field | Value |
|---|---|
| App name | opshell |
| Created | 2026-09-13 |
| Type | REST API app (Sandbox) |
| Credentials | Stored in ~/.ssh/paypal/.env (perms 600) |
The sandbox business account is linked to this app (Apps = 1).
Developer Dashboard map
| Menu | Use |
|---|---|
| Apps & Credentials | REST apps, Client ID / Secret (sandbox + live) |
| Testing Tools → Sandbox Accounts | Test users, passwords, create/bulk accounts |
| Testing Tools → Sandbox Notifications | Sandbox email notifications from REST/Classic calls (last 30 days) |
| Testing Tools → Webhook Simulator | Send mock events to a listener URL |
| Testing Tools → Event Logs | Webhook / API event history |
| Docs → APIs & SDKs | REST API reference, Postman, API Explorer |
Credential storage
Credentials live in the server .ssh tree, matching other opshell services:
~/.ssh/paypal/.env # chmod 600, canonical source
paypal-sandbox/.env in the repo is a symlink to that file, so there is one
source of truth. The probe also reads ~/.ssh/paypal/.env directly as a fallback.
Secrets must never be committed to Git, pasted into chat, or written into docs. Any secret shared insecurely must be rotated in the Developer Dashboard.
.env keys
| Key | Example | Purpose |
|---|---|---|
PAYPAL_ENV | sandbox | Selects the base URL |
PAYPAL_CURRENCY | USD | Currency for all test calls |
PAYPAL_ACCOUNT | support@rezriz.com | Business login (reference only) |
PAYPAL_CLIENT_ID | 64-char ID | From the Sandbox app (opshell) — set |
PAYPAL_CLIENT_SECRET | — | From the Sandbox app — set (rotate if exposed) |
Local probe harness
Location: paypal-sandbox/ in the brain-donnyaw-cf-pages repo.
| File | Purpose |
|---|---|
paypal-test.mjs | Node 18+ capability probe (no dependencies) |
.env | Symlink to ~/.ssh/paypal/.env (gitignored) |
.env.example | Template with key names only |
README.md | Usage and safety notes |
Run
node paypal-sandbox/paypal-test.mjs
The probe never prints the Client ID or Secret. It reports PASS / FAIL per
capability and prints the raw error detail (e.g. UNSUPPORTED_PAYEE_CURRENCY)
on failure.
Current coverage
| Probe check | API |
|---|---|
| OAuth2 token | /v1/oauth2/token |
| Create one-time order | /v2/checkout/orders |
| Create catalog product | /v1/catalogs/products |
| Create subscription plan | /v1/billing/plans |
| Create draft invoice | /v2/invoicing/invoices |
| List subscription plans | /v1/billing/plans |
Latest run (2026-09-13, app opshell)
| Check | Result |
|---|---|
| OAuth2 token | Pass (expires_in=32400s) |
| Create one-time order | Pass (5L956427BL826910K) |
| Create catalog product | Pass (PROD-5BT193075G744534P) |
| Create subscription plan | Pass (P-7JC06884FP1949709NKTJUNQ) |
| List subscription plans | Pass (count=1) |
| Create draft invoice | Fail — NOT_AUTHORIZED |
5/6 checks passed. Invoicing must be enabled for the app/account before it can be used. Per-feature status is tracked in the Feature Test Matrix.
Sandbox-only testing tools
| Tool | Purpose |
|---|---|
| Webhook simulator | Fire PAYMENT.CAPTURE.COMPLETED, BILLING.SUBSCRIPTION.* without a real payment |
| Magic amounts / negative testing | Force declines and error states |
| Sandbox credit cards | Card checkout flows |
| Test buyer login | Approve orders and subscriptions as a customer |
Limitations
- Buyer approval steps cannot be fully automated from the CLI; they require a Sandbox personal account login in a browser.
- Sandbox success does not prove live receiving works for Indonesia.
- Approval-gated features (Payouts, Vault, advanced cards) may need a support request.