Accept Payments
In a nutshell
To accept a payment, create a transaction using our API, our client Javascript library, Popup JS, or our SDKs. Every transaction includes a link that can be used to complete payment.
Popup
Paystack Popup provides a simple and convenient payment flow for web. It can be integrated in five easy steps, making it the easiest way to start accepting payments. See demo of the payment methods on the checkout here.
Collect customer information
To initialize the transaction, you need to pass information such as email, amount, transaction reference, etc. The key
, email
and amount
parameters are the only required parameters. The table below lists the parameters that you can pass when initializing a transaction.
Param | Required? | Description |
---|---|---|
key | Yes | Your public key from Paystack. Use test key for test mode and live key for live mode |
Yes | Email address of customer | |
amount | Yes | Amount in the subunit of the supported currency you are debiting customer. Do not pass this if creating subscriptions. |
ref | No | Unique case sensitive transaction reference. Only -,., =and alphanumeric characters allowed. If you do not pass this parameter, Paystack will generate a unique reference for you. |
currency | No | On of the supported currency the charge should be performed in. It defaults to your integration currency. |
channels | No | An array of payment channels to control what channels you want to make available to the user to make a payment with. Available channels include; ['card', 'bank', 'ussd', 'qr', 'mobile_money', 'bank_transfer'] |
metadata | No | Object containing any extra information you want recorded with the transaction. Fields within the custom_field object will show up on merchant receipt and within the transaction information on the Paystack Dashboard. You can learn more on the Metadata page. |
label | No | String that replaces customer email as shown on the checkout form |
callback | No | Function that runs when payment is successful. This should ideally be a script that uses the verify endpoint on the Paystack API to check the status of the transaction. |
onClose | No | Javascript function that is called if the customer closes the payment window instead of making a payment. |
onBankTransferConfirmationPending | No | Javascript function that is called if the customer clicks on Close Checkout before we receive their bank transfer. (This only applies to Pay-with-Transfer transactions) |
For single split payments | ||
subaccount | Yes | The code for the subaccount that owns the payment. e.g. ACCT_8f4s1eq7ml6rlzj |
transaction_charge | No | A flat fee to charge the subaccount for this transaction, in the subunit of the supported currency. This overrides the split percentage set when the subaccount was created. Ideally, you will need to use this if you are splitting in flat rates (since subaccount creation only allows for percentage split). |
bearer | No | Decide who will bear Paystack transaction charges between account and subaccount . Defaults to account . |
For multi-split payments | ||
split_code | Yes | The split code of the transaction split. e.g. SPL_98WF13Eb3w |
For subscriptions | ||
plan | Yes | Plan code generated from creating a plan. This makes the payment become a subscription payment. |
quantity | No | Used to apply a multiple to the amount returned by the plan code above. |
The customer information can be retrieved from your database if you already have it stored, or from a form like in the example below:
- HTML
- Javascript
1<form id="paymentForm">2 <div class="form-group">3 <label for="email">Email Address</label>4 <input type="email" id="email-address" required />5 </div>6 <div class="form-group">7 <label for="amount">Amount</label>8 <input type="tel" id="amount" required />9 </div>10 <div class="form-group">11 <label for="first-name">First Name</label>12 <input type="text" id="first-name" />13 </div>14 <div class="form-group">15 <label for="last-name">Last Name</label>16 <input type="text" id="last-name" />17 </div>18 <div class="form-submit">19 <button type="submit" onclick="payWithPaystack()"> Pay </button>20 </div>21</form>2223<script src="https://js.paystack.co/v1/inline.js"></script>
In this sample, notice how:
- The Paystack inline javascript is included using a
script
tag. This is how you import Paystack into your code. - The amount here can be hardcoded if you want to charge a specific amount.
- The
Pay
button has been tied to anonClick
function calledpayWithPaystack
. This is the action that causes the Paystack popup to load.
Helpful Tip
If you don't collect email addresses from your customer, you can generate an email address using the information you have alongside your website url. E.g, if you only collect phone numbers from your customers, you can create email addresses like 080300000@mybusiness.com.
Initialize transaction
When you have all the details needed to initiate the transaction, the next step is to tie them to the javascript function that passes them to Paystack and displays the checkout popup modal.
- Javascript
1var paymentForm = document.getElementById('paymentForm');2paymentForm.addEventListener('submit', payWithPaystack, false);3function payWithPaystack() {4 var handler = PaystackPop.setup({5 key: 'YOUR_PUBLIC_KEY', // Replace with your public key6 email: document.getElementById('email-address').value,7 amount: document.getElementById('amount').value * 100, // the amount value is multiplied by 100 to convert to the lowest currency unit8 currency: 'NGN', // Use GHS for Ghana Cedis or USD for US Dollars9 ref: 'YOUR_REFERENCE', // Replace with a reference you generated10 callback: function(response) {11 //this happens after the payment is completed successfully12 var reference = response.reference;13 alert('Payment complete! Reference: ' + reference);14 // Make an AJAX call to your server with the reference to verify the transaction15 },16 onClose: function() {17 alert('Transaction was not completed, window closed.');18 },19 });20 handler.openIframe();21}
- The
key
field here takes your Paystack public key. - The
amount
should be in the subunit of the supported currency. - It's ideal to generate a unique
reference
from your system for every transaction to avoid duplicate attempts. - The
callback
method is called when payment has been completed successfully on the Paystack checkout. See the next section to see for how to handle the callback. - the
onClose
method is called if the user closes the modal without completing payment.
Handle the callback method
The callback method is triggered when the transaction is completed. This is where you verify the transaction status.
Helpful Tip
To verify the transaction, you have to set up a route or page on your server that you pass the transaction reference to. From your server, you call the Paystack verify endpoint to confirm the status of the transaction. You should then return the response to your frontend.
In your callback function, you should make a request to your server where the verification is performed:
1callback: function(response){2 // make API request to your server or serveless function here3}
Do not use your secret key in your frontend
Never call the Paystack API directly from your frontend to avoid exposing your secret key on the frontend. All requests to the Paystack API should be initiated from your server, and your frontend gets the response from your server.
Verify the transaction status
After payment is made, the next step is to confirm the status of the transaction. A transaction can be confirmed by using either webhooks or the verify transactions endpoint. Regardless of the method used, you need to use the following parameter to confirm if you should deliver value to your customer or not:
Parameter | Description |
---|---|
data.status | This inidicates if the payment is successful or not |
data.amount | This indicates the price of your product or service in the lower denomination (e.g for NGN 50, you'd see 5000 and so on) |
Verify amount
When verifying the status of a transaction, you should also verify the amount to ensure it matches the value of the service you are delivering. If the amount doesn't match, do not deliver value to the customer.
Redirect
Here, you call the Initialize TransactionAPI from your server to generate a checkout link, then redirect your users to the link so they can pay. After payment is made, the users are returned to your website at the callback_url
Warning
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.
Collect customer information
To initialize the transaction, you'll need to pass information such as email, first name, last name amount, transaction reference, etc. Email and amount are required. You can also pass any other additional information in the metadata
object field.
The customer information can be retrieved from your database, session or cookie if you already have it stored, or from a form like in the example below.
- HTML
1<form action="/save-order-and-pay" method="POST">2 <input type="hidden" name="user_email" value="<?php echo $email; ?>">3 <input type="hidden" name="amount" value="<?php echo $amount; ?>">4 <input type="hidden" name="cartid" value="<?php echo $cartid; ?>">5 <button type="submit" name="pay_now" id="pay-now" title="Pay now">Pay now</button>6</form>
Initialize transaction
When a customer clicks the payment action button, initialize a transaction by making a POST request to our API. Pass the email, amount and any other parameters to the Initialize TransactionAPI endpoint.
If the API call is successful, we will return an authorization URL which you will redirect to for the customer to input their payment information to complete the transaction.
Important notes
- The
amount
should be in the subunit of the supported currency. - We used the
cart_id
from the form above as our transactionreference
. You should use a unique transaction identifier from your system as your reference. - We set the
callback_url
in the transaction_data array. If you don't do this, we'll use the one that is set on your dashboard. Setting it in the code allows you to be flexible with the redirect URL if you need to - If you don't set a callback URL on the dashboard or on the code, the users will not be redirected back to your site after payment.
- You can set test callback URLs for test transactions and live callback URLs for live transactions.
- PHP
1<?php2 $url = "https://api.paystack.co/transaction/initialize";34 $fields = [5 'email' => "customer@email.com",6 'amount' => "20000"7 ];89 $fields_string = http_build_query($fields);1011 //open connection12 $ch = curl_init();1314 //set the url, number of POST vars, POST data15 curl_setopt($ch,CURLOPT_URL, $url);16 curl_setopt($ch,CURLOPT_POST, true);17 curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);18 curl_setopt($ch, CURLOPT_HTTPHEADER, array(19 "Authorization: Bearer SECRET_KEY",20 "Cache-Control: no-cache",21 ));2223 //So that curl_exec returns the contents of the cURL; rather than echoing it24 curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);2526 //execute post27 $result = curl_exec($ch);28 echo $result;29?>
Verify Transaction
If the transaction is successful, Paystack will redirect the user back to a callback_url
you set. We'll append the transaction reference in the URL. In the example above, the user will be redirected to http://your_website.com/postpayment_callback.php?reference=YOUR_REFERENCE
.
So you retrieve the reference from the URL parameter and use that to call the verify endpoint to confirm the status of the transaction. Learn more about verifying transactions.
It's very important that you call the Verify endpoint to confirm the status of the transactions before delivering value. Just because the callback_url
was visited doesn't prove that transaction was successful.
Handle Webhook
When a payment is successful, Paystack sends a charge.success
webhook event to webhook URL that you provide. Learn more about using webhooks.
Mobile SDKs
You can integrate Paystack directly into your Android or iOS app using our mobile SDK. For mobile frameworks like Ionic or React Native, please find the libraries here.
Charge API
The Create ChargeAPI endpoint allows you to pass details of any payment channel directly to Paystack, along with the transaction details (email
, amount
, etc). We provide a couple of payment channels that you can harness based on your use case.
Use cases
The Charge API exposes the core components powering our checkout. Developers can use these component to develop solutions that will cater to their customers specific needs. Some of these needs include:
- Serving non-smartphone users. Some of your users might be using mobile phones that can't access the internet. With the charge API, you can initiate a payment request form your server and send a prompt for payment completion via phone numbers to these users.
- Harnessing mobile OS APIs for a better user experience. Some businesses offer their products via mobile apps (Android and iOS). Mobile operating systems provide a rich set of APIs that developers can take advantage of. One of such APIs allow developers to autofill an OTP in a form. There are also APIs for dialing codes. Developers can combine the charge API with the mobile OS APIs to provide a richer experience to their users.
Here is a sample payload to the Charge API containing transaction details and an object for a payment instrument - in this case Mobile money:
- JSON
1{2 "amount": 1000,3 "email": "customer@email.com",4 "currency": "GHS",5 "mobile_money": {6 "phone": "0553241149",7 "provider": "MTN"8 }9}
Handling Charge API responses
When you call the Create ChargeAPI endpoint, the response contains a data.status
which tells you what the next step in the process. Depending on the value in the data.status
, you may need to prompt the user for an input as indicated in the response message (like OTP or pin or date of birth), or display an action that the user needs to complete on their device - like scanning a QR code or dialling a USSD code or redirecting to a 3DSecure page. So you follow the prompt on the data.status
until there is no more user input required, then you listen for events via webhooks.
For the steps that prompt for user input, you will be required to display a form to the user to collect the requested input and send it to the relevant endpoint as shown in the table below. For the steps that require the user to complete an action on their device, we recommend that you display a button for the user to confirm the payment after they have performed that action so that you can listen for events via webhooks.
Below is the list of responses you can receive from the Create ChargeAPI endpoint and what you should do next:
Value | Description |
---|---|
pending | Transaction is being processed. Call Check pending charge at least 10seconds after getting this status to check status |
timeout | Transaction has failed. You may start a new charge after showing data.message to user |
success | Transaction is successful. You can now provide value |
send_birthday | Customer's birthday is needed to complete the transaction. Show data.display_text to user with an input that accepts the birthdate and
submit to the Submit BirthdayAPI endpoint with reference and birthday |
send_otp | Paystack needs OTP from customer to complete the transaction. Show data.display_text to user with an input that accepts OTP and submit the
OTP to the Submit OTPAPI endpoint with reference and otp |
failed | Transaction failed. No remedy for this, start a new charge after showing data.message to user |
Handle Webhook
When a payment is successful, Paystack sends a charge.success
webhook event to webhook URL that you provide. It is highly recommended that you use webhooks to confirm the payment status before delivering value to your customers.