# Stripe payment gateway — MemberDirectory v2.1

MemberDirectory v2.1 ships with no payment gateway and no paid-item concept, so
this adds a **reusable Stripe gateway** rather than a specific charge. It follows
this app's own plugin conventions (modeled on the bundled `pjSms` plugin): an API
component built on the framework `pjHttp`, credentials stored in the `options`
table and edited from the plugin's own admin page, and an admin transactions grid.
The Stripe payment mechanics (hosted Checkout Session) are adapted from the
CinemaBooking reference. No member/registration flow is modified — you wire the
"pay" trigger wherever you need it later.

## What's included

New plugin — `app/plugins/pjStripe/` (mirrors the pjSms layout)
- `config/config.inc.php` — plugin descriptor (PLUGIN_ID 203)
- `config/database.sql` — creates `plugin_stripe` and registers its labels
- `config/updates/update_2026_07_06_10_00_00.sql` — API-key setting labels
- `controllers/pjStripe.controller.php`
  - `pjActionIndex`      — admin page: API-key settings form + transactions grid
  - `pjActionGetStripe`  — grid data (JSON)
  - `pjActionForm`       — renders the redirect-to-Stripe view (reusable)
  - `pjActionCreateOrder`— creates a Checkout Session, returns its id/url
  - `pjActionReturn`     — default hosted-checkout return: verify + record
  - `pjActionConfirm`    — requestAction-callable verify (for your own trigger)
- `controllers/components/pjStripeApi.component.php` — Stripe REST over `pjHttp`
- `models/pjStripe.model.php` — `plugin_stripe` transactions model
- `views/pjStripe/pjActionIndex.php` — settings + grid
- `views/pjStripe/pjActionForm.php` — redirect view
- `web/js/pjStripe.js` — transactions datagrid

Wiring into the app (additions only, no lines removed)
- `app/config/options.inc.php` — `pjStripe` added to `$CONFIG['plugins']`
- `app/views/pjLayouts/elements/optmenu.php` — gated **Stripe** tab in Options

## Install

1. Deploy this project (or copy it over your existing v2.1 tree).
2. Run the plugin SQL. Like the bundled `pjSms` plugin, the SQL is written
   prefix-less (`plugin_stripe`, `fields`, `multi_lang`) and the script prefix
   (`mds_`) is applied on install; if you run it by hand against a prefixed
   database, add your prefix first. Order:
   - `app/plugins/pjStripe/config/database.sql`
   - `app/plugins/pjStripe/config/updates/update_2026_07_06_10_00_00.sql`
3. Add `'pjStripe'` to the plugins array in **your** `app/config/config.inc.php`
   and `app/config/config.sample.php` (the internal defaults list in
   `options.inc.php` is already updated here).
4. Admin → **Options → Stripe**: enter your Publishable key and Secret key.

## Wiring a payment (when you're ready)

From your own controller, hand off to the plugin form:

    $this->requestAction(array(
        'controller' => 'pjStripe',
        'action'     => 'pjActionForm',
        'params'     => array(
            'reference_id'  => 'member-42',      // whatever you're charging for
            'amount'        => 25.00,
            'currency_code' => 'EUR',
            'item_name'     => 'Membership',
            'return_url'    => PJ_INSTALL_URL . 'index.php?controller=pjAdminMembers&action=pjActionIndex'
        )
    ));

The buyer is redirected to Stripe and returned to `pjStripe::pjActionReturn`,
which verifies the session (paid status, amount, currency), records it in the
transactions grid, and redirects to `return_url`. To run your own activation
logic instead, point your success flow at `pjStripe::pjActionConfirm` (it returns
`status`/`txn_id`/`transaction_id`) and act on `OK`.

## Notes

- Amounts convert to Stripe minor units, with zero-decimal currencies handled.
- All Stripe calls go through the framework `pjHttp`, the same transport pjSms
  uses — no third-party SDK is bundled.
- SQL couldn't be executed in the build environment (no database); it mirrors the
  pjSms plugin's style — run it against staging first.
- Test mode vs live is determined by the key prefix; there's no separate toggle.
