---
title: "Create a Stripe payment with the Jovvie PHP SDK"
description: "Create a one-time payment with the Stripe SDK and send your staff to the Jovvie payment page to take it on a card reader."
url: https://docs.jovvie.com/developers/create-a-payment/
section: "Developers"
last_updated: 2026-10-26
---

# Create a Stripe payment with the Jovvie PHP SDK

Section: Developers

> Create a one-time payment with the Stripe SDK and send your staff to the Jovvie payment page to take it on a card reader.

This page shows you how to create a one-time payment with the Stripe SDK. Your server creates the payment, and Jovvie gives you a checkout link to the Jovvie payment page. Your staff open that link, choose a card reader, and the customer pays.

For NMI, see [Take payments with NMI](https://docs.jovvie.com/developers/nmi-payments/). For recurring payments, see [Recurring payments](https://docs.jovvie.com/developers/subscriptions/).

## Before you start

- You installed the Stripe SDK and can create a client. See [Install the SDK](https://docs.jovvie.com/developers/install-the-sdk/).
- The merchant’s Stripe account is connected, and you have the server application keys. See [Get started](https://docs.jovvie.com/developers/get-started/).
- You use test mode while you build. See [Test your integration](https://docs.jovvie.com/developers/test-mode/).

## Create the payment

Call `payments()->createOneTimePayment()` on your server. It takes these arguments, in this order:

| Argument       | Type    | What it is                                                                                                                                                                               |
| -------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `$amount`      | integer | The amount to charge, in the smallest currency unit. See [Amounts](https://docs.jovvie.com/developers/create-a-payment/#amounts).                                                        |
| `$currency`    | string  | A three-letter ISO currency code, such as `usd`. The SDK sends it in lowercase.                                                                                                          |
| `$description` | string  | A description of the payment. It cannot be empty. The payment page shows it.                                                                                                             |
| `$returnUrl`   | string  | Where the browser goes after the payment page is done. Must be a full URL.                                                                                                               |
| `$cancelUrl`   | string  | Where the browser goes when staff click **← Back** and the payment is `cancelled`. A `pending` payment is first marked `cancelled`. Other statuses use `$returnUrl`. Must be a full URL. |
| `$options`     | array   | Optional. See [Options](https://docs.jovvie.com/developers/create-a-payment/#options).                                                                                                   |

```php
<?php
use JovviePayments\JovviePaymentsClient;

$client = new JovviePaymentsClient(
    'YOUR_PUBLIC_KEY',
    'YOUR_SECRET_KEY',
    'YOUR_PLATFORM_PROVIDER',
    'test'
);

$payment = $client->payments()->createOneTimePayment(
    2500,                                         // 25.00 in USD
    'usd',
    'Order YOUR_ORDER_ID',
    'YOUR_RETURN_URL',
    'YOUR_CANCEL_URL',
    [
        'lineItems' => [
            ['name' => 'Coffee beans', 'quantity' => '2', 'amount' => '20.00'],
            ['name' => 'Mug', 'quantity' => '1', 'amount' => '5.00'],
        ],
        'lineTotal' => '25.00',
        'metadata' => [
            'order_id' => 'YOUR_ORDER_ID',
        ],
    ]
);

// Save these with your order.
$paymentId = $payment->id;
$checkoutLink = $payment->generatedData->checkoutLink;
```

The method returns a `OneTimePayment` object. The fields you will use most:

| Field                            | What it is                                                                                                                                |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                             | The Jovvie payment ID. Save it with your order. You need it to check the payment and to match webhooks.                                   |
| `status`                         | The payment status. A new payment is `pending`. See [Check a payment’s status](https://docs.jovvie.com/developers/check-payment-status/). |
| `mode`                           | `live` or `test`.                                                                                                                         |
| `amount`, `currency`             | The amount (smallest currency unit) and currency.                                                                                         |
| `generatedData->checkoutLink`    | The link to the Jovvie payment page for this payment.                                                                                     |
| `generatedData->paymentIntentId` | The ID of the Stripe payment behind this Jovvie payment. It helps you find the payment in your Stripe Dashboard.                          |

## Amounts

Pass `$amount` as an integer in the smallest unit of the currency. For example, pass `2500` for 25.00 USD.

Stripe treats some currencies, such as JPY and KRW, as zero-decimal currencies. They have no smaller unit, so you pass the whole amount. For example, pass `1000` for 1,000 JPY, not `100000`. Check Stripe’s list of zero-decimal currencies and keep your own list in your code.

> **Caution**
>
> Always pass `lineItems` and `lineTotal` when you use a zero-decimal currency, so the payment page shows the right amounts.

The amount you charge is always `$amount`. Line items and the line total only control what the payment page shows.

If the merchant’s Stripe account cannot take the currency for this payment, the SDK throws a `BadRequestError`. See [Handle errors](https://docs.jovvie.com/developers/errors/).

## Options

All options are optional. Pass them in the `$options` array.

| Option        | What it does                                                                                                                                                                                                                                                                                              |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `lineItems`   | An array of items to show on the payment page. Each item has `name`, `amount`, and `quantity`, all as strings. `amount` is the amount to show for that line, in normal currency units, such as `'20.00'`. If you leave it out, the page shows one line with your description.                             |
| `lineTotal`   | The total to show on the payment page, as a plain number in normal currency units, such as `'25.00'`. Do not add a currency code to it.                                                                                                                                                                   |
| `metadata`    | Your own key and value pairs, such as your order ID. Values can be strings, numbers, or null.                                                                                                                                                                                                             |
| `preferences` | Settings for the payment page. `locationId` limits the reader list to one Stripe Terminal location. `terminalType` can be `web`, `app`, or `all` (the default) to choose which terminals the page offers. See [Web terminals and app terminals](https://docs.jovvie.com/hardware/web-and-app-terminals/). |

About metadata:

- Jovvie stores metadata on the Stripe payment, so you can see it in your Stripe Dashboard.
- Do not use the keys `lineItems`, `lineTotal`, or `preferences`. Jovvie uses them for its own data.
- Never put card data, passwords, or keys in metadata.

> **Note**
>
> Jovvie stores your line items with the Stripe payment, and Stripe limits how long that stored value can be. Keep line item names short. If an order has many items, show a summary line instead of every item.

## Send staff to the payment page

The checkout link opens the Jovvie payment page for this payment.

1. Store the payment ID with your order.

2. Send your staff member’s browser to the payment page.

   - If the staff member is signed in to your app, create an authorization link that redirects to the checkout link, and send the browser to the authorization link. The payment page then shows the card readers without asking for the Access PIN. See [Unlock card readers for staff](https://docs.jovvie.com/developers/unlock-card-readers/).
   - Otherwise, send the browser to the checkout link. To use a reader, staff select **In-Person Payment** and enter the Access PIN when the page shows **Provide PIN to access**.

3. Staff take the payment on the payment page. See [Take a payment on the Jovvie payment page](https://docs.jovvie.com/checkout/jovvie-payment-page/).

When payment processing finishes, Jovvie sends the browser to your `$returnUrl`. Clicking **← Back** changes a `pending` payment to `cancelled`. Jovvie then uses `$cancelUrl` for a `cancelled` payment and `$returnUrl` for any other status, for example a `failed` payment after a declined card.

> **Caution**
>
> Treat the checkout link like a key to this payment. Show it only to the merchant’s staff. Do not put it in emails, logs, or pages that customers can see.
>
> If a payment’s outcome is unclear, do not create another payment for the same order yet. Check every saved payment for the order with `payments()->get()` and check your Stripe Dashboard. Confirm that no payment went through and none is still processing before retrying or using another payment method. If you are unsure, contact [Jovvie support](https://jovvie.com/support/).

## Confirm the payment

A visit to your return URL does not prove that the customer paid. Anyone can open that URL.

When the browser arrives at your return URL:

1. Look up the Jovvie payment ID you saved for this order. Do not take the payment ID from the URL.
2. Fetch the payment with `$client->payments()->get($paymentId)`.
3. Mark the order paid only if `status` is `completed`.

See [Check a payment’s status](https://docs.jovvie.com/developers/check-payment-status/) for the full list of statuses and how to find payments that never came back. Also handle webhooks for changes that happen later, such as refunds. See [Handle webhooks](https://docs.jovvie.com/developers/webhooks/).

## Related pages

- [Unlock card readers for staff](https://docs.jovvie.com/developers/unlock-card-readers/)
- [Check a payment’s status](https://docs.jovvie.com/developers/check-payment-status/)
- [Handle webhooks](https://docs.jovvie.com/developers/webhooks/)
- [Handle errors](https://docs.jovvie.com/developers/errors/)
