This page shows how to perform card payments using Rave's APIs
Rave allows you charge local (card's issued in Nigeria) and International cards using our APIs. When charging cards with Rave you have to take into account card authentication methods
this is primarily how the user who is meant to pay authenticates their transaction e.g. using a one time pin
(OTP), a card internet PIN
(i-Pin) or an address verification system
(AVS) or without any authentication set.
Rave automatically determines the authentication model to be used by the card and sends a response requiring you pass the needed parameter for that authentication model.
The guide below would show you how to charge cards on rave using our APIs.
Pre-requisites for accepting card payments on rave.
-
Sign-up for an account here .
-
You can use Webhooks to get notified of transactions or use the response returned by the endpoint.
-
For all card payments, you would need to implement three steps to the transactions,
Initiate payment
,Validate payment
,Verify completed payment
. Excluding transactions that don't require authentication. -
Get a more detailed overview of card payments with Rave by reading our ultimate guide to card payments
Step 1: Collect the card details from the customer
You can use a custom form to collect the card details from the customer including extra information needed, see a sample of the card details to collect from the customer.
{
"PBFPubKey": "FLWPUBK-4e581ebf8372cd691203b27227e2e3b8-X",
"cardno": "5438898014560229",
"cvv": "890",
"expirymonth": "09",
"expiryyear": "19",
"currency": "NGN",
"country": "NG",
"amount": "10",
"email": "[email protected]",
"phonenumber": "0902620185",
"firstname": "temi",
"lastname": "desola",
"IP": "355426087298442",
"txRef": "MC-" + Date.now(),// your unique merchant reference
"meta": [{metaname: "flightID", metavalue: "123949494DC"}],
"redirect_url": "https://rave-webhook.herokuapp.com/receivepayment",
"device_fingerprint": "69e6b7f0b72037aa8428b70fbe03986c"
}
{
"PBFPubKey": "FLWPUBK-4e581ebf8372cd691203b27227e2e3b8-X",
"cardno": "5438898014560229",
"cvv": "890",
"expirymonth": "09",
"expiryyear": "19",
"currency": "NGN",
"country": "NG",
"amount": "10",
"email": "[email protected]",
"phonenumber": "0902620185",
"firstname": "temi",
"lastname": "desola",
"subaccounts": [
{
"id": "RS_D87A9EE339AE28BFA2AE86041C6DE70E",
"transaction_split_ratio": "2"
},
{
"id": "RS_344DD49DB5D471EF565C897ECD67CD95",
"transaction_split_ratio": "3"
},
{
"id": "RS_839AC07C3450A65004A0E11B83E22CA9",
"transaction_split_ratio": "5"
}
],
"IP": "355426087298442",
"txRef": "MC-",
"meta": [
{
"metaname": "flightID",
"metavalue": "123949494DC"
}
],
"IP": "355426087298442",
"txRef": "MC-" + Date.now(),// your unique merchant reference
"redirect_url": "https://rave-webhook.herokuapp.com/receivepayment",
"device_fingerprint": "69e6b7f0b72037aa8428b70fbe03986c"
}
{
"PBFPubKey": "FLWPUBK-4e581ebf8372cd691203b27227e2e3b8-X",
"cardno": "5438898014560229",
"cvv": "890",
"expirymonth": "09",
"expiryyear": "19",
"currency": "NGN",
"country": "NG",
"amount": "10",
"email": "[email protected]",
"phonenumber": "0902620185",
"firstname": "temi",
"lastname": "desola",
"subaccounts": [
{
"id": "RS_D87A9EE339AE28BFA2AE86041C6DE70E"
}
],
"IP": "355426087298442",
"txRef": "MC-",
"meta": [
{
"metaname": "flightID",
"metavalue": "123949494DC"
}
],
"IP": "355426087298442",
"txRef": "MC-" + Date.now(),// your unique merchant reference
"redirect_url": "https://rave-webhook.herokuapp.com/receivepayment",
"device_fingerprint": "69e6b7f0b72037aa8428b70fbe03986c"
}
Parameter Description
Parameter | Required | Description |
---|---|---|
PBFPubKey | true | This is a unique key generated for each button created on Rave’s dashboard. It starts with a prefix FLWPUBK and ends with suffix X . |
cardno | true | This is the number on the cardholders card. E.g. 5399 6701 2349 0229. |
cvv | true | Card security code. This is 3/4 digit code at the back of the customers card, used for web payments. |
expirymonth | true | Two-digit number representing the card's expiration month. |
expiryyear | true | Two- digit number representing the card's expiration year. |
currency | falsedefaults to NGN | This is the specified currency to charge the card in. With Rave you can charge cards in more than 90 currencies, all you need to do is pass the specified currency you would like to charge the in. |
country | falsedefaults to NG | This is the pair country for the transaction with respect to the currency. See a list of Multicurrency support here Multicurrency Payments ] |
amount | true | This is the amount to be charged from card it is passed as - (“amount”:10). |
email | true | This is the email address of the customer. |
phonenumber | false | This is the phone number of the customer. |
firstname | false | This is the first name of the card holder or the customer. |
lastname | false | This is the last name of the card holder or the customer. |
IP | false | IP - Internet Protocol. This represents the current IP address of the customer carrying out the transaction. |
txRef | true | This is the unique reference, unique to the particular transaction being carried out. It is generated by the merchant for every transaction |
meta | false | Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. |
subaccounts | false | This is an array of objects containing the subaccount IDs to split the payment into. |
redirect_url | false3DSecure only | This is a url you provide, we redirect to it after the customer completes payment and append the response to it as query parameters. |
device_fingerprint | false | This is the fingerpringt for the device being used. It can be generated using a library on whatever platform is being used. |
charge_type | falseexpected value: preauth | This identifies that you are making a Preauthorised payment request call to the charge endpoint by passing the value preauth. It should be built with your payment request only when carrying out a preauthorised transaction. |
usesecureauth | false | This field is set to send OTPs to authenticate preauth transactions. |
Step 2: Encrypt the card details.
To see how to encrypt using any of our encryption function copy the sample request below and visit the Rave Encryption section.
Step 3: Initiate your payment.
After encryption, the next step is to initiate your payment using the encrypted string by sending a request to the /charge
endpoint. See how to do that below.
https://api.ravepay.co/flwv3-pug/getpaidx/api/charge
Sample Request:
Copy the curl request and make a request in your terminal to see how it works!
curl --request POST \
--url https://api.ravepay.co/flwv3-pug/getpaidx/api/charge \
--header 'content-type: application/json' \
--data '{"PBFPubKey":"FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X","client":"VodhvFFsni0CBeieHPq9HTuG5lbNPgmD5rbEw6Uxb0TD9eD9B3VM5uZ1B5lC3thQMbPypNBCAYxaW2W21VnGuznMPf1G1digW0sHjuO6BGLGbzkwv12rmgNelv19ECSaKfyJmWOSPBvQifHMXZz2M35WuZpE2oD78Be54Xz7vUy3b6MkxrFc+d5gTnuiluBcSDSmnpj/d1ovlo5bix3PeuMUtIYzGFE/RK/EcIYyfYnpL26VFT1aEn5d/iOPyHecqFYVhCMwzV0E6j0uBtT/DMWg+Bi4O1VHej2EBxxKcmwu9rTYvsFf81AtOKZazJEKOea9Xn7mx0J/QpcP2kEf3asWrUqNUgvacl8y8IyaS4jGtU7fCcrIreHttSekpT/16rc45sC428zQy6OfSLoJDA4D2Ww+TEYnMWRNhzuBDHJ9wJTfHmgQcipiD/r7cQyLAzyllfhXsHWFIv3R+ECgrrvxpYMe2lVQ5d+DdTO2pC1MyhkOscNBp7dUwoEGfU7nxY/UGoRWV5WSAg9nFYELS2F4gfvWVkbP07Q+ap11GYUbuZFTMmfULbK/3j//q+9eElWS+E2m6mY4upgehIat8qIGsvGLKR3kagL4wQPZlBMD/S8eiQ8sUD+ngFS8T0XfZUXC5m6IMQdZ7Bfz0mAT2w==","alg":"3DES-24"}'
{
"PBFPubKey": "FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X",
"client": "VodhvFFsni0CBeieHPq9HTuG5lbNPgmD5rbEw6Uxb0TD9eD9B3VM5uZ1B5lC3thQMbPypNBCAYxaW2W21VnGuznMPf1G1digW0sHjuO6BGLGbzkwv12rmgNelv19ECSaKfyJmWOSPBvQifHMXZz2M35WuZpE2oD78Be54Xz7vUy3b6MkxrFc+d5gTnuiluBcSDSmnpj/d1ovlo5bix3PeuMUtIYzGFE/RK/EcIYyfYnpL26VFT1aEn5d/iOPyHecqFYVhCMwzV0E6j0uBtT/DMWg+Bi4O1VHej2EBxxKcmwu9rTYvsFf81AtOKZazJEKOea9Xn7mx0J/QpcP2kEf3asWrUqNUgvacl8y8IyaS4jGtU7fCcrIreHttSekpT/16rc45sC428zQy6OfSLoJDA4D2Ww+TEYnMWRNhzuBDHJ9wJTfHmgQcipiD/r7cQyLAzyllfhXsHWFIv3R+ECgrrvxpYMe2lVQ5d+DdTO2pC1MyhkOscNBp7dUwoEGfU7nxY/UGoRWV5WSAg9nFYELS2F4gfvWVkbP07Q+ap11GYUbuZFTMmfULbK/3j//q+9eElWS+E2m6mY4upgehIat8qIGsvGLKR3kagL4wQPZlBMD/S8eiQ8sUD+ngFS8T0XfZUXC5m6IMQdZ7Bfz0mAT2w==",
"alg": "3DES-24"
}
-
client
: This is the encrypted request parameters. -
PBFPubKey
: This is your merchant public key. -
alg
: must always be passed as3DES-24
When you initiate the payment you would get a response based on the card that was sent to Rave, we explain the response you would get for each card type and what you need to do next.
Using a Local Mastercard/verve i.e. card issued in Nigeria
When using a local mastercard/Verve card, we suggest that you charge the card using the customers PIN, the suggested auth is returned after initiating payment
, you would get a response that looks like this:
{
"status": "success",
"message": "AUTH_SUGGESTION",
"data": {
"suggested_auth": "PIN"
}
}
When you get this response you are to add pin
and suggested_auth
to your payload again, re-encrypt
it and Initiate the payment again. See an example of the new request to send to the Initiate the payment.
{
"PBFPubKey": "FLWPUBK-4e581ebf8372cd691203b27227e2e3b8-X",
"cardno": "5438898014560229",
"cvv": "890",
"expirymonth": "09",
"expiryyear": "19",
"currency": "NGN",
"pin": "3310",
"country": "NG",
"amount": "10",
"email": "[email protected]",
"suggested_auth": "PIN",
"phonenumber": "0902620185",
"firstname": "temi",
"lastname": "desola",
"IP": "355426087298442",
"txRef": "MC-" + Date.now(),
"redirect_url": "https://rave-webhook.herokuapp.com/receivepayment",
"meta": [{metaname: "flightID", metavalue: "123949494DC"}],
"device_fingerprint": "69e6b7f0b72037aa8428b70fbe03986c"
}
Using AVS (Address verification system) to charge an international card.
When using an international card that uses the AVS system, we detect this automatically and suggest using the AVS authmodel. The suggested authmodel is returned after initiating payment with the card details, see a sample response below.
{
"status": "success",
"message": "AUTH_SUGGESTION",
"data": {
"suggested_auth": "NOAUTH_INTERNATIONAL"
}
}
{
"status": "success",
"message": "AUTH_SUGGESTION",
"data": {
"suggested_auth": "AVS_VBVSECURECODE"
}
}
When you get this response you are to add the cards billing address details
and suggested_auth
to your payload again, re-encrypt it and Initiate the payment again. See an example of the new request to send to the Initiate the payment.
{
"PBFPubKey": "FLWPUBK-4e581ebf8372cd691203b27227e2e3b8-X",
"cardno": "4556052704172643",
"cvv": "828",
"expirymonth": "09",
"expiryyear": "19",
"currency": "USD",
"country": "NG",
"amount": "10",
"email": "[email protected]",
"phonenumber": "0902620185",
"firstname": "temi",
"lastname": "desola",
"IP": "355426087298442",
"txRef": "MC-" + Date.now(),
"meta": [{metaname: "flightID", metavalue: "123949494DC"}],
"suggested_auth": "AVS_VBVSECURECODE"/ "NOAUTH_INTERNATIONAL",
"billingzip": "07205",
"billingcity": "Hillside",
"billingaddress": "470 Mundet PI",
"billingstate": "NJ",
"billingcountry": "US",
"redirect_url": "https://rave-webhook.herokuapp.com/receivepayment",
"device_fingerprint": "69e6b7f0b72037aa8428b70fbe03986c"
}
The billing details of the card include, billingzip
, billingcity
, billingaddress
, billingstate
, billingcountry
.
-
billingzip
: This is the zip code or postal card registered with the card, customers can easily find this on their bank statement. -
billingcity
: This is the city registered with the card, it makes up part of the address the customer used for their card. Customers can easily find this on their bank statement. -
billingaddress
: This is the house/building address registered with the card. Customers can easily find this on their bank statement. -
billingstate
: This is the state registered with the card. Customers can easily find this on their bank statement. -
billingcountry
: This is the country registered with the card. Customers can easily find this on their bank statement.
Handling AVS_VBVSECURECODE & 3DSecure Transactions
When the suggested auth is AVS_VBVSECURECODE
it means the payment requires that the billing address of the card is sent, and after the Initiate payment
step the validation
step would happen using 3DSecure
authentication.
What you need to do after receiving the initial payment response is load the authUrl
returned in an iFrame and allow the customer to validate the transaction, once that is completed we would call your redirect _url
and append the response as query parameters.
3Dsecure Transactions.
Billing address details are not required for strictly 3DSecure transactions.
Final response to expect from the Initiate payment call.
{
"status": "success",
"message": "V-COMP",
"data": {
"id": 12945,
"txRef": "MC-7663-YU",
"orderRef": "URF_1501241395442_2906135",
"flwRef": "FLW-MOCK-9deabfa86935b9f0805ae276d49ad079",
"redirectUrl": "http://127.0.0",
"device_fingerprint": "69e6b7f0b72037aa8428b70fbe03986c",
"settlement_token": null,
"cycle": "one-time",
"amount": 10,
"charged_amount": 10,
"appfee": 0,
"merchantfee": 0,
"merchantbearsfee": 0,
"chargeResponseCode": "02",
"chargeResponseMessage": "Success-Pending-otp-validation",
"authModelUsed": "PIN",
"currency": "NGN",
"IP": "::ffff:127.0.0.1",
"narration": "FLW-PBF CARD Transaction ",
"status": "success-pending-validation",
"vbvrespmessage": "Approved. Successful",
"authurl": "N/A",
"vbvrespcode": "00",
"acctvalrespmsg": null,
"acctvalrespcode": null,
"paymentType": "card",
"paymentId": "2",
"fraud_status": "ok",
"charge_type": "normal",
"is_live": 0,
"createdAt": "2017-07-28T11:29:55.000Z",
"updatedAt": "2017-07-28T11:29:56.000Z",
"deletedAt": null,
"customerId": 168,
"AccountId": 134,
"customer": {
"id": 168,
"phone": null,
"fullName": "demi adeola",
"customertoken": null,
"email": "[email protected]",
"createdAt": "2017-02-25T12:20:22.000Z",
"updatedAt": "2017-02-25T12:20:22.000Z",
"deletedAt": null,
"AccountId": 134
},
"customercandosubsequentnoauth": true
}
}
https://rave-webhook.herokuapp.com/newregistration?response=%7B%22name%22%3A%22opop%22%2C%22data%22%3A%7B%22status%22%3A%22success%22%2C%22message%22%3A%22V-COMP%22%2C%22data%22%3A%7B%22id%22%3A301782%2C%22txRef%22%3A%22rave-checkout-1541080175862%22%2C%22orderRef%22%3A%22URF_1541080202653_2603435%22%2C%22flwRef%22%3A%22FLWACHMOCK-1541080203844%22%2C%22redirectUrl%22%3A%22https%3A%2F%2Frave-webhook.herokuapp.com%2Fnewregistration%22%2C%22device_fingerprint%22%3A%22532b4e9fa7695279392f4780b9868b9b%22%2C%22settlement_token%22%3Anull%2C%22cycle%22%3A%22one-time%22%2C%22amount%22%3A60%2C%22charged_amount%22%3A60%2C%22appfee%22%3A0.9%2C%22merchantfee%22%3A0%2C%22merchantbearsfee%22%3A1%2C%22chargeResponseCode%22%3A%2200%22%2C%22raveRef%22%3A%22RV31541080202194E1A956BA48%22%2C%22chargeResponseMessage%22%3A%22Approved.+Successful.%22%2C%22authModelUsed%22%3A%22AUTH%22%2C%22currency%22%3A%22NGN%22%2C%22IP%22%3A%22197.149.95.62%22%2C%22narration%22%3A%22Synergy+Group%22%2C%22status%22%3A%22successful%22%2C%22modalauditid%22%3A%2276d43165b4e49f5ce5e71736298e109d%22%2C%22vbvrespmessage%22%3A%22N%2FA%22%2C%22authurl%22%3A%22NO-URL%22%2C%22vbvrespcode%22%3A%22N%2FA%22%2C%22acctvalrespmsg%22%3Anull%2C%22acctvalrespcode%22%3Anull%2C%22paymentType%22%3A%22account%22%2C%22paymentPlan%22%3Anull%2C%22paymentPage%22%3Anull%2C%22paymentId%22%3A%22478%22%2C%22fraud_status%22%3A%22ok%22%2C%22charge_type%22%3A%22normal%22%2C%22is_live%22%3A0%2C%22createdAt%22%3A%222018-11-01T13%3A50%3A02.000Z%22%2C%22updatedAt%22%3A%222018-11-01T13%3A50%3A03.000Z%22%2C%22deletedAt%22%3Anull%2C%22customerId%22%3A58159%2C%22AccountId%22%3A134%2C%22customer%22%3A%7B%22id%22%3A58159%2C%22phone%22%3A%22N%2FA%22%2C%22fullName%22%3A%22Anonymous+customer%22%2C%22customertoken%22%3Anull%2C%22email%22%3A%22cchizie26%40gmail.com%22%2C%22createdAt%22%3A%222018-10-24T16%3A58%3A21.000Z%22%2C%22updatedAt%22%3A%222018-10-24T16%3A58%3A21.000Z%22%2C%22deletedAt%22%3Anull%2C%22AccountId%22%3A134%7D%2C%22validateInstructions%22%3A%7B%22valparams%22%3A%5B%5D%2C%22instruction%22%3A%22%22%7D%2C%22validateInstruction%22%3A%22Please+dial+*901*4*1%23+to+get+your+OTP.+Enter+the+OTP+gotten+in+the+field+below%22%7D%7D%2C%22tx%22%3A%7B%22id%22%3A301782%2C%22txRef%22%3A%22rave-checkout-1541080175862%22%2C%22orderRef%22%3A%22URF_1541080202653_2603435%22%2C%22flwRef%22%3A%22FLWACHMOCK-1541080203844%22%2C%22redirectUrl%22%3A%22https%3A%2F%2Frave-webhook.herokuapp.com%2Fnewregistration%22%2C%22device_fingerprint%22%3A%22532b4e9fa7695279392f4780b9868b9b%22%2C%22settlement_token%22%3Anull%2C%22cycle%22%3A%22one-time%22%2C%22amount%22%3A60%2C%22charged_amount%22%3A60%2C%22appfee%22%3A0.9%2C%22merchantfee%22%3A0%2C%22merchantbearsfee%22%3A1%2C%22chargeResponseCode%22%3A%2200%22%2C%22raveRef%22%3A%22RV31541080202194E1A956BA48%22%2C%22chargeResponseMessage%22%3A%22Approved.+Successful.%22%2C%22authModelUsed%22%3A%22AUTH%22%2C%22currency%22%3A%22NGN%22%2C%22IP%22%3A%22197.149.95.62%22%2C%22narration%22%3A%22Synergy+Group%22%2C%22status%22%3A%22successful%22%2C%22modalauditid%22%3A%2276d43165b4e49f5ce5e71736298e109d%22%2C%22vbvrespmessage%22%3A%22N%2FA%22%2C%22authurl%22%3A%22NO-URL%22%2C%22vbvrespcode%22%3A%22N%2FA%22%2C%22acctvalrespmsg%22%3Anull%2C%22acctvalrespcode%22%3Anull%2C%22paymentType%22%3A%22account%22%2C%22paymentPlan%22%3Anull%2C%22paymentPage%22%3Anull%2C%22paymentId%22%3A%22478%22%2C%22fraud_status%22%3A%22ok%22%2C%22charge_type%22%3A%22normal%22%2C%22is_live%22%3A0%2C%22createdAt%22%3A%222018-11-01T13%3A50%3A02.000Z%22%2C%22updatedAt%22%3A%222018-11-01T13%3A50%3A03.000Z%22%2C%22deletedAt%22%3Anull%2C%22customerId%22%3A58159%2C%22AccountId%22%3A134%2C%22customer%22%3A%7B%22id%22%3A58159%2C%22phone%22%3A%22N%2FA%22%2C%22fullName%22%3A%22Anonymous+customer%22%2C%22customertoken%22%3Anull%2C%22email%22%3A%22cchizie26%40gmail.com%22%2C%22createdAt%22%3A%222018-10-24T16%3A58%3A21.000Z%22%2C%22updatedAt%22%3A%222018-10-24T16%3A58%3A21.000Z%22%2C%22deletedAt%22%3Anull%2C%22AccountId%22%3A134%7D%2C%22validateInstructions%22%3A%7B%22valparams%22%3A%5B%5D%2C%22instruction%22%3A%22%22%7D%2C%22validateInstruction%22%3A%22Please+dial+*901*4*1%23+to+get+your+OTP.+Enter+the+OTP+gotten+in+the+field+below%22%7D%2C%22success%22%3Atrue%7D
Some of the important responses you need to check are broken down below:
-
data.chargeResponseCode
: This is the response code of the transaction, it typically tells you when a transaction is successful with a response code00
or when the transaction requires validation02
. -
data.chargeResponseMessage
: This is the response message and it can be shown to the customer to show what needs to be done next. -
data.authModelUsed
: This shows you the authentication model used for the transaction, it can also help you decide internally what steps to take after the payment is initiated, e.g. if the value isPIN
the customer would be required to submit theirotp
based on the message returned inchargeResponseMessage
or if the value isVBVSECURECODE
you would be required to load theauthurl
returned in the response in an iframe. -
data.authurl
: This is used for authenticating the customer in a VBVSECURECODE transaction, you need to load it in an iFrame if returned to you -
data.paymentType
: This shows you the payment instrument used i.e. if the customer used acard
,account
orussd
to complete the payment.
Step 4: Validate the payment.
After initiating the payment you would need to validate the transaction, validation is like authentication, essentially the customer is required to validate that he is the customer with the correct permissions to carry out the payment.
When validating transactions you need to take into account the authModelUsed
and the chargeResponseMessage
returned.
Scenario 1:
When
-
authModelUsed
:PIN
you would be asked to validate the transaction by asking the customer for the OTP sent to their registered(with the bank account) mobile number. -
chargeResponseMessage
: You need to show this to the customer, it would come with the instructions needed to complete validation.
Scenario 2:
When
authModelUsed
:VBVSECURECODE
you would be asked to validate by loading the authurl returned in an iframe, the customer would see a page with their bank's branding asking them to validate the transaction, once this is completed we would call yourredirect_url
and append the response as query parameters.
NB: When validating a transaction with VBVSECURECODE
as the auth model there would be no use of the /validatecharge
endpoint.
To Validate a transaction, see how below:
https://api.ravepay.co/flwv3-pug/getpaidx/api/validatecharge
Sample Request:
curl --request POST \
--url https://api.ravepay.co/flwv3-pug/getpaidx/api/validatecharge \
--header 'content-type: application/json' \
--data '{"PBFPubKey":"FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X","transaction_reference":"FLW-MOCK-ce3654ac725278c4e2b7700c3af1fab8","otp":12345}'
{
"PBFPubKey": "FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X",
"transaction_reference": "FLW-MOCK-744927fe5cae22fddef891d1ee14ac7b",
"otp": "181971713"
}
-
PBFPubKey
: This is your merchant public key. -
transaction_reference
: This is theflwRef
returned in the Initiate payment response. -
otp
: This is the one time pin inputed by the customer.
When you validate a payment you would get a response that looks like responses below:
{
"status": "success",
"message": "Charge Complete",
"data": {
"data": {
"responsecode": "00",
"responsemessage": "successful"
},
"tx": {
"id": 12935,
"txRef": "Ghshsh",
"orderRef": "URF_1501241077083_3844735",
"flwRef": "FLW-MOCK-a71d1de9130a1e221720ef52456943e5",
"redirectUrl": "http://127.0.0",
"device_fingerprint": "N/A",
"settlement_token": null,
"cycle": "one-time",
"amount": 1000,
"charged_amount": 1000,
"appfee": 0,
"merchantfee": 0,
"merchantbearsfee": 0,
"chargeResponseCode": "00",
"chargeResponseMessage": "Success-Pending-otp-validation",
"authModelUsed": "PIN",
"currency": "NGN",
"IP": "::ffff:127.0.0.1",
"narration": "FLW-PBF CARD Transaction ",
"status": "successful",
"vbvrespmessage": "successful",
"authurl": "http://flw-pms-dev.eu-west-1.elasticbeanstalk.com/mockvbvpage?ref=FLW-MOCK-a71d1de9130a1e221720ef52456943e5&code=00&message=Approved. Successful",
"vbvrespcode": "00",
"acctvalrespmsg": null,
"acctvalrespcode": null,
"paymentType": "card",
"paymentId": "2",
"fraud_status": "ok",
"charge_type": "normal",
"is_live": 0,
"createdAt": "2017-07-28T11:24:37.000Z",
"updatedAt": "2017-07-28T13:42:20.000Z",
"deletedAt": null,
"customerId": 85,
"AccountId": 134,
"customer": {
"id": 85,
"phone": null,
"fullName": "Anonymous customer",
"customertoken": null,
"email": "[email protected]",
"createdAt": "2017-01-24T08:09:05.000Z",
"updatedAt": "2017-01-24T08:09:05.000Z",
"deletedAt": null,
"AccountId": 134
},
"chargeToken": {
"user_token": "1b7d7",
"embed_token": "flw-t0-fcebba188b33ecc6a3dca944a638e28f-m03k"
}
}
}
}
Once you get this response you need to the last step to complete the payment; Payment verification.
Implement Webhooks
It is advised all merchants use webhooks to get automatic updates on their transactions. To setup webhooks please visit the Webhooks ] section.
Step 5: Verify the payment.
After charging a card successfully, you need to verify that the payment was successful with Rave before giving value to your customer on your website.
Below are the important things to check for when validating the payment:
Verify the transaction reference.
Verify the data.status
of the transaction to be successful
.
Verify the currency to be the expected currency
Most importantly validate the amount paid to be equal to or at least greater than the amount of the value to be given.
Below is sample code of how to implement server side validation in different programming languages
curl --request POST \
--url https://api.ravepay.co/flwv3-pug/getpaidx/api/v2/verify \
--header 'content-type: application/json' \
--data '{"txref":"MC-1520443531487","SECKEY":"FLWSECK-e6db11d1f8a6208de8cb2f94e293450e-X"}'
<?php
$result = array();
$postdata = array(
'txref' => 'OH-AAED44',
'SECKEY' => 'FLWSECK-bb971402072265fb156e90a3578fe5e6-X'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://api.ravepay.co/flwv3-pug/getpaidx/api/v2/verify");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,json_encode($postdata)); //Post Fields
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$headers = [
'Content-Type: application/json',
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$request = curl_exec ($ch);
$err = curl_error($ch);
if($err){
// there was an error contacting rave
die('Curl returned error: ' . $err);
}
curl_close ($ch);
$result = json_decode($request, true);
if('error' == $result->status){
// there was an error from the API
die('API returned error: ' . $result->message);
}
if('successful' == $result->data->status && '00' == $result->data->chargecode){
// transaction was successful...
// please check other things like whether you already gave value for this ref
// If the amount and currency matches the expected amount and currency etc.
// if the email matches the customer who owns the product etc
// Give value
}
//Endpoint to verify transaction
private final String VERIFY_ENDPOINT = "https://api.ravepay.co/flwv3-pug/getpaidx/api/v2/verify";
/**
*
* Method to
*
* @param paymententity - <b>paymententity - set as a constant with default value as 1</b>
* @param txref - <b>txref - is the unique payment reference generated by the merchant.</b>
* @param secret - <b>secret - is the merchant secret key</b>
* @return
* @throws UnirestException
*/
public JSONObject verify(String flwRef, String secret, double amount, int paymententity) throws UnirestException, Exception {
// This packages the payload
JSONObject data = new JSONObject();
data.put("txref", txref);
data.put("SECKEY", secret)
// end of payload
// This sends the request to server with payload
HttpResponse<JsonNode> response = Unirest.post(VERIFY_ENDPOINT)
.header("Content-Type", "application/json")
.body(data)
.asJson();
// This get the response from payload
JsonNode jsonNode = response.getBody();
// This get the json object from payload
JSONObject responseObject = jsonNode.getObject();
// check of no object is returned
if(responseObject == null)
throw new Exception("No response from server");
// This get status from returned payload
String status = responseObject.optString("status", null);
// this ensures that status is not null
if(status == null)
throw new Exception("Transaction status unknown");
// This confirms the transaction exist on rave
if(!"success".equalsIgnoreCase(status)){
String message = responseObject.optString("message", null);
throw new Exception(message);
}
data = responseObject.getJSONObject("data");
// This get the amount stored on server
double actualAmount = data.getDouble("amount");
// This validates that the amount stored on client is same returned
if(actualAmount != amount)
throw new Exception("Amount does not match");
// now you can give value for payment.
}
var data = new {txref = "OH-AAED44", SECKEY = "FLWSECK-e6db11d1f8a6208de8cb2f94e293450e-X"};
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var responseMessage = client.PostAsJsonAsync("https://api.ravepay.co/flwv3-pug/getpaidx/api/v2/verify", data).Result;
var responseStr = responseMessage.Content.ReadAsStringAsync().Result;
var response = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseData>(responseStr);
if (response.data.status == "successful" && response.data.amount == amount && response.data.chargecode == "00")
{
System.Console.WriteLine("Payment Successful then give value");
}
When you successfully verify a completed payment see sample response below:
{
"status": "success",
"message": "Tx Fetched",
"data": {
"txid": 161196,
"txref": "MC-1520443531487",
"flwref": "FLW-MOCK-6404ffd177d60ff20b6ddf92d01dab84",
"devicefingerprint": "69e6b7f0b72037aa8428b70fbe03986c",
"cycle": "one-time",
"amount": 100,
"currency": "NGN",
"chargedamount": 100,
"appfee": 0,
"merchantfee": 0,
"merchantbearsfee": 1,
"chargecode": "02",
"chargemessage": "Please enter the OTP sent to your mobile number 080****** and email te**@rave**.com",
"authmodel": "PIN",
"ip": "::ffff:10.150.200.23",
"narration": "CARD Transaction ",
"status": "success-pending-validation",
"vbvcode": "00",
"vbvmessage": "Approved. Successful",
"authurl": "N/A",
"acctcode": null,
"acctmessage": null,
"paymenttype": "card",
"paymentid": "878",
"fraudstatus": "ok",
"chargetype": "normal",
"createdday": 1,
"createddayname": "MONDAY",
"createdweek": 23,
"createdmonth": 5,
"createdmonthname": "JUNE",
"createdquarter": 2,
"createdyear": 2018,
"createdyearisleap": false,
"createddayispublicholiday": 0,
"createdhour": 7,
"createdminute": 9,
"createdpmam": "am",
"created": "2018-06-04T07:09:42.000Z",
"customerid": 17573,
"custphone": "09026420185",
"custnetworkprovider": "AIRTEL",
"custname": "temi desola",
"custemail": "[email protected]",
"custemailprovider": "GMAIL",
"custcreated": "2018-02-27T09:55:51.000Z",
"accountid": 134,
"acctbusinessname": "Synergy Group",
"acctcontactperson": "Desola Ade",
"acctcountry": "NG",
"acctbearsfeeattransactiontime": 1,
"acctparent": 1,
"acctvpcmerchant": "N/A",
"acctalias": "temi",
"acctisliveapproved": 0,
"orderref": "URF_1528096182393_8660935",
"paymentplan": null,
"paymentpage": null,
"raveref": "RV3152809618136771B0698BF4",
"card": {
"expirymonth": "09",
"expiryyear": "19",
"cardBIN": "539983",
"last4digits": "8381",
"brand": "GUARANTY TRUST BANK DEBITSTANDARD",
"card_tokens": [
{
"embedtoken": "flw-t1nf-f22c700a552802803e89732bdf808b33-m03k",
"shortcode": "e0371",
"expiry": "9999999999999"
}
],
"type": "MASTERCARD",
"life_time_token": "flw-t1nf-f22c700a552802803e89732bdf808b33-m03k"
},
"meta": []
}
}
Save a card after charging so user's don't have to enter card details again
Awesome now you are done charging a card, you can always save the card for future charges using our Save a card APIs.