Card payments

This describes how to accept payments directly from customers cards

Flutterwave allows you to charge both local cards (issued in your country of operations) and International cards using our APIs. When charging cards with Flutterwave, you have to take card authentication methods into account. This is primarily how the user who is meant to pay you 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.

We automatically detect the authentication model to be used by the card and send a response requiring you to pass the needed parameter for that authentication model.

The guide below would show you how to charge cards on Flutterwave using our APIs.

Pre-requisites for accepting card payments on Flutterwave.

  1. Sign-up for an account here .

  2. Set up a webhook to get notified on payments, to see more on webhooks visit our Webhook section.

  3. For all card payments, you would need to implement three steps to complete the transaction, Initiate payment, Validate payment, Verify completed payment. Excluding transactions that don't require extra authentication, in which case you'll only need two steps - Initiate payment and verify the transaction.

  4. If you would prefer to accept payments using our APIs, see our API reference to learn more about [accepting card payments via APIs](ref: charge-a-card).

Step 1 - Collect payment details from customer

You can use a custom form to collect the card details from the customer including any extra information needed, see a sample of the card details to collect from the customer.

{
   "card_number":"4556052704172643",
   "cvv":"899",
   "expiry_month":"01",
   "expiry_year":"21",
   "currency":"NGN",
   "amount":"1000",
   "email":"[email protected]",
   "fullname":"yemi desola",
   "tx_ref":"MC-3243e",
   "redirect_url":"https://webhook.site/3ed41e38-2c79-4c79-b455-97398730866c"
}

Parameter Definition

ParameterRequiredDescription
tx_refTrueThis is a transaction reference you supply to identify different transactions on your account. It is important to ensure that you pass unique references for every transaction.
amountTrueThis is the amount to be charged. It is passed as - ('amount':'100').
currencyTrueThis is the specified currency to charge in.
card_numberTrueThis is the number on the cardholders card. E.g. 5399 6701 2349 0229
cvvTrueCard security code. This is 3/4 digit code at the back of the customers card, used for web payments.
expiry_monthTrueTwo-digit number representing the card's expiration month.
expiry_yearTrueTwo- digit number representing the card's expiration year
emailTrueThis is the email address of the customer.
phone_numberFalseThis is the phone number linked to the customer's mobile money account.
client_ipFalseInternet Protocol. This represents the current IP address of the customer carrying out the transaction.
device_fingerprintFalseThis is the fingerprint for the device being used. It can be generated using a library on whatever platform is being used.
metaFalseThis is an object you can use to include any additional payment information you would like to associate with this charge
fullnameFalseShould include the first and last name of the customer
authorizationFalseThis is an object that should contain the authorization mode, pin, and biller address
preauthorizeFalseThis should be set to true for preauthoize card transactions
modeFalseThe Auth model to use when validating - e.g pin, avs_noauth or avs
redirect_urlFalseThis is a url you provide, we redirect to it after the customer completes payment and append the response details (tx_ref and status) to it as query parameters. (3DSecure only)

Step 2 - Encrypt payment details

To see how to encrypt using any of our encryption functions copy the sample request above and visit the [Flutterwave Encryption](doc: encryption) section. If you handle your encryption well, you should receive an encrypted payload like the one below:

{
    "client": "Rd8k8kDWguht2vKTq3fy4InO8JjaYVXSIBEioVRIJta6EmdhI5Z/9VRpTw88inynsfcsa76fZd4pjvt2kwx8JaWWjHPmXx02Apsl7SgzRLcK48su4zcCpmJFcX1YQHnIJa36T4KC0/JVd0GUD/m9d6N/D/RKSJTDbBnfj6hI9c9UaU1AmnFj3vmhq0/eyH56rjqOB2ryS9lr37Tb0ZttMPjfTQl7ziZwUksb0tC2XHeQaDM+SNCAZAAwE1CfLh2RXCTzGXg6F+basDvg4yT8XtvkaQKN33no1X+jCBL2Pc7ub8RmL9Hvc+8th7XF8Ye0eTElolaGlhuFAIcn0yL3B5JZ2eAoNevp0dDmqMdQi9qY6QJRUK3pVOW11u5qsLnB3flQtshB7V4v9fgzN4qCE7+emacE6pbwg+7aHQICykf69p2DtZTmZvK9CpVrtYSA5PABX/TV8Vw="
}

You can then use this payload to initiate payment

Step 3 - Initiate payment

Send your encrypted payload to our charge endpoint: https://api.flutterwave.com/v3/charges?type=card

Method: POST

Sample Request:

Copy the cURL request below and make a request in your terminal to see how it works!

curl --request POST \
  --url https://api.flutterwave.com/v3/charges?type=card \
  --header 'content-type: application/json' \
  --data '{
        "client": "W+C+Mi//JFO5/JIbjMu1a/V8bI4vI2wYwNN3VyLb+GiPGpNhjEGakpXboR6O2utcezwqtjpIHlDmPh93Kb0LkbTWuYvDw3fTMnlLu+uUE5UU1YQElo/nHE/BIwM4pNStcPrEYN0ecfBdn7kaJo+QKFz1lm7/HGfeJzK0O37eoCy4PJb+ZIhhoIOgoHWUVvz7IlqgE4OImagpJn4NtNeaOKHIxWBQJLUI3mBOuw5VMVk3GXAb8SZh39oW/VfeEUOVyCMxBC3ZsTVLcd5m599qh78RrcVMky1ZYxNUJCLgTQp0i0uyF5hqAQJ2dFGYBtdWKu0eaZqCkn4VjkiH1jWkrxWAKdD7HmIwhhprJ20V5qGWjX66MFYpzxdMKMQl/f1ncCfgq/jA7J2VjfyUr0zHM9LcCZ7wUiPjVCG0ejpCyvMYBZxz2x+exEd2O8tU7UR0UkJclieLjjXGsaF+Q2PVv+NzARz9MHIBzPQy5zPZKhxfJkbjX/wTVzZzaGFLxcUiXIqeXkA8znR0wpNZvXKUSwpVCA+hCAOd+9Nkofd/6fOnl2ZFkvCkTW+gF5wgSKUs9/MWcJG4Xr9lu74pEFYtqLWFSy4lPJNBDzuBvaIrfOp8bHvEch96XT3lHhBc49g1ntoFZ2Unp8tbUg99BLRj3I9LCPqN4aP4M73jXAgSLWeqgXnHYWeCsbcN5Go3ZzjQ8ng3ElKBHxcHx08t5trn1f5DkoVNoEKv/pJRniOLvONtMSrG/9jcm9LpDUKbo+NVPswax+e+r95YHsvJw8yb4dt1ZTonO+nUzs/xIYCLoYntlyl2dT58lw=="}'
  • client: This is the encrypted request parameters.

Payment Responses

When you initiate the payment you would get a response based on the type of card that was sent to Flutterwave, we'll explain the response you would get for each card type and what you need to do next for each of the card types.

1. Using a Nigerian Issued Mastercard / Verve card

When your customer is paying with a Nigerian MasterCard/Verve card, we suggest that you charge the card using the customer's PIN, the suggested authorization mode is returned after initiating payment, you would get a response that looks like this:

{
   "status":"success",
   "message":"Charge authorization data required",
   "meta":{
      "authorization":{
         "mode":"pin",
         "fields":[
            "pin"
         ]
      }
   }
}

This response tells you that the authentication model for the card is PIN. What you need to do next is add an authorization object containing the cards authorization mode i.e pin and the card's pin to your initial payload, re-encrypt it and send the payload again to our charge endpoint.

"authorization": {
   "mode": "pin",
   "pin": "3310"
} 
// Adding the above object to your initial payload will give rise to this final request object

{
   "card_number":"4556052704172643",
   "cvv":"899",
   "expiry_month":"01",
   "expiry_year":"21",
   "currency":"NGN",
   "amount":"1000",
   "email":"[email protected]",
   "fullname":"yemi desola",
   "tx_ref":"MC-3243e",
   "redirect_url":"https://webhook.site/3ed41e38-2c79-4c79-b455-97398730866c",
   "authorization": {
     "mode": "pin",
     "pin": "3310"
	 } 
}

// Re-encrypt the above payload and charge

Send the encrypted payload to our /charges?type=card endpoint, you will get a charge response like the one below:

{
    "status": "success",
    "message": "Charge initiated",
    "data": {
        "id": 288192886,
        "tx_ref": "LiveCardTest",
        "flw_ref": "YemiDesola/FLW275389391",
        "device_fingerprint": "N/A",
        "amount": 100,
        "charged_amount": 100,
        "app_fee": 1.4,
        "merchant_fee": 0,
        "processor_response": "Kindly enter the OTP sent to *******0328",
        "auth_model": "PIN",
        "currency": "NGN",
        "ip": "::ffff:10.7.214.204",
        "narration": "CARD Transaction ",
        "status": "pending",
        "auth_url": "N/A",
        "payment_type": "card",
        "fraud_status": "ok",
        "charge_type": "normal",
        "created_at": "2020-07-15T14:06:55.000Z",
        "account_id": 17321,
        "customer": {
            "id": 216517630,
            "phone_number": null,
            "name": "Yemi Desola",
            "email": "[email protected]",
            "created_at": "2020-07-15T14:06:55.000Z"
        },
        "card": {
            "first_6digits": "123456",
            "last_4digits": "2343",
            "issuer": "MASTERCARD GUARANTY TRUST BANK Mastercard Naira Debit Card",
            "country": "NG",
            "type": "MASTERCARD",
            "expiry": "08/22"
        }
    },
    "meta": {
        "authorization": {
            "mode": "otp",
            "endpoint": "/v3/validate-charge"
        }
    }
}

Validate transactions

At this point, two things are to be expected, depending on the type of card you're charging.

  1. A redirect link will be returned with a processor_response message saying Pending Validation. In this case, you only need to redirect your customers to the returned link where they can complete the payment. You can check the 3DS Auth model section further down on this page for more guides on how to complete this process.

  2. An OTP will be sent to your customer for validation. This is the case for the response we have above.

In the charge response above, processor_response contains the instructions on how to complete this transaction using the OTP sent to the card owner. To validate the transaction, call our /validate-charge/ endpoint with the customer's OTP and pass the flw_ref in the request body. More on how to validate transactions Validate a charge

Sample validate charge response

{
    "status": "success",
    "message": "Charge validated",
    "data": {
        "id": 288200108,
        "tx_ref": "LiveCardTest",
        "flw_ref": "YemiDesola/FLW275407301",
        "device_fingerprint": "N/A",
        "amount": 100,
        "charged_amount": 100,
        "app_fee": 1.4,
        "merchant_fee": 0,
        "processor_response": "Approved by Financial Institution",
        "auth_model": "PIN",
        "currency": "NGN",
        "ip": "::ffff:10.5.179.3",
        "narration": "CARD Transaction ",
        "status": "successful",
        "auth_url": "N/A",
        "payment_type": "card",
        "fraud_status": "ok",
        "charge_type": "normal",
        "created_at": "2020-07-15T14:31:16.000Z",
        "account_id": 17321,
        "customer": {
            "id": 216519823,
            "phone_number": null,
            "name": "Yemi Desola",
            "email": "[email protected]",
            "created_at": "2020-07-15T14:31:15.000Z"
        },
        "card": {
            "first_6digits": "232343",
            "last_4digits": "4567",
            "issuer": "VERVE FIRST CITY MONUMENT BANK PLC",
            "country": "NG",
            "type": "VERVE",
            "expiry": "03/23"
        }
    }
}

Verify payment

After charging a customer successfully, you need to verify that the payment was successful with Flutterwave before giving value to your customer on your website. To do so, call our verify transactions endpoint /transactions/:id/verify with your transaction ID transaction_id to ensure that the transaction went through successfully with Flutterwave. More on how to verify transactions Transaction verification

Although the Flutterwave inline already verifies the payment from the client-side, we strongly recommend you still do a server-side verification to be double sure no foul play occurred during the payment flow.

Below are the important things to check for in the response object 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.

Here's a sample transaction verification response

{
    "status": "success",
    "message": "Transaction fetched successfully",
    "data": {
        "id": 288200108,
        "tx_ref": "LiveCardTest",
        "flw_ref": "YemiDesola/FLW275407301",
        "device_fingerprint": "N/A",
        "amount": 100,
        "currency": "NGN",
        "charged_amount": 100,
        "app_fee": 1.4,
        "merchant_fee": 0,
        "processor_response": "Approved by Financial Institution",
        "auth_model": "PIN",
        "ip": "::ffff:10.5.179.3",
        "narration": "CARD Transaction ",
        "status": "successful",
        "payment_type": "card",
        "created_at": "2020-07-15T14:31:16.000Z",
        "account_id": 17321,
        "card": {
            "first_6digits": "232343",
            "last_4digits": "4567",
            "issuer": "FIRST CITY MONUMENT BANK PLC",
            "country": "NIGERIA NG",
            "type": "VERVE",
            "token": "flw-t1nf-4676a40c7ddf5f12scr432aa12d471973-k3n",
            "expiry": "02/23"
        },
        "meta": null,
        "amount_settled": 98.6,
        "customer": {
            "id": 216519823,
            "name": "Yemi Desola",
            "phone_number": "N/A",
            "email": "[email protected]",
            "created_at": "2020-07-15T14:31:15.000Z"
        }
    }
}

That's it, you've completed the charge process for customers paying with Mastercard/Verve debit cards with PIN auth models.

2. Using AVS (Address verification system) to charge an international card.

When customers are paying with an international card that uses the AV system, we detect this automatically after the initial charge request 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":"Charge authorization data required",
   "meta":{
      "authorization":{
         "mode":"avs_noauth",
         "fields":[
            "city",
            "address",
            "state",
            "country",
            "zipcode"
         ]
      }
   }
}

This response tells you that the authentication model for the card is AVS. What you need to do next is add an authorization object containing the cards authorization mode i.e avs_noauth` and the card address details to your initial payload, re-encrypt it and send the payload again to our charge endpoint.

You will get a response like so:

{
   "status":"success",
   "message":"Charge initiated",
   "data":{
      "id":1222390,
      "tx_ref":"MC-3243e-visa3ds",
      "flw_ref":"FLW-MOCK-0f6a173e664d3c6c98e3026ab4baa3e0",
      "device_fingerprint":"69e6b7f0b72037aa8428b70fbe03986c",
      "amount":20000,
      "charged_amount":20000,
      "app_fee":760,
      "merchant_fee":0,
      "processor_response":"Please enter the OTP sent to your mobile number 080****** and email te**@rave**.com",
      "auth_model":"VBVSECURECODE",
      "currency":"NGN",
      "ip":"169.123.8.9",
      "narration":"CARD Transaction ",
      "status":"pending",
      "payment_type":"card",
      "fraud_status":"ok",
      "charge_type":"normal",
      "created_at":"2020-04-13T16:08:11.000Z",
      "account_id":1643,
      "customer":{
         "id":355959,
         "phone_number":"0902620185",
         "name":"Anonymous customer",
         "email":"[email protected]",
         "created_at":"2020-04-07T11:59:45.000Z"
      },
      "card":{
         "first_6digits":"455605",
         "last_4digits":"2643",
         "issuer":"VISA  CREDIT",
         "country":"GB",
         "type":"VISA",
         "expiry":"01/21"
      }
   },
   "meta":{
      "authorization":{
         "mode":"redirect",
         "redirect":"https://ravesandboxapi.flutterwave.com/mockvbvpage?ref=FLW-MOCK-0f6a173e664d3c6c98e3026ab4baa3e0&code=00&message=Approved. Successful&receiptno=RN1586794091383"
      }
   }
}

From the response above you will note a few things,

  1. The status of the transaction says it is pending validation which means the transaction hasn't been approved yet by the customer.
  2. You will notice that we returned a redirect link in the response. To complete this payment, you can direct your customers to the link returned in the response where they can complete the transaction. Afterward, we will redirect the customer back to your provided redirect_url if available.

Finally, you can head over to Transaction verification to ensure that the payment went through.

3. Charge a card using the 3DS Auth model

Flutterwave also allows you to charge customers paying with 3DS cards. Unlike the previous auth models we've discussed, the 3DS flow doesn't require the provision of the authorization object.

After you initiate the payment, we automatically detect that the paying card is a 3DS card and immediately return a redirect link in the charge response.

See a sample 3DS charge response below:

{
   "status":"success",
   "message":"Charge initiated",
   "data":{
      "id":1254647,
      "tx_ref":"MC-3243enewtest",
      "flw_ref":"FLW-MOCK-587df5c89bd607a52f3e0ba71e671cd3",
      "device_fingerprint":"N/A",
      "amount":100000,
      "charged_amount":100000,
      "app_fee":3800,
      "merchant_fee":0,
      "processor_response":"Please enter the OTP sent to your mobile number 080****** and email te**@rave**.com",
      "auth_model":"VBVSECURECODE",
      "currency":"NGN",
      "ip":"::ffff:10.16.250.243",
      "narration":"CARD Transaction ",
      "status":"pending",
      "payment_type":"card",
      "fraud_status":"ok",
      "charge_type":"normal",
      "created_at":"2020-04-30T20:09:56.000Z",
      "account_id":27468,
      "customer":{
         "id":370672,
         "phone_number":null,
         "name":"Anonymous customer",
         "email":"[email protected]",
         "created_at":"2020-04-30T20:09:56.000Z"
      },
      "card":{
         "first_6digits":"543889",
         "last_4digits":"0229",
         "issuer":"MASTERCARD MASHREQ BANK CREDITSTANDARD",
         "country":"EG",
         "type":"MASTERCARD",
         "expiry":"10/20"
      }
   },
   "meta":{
      "authorization":{
         "mode":"redirect",
         "redirect":"https://ravesandboxapi.flutterwave.com/mockvbvpage?ref=FLW-MOCK-587df5c89bd607a52f3e0ba71e671cd3&code=00&message=Approved. Successful&receiptno=RN1588277396664"
      }
   }
}

From the response above, you're required to redirect your customer to the returned redirect link in the meta.authorization object. They will provide their OTP in the provided field and complete the transaction.

Once the transaction is completed, we will redirect the customer to your provided redirect_url if available.

Verify payment

After charging a customer successfully, you need to verify that the payment was successful with Flutterwave before giving value to your customer on your website.

Check our Transaction verification section for implementation instructions