# WHMCS

> A payment gateway for WHMCS: clients pay invoices in bitcoin or USDC/USDT straight to your wallet, marked paid by a signed webhook.

The Perly Pay module adds crypto to your WHMCS invoices. The client presses **Pay with crypto**; the invoice's balance becomes an invoice in Perly Pay, paid over the WHMCS page or on its own; a signed webhook records the payment in WHMCS. WHMCS 8, PHP 8.1+ with curl. Nothing to install with Composer: the [PHP SDK](https://pay.perly.io/docs/sdks.md) is inside.

> **Note:** Perly Pay bills in USD or EUR. For clients in another currency, set the gateway's **Convert To For Processing** to USD or EUR; the payment is still recorded in the invoice's own currency. Without it, those clients see a note to choose another way to pay.

## Install

1. **Get the zip** — The module is on its way to the WHMCS Marketplace. Until it is listed, [write to us](https://pay.perly.io/contact) for `perly-pay-whmcs.zip`.
2. **Upload** — Unzip it over your WHMCS folder. It adds `modules/gateways/perlypay.php`, `modules/gateways/callback/perlypay.php` and `modules/gateways/perlypay/`.
3. **Activate** — Configuration → Apps & Integrations → Payment Gateways (or Setup → Payment Gateways), activate **Perly Pay**.

## Settings

| Setting | What to put |
| --- | --- |
| Secret key | From Dashboard → Developers → API keys. `sk_test_…` for [test mode](https://pay.perly.io/docs/test-mode.md), `sk_live_…` for real money. |
| Webhook signing secret | `whsec_…`, from the webhook you add for this WHMCS (below). |
| Payment page | **Overlay** opens the checkout over the invoice (pay.js). **Redirect** sends the client to it. Phones always get the page itself. |
| Currencies | USD and EUR, or only one of them. |

1. **Paste the key** — Save, then press **Test connection** in the key's field: it says whether the key works, its mode, and whether this WHMCS's webhook is in Perly Pay.
2. **Add the webhook** — In Dashboard → Developers → Webhooks, add the address the settings show, `https://your-whmcs/modules/gateways/callback/perlypay.php`, with the invoice and refund events. Paste its secret and save.
3. **Allow the overlay** — In Dashboard → Settings, add your WHMCS address to **Sites that may embed the checkout**. Without it the overlay offers to open the checkout in a new tab.

## Test

With a `sk_test_…` key, open an unpaid invoice in the client area and press **Pay with crypto**. Pay it with test coins, or from the API — the invoice's id is on the checkout page:

```bash
curl -X POST https://pay.perly.io/api/v1/invoices/inv_…/simulate \
  -H "Authorization: Bearer $PERLY_PAY_SECRET_KEY" -H "Content-Type: application/json" -d '{}'
```

Within seconds the WHMCS invoice is **Paid**. Billing → Gateway Log shows the network, the amount and a link to the transaction.

## How invoices follow payments

| In Perly Pay | In WHMCS |
| --- | --- |
| Paid and the sender checked (`invoice.fulfilled`) | A payment for the balance the client was billed, in the invoice's currency, under the Perly Pay payment id (`pay_…`). WHMCS marks the invoice Paid and does the rest as usual. |
| Seen, part paid, paid but still screening | A Gateway Log line. No payment. |
| Held for [review](https://pay.perly.io/docs/screening.md) | A Gateway Log line with the reason. Decide in Perly Pay. |
| Expired or canceled | A Gateway Log line. Pressing the button again makes a new invoice. |
| Refund opened, ready, sent, confirmed | A Gateway Log line, with what to send where. |

Pressing the button again reuses the open invoice while the balance is the same. Each payment is recorded once, however often the webhook arrives, and only for invoices this WHMCS made.

## Refunds

Refund the transaction in WHMCS as usual: the module opens a [refund](https://pay.perly.io/docs/refunds.md) in Perly Pay, in the coin that was paid (the same share of it for part). Perly Pay emails the client for an address and checks it; the Gateway Log then says what to send where. You send from your wallet and paste the transaction id in Perly Pay — Perly Pay never holds the money.

## Go live

- Turn on live mode in Perly Pay and connect your wallet's public keys.
- Paste a `sk_live_…` key. Live keys and webhooks are separate from test ones: add the callback address again in live mode and paste its secret.
- Add your WHMCS's https address to **Sites that may embed the checkout** in live mode.
- Pay one small real invoice and refund it.
