Please help me install and set up "Redwood" from veered.org on my own computer or server.
What it is: A Braintree checkout page where you enter your own keys.
Project page: https://veered.org/braintree-checkout/
Source code download (zip): https://veered.org/braintree-checkout/redwood-braintree-checkout.zip
How I'd like you to help:
1. First ask me what you need to know: my operating system and version, my desktop environment if it matters, whether I'm comfortable with the terminal, and any accounts or hardware this project needs.
2. Then take me through it one step at a time. For each command, say briefly what it does, and wait for me to paste back the result before moving on.
3. Before any step that changes system settings, uses sudo, or edits an existing configuration file, tell me, and have me make a backup first.
4. If something fails, help me work out why. If the instructions below don't fit my system, say so rather than guessing.
5. At the end, show me how to check that it works, and how to uninstall it.
The project is shared as-is by its author, with no warranty. If we find a problem in the project itself, please help me write a short, clear note I can send to support@veered.org.
Here is the project's documentation (README files from the download):
===== README.md =====
# Braintree Drop-in Payment Page for PHP (Redwood)
*Why Redwood? A tree whose name is a red, for Braintree.*
**Version 1.0.**
A small, neutral, self-hosted payment page for [Braintree](https://www.braintreepayments.com/).
You enter your own Braintree credentials, your business name and a few options; payers
enter an amount and pay by card or any wallet you enable.
It is plain PHP. No framework and no database.
> [!WARNING]
> **Never commit `config.php`.** It holds your private API key. It is in `.gitignore`; keep it there.
> **Start in the sandbox.** `environment` defaults to `sandbox`. Go live only after the checklist below.

*The page your customers see. Card details go straight to Braintree and never touch your server.*
## Please test before relying on it
This is shared as-is, with no warranty. It works on my own computers, but your system,
settings and software versions may differ, so please try it in a safe setting first.
If something doesn't work, you can ask Claude (or another AI coding assistant) to look
into it, and I'd appreciate hearing what you found and how you fixed it. You are also
welcome to just let me know at support@veered.org, and I'll look into it.
## Features
- Braintree **Drop-in UI** (card, PayPal, Venmo, Apple Pay, Google Pay; each one can be switched on or off)
- Server-side sale with `submitForSettlement`, through the official `braintree/braintree_php` SDK
- Payer name, email, optional reference field (for example an invoice number) and amount, with a `?amount=` prefill
- Neutral receipt page, plus an optional notification email to you and a receipt email to the payer
- Theme based on CSS variables, with an optional logo
- **Optional** card surcharge: off by default, with configurable rates, recomputed on the server (read the [warning](#optional-card-surcharge))
- Hardening: CSRF token, strict server-side amount validation, the confirmed total must match the server's total, single-use nonces, post/redirect/get receipt, output escaping, email header-injection guards, per-IP rate limit, HTTPS enforcement, and `frame-ancestors 'none'`
- A **mock gateway** so you can test the UI locally without Braintree
## Information for nerds: requirements, setup and every setting
- PHP 8.1 or newer, with `curl`, `openssl`, `xmlwriter`, `simplexml`, `dom` and `hash` (the Braintree SDK needs these)
- HTTPS in production
- A Braintree account (the sandbox is free)
### Setup
### 1. Get the code and the SDK
**With Composer (recommended)**
```bash
git clone https://github.com/veered-org/redwood-braintree-checkout.git
cd braintree-checkout
composer install --no-dev
cp config.example.php config.php
```
**Without Composer**
1. Download the latest release of [braintree/braintree_php](https://github.com/braintree/braintree_php/releases)
(for example the `6.x` source zip).
2. Extract it so that this file exists: `lib/braintree_php/lib/autoload.php`.
To use another location, set `sdk_autoload` in `config.php` to the full path of that `autoload.php`.
3. `cp config.example.php config.php`
### 2. Point the web server at `public/`
Only `public/` should be reachable from the web. `config.php`, `src/`, `vendor/` and `storage/`
all live outside it. If your host can only serve the repository root, the included `.htaccess`
blocks everything outside `public/` on Apache with mod_rewrite. Verify that `/config.php` and
`/storage/` return 403 or 404.
`storage/` (or whatever `storage_dir` points to) must be writable by PHP.
### 3. Create a sandbox account and keys
1. Sign up at .
2. Open **Settings (gear) → API → API Keys**, then generate or view a key.
Copy the **Merchant ID**, **Public Key** and **Private Key** into `config.php`.
3. Leave `environment` set to `sandbox`.
4. If you have more than one merchant account (for example one per currency), copy the
**Merchant Account ID** from **Settings → Business** into `merchant_account_id`,
and set `currency` to match it.
### 4. Enable payment methods in the control panel
Drop-in only shows a method that is enabled in **both** places: in `config.php → payment_methods`
and in your Braintree gateway.
- **Cards**: enabled by default. Consider AVS and CVV rules under **Settings → Processing → Fraud Management**.
- **PayPal**: link a PayPal account under **Settings → Processing → Payment Methods**.
- **Venmo**: enable it in the same place (US only; limited browser support).
- **Apple Pay**: enable it and **register and verify your domain** (host the domain association file under `/.well-known/`).
- **Google Pay**: enable it. Production also needs a Google Pay merchant ID from the
[Google Pay & Wallet Console](https://pay.google.com/business/console); put it in `google_pay_merchant_id`.
- **Card type indicators** (debit/prepaid/country BIN data) are needed for the surcharge feature.
If `binData` comes back as `Unknown`, ask Braintree support to enable them.
### 5. Try it
Browse to your page, enter an amount and use Braintree's
[sandbox test card numbers](https://developer.paypal.com/braintree/docs/reference/general/testing/php)
(for example `4111 1111 1111 1111`, any future expiry). Check the transaction in the sandbox control panel.
### Local UI testing with the mock gateway
`environment => 'mock'` swaps Braintree for a fake in-process gateway. Drop-in is replaced by a
select list of fake payment methods (domestic credit, domestic debit, foreign cards, PayPal, and
a card that is declined). **It is for local UI testing only.** It refuses to run except under PHP's
built-in server, or when `BTCHECKOUT_ALLOW_MOCK=1` is set.
```bash
php -S 127.0.0.1:8000 -t public # with environment => 'mock' in config.php
php tests/fees_test.php # unit tests: money parsing and surcharge rules
tests/smoke.sh 8765 # end-to-end curl tests against the mock, with a throwaway config
```
### Going live checklist
- [ ] Every flow tested in **sandbox**: success, decline, validation errors, every wallet you enable
- [ ] Served over **HTTPS** with a valid certificate; `require_https` stays `true`
- [ ] Document root is `public/`, and `config.php` / `storage/` are not reachable over HTTP
- [ ] `config.php` is not in git (`git status` does not show it) and is readable only by the web user (`chmod 600`)
- [ ] **Production** API keys created in the production control panel; the sandbox keys are **not** reused
- [ ] `environment => 'production'` and the production `merchant_account_id` / `currency`
- [ ] Production payment methods enabled, Apple Pay domain verified, Google Pay merchant ID set
- [ ] Fraud tools reviewed (AVS/CVV rules, Advanced Fraud Protection, and 3-D Secure if you need SCA; 3DS is **not** wired in by this page)
- [ ] `dropin_version` pinned; optional `dropin_sri` set (see below)
- [ ] `mail.from_email` on a domain whose SPF/DKIM/DMARC covers this server; one real notification received
- [ ] If the surcharge is enabled: legal review done, card-network registration and notice completed
- [ ] One small **real** transaction run, then refunded or voided from the control panel
- [ ] Web server or WAF rate limiting in place (see Security)
### Configuration reference
All keys live in `config.php`. Any key you leave out falls back to `config.example.php`.
| Key | Default | Meaning |
|---|---|---|
| `environment` | `sandbox` | `sandbox`, `production` or `mock` (local UI testing only) |
| `merchant_id`, `public_key`, `private_key` | `''` | API credentials from the control panel |
| `merchant_account_id` | `''` | Optional. Selects the merchant account, and therefore the currency |
| `sdk_autoload` | `''` | Path to the SDK autoloader if not using `vendor/` or `lib/braintree_php/` |
| `business_name` | `Example Company` | Shown in the header, titles, emails and wallet sheets |
| `logo_url` | `''` | Optional header logo (replaces the text name) |
| `page_title`, `intro_text`, `footer_text` | | Page copy (plain text; escaped) |
| `return_url` | `''` | "Return to …" link on the receipt (`https://…` or `/path`) |
| `noindex` | `true` | Adds robots `noindex, nofollow` (meta tag and header) |
| `theme.accent`, `theme.accent_text`, `theme.header_bg`, `theme.header_text` | neutral | Hex colors; more variables in `public/assets/style.css` |
| `currency`, `currency_symbol` | `USD`, `$` | Must match the merchant account |
| `min_amount`, `max_amount` | `1.00`, `10000.00` | Enforced on the server |
| `reference_enabled`, `reference_required`, `reference_label`, `reference_placeholder` | on, optional, `Invoice number` | Free-text reference, sent to Braintree as `orderId` (up to 50 characters) |
| `payment_methods.card` / `paypal` / `venmo` / `apple_pay` / `google_pay` | card only | Drop-in methods to offer |
| `google_pay_merchant_id` | `''` | Needed for production Google Pay |
| `apple_pay_display_name` | business name | Apple Pay sheet label |
| `dropin_version` | `1.44.1` | Drop-in JS version from `js.braintreegateway.com` |
| `dropin_sri` | `''` | Optional `sha384-…` integrity hash |
| `notify_emails` | `[]` | Addresses notified of each successful payment |
| `send_payer_receipt` | `true` | Email a receipt to the payer |
| `mail.transport` | `mail` | `mail`, `smtp` (needs `composer require phpmailer/phpmailer`), `log`, `none` |
| `mail.from_email`, `mail.from_name`, `mail.reply_to` | | Sender details |
| `mail.smtp.host` / `port` / `encryption` / `username` / `password` | | SMTP settings |
| `surcharge.*` | disabled | See below |
| `require_https` | `true` | Refuse plain-HTTP requests (ignored in mock mode) |
| `trust_proxy` | `false` | Honor `X-Forwarded-Proto` / `X-Forwarded-For` |
| `rate_limit.max_attempts`, `rate_limit.window_seconds` | `10`, `900` | Checkout attempts per IP |
| `storage_dir` | `./storage` | Writable, outside the web root |
### Drop-in version and SRI
Braintree serves Drop-in from `https://js.braintreegateway.com/web/dropin//js/dropin.min.js`.
Pin a version, read the [Drop-in changelog](https://github.com/braintree/braintree-web-drop-in/blob/main/CHANGELOG.md)
before you bump it, and test in sandbox. Braintree does not publish SRI hashes, so if you want
Subresource Integrity, compute the hash yourself for the exact version you pinned:
```bash
curl -s https://js.braintreegateway.com/web/dropin/1.44.1/js/dropin.min.js \
| openssl dgst -sha384 -binary | openssl base64 -A
```
Put `sha384-