Check a payment's status with the Jovvie PHP SDKs
This page shows you how to fetch a payment with the SDK and read its status. Fetching the payment is how you confirm that a customer paid. Do it when the browser returns to your app, before any important change, and on a schedule for payments that never came back.
Fetch a payment
Section titled “Fetch a payment”Call payments()->get() with the Jovvie payment ID you saved when you created the payment. Use a client in the same mode (live or test) as the one that created the payment.
<?php// $client is your JovviePaymentsClient (Stripe) or JovviePaymentsGatewayClient (NMI).$payment = $client->payments()->get($paymentId);
if ($payment->type === 'subscription') { // Stripe recurring payment: the first payment went through when the status is 'active'. if ($payment->status === 'active') { // Start the subscription in your app. }} elseif ($payment->status === 'completed') { // One-time payment: mark the order paid.}A one-time payment that went through is completed. A recurring payment whose first payment went through is active, not completed. Always check type before you read status.
With the Stripe SDK, get() returns a OneTimePayment or a SubscriptionPayment, depending on the payment’s type (one-time or subscription). With the NMI SDK, it always returns a OneTimePayment.
Fields you can use:
| Field | What it is |
|---|---|
id |
The Jovvie payment ID. |
type |
one-time or subscription. |
status |
The payment status. See Statuses for Stripe one-time payments, Statuses for Stripe recurring payments, and Statuses for NMI payments. |
amount, currency |
The amount (smallest currency unit) and currency. With the Stripe SDK, when a refund is reflected in the Jovvie payment, amount is the amount left. Reconcile refunds against the Stripe Dashboard. |
description |
The payment description. |
createdAt, updatedAt |
When the payment was created and last changed. |
mode |
live or test. Stripe SDK only. |
generatedData->checkoutLink |
The link to the Jovvie payment page. |
generatedData->paymentIntentId |
The ID of the Stripe payment. Stripe SDK only. |
To get the NMI transaction ID, use getTransactionId() on a verified NMI webhook event. See Handle webhooks.
Take the payment ID from your own records, never from a URL or form field the browser sends you.
If no payment has that ID, the SDK throws a NotFoundError. If the payment belongs to another merchant account, it throws a ForbiddenError. See Handle errors.
Statuses for Stripe one-time payments
Section titled “Statuses for Stripe one-time payments”| Status | What it means |
|---|---|
pending |
The payment was created and is not paid yet. |
completed |
The customer paid. |
failed |
A payment attempt failed. Staff may still try again on the same payment page. |
cancelled |
Staff went back from the payment page before the customer paid, or the payment was cancelled. |
abandoned |
The payment was closed without being paid. |
refunded |
The payment was refunded, fully or in part. Check amount for what is left. |
Statuses for Stripe recurring payments
Section titled “Statuses for Stripe recurring payments”| Status | What it means |
|---|---|
pending |
The recurring payment was created and the first payment is not done yet. |
active |
The first payment went through and the recurring payment is running. |
failed |
A payment for the recurring payment failed and is unpaid. |
cancelled |
The recurring payment was cancelled before it started. |
ended |
The recurring payment was running and has now ended. |
abandoned |
The recurring payment was closed without being started. |
refunded |
A payment for the recurring payment was refunded. |
See Recurring payments.
Statuses for NMI payments
Section titled “Statuses for NMI payments”| Status | What it means |
|---|---|
pending |
The payment was created and is not paid yet. |
requested |
The payment was sent to a terminal and is waiting for the customer. |
completed |
The customer paid. |
failed |
The payment failed. |
cancelled |
The payment was cancelled on the terminal, or it was voided. |
refunded |
The payment was refunded. |
Statuses can change
Section titled “Statuses can change”A status is not always final. For example, a charge that goes through on a reader after staff clicked ← Back can move a payment from cancelled to completed. A refund can move a completed payment to refunded.
Before you close an order, retry a payment, or create a new payment for the same order:
- Fetch the payment again, and every other payment you created for the same order.
- Look for any payment that went through. A
completedoractivepayment went through. Arefundedpayment also went through, and it may only be partly refunded, so the customer may still have paid part of it. - Look for any payment that may still be processing, such as a
pendingorrequestedpayment. - Check the payments in your Stripe Dashboard or the NMI portal.
- If you are not sure, contact Jovvie support.
A status check alone never means it is safe to charge again. Only create another payment for the order when you have confirmed that no payment for it went through and none is still processing. Otherwise the customer could be charged twice.
Find payments that never came back
Section titled “Find payments that never came back”Sometimes a customer pays, but the browser never reaches your return URL. For example, staff close the tab, or the device loses its connection. A webhook can also be lost if your server is down. Check for these payments on a schedule:
- Keep a list of orders whose payment is
pending(orrequestedfor NMI). - On a schedule, such as every hour, fetch each of these payments with
payments()->get(). - Check the payment’s
type. When a one-time payment iscompleted, mark the order paid. When a recurring payment isactive, start the subscription in your app. See Recurring payments. - When a payment is
failed,cancelled, orabandoned, update the order. Keep it on the list for a while, in case the status changes again. - If a payment stays
pendingfor a long time, check it in your Stripe Dashboard or the NMI portal before you close the order.
Make this check safe to run more than once, just like your webhook handler. See Handle webhooks.