Payment Channels
In a nutshell
Paystack enables you accept payments from customers using different payment channels such as: cards, mobile money accounts, QR codes, directly from their bank account or USSD.
If you use the the Popup or Redirect method, the paying customer will be shown all the payment methods selected on your dashboard. But if you don't want to use either option, you can initiate all the different payment channels directly from your server using the charge API.
What channels are available?
Card payment channels are available on all Paystack accounts, while the other payment channels are only available in countries where they are supported.
Cards
We strongly discourage passing card information directly to the API to avoid transmitting card data through systems that are not PCI compliant.
If you are PCI-DSS certified and would like to be able to send cardholder information directly to our APIs from your servers, reach out to us!
Bank accounts
Feature availability
This feature is currently available to businesses in Nigeria.
The Pay with Bank feature allows customers pay through internet banking portal or by providing their bank account number and authenticating using an OTP sent to their phone or email.
This is different from Bank Transfers where customers transfer money into a bank account.
Collect bank details
To collect bank details, you would need to prompt the user to select their bank and enter their account number. To fetch the list of supported banks, make a GET
request to the list banksAPI endpoint, with the additional filter pay_with_bank=true
.
The banks can be listed in a dropdown or any other format that allows the user to easily pick their bank of choice.
Create a charge
Send email
, amount
, metadata
, bank
(an object that includes the code
of the bank and account_number
supplied by customer) and birthday
to our Charge endpoint to start.
1curl https://api.paystack.co/charge2-H "Authorization: Bearer YOUR_SECRET_KEY"3-H "Content-Type: application/json"4-d '{ "email": "customer@email.com",5 "amount": "10000",6 "bank": {7 "code": "057",8 "account_number": "0000000000"9 }10 }'11-X POST
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "z8q981z5kp7sfde",6 "status": "send_birthday",7 "display_text": "Please enter your birthday"8 }9}
If the selected bank is Kuda, you need to make use of phone
and token
instead of account_number
in the bank
object:
1curl https://api.paystack.co/charge2-H "Authorization: Bearer YOUR_SECRET_KEY"3-H "Content-Type: application/json"4-d '{ "email": "customer@email.com",5 "amount": "10000",6 "bank": {7 "code": "057",8 "phone": "+23481234567890",9 "token": "123456"10 }11 }'12-X POST13
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "z8q981z5kp7sfde",6 "status": "pending",7 "display_text": "Processing transaction"8 }9}
When the API call is made, the value of the data.status
key is pending
as the payment is being processed in the background. The data.status
then updates to either, success
or failed
depending on whether the transaction was successful or not.
Pay with Transfer
Feature availability
This feature is currently available to businesses in Nigeria and merchants need to reach out to support@paystack.com to enable it on their integration.
Pay with Transfer (PwT) is a feature that allow merchants or businesses create temporary bank accounts that customers can use to pay for goods or services. The account number is generated and tied to the current customer’s transaction. The account number becomes invalid after the customer’s transaction or when it exceeds it’s expiry time.
Create a PwT charge
At the point of payment, you initiate a request to the Create ChargeAPI endpoint, passing the email
, amount
and bank_transfer
object. The bank_transfer
object takes the account_expires_at
which is used to set the expiry of an account number for a transaction:
1#!/bin/sh23url="https://api.paystack.co/charge"4authorization="Authorization: Bearer YOUR_SECRET_KEY"5content_type="Content-Type: application/json"6data='{7 "email": "another@one.com",8 "amount": "25000",9 "bank_transfer": {10 "account_expires_at": "2023-09-12T13:10:00Z"11 }12}'1314curl "$url" -H "$authorization" -H "$content_type" -d "$data" -X POST
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "status": "pending_bank_transfer",6 "display_text": "Please make a transfer to the account specified",7 "reference": "4tn28gwznc",8 "amount": 20000,9 "account_name": "PAYSTACK CHECKOUT",10 "account_number": "1231084927",11 "bank": {12 "slug": "test-bank",13 "name": "Test Bank",14 "id": 2415 },16 "account_expires_at": "2023-09-12T13:10:55.000Z"17 }18}
Bank Transfer Param | Type | Description |
---|---|---|
account_expires_at | String | Account validity period in ISO 8601 format (YYYY-MM-DDThh:mm:ssZ ). Minimum time is 15 mins from the current time and maximum time is 8 hours from the current time. You can also set this to null so we automatically set it to 8 hours from the current time. |
Account expiry
If the difference between account_expires_at
and the current time is less than 15 mins we will default to a 15 mins. If the difference between account_expires_at
and the current time exceeds 8 hours we will default to 8 hours.
Verifying transfer
Receiving notifications
To receive notifications, you need to implement a webhook URL and set the webhook URL on your Paystack Dashboard
A bank transfer is initiated by a customer and processed by their bank. In order to confirm payment, you need to implement webhooks and listen to the following events:
Event | Description |
---|---|
charge.success | This is sent when the customer’s transfer is successful. |
bank.transfer.rejected | This is sent when the customer either sent an incorrect amount or when the customer has been flagged by our fraud system. |
- Charge Successful
- Transfer Rejected
1{2 "event": "charge.success",3 "data": {4 "id": 3104021987,5 "domain": "test",6 "status": "success",7 "reference": "zuz8ggd1ro",8 "amount": 25000,9 "message": null,10 "gateway_response": "Approved",11 "paid_at": "2023-09-12T13:29:09.000Z",12 "created_at": "2023-09-12T13:27:50.000Z",13 "channel": "bank_transfer",14 "currency": "NGN",15 "ip_address": "172.91.42.100",16 "metadata": "",17 "fees_breakdown": null,18 "log": null,19 "fees": 375,20 "fees_split": null,21 "authorization": {22 "authorization_code": "AUTH_q5nfynycgm",23 "bin": "008XXX",24 "last4": "X553",25 "exp_month": "09",26 "exp_year": "2023",27 "channel": "bank_transfer",28 "card_type": "transfer",29 "bank": null,30 "country_code": "NG",31 "brand": "Managed Account",32 "reusable": false,33 "signature": null,34 "account_name": null,35 "sender_country": "NG",36 "sender_bank": null,37 "sender_bank_account_number": "XXXXXXX553",38 "sender_name": "Jadesola Oluwashina",39 "narration": "Channel Tests"40 },41 "customer": {42 "id": 138496675,43 "first_name": null,44 "last_name": null,45 "email": "another@one.com",46 "customer_code": "CUS_1eq06yu8efl8u63",47 "phone": null,48 "metadata": null,49 "risk_action": "default",50 "international_format_phone": null51 },52 "plan": {},53 "subaccount": {},54 "split": {},55 "order_id": null,56 "paidAt": "2023-09-12T13:29:09.000Z",57 "requested_amount": 25000,58 "pos_transaction_data": null,59 "source": {60 "type": "api",61 "source": "merchant_api",62 "entry_point": "charge",63 "identifier": null64 }65 }66}
Alternatively, you can use the Check Pending ChargeAPI endpoint to manually verify the status of the transaction.
USSD
This Payment method is specifically for Nigerian customers. Nigerian Banks provide USSD services that customers use to perform transactions, and we've integrated with some of them to enable customers complete payments.
The Pay via USSD channel allows your Nigerian customers to pay you by dialling a USSD code on their mobile device. This code is usually in the form of * followed by some code and ending with #
. The user is prompted to authenticate the transaction with a PIN and then it is confirmed.
All you need to initiate a USSD charge is the customer email and the amount to charge.
When the user pays, a response will be sent to your webhook. Hence, for this to work properly as expected, webhooks must be set up on your Paystack Dashboard.
Create a charge
Send an email and amount to the chargeAPI endpoint. Specify the USSD type you are charging as well.
Below are all the USSD types
we support. We'll add to list as we have more:
Bank | Type |
---|---|
Guaranty Trust Bank | 737 |
United Bank of Africa | 919 |
Sterling Bank | 822 |
Zenith Bank | 966 |
1curl https://api.paystack.co/charge2-H "Authorization: Bearer YOUR_SECRET_KEY"3-H "Content-Type: application/json"4-d '{ "email": "some@body.nice",5 "amount":"10000",6 "ussd": {7 "type": "737"8 },9 "metadata": {10 "custom_fields":[{11 "value": "makurdi",12 "display_name": "Donation for",13 "variable_name": "donation_for"14 }]15 }16 }'17-X POST
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "yjr1r8rwhedara4",6 "status": "pay_offline",7 "display_text": "Please dial *737*33*4*18791# on your mobile phone to complete the transaction",8 "ussd_code": "*737*33*4*18791#"9 }10}
When a charge is made, the default response provides a USSD code for the customer to dial to complete the payment.
Handle response
When the user completes payment, a response is sent to the merchant’s webhook. Hence, for this to work properly as expected, webhooks must be set up for the merchant..
The charge.success
event is raised on successful payment. The sample response to be sent to the user’s webhook would look like:
- JSON
1{2 "event": "charge.success",3 "data": {4 "id": 53561,5 "domain": "live",6 "status": "success",7 "reference": "2ofkbk0yie6dvzb",8 "amount": 150000,9 "message": "madePayment",10 "gateway_response": "Payment successful",11 "paid_at": "2018-06-25T12:42:58.000Z",12 "created_at": "2018-06-25T12:38:59.000Z",13 "channel": "ussd",14 "currency": "NGN",15 "ip_address": "54.246.237.22, 162.158.38.185, 172.31.15.210",16 "metadata": "",17 "log": null,18 "fees": null,19 "fees_split": null,20 "authorization": {21 "authorization_code": "AUTH_4c6mhnmmeusp4yd",22 "bin": "XXXXXX",23 "last4": "XXXX",24 "exp_month": "05",25 "exp_year": "2018",26 "channel": "ussd",27 "card_type": "offline",28 "bank": "Guaranty Trust Bank",29 "country_code": "NG",30 "brand": "offline",31 "reusable": false,32 "signature": null,33 "account_name": null34 },35 "customer": {36 "id": 16200,37 "first_name": "John",38 "last_name": "Doe",39 "email": "customer@email.com",40 "customer_code": "CUS_bpy9ciomcstg55y",41 "phone": "",42 "metadata": null,43 "risk_action": "default"44 },45 "plan": {},46 "subaccount": {},47 "paidAt": "2018-06-25T12:42:58.000Z"48 }49}
USSD recurring charge
Charging returning customers directly is not currently available. Simply call the endpoint to start a new transaction.
Mobile money
Feature Availability
This feature is only available to businesses in Ghana and Kenya.
The Mobile Money channel allows your customers to pay you by using their phone number enabled for mobile money. At the point of payment, the customer is required to authorize the payment on the mobile phones.
Since payment is completed offline, you need to have a webhook URL which we’ll use to send the final status of the payment to your server.
Create a charge
Send an email and amount to the chargeAPI endpoint along with a mobile_money
object.
1curl https://api.paystack.co/charge2-H "Authorization: Bearer YOUR_SECRET_KEY"3-H "Content-Type: application/json"4-d '{ "amount": 100,5 "email": "customer@email.com",6 "currency": "GHS",7 "mobile_money": {8 "phone" : "0551234987",9 "provider" : "mtn"10 }11 }'12-X POST
Provider code
Here are the 3 character code for the supported mobile money providers:
Provider | Code | Country |
---|---|---|
MTN | mtn | Ghana |
AirtelTigo | tgo | Ghana |
Vodafone | vod | Ghana |
M-Pesa | mpesa | Kenya |
Create a charge
To initiate a charge for mobile money, you need to make a POST
request to the chargeAPI passing the customer’s email
, amount
, and mobile_money
object:
1curl https://api.paystack.co/charge2-H "Authorization: Bearer YOUR_SECRET_KEY"3-H "Content-Type: application/json"4-d '{ "amount": 100,5 "email": "customer@email.com",6 "currency": "GHS",7 "mobile_money": {8 "phone" : "0551234987",9 "provider" : "mtn"10 }11 }'12-X POST
On the successful creation of the charge, you need to handle the response based on the provider selected.
AirtelTigo and MTN
AirtelTigo and MTN requires the customer to complete the transaction process offline, the data.status
field would be pay_offline
, once you get this status, there's nothing left to do. You're expected to display the data.display_text
to your user, and then listen for webhook for transaction notification or requery the verify transaction endpoint at interval.
Here is a sample response that requires the customer to complete the process offline:
- JSON
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "8nn5fqljd0suybr",6 "status": "pay_offline",7 "display_text": "Please complete authorization process on your mobile phone"8 }9}
Vodafone
For Vodafone, the customer is required to generate a voucher code by dialing the USSD code show in the data.display_text field, this voucher code should be collected and passed to the submit OTPAPI endpoint to authorize the transaction.
- JSON
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "r13havfcdt7btcm",6 "status": "send_otp",7 "display_text": "Please dial *110# to generate a voucher code. Then input the voucher"8 }9}
If the mobile money customer enters the otp on time and we are able to get a response just in time, we return the success response:
- JSON
1{2 "message": "Charge attempted",3 "status": true,4 "data": {5 "amount": 100,6 "channel": "mobile_money",7 "created_at": "2018-11-17T14:39:56.000Z",8 "currency": "GHS",9 "domain": "live",10 "fees": 153,11 "gateway_response": "Approved",12 "id": 59333,13 "ip_address": "35.177.189.123, 162.158.155.220",14 "message": "madePayment",15 "paid_at": "2018-11-17T14:40:18.000Z",16 "reference": "l7lvu4y3xcka6zu",17 "status": "success",18 "transaction_date": "2018-11-17T14:39:56.000Z",19 "authorization": {20 "authorization_code": "AUTH_33lz7ev5tq",21 "bank": "MTN Mobile Money",22 "bin": "055XXX",23 "brand": "Mtn mobile money",24 "channel": "mobile_money",25 "country_code": "GH",26 "exp_month": 12,27 "exp_year": 9999,28 "last4": "X149",29 "reusable": false,30 "account_name": null31 },32 "customer": {33 "customer_code": "CUS_s3aa4mx0yyvrqye",34 "email": "customer@email.com",35 "id": 16763,36 "risk_action": "default"37 }38 }39}
If the transaction is started successfully and the pin is not entered on time, we return this:
- JSON
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "84oow6t0rf715g6",6 "status": "pending"7 }8}
M-Pesa
Feature Availability
When creating the request for M-Pesa, kindly ensure the phone number is formated using the country code. For example, 0710000000
should be sent as +254710000000
.
With M-Pesa, the customer is required to use their PIN to authorize the payment. In the data
object, we return a status
of pay_offline
and a display_text
stating that the customer’s authorization is required to complete the payment:
- JSON
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "jq3psd5n96sprwl",6 "status": "pay_offline",7 "display_text": "Please complete authorization process on your mobile phone"8 }9}
Handle response
When the user completes payment, a response is sent to the merchant’s webhook. Hence, for this to work properly as expected, webhooks must be set up for the merchant.
The charge.success
event is raised on successful payment. The sample response to be sent to the user’s webhook would look like:
- JSON
1{2 "event": "charge.success",3 "data": {4 "id": 59214,5 "domain": "live",6 "status": "success",7 "reference": "gf4n3ykzj6a7u89",8 "amount": 100,9 "message": "madePayment",10 "gateway_response": "Approved",11 "paid_at": "2018-11-15T06:10:54.000Z",12 "created_at": "2018-11-15T06:10:32.000Z",13 "channel": "mobile_money",14 "currency": "GHS",15 "ip_address": "18.130.236.148, 141.101.99.73",16 "metadata": "",17 "log": null,18 "fees": 153,19 "fees_split": null,20 "authorization": {21 "authorization_code": "AUTH_0aqm8ddx6s",22 "bin": "055XXX",23 "last4": "X149",24 "exp_month": "12",25 "exp_year": "9999",26 "channel": "mobile_money",27 "card_type": "",28 "bank": "MTN Mobile Money",29 "country_code": "GH",30 "brand": "Mtn mobile money",31 "reusable": false,32 "signature": null,33 "account_name": "BoJack Horseman"34 },35 "customer": {36 "id": 16678,37 "first_name": "Babafemi",38 "last_name": "Aluko",39 "email": "customer@email.com",40 "customer_code": "CUS_2jk1i8ezoam49br",41 "phone": "",42 "metadata": null,43 "risk_action": "allow"44 },45 "plan": {},46 "subaccount": {},47 "subaccount_group": {},48 "paidAt": "2018-11-15T06:10:54.000Z"49 }50}
Charging returning customers directly is not currently available. Simply call the endpoint to start a new transaction. We have some test credentials that can be used to run some tests.
EFT
EFT payments are an instant bank transfer payment method where customers pay merchants through their internet banking interfaces. When the developer specifies an EFT provider, we do a redirect to the providers platform where the customer provides their payment details after which the payment is authorized.
Where is this available?
This feature is only available to South African customers.
Create a charge
You need to send the email
, amount
, currency
, and the EFT provider to the chargeAPI endpoint:
1curl https://api.paystack.co/charge2-H "Authorization: Bearer YOUR_SECRET_KEY"3-H "Content-Type: application/json"4-d '{5 "amount": 5000,6 "currency": "ZAR",7 "email": "customer@email.com",8 "eft": {9 "provider": "ozow"10 }11}'12-X POST
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "18c0ywb63zutno0",6 "status": "open_url",7 "url": "https://crayon.paystack.co/eft/EFT_OZOW/121502"8 }9}
Available Providers
Ozow is currently the only provider available.
Handle response
When the user completes payment, a response is sent to the merchant’s webhook. The merchant needs to setup webhooks to get the status of the payment. The charge.success
event is raised on successful payment.
QR code
The QR option generates a QR code that allow customers to use a supported mobile app to complete payments.
When the customer scans the code, they authenticate on a supported app to complete the payment. When the user pays, a response will be sent to your webhook. This means that you need to implement and set a webhook URL on your Paystack Dashboard.
Create a charge
Send an email and amount to the chargeAPI endpoint along with a qr
object. The qr
object should contain a provider
parameter, specifying the QR provider for the transaction. The available QR providers are:
Provider | Availability |
---|---|
masterpass | South Africa |
visa | Nigeria |
Supported Apps
The masterpass
provider supports both SnapScan and Masterpass-supported apps for completing a payment.
1curl https://api.paystack.co/charge2-H "Authorization: Bearer YOUR_SECRET_KEY"3-H "Content-Type: application/json"4-d '{ "amount": 100,5 "email": "customer@email.com",6 "currency": "NGN",7 "qr": {8 "provider" : "visa"9 }10 }'11-X POST
1{2 "status": true,3 "message": "Charge attempted",4 "data": {5 "reference": "48rx32f1womvcr4",6 "status": "pay_offline",7 "qr_code": "0002010216421527000104176552045499530356654031005802NG5920Babafemi enterprises6005Lagos62230519PSTK_104176000926|16304713a",8 "url": "https://files.paystack.co/qr/visa/104176/Babafemi_enterprises_visaqr_1544025482956.png"9 }10}
Handle response
When the user completes payment, a response is sent to the merchant’s webhook. Hence, for this to work properly as expected, webhooks must be set up for the merchant.
The charge.success
event is raised on successful payment. The sample response to be sent to the user’s webhook would look like:
- JSON
1{2 "event": "charge.success",3 "data": {4 "id": 59565,5 "domain": "test",6 "status": "success",7 "reference": "48rx32f1womvcr4",8 "amount": 10000,9 "message": "madePayment",10 "gateway_response": "Payment successful",11 "paid_at": "2018-12-05T15:58:45.000Z",12 "created_at": "2018-12-05T15:58:02.000Z",13 "channel": "qr",14 "currency": "NGN",15 "ip_address": "18.130.45.28, 141.101.107.157",16 "metadata": "",17 "log": null,18 "fees": null,19 "fees_split": null,20 "authorization": {21 "authorization_code": "AUTH_2b4zs69fgy7qflh",22 "bin": "483953",23 "last4": "6208",24 "exp_month": "12",25 "exp_year": "2018",26 "channel": "qr",27 "card_type": "DEBIT",28 "bank": "Visa QR",29 "country_code": "NG",30 "brand": "VISA",31 "reusable": false,32 "signature": null,33 "account_name": "BoJack Horseman"34 },35 "customer": {36 "id": 16787,37 "first_name": "I",38 "last_name": "SURRENDER",39 "email": "customer@email.com",40 "customer_code": "CUS_ehg851zbxon0bvx",41 "phone": "",42 "metadata": null,43 "risk_action": "default"44 },45 "plan": {},46 "subaccount": {},47 "subaccount_group": {},48 "paidAt": "2018-12-05T15:58:45.000Z"49 }50}
QR code recurring charge
Charging returning customers directly is currently not available. You need to call the endpoint to start a new transaction.
Supported Apps
In order to complete a payment, your customers can scan or enter the code in a supported application. Here are the supported applications by providers:
Visa
Customers can scan Visa QR codes from the following banking apps:
- Ecobank
- First Bank
- Fidelity Bank
- Access Bank
- Access (Diamond) Bank
- Zenith Bank
SnapScan
Customers can complete a payment in a snap by scanning the QR code with their SnapScan iOS or Android app.
Masterpass
Customers can scan Masterpass QR codes from any of the mobile apps listed below:
Standalone Masterpass | Banking | 3rd Party |
---|---|---|
Nedbank Masterpass | FNB Pay | Spot (by Virgin Money) |
Standard Bank SA Masterpass | Capitec Banking | Vodapay |
Capitec Masterpass | Nedbank Money | Chips |
Absa Masterpass | Nedbank Avo |