VITAL: Capture charge.success

Asynchronous value provision. Avoid "Paid but no value" scenarios caused by bad network

During this session, you will add a webhook url to your Paystack Dashboard and handle the events posted. JSON data for events are posted to your webhook url when a transaction is successful on your account in the webhook's domain. Your webhook has to be a publicly available url which doesn't redirect.

Note that charge.success is not the only event we sent. Click for more information on handling events

🚧

Tips for a good webhook url

  • if using .htaccess, remember to add or remove the trailing / depending on the configuration. Redirected webhook calls fail
  • Do a test post to your URL and ensure the script gets the post body.
  • Publicly available url (http://localhost cannot receive!)
  1. Add a webhook url to your account here: https://dashboard.paystack.co/#/settings/developer
  2. Sample webhook code is below
<?php
// Retrieve the request's body
$body = @file_get_contents("php://input");
$signature = (isset($_SERVER['HTTP_X_PAYSTACK_SIGNATURE']) ? $_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] : '');

/* It is a good idea to log all events received. Add code *
 * here to log the signature and body to db or file       */

if (!$signature) {
    // only a post with paystack signature header gets our attention
    exit();
}

define('PAYSTACK_SECRET_KEY','sk_xxxx_xxxxxx');
// confirm the event's signature
if( $signature !== hash_hmac('sha512', $body, PAYSTACK_SECRET_KEY) ){
  // silently forget this ever happened
  exit();
}

http_response_code(200);
// parse event (which is json string) as object
// 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
$event = json_decode($body);
switch($event->event){
    // charge.success
    case 'charge.success':
        // TIP: you may still verify the transaction
            // before giving value.
        break;
}
exit();

Drop comments here

Below is a sample JSON object for charge.success.

{
  "event": "charge.success",
  "data": {
    "id": 748541,
    "domain": "test",
    "status": "success",
    "reference": "87pfjx9yjj",
    "amount": 67800,
    "message": null,
    "gateway_response": "Successful",
    "paid_at": "2017-02-09T17:36:15.000Z",
    "created_at": "2017-02-09T17:35:48.000Z",
    "channel": "card",
    "currency": "NGN",
    "ip_address": "154.118.45.106",
    "metadata": {},
    "log": null,
    "fees": null,
    "fees_split": null,
    "customer": {
      "id": 181336,
      "first_name": null,
      "last_name": null,
      "email": "[email protected]",
      "customer_code": "CUS_dw5posshfd1i5uj",
      "phone": null,
      "metadata": null,
      "risk_action": "default"
    },
    "authorization": {
      "authorization_code": "AUTH_z7k6ysdd",
      "bin": "412345",
      "last4": "1381",
      "exp_month": "01",
      "exp_year": "2020",
      "channel": "card",
      "card_type": "visa visa",
      "bank": "TEST BANK",
      "country_code": "NG",
      "brand": "visa",
      "reusable": true
    },
    "plan": {
      "id": 2511,
      "name": "bleh",
      "plan_code": "PLN_3g5vcz2c1pkc4n0",
      "description": null,
      "amount": 67800,
      "interval": "hourly",
      "send_invoices": true,
      "send_sms": true,
      "currency": "NGN"
    },
    "subaccount": {
      
    },
    "paidAt": "2017-02-09T17:36:15.000Z"
  }
}