PHPackages                             thepublicgood/payfast - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. thepublicgood/payfast

ActiveLibrary[Payment Processing](/categories/payments)

thepublicgood/payfast
=====================

Simple PayFast integration

v0.6.1(10mo ago)65.8k↓50%MITPHPPHP &gt;=8.1CI passing

Since Apr 14Pushed 10mo ago2 watchersCompare

[ Source](https://github.com/tpg/payfast)[ Packagist](https://packagist.org/packages/thepublicgood/payfast)[ RSS](/packages/thepublicgood-payfast/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (7)Versions (19)Used By (0)

[![Run Tests](https://github.com/tpg/payfast/actions/workflows/php.yml/badge.svg)](https://github.com/tpg/payfast/actions/workflows/php.yml)

Payfast
=======

[](#payfast)

A simple PayFast library.

Installation
============

[](#installation)

Install the PayFast library through composer using the command line:

```
composer require thepublicgood/payfast
```

Usage
=====

[](#usage)

PayFast doesn't currently have an on-site payment solution in production. There is a beta service available, but this library does not support that. When the service is in production and support has been added to the sandbox environment, then I'll update this library. Until then, this library only supports the PayFast custom integration option.

Merchant
--------

[](#merchant)

All transactions require a merchant object. PayFast will provide you with your merchant ID and merchant Key. You will also need to log into your PayFast account and set a passphrase. Although not required by PayFast, this library requires a passphrase to be set.

Create a new merchant object from the `Merchant` class and pass your authentication data in. You can set the return URL, cancel URL and notify URL on the Merchant instance. You'll want to set all of these to endpoints at your website.

```
$merchant = new \TPG\PayFast\Merchant('MERCHANT_ID', 'MERCHANT_KEY', 'PASSPHRASE');

$merchant
    ->setReturnUrl($returnUrl)
    ->setCancelUrl($cancelUrl)
    ->setNotifyUrl($notifyUrl);
```

Since PayFast will need to have access to these URLs, during testing it can be useful to have access to your test environment. Take a look at [Expose](https://beyondco.de/docs/expose/introduction) if you need this.

Customer
--------

[](#customer)

A customer is not required for any transaction. However, if you'd like to set this data, you can do so by creating a new `Customer` instance and setting the name, email and cell number. This can help improve the customer experience if the user has registered an account with PayFast.

```
$customer = new \TPG\PayFast\Customer();

$customer
    ->setName('First', 'Last')
    ->setEmail('email@test.com')
    ->setCellNumber('1234567890');
```

Transactions
------------

[](#transactions)

Transactions are where all the magic happens. The `Transaction` class constructor accepts three parameters: the `Merchant` instance, the value of the transaction (in South African cents) and the name of the item. The name could be some reference to the transaction so users can see what they're paying for on the PayFast website.

```
$transaction = new \TPG\PayFast\Transaction($merchant, 10000, 'Item Name');
```

Once you have a transaction object, you can make a number of changes:

```
$transaction
    ->setCustomer($customer)                  // Set a customer
    ->setMerchantPaymentId('PAYID123').       // A payment reference
    ->setDescription('Item Description')      // A payment description
    ->setCustomIntegers([                     // Up to 5 custom integers
        1,
        2,
        3,
        4,
        5,
    ])
    ->setCustomStrings([                     // Up to 5 custom strings
        'S1',
        'S2',
        'S3',
        'S4',
        'S5'
    ])
    ->setEmailConfirmation(true)            // Where to send email confirmations
    ->setEmailConfirmationAddress('email@test.com')  // The confirmation email
    ->setPaymentMethod(\TPG\PayFast\PaymentMethod::ALL); // Payment method
```

The payment method is just a way to limit what payment methods you accept. In most cases you'll probably want `PaymentMethod::ALL`, but there are a few others:

```
PaymentMethod::ALL;  // All payment methods allowed
PaymentMethod::CC;   // Credit Cards
PaymentMethod::DC;   // Debit cards
PaymentMethod::EFT;  // EFT
PaymentMethod::MP;   // MasterPass
PaymentMethod::MC;   // Mobicred
PaymentMethod::SC;   // SCode
```

There is no way to allow a combination of these. It's either all or one.

Creating a form
---------------

[](#creating-a-form)

Create a new `PayFast` instance and pass in the transaction. We can now generate a simple HTML form which can be placed in your view. The form ID is always `#payfast_form` so you can refer to it using a bit of JavaScript, or you can pass an integer value to the `form()` method to automatically submit the form after that number of seconds have elapsed.

```
$payfast = new \TPG\PayFast\PayFast($transaction);

$submissionDelay = 10; // seconds to wait before automatically submitting the form.
$form = $payfast->form($submissionDelay);

echo $form;
```

If you don't supply a delay, you will need to submit the form yourself. Remember that you should not display this form to the end user and all the form fields are of type "hidden".

Validating the ITN
------------------

[](#validating-the-itn)

Once a transaction has ben submitted to PayFast and you've set a notify URL, you can validate the ITN that comes back from PayFast using the `ItnValidator` class. PayFast recommend setting a header right away and then continuing with the validation process.

```
namespace App\Http\Controllers;

class PayFastController
{
    public function webhook(Request $request)
    {
        // Create a new validator
        $validator = new \TPG\PayFast\ItnValidator($request->input());

        // From the PayFast docs... Send a 200 response right away...
        $validator->flush();

        // You have access to all the response data through the `PayfastResponse` class.
        $response = $validator->response();

        $mpid = $response->merchantPaymentId();  // Original payment ID set on the transaction
        $pfid = $response->payFastPaymentId();   // PayFast's payment ID
        $name = $response->name();           // Item name or order number
        $description = $response->description();    // Item or order description
        $gross = $response->amountGross();        // Total charge
        $fee = $response->amountFee();          // Payfast fee amount
        $net = $response->amountNet();          // Net amount
        $integer = $response->customIntegers();    // Array of custom integers
        $string = $response->customStrings();     // Array of custom strings

        $firstName = $response->customer()->firstName();      // Customers first name
        $lastName = $response->customer()->lastName();       // Customers last name
        $emailAddress = $response->customer()->emailAddress();   // Customers email address
        $cellNumber = $response->customer()->cellNumber();     // Customers cell number

        $signature = $response->signature();                  // Signature for validation

        //--------------------

        // To validate the transaction, first ensure the transaction is COMPLETE:
        if ($response->paymentStatus() !== \TPG\PayFast\PaymentStatus::COMPLETE) {
            // incomplete...
        }

        // Then `validate()` will return true or throw an exception
        $valid = $validator->validate(10000, $passphrase, $request->ip());

        if (!$valid) {
            echo $validator->error();
        }

        // validated!
    }
}
```

Subscriptions
-------------

[](#subscriptions)

Subscriptions are started in the same way as standard transactions. Simply add a call to `subscription()` on the `Transaction` instance:

```
$transaction = new Transaction($merchant, 10000);
$transaction->subscription();
```

This will ensure the transaction is passed to PayFast as a recurring transaction. The `subscription` method also takes a few options to customise the subscription. You can specify the frequency, the number of cycles and the billing date:

```
$transaction->subscription(
    Transaction::SUBSCRIPTION_FREQUENCY_QUARTERLY,  // frequency
    10,                                             // number of cycles
    new DateTime('tomorrow'),                       // Billing start date
);
```

PayFast supports four frequency options:

```
$monthly = Transaction::SUBSCRIPTION_FREQUENCY_MONTHLY;  // default
$quarterly = Transaction::SUBSCRIPTION_FREQUENCY_QUARTERLY;
$biannually = Transaction::SUBSCRIPTION_FREQUENCY_BIANNUALLY;
$annually = Transaction::SUBSCRIPTION_FREQUENCY_ANNUALLY;
```

The `cycles` parameter defaults to 0 meaning indefinite. The subscription will continue until cancelled.

Once you've submitted the transaction, you can use the `token()` method on the `ItnValidator` instance to get a token reference for the transaction which can then be used to manage that subscription:

```
$validator = new ItnValidator($request->input());

if ($validator->validate(10000, 'passphrase', $request->ip()) {
    $token = $validator->token();
}
```

### Fetching a subscription from PayFast

[](#fetching-a-subscription-from-payfast)

You can fetch details for any subscription using the `Subscription` class. Pass a `Merchant` instance as the first parameter and the subscription token as the second to the constructor and call the `fetch` method:

```
$subscription = new Subscription($merchant, $token);
$subscription->fetch();

$data = $subscription->toArray();
```

There are number of features on the `Subscription` class which you can use to manage any subscription:

### Pausing/Unpausing a subscription

[](#pausingunpausing-a-subscription)

You can pause a subscription for any number of cycles, but by default a subscription is paused for just 1. The next billing cycle will then be skipped. You get the next billing date using the `runDate` method on the `Subscription` object.

```
$subscription->pause();

$subscription->fetch()->runDate();  // Will skip the next billing date

//---------------------------------------

$subscription->pause(2);

$subscription->fetch()->runDate(); // Will skip the next two billing dates
```

Note that PayFast does not allow you to alter the number of cycles paused here. You will need to `unpause` and then `pause` again with the new cycles.

To unpause a subscription, simply call the `unpause()` method:

```
$subscription->unpause();
```

To check if a subscription is paused, the `paused()` method will return true.

```
$subscription->pause();
$subscription->paused();  // true
```

### Cancelling a subscription

[](#cancelling-a-subscription)

To cancel a subscription, simply call the `cancel()` method:

```
$subscription->cancel();
$subscription->cancelled();  // true
```

PayFast retains the information about cancelled transaction, so even if you fetched data from a transaction that had been previously cancelled, you'll still get that transaction data, but `cancelled()` will return `true`.

Sandbox
-------

[](#sandbox)

PayFast provides a simple sandbox against which transactions can be tested. The sandbox can be found at . In order to use the sandbox, you'll need to tell the library that you're testing. You can do so by calling the `testing()` method on the `Payfast` instance when creating a form:

```
$payfast = new PayFast($transaction);

$form = $payfast->testing()->form();
```

This will ensure that requests are sent to the sandbox and not the actual PayFast endpoint. The same is true for the `ItnValidator`:

```
$validator = new ItnValidator($request->input());
$valid = $validator->testing()->validate(10000, $passphrase, $request->ip());
```

And when managing subscriptions:

```
$subscription = new Subscription($merchant, 'TOKEN');
$subscription->testing()->pause();
```

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance54

Moderate activity, may be stable

Popularity27

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~103 days

Recently: every ~215 days

Total

16

Last Release

307d ago

PHP version history (3 changes)v0.1.0PHP ^7.4|^8.0

v0.3.0PHP &gt;=7.4

v0.4.0PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/89ea2dc12cd0a934de60705f8cfe47397095d842121b7d5f545dc9d1cee554ec?d=identicon)[warrickbayman](/maintainers/warrickbayman)

---

Top Contributors

[![warrickbayman](https://avatars.githubusercontent.com/u/856840?v=4)](https://github.com/warrickbayman "warrickbayman (53 commits)")

---

Tags

payfastpaymentphpsubscriptiontransactionpayfastcommerce

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/thepublicgood-payfast/health.svg)

```
[![Health](https://phpackages.com/badges/thepublicgood-payfast/health.svg)](https://phpackages.com/packages/thepublicgood-payfast)
```

###  Alternatives

[omnipay/payfast

PayFast driver for the Omnipay payment processing library

24626.9k3](/packages/omnipay-payfast)[ondrakoupil/csob-eapi-paygate

PHP Client library for easy integration of ČSOB payment gateway

44416.9k3](/packages/ondrakoupil-csob-eapi-paygate)[craftcms/commerce-stripe

Stripe integration for Craft Commerce 5.0+

32157.4k3](/packages/craftcms-commerce-stripe)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[billowapp/payfast

Laravel 5.4+ package for processing ITN payments through payfast.co.za

2918.2k3](/packages/billowapp-payfast)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
