yabacon/paystack-php

Helps make your Paystack API calls giving a stdClass object.

v2.2.1 2020-08-19 13:24 UTC

README

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

A PHP API wrapper for Paystack.

Paystack

Requirements

  • Curl 7.34.0 or more recent (Unless using Guzzle)
  • PHP 5.4.0 or more recent
  • OpenSSL v1.0.1 or more recent

Install

Via Composer

    $ composer require yabacon/paystack-php

Via download

Download a release version from the releases page. Extract, then:

    require 'path/to/src/autoload.php';

IMPORTANT

Version 2 is not compatible with version 1 code! It throws an error if there's problem error in cURL or if the Paystack API gives a false status in the response body.

Usage

Do a redirect to the authorization URL received from calling the transaction/initialize endpoint. This URL is valid for one time use, so ensure that you generate a new URL per transaction.

When the payment is successful, we will call your callback URL (as setup in your dashboard or while initializing the transaction) and return the reference sent in the first step as a query parameter.

If you use a test secret key, we will call your test callback url, otherwise, we'll call your live callback url.

0. Prerequisites

Confirm that your server can conclude a TLSv1.2 connection to Paystack's servers. Most up-to-date software have this capability. Contact your service provider for guidance if you have any SSL errors. Don't disable SSL peer verification!

1. Prepare your parameters

email and amount are the most common compulsory parameters. Do send a unique email per customer. If your customers do not provide a unique email, please devise a strategy to set one for each of them. Any of those below work fine. The amount we accept on all endpoint are in kobo and must be an integer value. For instance, to accept 456 naira, 78 kobo, please send 45678 as the amount.

2. Initialize a transaction

Initialize a transaction by calling our API.

    $paystack = new Yabacon\Paystack(SECRET_KEY);
    try
    {
      $tranx = $paystack->transaction->initialize([
        'amount'=>$amount,       // in kobo
        'email'=>$email,         // unique to customers
        'reference'=>$reference, // unique to transactions
      ]);
    } catch(\Yabacon\Paystack\Exception\ApiException $e){
      print_r($e->getResponseObject());
      die($e->getMessage());
    }

    // store transaction reference so we can query in case user never comes back
    // perhaps due to network issue
    save_last_transaction_reference($tranx->data->reference);

    // redirect to page so User can pay
    header('Location: ' . $tranx->data->authorization_url);

When the user enters their card details, Paystack will validate and charge the card. It will do all the below:

Redirect back to a callback_url set when initializing the transaction or on your dashboard at: https://dashboard.paystack.co/#/settings/developer . If neither is set, Customers see a Transaction was successful message.

Send a charge.success event to your Webhook URL set at: https://dashboard.paystack.co/#/settings/developer

If receipts are not turned off, an HTML receipt will be sent to the customer's email.

Before you give value to the customer, please make a server-side call to our verification endpoint to confirm the status and properties of the transaction.

3. Handle charge.success Event

We will post a charge.success event to the webhook URL set for your transaction's domain. If it was a live transaction, we will post to your live webhook url and vice-versa.

  • if using .htaccess, remember to add the trailing / to the url you set.
  • Do a test post to your URL and ensure the script gets the post body.
  • Publicly available url (http://localhost cannot receive!)
    // Retrieve the request's body and parse it as JSON
    $event = Yabacon\Paystack\Event::capture();
    http_response_code(200);

    /* It is a important to log all events received. Add code *
     * here to log the signature and body to db or file       */
    openlog('MyPaystackEvents', LOG_CONS | LOG_NDELAY | LOG_PID, LOG_USER | LOG_PERROR);
    syslog(LOG_INFO, $event->raw);
    closelog();

    /* Verify that the signature matches one of your keys*/
    $my_keys = [
                'live'=>'sk_live_blah',
                'test'=>'sk_test_blah',
              ];
    $owner = $event->discoverOwner($my_keys);
    if(!$owner){
        // None of the keys matched the event's signature
        die();
    }

    // Do something with $event->obj
    // Give value to your customer but don't give any output
    // Remember that this is a call from Paystack's servers and
    // Your customer is not seeing the response here at all
    switch($event->obj->event){
        // charge.success
        case 'charge.success':
            if('success' === $event->obj->data->status){
                // TIP: you may still verify the transaction
                // via an API call before giving value.
            }
            break;
    }

4. Verify Transaction

After we redirect to your callback url, please verify the transaction before giving value.

    $reference = isset($_GET['reference']) ? $_GET['reference'] : '';
    if(!$reference){
      die('No reference supplied');
    }

    // initiate the Library's Paystack Object
    $paystack = new Yabacon\Paystack(SECRET_KEY);
    try
    {
      // verify using the library
      $tranx = $paystack->transaction->verify([
        'reference'=>$reference, // unique to transactions
      ]);
    } catch(\Yabacon\Paystack\Exception\ApiException $e){
      print_r($e->getResponseObject());
      die($e->getMessage());
    }

    if ('success' === $tranx->data->status) {
      // transaction was successful...
      // please check other things like whether you already gave value for this ref
      // if the email matches the customer who owns the product etc
      // Give value
    }

5. Closing Notes

Generally, to make an API request after constructing a paystack object, Make a call to the resource/method thus: $paystack->{resource}->{method}(); for gets, use $paystack->{resource}(id) and to list resources: $paystack->{resource}s().

Currently, we support: 'customer', 'page', 'plan', 'subscription', 'transaction' and 'subaccount'. Check our API reference(link-paystack-api-reference) for the methods supported. To specify parameters, send as an array.

Check SAMPLES for more sample calls

Extras

There are classes that should help with some tasks developers need to do on Paystack often:

Fee

This class works with an amount and your Paystack fees. To use, create a new Fee object

    $fee = new Yabacon\Paystack\Fee();

Configure it:

    $fee->withPercentage(0.015);        // 1.5%
    $fee->withAdditionalCharge(10000);  // plus 100 NGN
    $fee->withThreshold(250000);        // when total is above 2,500 NGN
    $fee->withCap(200000);              // capped at 2000

Calculate fees

    $chargeOn300naira = $fee->calculateFor(30000);
    $chargeOn7000naira = $fee->calculateFor(700000);

To know what to send to the API when you want to be settled a particular amount

    $iWant100Naira = $fee->addFor(10000);
    $iWant4000Naira = $fee->addFor(400000);

Event

This class helps you capture and our events:

    $event = Yabacon\Paystack\Event::capture();

Verify it against a key:

    if($event->validFor($mySecretKey))
    {
        // awesome
    }

Discover the key that owns it (IN case same webhook receives for several integrations). This can come in handy for multi-tenant systems. Or simply if you want to have same test and live webhook url.

    $my_keys = [
                'live'=>'sk_live_blah',
                'test'=>'sk_test_blah',
              ];
    $owner = $event->discoverOwner($my_keys);
    if(!$owner){
        // None of my keys matched the event's signature
        die();
    }

To forward the event to another url. In case you want other systems to be notified of exact same event.

    $evt->forwardTo('http://another-webhook.url');

MetadataBuilder

This class helps you build valid json metadata strings to be sent when making transaction requests.

    $builder = new MetadataBuilder();

Add metadata

Add MetaData by calling the withKeyName magic function (These will not be shown on dashboard). Do not use CustomFields as a KeyName

    $builder->withQuoteId(10); // will add as quote_id: 10 unless you turn auto_snake_case off
    $builder->withMobileNumber(08012345678); // will add as mobile_number: 08012345678
    $builder->withCSRF('dontacceptpaymentunlessthismatches');

To turn off automatic snake-casing of Key names, do:

    MetadataBuilder::$auto_snake_case = false;

before you start adding metadata to the $builder.

Add Custom Fields

Add Custom Fields by calling the withCustomField function (These will shown on dashboard).

    $builder->withCustomField('Mobile Number', '080123456789');
    $builder->withCustomField('See Me', 'I\'m Visible on your Dashboard');

Build JSON

Finally call build() to get your JSON metadata string.

Using Custom Routes

You can add your custom routes by calling the useRoutes method on the paystack object.

    $paystack = new Yabacon\Paystack(SECRET_KEY);
    $paystack->useRoutes(["charge" => Charge::class]);

    $paystack->charge->chargeMobileMoney([
          'email' => 'hey@example.com',
          'reference' => 'trnx_ref',
          'amount' => 50 * 100,
          'currency' => 'GHS',
          'mobile_money' => [
            'phone' => '5533467',
            'provider' => 'MTN'
          ]
    ]);

Your custom routes should implement the Yabacon\Paystack\Contracts\RouteInterface contract

    class Charge implements RouteInterface
    {

        public static function root()
        {
            return '/charge';
        }

        public static function chargeMobileMoney()
        {
            return [
                RouteInterface::METHOD_KEY => RouteInterface::POST_METHOD,
                RouteInterface::ENDPOINT_KEY => Charge::root(),
                RouteInterface::PARAMS_KEY => [
                    'email',
                    'reference',
                    'amount',
                    'currency',
                    'mobile_money',
                ],
            ];
        }
    }

Change log

Please see CHANGELOG for more information what has changed recently.

Testing

    $ composer test

Contributing

Please see CONTRIBUTING and CONDUCT for details. Check our todo list for features already intended.

Security

If you discover any security related issues, please email yabacon.valley@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.