# FOSSBilling

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

The Perly Pay adapter adds crypto to your FOSSBilling invoices. The client opens an unpaid invoice, picks Perly Pay and presses **Pay Now**; the adapter makes an invoice in Perly Pay for the invoice's total with tax and opens it, over the page or on its own. A signed webhook pays the FOSSBilling invoice. FOSSBilling 0.8.4 or later, PHP 8.1+ with `curl` and `json`. 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. Set **Accepted Currencies** to those two; on an invoice in another currency the client is asked to choose another way to pay.

## Install

1. **Get the adapter** — Download `perly-pay-fossbilling.zip` from the latest release on [GitHub](https://github.com/volodymyrslipak/perly-pay-fossbilling/releases/latest).
2. **Upload** — Make the folder `library/Payment/Adapter/Perlypay/` in your FOSSBilling and unzip `perly-pay-fossbilling.zip` into it, so that `library/Payment/Adapter/Perlypay/Perlypay.php` exists.
3. **Install it** — System → Payment Gateways → **Add New Payment Gateway**: under **Install Locally**, install **Perlypay**. It shows as Perlypay until you give it a title in its settings.

## Settings

| Setting | What to put |
| --- | --- |
| Test secret key | From Dashboard → Developers → API keys, in test mode: `sk_test_…`. Used while **Enable Test Mode** is on: test coins on test networks. |
| Test webhook signing secret | The `whsec_…` secret of the test-mode webhook (below). |
| Live secret key | The same page in live mode: `sk_live_…`. Takes real money. |
| Live webhook signing secret | The `whsec_…` secret of the live-mode webhook. |
| Payment page | **Over FOSSBilling (overlay)** opens the checkout over FOSSBilling's payment page. **On pay.perly.io (redirect)** sends the client there. Phones always get the page itself. |
| Accepted Currencies | USD and EUR. |
| Allow One Time Payments | On. Each invoice is paid on its own: there are no subscription payments. |

1. **Add the webhook** — In Dashboard → Developers → Webhooks, add the gateway's **Callback URL** (its settings page shows it: `https://your-fossbilling/ipn.php?gateway_id=…`) with the invoice and refund events. Do it once in test mode and once in live mode: each mode signs with its own secret.
2. **Paste the secrets** — Paste each webhook's secret in its field. **Send test** in Perly Pay puts a "Perly Pay test event" in FOSSBilling's Invoices → Transactions when the address and the secret are right.
3. **Allow the overlay** — For the overlay, add your FOSSBilling address in Dashboard → Settings → Checkout → **Sites that may embed the checkout**.

FOSSBilling checks the settings when you enable the gateway: a missing key for the gateway's mode, or a live key in a test field, stops it there.

## What clients pay with

The client picks a coin and network on the payment page and pays from any wallet. The money goes straight to yours.

| Coin | Networks |
| --- | --- |
| BTC | Bitcoin |
| USDC | Base, Arbitrum, Optimism and Ethereum |
| USDT0 | Arbitrum and Optimism |
| USDT | Ethereum and TRON |

> **Note:** The adapter is free and open source (MIT). Perly Pay costs 2.5¢ a payment, never more than 0.5% of it, billed after the month. A month of up to 21 payments costs $0. Nothing is taken from the payment: see [Pricing](https://pay.perly.io/pricing).

## Test

With **Enable Test Mode** on and the test key and secret saved, open an unpaid invoice as the client, choose Perly Pay and press **Pay Now**. Pay with test coins, or from the API — the invoice id `inv_…` 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 FOSSBilling invoice is **Paid**.

## How invoices follow payments

| In Perly Pay | In FOSSBilling |
| --- | --- |
| Paid and the sender checked (`invoice.fulfilled`) | The amount goes to the client's balance and pays the invoice. The transaction keeps the Perly Pay payment (`pay_…`) as its id, and a note names the network, the coin amount and the transaction. |
| Part paid, expired with money received, held for [review](https://pay.perly.io/docs/screening.md) | A note on the transaction and on the invoice. No payment. |
| Expired, nothing paid | A note on the transaction. Paying again makes a new Perly Pay invoice. |
| Refund events | A note on the transaction, from the refund as Perly Pay's API returns it. |

A replayed or doubled webhook records nothing twice. Events for invoices another shop, another FOSSBilling or another gateway made on the same Perly Pay account are dropped. If recording fails, the webhook is answered 503 and Perly Pay sends it again for up to 72 hours.

## Refunds

FOSSBilling has no refund hook for payment gateways, so open the [refund](https://pay.perly.io/docs/refunds.md) in Perly Pay: Payments → the payment → Refund. Perly Pay emails the client for an address; you send from your wallet. The refund's steps are noted on FOSSBilling's transactions.

## Go live

- Turn on live mode in Perly Pay and connect your wallet's public keys.
- Paste the `sk_live_…` key and the live webhook's secret, and turn **Enable Test Mode** off.
- For the overlay, add your FOSSBilling's https address to **Sites that may embed the checkout** in live mode too: test and live keep separate lists.
- Pay one small real invoice and refund it in Perly Pay.
