Card Payments
This API allows you to accept payment from your customers’ local cards (cards issued in Nigeria) or USD denominated international cards (USA, Canada, Europe and Australia). Cards are issued to customers by their different banks and the authentication protocol for each card is determined by the issuing bank.
These authentication protocols are means by which the customers authenticate their transactions and they include:
- One Time Pin (OTP)
- Card Pin (PIN)
- Address Verification Sytems (AVS)
- Date of Birth (DOB)
- 3Ds (3-D Secure)
Here, we describe how to use our card transaction API to enable you accept direct card payments without utilizing the full power of OPay’s payment gateway.
Mandatory preparations to accept card payments on OPay’s platform
- Create a merchant account here.
- Go to “Settings” and retrieve your Merchant ID
- Go to “Settings” and click on the “API Keys & Webhooks” tab
- Note your Secret & Public Keys as you’ll need them for your headers going forward
Step 1: Initialize a transaction
You can commence a card transaction using 3 different payment methods namely:
- Bank Card: This API requires you providing details of the customers’ card i.e. PAN, CVV, Expiry etc.
- Token: This is mostly used when you have a card that’s been tokenized & you have the token value.
- Bank Account: It’s for scenarios whereby the card details isn’t available but you have the details of the account linked to the card
Each payment method has their own unique request payload.
Step 1a: Initializing a transaction using a bank card
When using this payment method, you give customers the option to provide their card details such as card number, CVV and other relevant details. Go ahead and initialize payment by making a POST
request to the /transaction/initialize
endpoint using the pay by bank card request body below.
HTTP Method
POST
Header Parameters
Parameter | Description |
---|---|
Content-type | application/JSON |
MerchantId | OPay merchant ID is a unique 15-digit number assigned to all OPay merchants. To get your merchantID, login to your OPay Dashboard and click on Settings. |
Authorization | Bearer + Public Key |
Example bankcard pay request body
{
"reference": "test_20191123132234",
"amount": "10000",
"currency": "NGN",
"country": "NG",
"payType": "bankcard",
"firstName;": "firstName",
"lastName": "lastName",
"customerEmail": "123@qq.com",
"cardNumber": "5399237079779357",
"cardDateMonth": "11",
"cardDateYear": "22",
"cardCVC": "590",
"return3dsUrl": "http://www.your.domain.com",
"bankAccountNumber": "22445566787",
"bankCode": "057",
"reason": "transaction reason message",
"callbackUrl": "https://you.domain.com/callbackUrl",
"expireAt": "100",
"billingZip": "xxx",
"billingCity": "xxxx",
"billingAddress": "xxxx",
"billingState": "xxxx",
"billingCountry": "xxxx"
}
Sample Response
{
"code": "00000",
"message": "SUCCESSFUL",
"data": {
"orderNo": "210323140538929542",
"reference": "test_20191123132234",
"amount": null,
"currency": null,
"status": "PENDING",
"token": null,
"authURL": null,
"failureReason": null
}
}
PROPERTY | DESCRIPTION |
---|---|
reference | Order number of merchant (unique order number from merchant platform) |
amount | For NGN transactions, Amount in kobo |
currency | The following currency types are accepted: 1. NGN 2. USD |
country | USA, Canada, Europe and Australia international cards accepted |
payType | token, bankCard, bankAccount |
firstName | First name |
lastName | Last name |
customerEmail | Email address |
cardNumber | Bankcard Number |
cardDateMonth | Bankcard expiration month e.g. 01 |
cardDateYear | Bankcard expiration year e.g. 22 |
cardCVC | Bankcard cvc |
return3dsUrl | What page do you need to call back to after 3ds verification is successful |
bankAccountNumber | Bank Account number, needed when payType is bankAccount |
bankCode | Bank code |
reason | Reason |
expireAt | Transaction would be closed within specific time. Value is in minutes |
billingZip | Zip code or postal card registered with the card |
billingCity | The city registered with the card |
billingAddress | The house/building address registered with the card |
billingState | The state registered with the card. e.g. NY for New York, CA for California, etc |
billingCountry | The country registered with the card. e.g. US, CA, AU, etc |
- The following details are mandatory in the Initialize request payload:
- Billing Zip code
- Billing City
- Billing Address
- Billing State
- Billing Country - You will need to create a different merchant account to process USD transactions. You can’t utilize the same merchant account for a NGN & USD transaction. Kindly notify us at hackathonsupport@opay-inc.com immediately you create a merchant account to be utilized for USD transactions so we can activate all necessary permissions.
- When testing USD transactions, if test is conducted using a card not listed in the provided samples, the default transaction amount is 8.
Step 1a: Initializing a transaction using a token
Card payments can be processed using the token value associated with the card. Hence, by using this token, it will eliminate the need for customers to input other details like card number and expiry date in the request. You can now initialize payment by making a POST
request to the /transaction/initialize
endpoint using the pay by token request body below.
HTTP Method
POST
Header Parameters
Parameter | Description |
---|---|
Content-type | application/JSON |
MerchantId | OPay merchant ID is a unique 15-digit number assigned to all OPay merchants. To get your merchantID, login to your OPay Dashboard and click on Settings. |
Authorization | Bearer + Public key |
API Endpoint
/transaction/initialize
Sample Request
curl -X POST --header 'Authorization: Bearer public_key' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.opayweb.com/api/v3/transaction/initialize
Sample Token Pay Request Body
{
"reference": "test_20191123132233",
"amount": "10000",
"currency": "NGN",
"country": "NG",
"payType": "token",
"token": "BDEFDFDFE43F4DGD2",
"customerPhone": "+2348686868686",
"customerEmail": "123@qq.com",
"reason": "transaction reason message",
"callbackUrl": "https://you.domain.com/callbackUrl",
"expireAt": "100",
}
Sample Response
{
"code": "00000",
"message": "SUCCESSFUL",
"data": {
"orderNo": "210319140538363559",
"reference": "test_20191123133456",
"amount": null,
"currency": null,
"status": "PENDING",
"token": "BDEFDFDFE43F4DGD2",
"authURL": null,
"failureReason": null
}
}
PROPERTY | DESCRIPTION |
---|---|
reference | Order number of merchant (unique order number from merchant platform) |
amount | For NGN transactions, Amount in kobo |
currency | The following currency types are accepted: 1. NGN 2. USD |
country | USA, Canada, Europe and Australia international cards accepted |
payType | token, bankCard, bankAccount |
token | If it is token payment, you need to fill in here |
customerPhone | phone |
customerEmail | |
reason | Reason |
callbackUrl | The asynchronous callback address after transaction successful |
expireAt | Transaction would be closed within specific time. Value is in minutes |
Step 1b: Initializing a transaction using a bank account
Step 1b (part A) - Get list of supported banks and their codes
Before making this API call, you need to make a POST
request to the transaction/banks
API to fetch a list of all supported banks and their codes. Once completed, please proceed to calling the transaction/initialize
endpoint using the pay by bank account request body.
HTTP Method
POST
API Endpoint
/transaction/banks
Sample Request
curl -X POST --header 'Authorization: Bearer public_key' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.operapay.com/api/v3/transaction/banks
Sample Request Body
{
"country": "NG"
}
Sample Response
{
"code": "00000",
"message": "SUCCESSFUL",
"data": {
"banks": [
{
"code": "011",
"name": "First Bank Of Nigeria",
"type": "firstBank",
"icon": "https://owallet-prod-public.oss-eu-west-1.aliyuncs.com/images/api/icon/bank/firstBank.png",
"color": "#CFD9E7",
"isSupportBankAccount": true
},
{
"code": "058",
"name": "Guaranty Trust Bank",
"type": "gtbBank",
"icon": "https://owallet-prod-public.oss-eu-west-1.aliyuncs.com/images/api/icon/bank/gtbBank.png",
"color": "#FDDFCE",
"isSupportBankAccount": true
},
{
"code": "133",
"name": "Providus Bank Plc",
"type": "providusBank",
"icon": "https://owallet-prod-public.oss-eu-west-1.aliyuncs.com/images/api/icon/bank/providusBank.png",
"color": "#FFF1D0",
"isSupportBankAccount": true
},
{
"code": "232",
"name": "Sterling Bank",
"type": "sterlingBank",
"icon": "https://owallet-prod-public.oss-eu-west-1.aliyuncs.com/images/api/icon/bank/sterlingBank.png",
"color": "#F6D6D8",
"isSupportBankAccount": true
},
{
"code": "033",
"name": "United Bank For Africa",
"type": "ubaBank",
"icon": "https://owallet-prod-public.oss-eu-west-1.aliyuncs.com/images/api/icon/bank/ubaBank.png",
"color": "#FBD2CF",
"isSupportBankAccount": true
},
{
"code": "215",
"name": "Unity Bank Plc",
"type": "unityBank",
"icon": "https://owallet-prod-public.oss-eu-west-1.aliyuncs.com/images/api/icon/bank/unityBank.png",
"color": "#E6F3DB",
"isSupportBankAccount": true
},
{
"code": "057",
"name": "Zenith Bank",
"type": "zenithBank",
"icon": "https://owallet-prod-public.oss-eu-west-1.aliyuncs.com/images/api/icon/bank/zenithBank.png",
"color": "#F9CCCF",
"isSupportBankAccount": true
}
],
"commonBanks": null
}
}
PROPERTY | DESCRIPTION |
---|---|
code | supported bankAccount bank code |
country | country |
Step 1b (part B) - Initalize transaction using bankaccount request body
After successfully getting the list of supported banks and their codes from step 1a (part A) above, you can now initialize payment by making a POST
request to the /transaction/initialize
endpoint using the pay by bankaccount request body below.
HTTP Method
POST
Header Parameters
Parameter | Description |
---|---|
Content-type | application/JSON |
MerchantId | OPay merchant ID is a unique 15-digit number assigned to all OPay merchants. To get your merchantID, login to your OPay Dashboard and click on Settings. |
Authorization | Bearer + Public Key |
API Endpoint
/transaction/initialize
Sample Request
curl -X POST --header 'Authorization: Bearer public_key' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.opayweb.com/api/v3/transaction/initialize
Sample Request Body
Example bankaccount pay request body
{
"reference": "test_20191123132236",
"amount": "10000",
"currency": "NGN",
"country": "NG",
"payType": "bankaccount",
"bankAccountNumber": "22445566787",
"bankCode": "057",
"return3dsUrl": "http://www.your.domain.com",
"reason": "transaction reason message",
"customerPhone": "+2341234567890",
"bvn": "1234567890",
"dobDay": "20",
"dobMonth": "04",
"dobYear": "1999"
}
Sample Response
{
"code": "00000",
"message": "SUCCESSFUL",
"data": {
"orderNo": "210323140538925917",
"reference": "test_20191123132236",
"amount": null,
"currency": null,
"status": "PENDING",
"token": null,
"authURL": null,
"failureReason": null
}
}
PROPERTY | DESCRIPTION |
---|---|
reference | Order number of merchant (unique order number from merchant platform) |
amount | For NGN transactions, Amount in kobo |
currency | The following currency types are accepted: 1. NGN 2. USD |
country | USA, Canada, Europe and Australia international cards accepted |
payType | token, bankCard, bankAccount |
bankAccountNumber | Bank Account number, needed when payType is bankAccount |
bankCode | Bank code |
return3dsUrl | What page do you need to call back to after 3ds verification is successful |
reason | Reason |
customerPhone | phone |
bvn | BVN |
dobDay | Day of birth |
dobMonth | Month of birth |
dobYear | Year of birth |
Step 2: Check the status of initialized transaction
For every Initialize Transaction call, the default status returned is “PENDING” or “INITIAL” as transactions are processed asynchronously. You’re to wait for 10 seconds or more before proceeding to check the status of the transaction.
Please note that the Authorization header consists of “Bearer Signature” which is essentially a HMAC SHA512 signature of the whole payload (arranged in alphabetical order) signed using your Secret Key. You can use our Signature calculator here.
HTTP Method
POST
Header Parameters
Parameter | Description |
---|---|
Content-type | application/JSON |
MerchantId | OPay merchant ID is a unique 15-digit number assigned to all OPay merchants. To get your merchantID, login to your OPay Dashboard and click on Settings. |
Authorization | Bearer + Signature (Signature is a combination of both the payload and your secret key) |
API Endpoint
/transaction/status
Sample Request
curl -X POST --header 'Authorization: Bearer Signature' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.opayweb.com/api/v3/transaction/status
Sample Request Body
{
"orderNo": "210323140538859499",
"reference": "test_20210302114235"
}
Sample Response
{
"code": "00000",
"message": "SUCCESSFUL",
"data": {
"amount": "100",
"authURL": null,
"currency": "NGN",
"failureReason": "",
"reference": "test_20210302114235",
"status": "PENDING",
"token": null,
"orderNo": "210323140538859499"
}
}
PROPERTY | DESCRIPTION |
---|---|
amount | Amount us in kobo |
authURL | If status=3DSECURE, it will need customer to access authURL in brower to complete transaction |
currency | NGN |
failureReason | failureReason |
reference | Order number of merchant (unique order number from merchant platform) |
status | INITIAL PENDING SUCCESS FAIL INPUT-PIN INPUT-OTP INPUT-PHONE 3DSECURE CLOSE |
token | Only returned when tokenize is true |
orderNo | Order number from OPay payment |
Step 3: Take Note of the Payment Status in your Response
There are different status(es) that could be returned when you initialize/requery the status of an initialized transaction namely:
- INITIAL
- PENDING
- SUCCESS
- FAIL
- CLOSE
- INPUT-PIN
- INPUT-OTP
- INPUT-PHONE
- 3DSECURE
- When status returns “PENDING” or “INITIAL”, wait a few more seconds, then re-check to see if its status has changed. Don't call too early as you may get a lot more "PENDING" statuses than you should.
- When status returns “CLOSE”, it means the transaction has been closed/canceled (it either expired or the Close API was called to cancel the transaction). You can re-initiate with a different Reference ID.
- When status returns “FAIL”, it means the transaction failed, failure reason would be specified in the failureReason field while “SUCCESS” indicates that the transaction has been processed successfully.
- When status returns any of the following:
- INPUT-PIN
- INPUT-OTP
- INPUT-PHONE
- 3DSECURE
- INPUT-DOB
It means that an authorization is required from the customer before the transaction can be processed. The authorization protocol is determined by the card type & issuing bank.
Below is a list of accepted cards and recognized authorization protocol:
- Nigerian Issued Mastercard / Verve card: INPUT-PIN &/ INPUT-OTP
- VISA Cards: 3DSECURE
- Zenith Bank Issued Card: INPUT-PIN &/ INPUT-OTP &/ INPUT-DOB
- International Cards: AVS &/ 3DSECURE
Step 4: Respond to an Authorization Status
Step 4a: When Status : INPUT-PIN
Request for the card pin from your customer and call the Transaction/input-pin endpoint passing the orderNo & reference gotten from Step 1 or Step 2 above as well as the pin.
HTTP Method
POST
Header Parameters
Parameter | Description |
---|---|
Content-type | application/JSON |
MerchantId | OPay merchant ID is a unique 15-digit number assigned to all OPay merchants. To get your merchantID, login to your OPay Dashboard and click on Settings. |
Authorization | Bearer + Public key |
Sample Request
curl -X POST --header 'Authorization: Bearer public_key' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.opayweb.com/api/v3/transaction/input-pin
Sample Request Body
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"pin": "123456"
}
Sample Response
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"status": "PENDING",
"token": "xxxx",
"authURL": "",
"failureReason": "failureReason "
}
PROPERTY | DESCRIPTION |
---|---|
orderNo | Order number from OPay payment |
reference | Order number of merchant (unique order number from merchant platform) |
status | INITIAL PENDING SUCCESS FAIL INPUT-PIN INPUT-OTP INPUT-PHONE 3DSECURE CLOSE |
authURL | |
failureReason | failureReason |
pin | PIN submitted by user |
Step 4b: When Status : INPUT-OTP
A unique OTP would be generated by the customers’ issuing bank and sent to them via SMS or email. You are required to retrieve the OTP from your customer and call the Transaction/input-otp endpoint passing the orderNo & reference gotten from Step 1 or Step 2 above as well as the OTP.
HTTP Method
POST
Header Parameters
Parameter | Description |
---|---|
Content-type | application/JSON |
MerchantId | OPay merchant ID is a unique 15-digit number assigned to all OPay merchants. To get your merchantID, login to your OPay Dashboard and click on Settings. |
Authorization | Bearer + Public key |
Sample Request
curl -X POST --header 'Authorization: Bearer public_key' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.opayweb.com/api/v3/transaction/input-otp
Sample Request Body
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"otp": "123456"
}
Sample Response
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"status": "PENDING",
"token": "xxxx",
"authURL": "",
"failureReason": "failureReason "
}
PROPERTY | DESCRIPTION |
---|---|
orderNo | Order number from OPay payment |
reference | Order number of merchant (unique order number from merchant platform) |
status | INITIAL PENDING SUCCESS FAIL INPUT-PIN INPUT-OTP INPUT-PHONE 3DSECURE CLOSE |
authURL | |
failureReason | failureReason |
Step 4c: When Status : INPUT-PHONE
Request for the customers’ mobile number linked to the card account and call the Transaction/input-phone endpoint passing the orderNo & reference gotten from Step 1 or Step 2 above as well as the phone number.
HTTP Method
POST
API Endpoint
/transaction/input-phone
Sample Request
curl -X POST --header 'Authorization: Bearer public_key' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.opayweb.com/api/v3/transaction/input-phone
Sample Request Body
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"phone": "+23401234567889"
}
Sample Response
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"status": "PENDING",
"token": "xxxx",
"authURL": "",
"failureReason": "failureReason "
}
PROPERTY | DESCRIPTION |
---|---|
orderNo | Order number from OPay payment |
reference | Order number of merchant (unique order number from merchant platform) |
status | INITIAL PENDING SUCCESS FAIL INPUT-PIN INPUT-OTP INPUT-PHONE 3DSECURE CLOSE |
token | Only returned when tokenize is true |
authURL | |
failureReason | failureReason |
phone | Phone number submitted by user |
Step 4d: When Status : INPUT-DOB
Getting the customer's date of birth is a requirement for Zenith bank accounts. As a result, call the Transaction/input-dob endpoint passing the orderNo & reference gotten from Step 1 or Step 2 above as well as the dob.
HTTP Method
POST
API Endpoint
/transaction/input-dob
Sample Request
curl -X POST --header 'Authorization: Bearer public_key' --header 'MerchantId:
256619092316009' --header 'content-type: application/json'
https://cashierapi.opayweb.com/api/v3/transaction/input-dob
Sample Request Body
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"dob": "dd/mm/yyyy"
}
Sample Response
{
"orderNo": "20019212912901281821982",
"reference": "test_20191123132233",
"status": "PENDING",
"token": "xxxx",
"authURL": "",
"failureReason": "failureReason "
}
PROPERTY | DESCRIPTION |
---|---|
orderNo | Order number from OPay payment |
reference | Order number of merchant (unique order number from merchant platform) |
status | INITIAL PENDING SUCCESS FAIL INPUT-PIN INPUT-OTP INPUT-PHONE 3DSECURE CLOSE |
token | Only returned when tokenize is true |
authURL | |
failureReason | failureReason |
phone | Phone submitted by user |
Step 4e: When Status : 3DSECURE
A link would be returned in the authURL field when you get this status. Kindly redirect the customer to that link to complete the transaction.
Step 5: Verify Payment Status
After completing all payment steps and authorizing the transaction, you need to verify that the payment was successful with OPay before giving value to your customer on your website/app. To do so, call our /transaction/status
endpoint with your orderNo & reference to ensure that the transaction went through successfully.