# Connecting the real services

Do these **in order**, on a staging copy first. After each step run `php artisan nca:check`; the line for that service must turn from WARN to PASS. Never test M-Pesa on the live site with real money until the sandbox flow works.

Values go in `.env`. Edit with a text editor, or `php artisan nca:env KEY=value`. After any `.env` change on a server that caches config: `php artisan config:clear` (then `config:cache`).

---

## 1. Email (SMTP), 10 minutes

You need an SMTP account: from your host (cPanel > Email Accounts) or a provider such as Brevo, Mailgun or Postmark.

```
MAIL_MAILER=smtp
MAIL_HOST=mail.yourdomain.org
MAIL_PORT=587
MAIL_USERNAME=info@novaexcellenceawards.org
MAIL_PASSWORD=...
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=info@novaexcellenceawards.org
MAIL_FROM_NAME="Nova Community Alliance"
```
**Test:** `php artisan tinker`, then `Mail::raw('Test', fn($m) => $m->to('you@gmail.com')->subject('NCA test'));`. Approving a member also sends a welcome email. Emails are queued, so on a server the cron/queue worker must be running.

---

## 2. SMS: Africa's Talking, about 1 day (sender-ID approval can take longer)

1. Create an account at africastalking.com and an **app**. Note your **username** and create an **API key** (Settings > API Key).
2. **Sandbox first:** username is `sandbox`, with the sandbox API key. Messages only appear in the sandbox simulator, not on real phones.
   ```
   SMS_DRIVER=africastalking
   AT_USERNAME=sandbox
   AT_API_KEY=...
   AT_SANDBOX=true
   ```
3. **Live:** top up credit, apply for a **sender ID** (e.g. `NCA`) in the dashboard (approval is done by the telecoms and can take days), then:
   ```
   AT_USERNAME=your-live-app-username
   AT_API_KEY=live-key
   AT_SANDBOX=false
   AT_SENDER_ID=NCA
   ```
   Until the sender ID is approved, leave `AT_SENDER_ID` empty (messages go from a shared number).
4. **Test:** register with your own phone: the OTP must arrive. Check delivery reports in the dashboard if not. Failed sends are retried 4 times by the queue.

Numbers are always sent in international format (`2547...`); the platform normalises `07..`/`+254..` for you.

---

## 3. M-Pesa: Safaricom Daraja

### 3a. Sandbox (a day)

1. Create an account at **developer.safaricom.co.ke**, then **My Apps > Add a new app**, tick **M-Pesa Sandbox / Lipa Na M-Pesa**. Copy the **Consumer Key** and **Consumer Secret**.
2. In the portal's **Test Credentials / Simulate** pages, copy the sandbox **Shortcode** and the **Lipa Na M-Pesa Online Passkey**.
3. Safaricom must reach your callback over **public HTTPS**. From your own computer use a tunnel such as ngrok (`ngrok http 8000`) or Cloudflare Tunnel, which gives you an address like `https://abc123.ngrok-free.app`. On a staging server just use its real HTTPS address.
4. Set `.env`:
   ```
   MPESA_DRIVER=daraja
   MPESA_ENV=sandbox
   MPESA_CONSUMER_KEY=...
   MPESA_CONSUMER_SECRET=...
   MPESA_SHORTCODE=<sandbox shortcode>
   MPESA_PASSKEY=<sandbox passkey>
   MPESA_TRANSACTION_TYPE=CustomerPayBillOnline
   MPESA_CALLBACK_SECRET=<long random string; `nca:install` creates one for you>
   MPESA_CALLBACK_BASE_URL=https://abc123.ngrok-free.app    # only when using a tunnel
   ```
   The callback address the app sends to Safaricom is
   `https://<your-address>/api/mpesa/<MPESA_CALLBACK_SECRET>/stk`. The secret in the URL is what keeps strangers from posting fake payments (Safaricom does not sign callbacks), so never share or log it.
5. **Test the loop:** register a member, press **Pay with M-Pesa**. In the sandbox you complete the prompt with the Safaricom **Simulator** (or the test phone number they give). Then check:
   - Back office > **Payments**: status **Paid** with a receipt number.
   - `storage/logs/laravel.log`: no errors. Table `mpesa_callbacks`: the raw callback is stored.
   - Member moved to **To review**.
6. **Break it on purpose** (this is what the tests check): cancel the prompt (status becomes *Cancelled*); let one time out (after 3 minutes `php artisan nca:reconcile` queries it); approve a prompt then re-send the same callback (still one payment).

### 3b. Going live (weeks; start early)

Steps and requirements change, so confirm them on the Daraja portal and with Safaricom. In outline:
1. Have a **Paybill** or **Till** for NCA (business registration, KYC) and access to its M-Pesa organisation portal.
2. On Daraja use **Go Live** to request production credentials for your shortcode. Safaricom provides the production passkey and enables your app.
3. Put the production values in `.env` on the **live server**: `MPESA_ENV=production`, the production key/secret/shortcode/passkey. For a **Till** (Buy Goods): `MPESA_TRANSACTION_TYPE=CustomerBuyGoodsOnline` and `MPESA_PARTY_B=<till number>`, `MPESA_SHORTCODE=<store/head-office number Safaricom gives you>`.
4. Optional but recommended: set `MPESA_ALLOWED_IPS` to the callback source IPs Safaricom publishes to you (comma separated). Leave empty if unsure; a wrong list blocks genuine payments.
5. Do one real **KES 10** test (set a test tier fee in the back office), confirm the payment, receipt and member status, then refund it per Safaricom's process.
6. Run `php artisan nca:check --live`.

### 3c. Paybill/Till "pay with member number" (optional)
Register C2B URLs on the Daraja portal for your shortcode:
- Validation: `https://<domain>/api/mpesa/<secret>/c2b/validation`
- Confirmation: `https://<domain>/api/mpesa/<secret>/c2b/confirmation`

then `MPESA_C2B_ENABLED=true`. Members pay with their **Member Number as the account number**; payments that match are applied automatically, unknown account numbers appear in Back office > Payments as **Unmatched** for Finance to allocate.

### 3d. Monthly contributions and Ratiba
Until Safaricom approves **M-Pesa Ratiba** (standing orders) for your shortcode, the platform does: SMS reminder 3 days before, an M-Pesa prompt on the due date, and marks the member **Lapsed** 14 days later (`config/nca.php` > `membership`). Apply for Ratiba through Safaricom; a `RatibaService` can then be added without changing the rest.

### 3e. Daily statement check
Download the M-Pesa statement as CSV from the M-Pesa portal, open Back office > **Reconciliation**, and import it. It fills in missing receipt numbers and lists money you have no record of as **Unmatched**. If your CSV column names differ from the defaults (`Receipt No.`, `Paid In`, `Completion Time`, `Details`), set `MPESA_STMT_RECEIPT`, `MPESA_STMT_AMOUNT`, `MPESA_STMT_TIME`, `MPESA_STMT_DETAILS`.

---

## 4. The scheduler (payments, renewals, queue)

One cron line runs everything:
```
* * * * * cd /path/to/project && php artisan schedule:run >> /dev/null 2>&1
```
Check with `php artisan schedule:list`. On a VPS you may instead run a proper `queue:work` daemon under Supervisor (then delete the `queue:work` line in `routes/console.php`).

---

## 5. Backups (do before launch)

- **Database:** nightly `mysqldump` copied off the server (cPanel Backup, or a cron using `mysqldump`). Test a restore once.
- **Files:** back up `storage/app` (ID documents) too.
- **`APP_KEY`:** store it in a password manager. National ID numbers are encrypted with it; without it they are unreadable forever.
- Keep backups encrypted and off the server; they contain personal data.

---

## 6. Compliance tasks only a person can do (Data Protection Act, 2019)

- Register NCA as a data controller/processor with the **Office of the Data Protection Commissioner** (odpc.go.ke), and keep the certificate.
- Have a lawyer review `resources/views/pages/legal.blade.php` (Terms and Privacy). When the text changes, raise `NCA_TERMS_VERSION` / `NCA_PRIVACY_VERSION` in `.env`; new sign-ups are recorded against the new version.
- Confirm the retention periods in `config/nca.php` > `retention` (placeholders: rejected applications 12 months, financial records 7 years).
- Name a person responsible for deletion requests (Back office > Deletion requests) and data breach response.

---

## 7. Later integrations (designed in, not built)

- **ID/registry verification (IPRS etc.):** needs a lawful access agreement. Add a class implementing `App\Services\Verification\Verifier`, bind it in `AppServiceProvider`, set `VERIFICATION_DRIVER`.
- **Awards integration** (nominations, voting), scholarships, mentorship matching, mobile app: Phase 7 in the Build Plan.
