Skip to main content

Credit Card Anti-fraud

Malga's API is capable of running risk analysis supported by anti-fraud providers without the need of further integrations, withing it's own credit cart payment flow. This risk evaluation is achieved synchronously and, for such, it needs some aditional informations to be present in the charge payload.

Anti-fraud Lifecycle

Malga's anti-fraud providers can be configured to be executed before or after the transaction is processed through the runBeforeCharge option.

For runBeforeCharge=false, the lifecycle of a transaction with anti-fraud evaluation within Malga's orchestration is composed of three steps:

  1. Pre Authorization
  2. Anti-fraud Analysis
  3. Capture

To ensure that the sale isn’t going to be lost and is eligible for anti-fraud processing, the payment is first pre authorized, then it's evaluated by the anti-fraud provider. By default, if it is approved, the payment will be captured. Otherwise, the transaction is automatically canceled.

Anti-fraud Flow

info

The automatic behavior of the transaction lifecycle can be set through the captureOnApprove and refundOnReprove flags on the Malga's antifraud provider setup.

For runBeforeCharge=true, the lifecycle of a transaction with anti-fraud evaluation is composed of two steps:

  1. Anti-fraud analysis
  2. Capture

Anti-fraud Flow

With this configuration, all transactions will be evaluated by the anti-fraud before being processed in the payment providers.

::info To simulate the asynchronous anti-fraud flow, use the anti-fraud status change endpoint and observe the various possible status changes in the transaction. :::

caution

It isn't possible to use the runBeforeCharge=true option with async or hybrid anti-fraud products. If you are uncertain abour your anti-fraud product support, please contact us.

Information about devices and user behavior - Fingerprints

Anti-fraud providers can ask for more information about the device used to make the transaction. We recommend that you configure the provider’s SDK in your payment flow and send us the fingerprint in your request payload. This will assure the quality of fraud analysis and help increase your approval rate.

caution

Some anti-fraud providers will require the use of Fingerprints in their integrations.

ProviderIs Fingerprint required?
ClearsaleYES

Anti-fraud providers configuration options

OptionDescription
runBeforeChargeDetermines if the anti-fraud provider is executed before the payment provider.
captureOnApproveDetermines if the transation is automatically captured upon anti-fraud approval.
refundOnReproveDetermines if the transaction must be automatically refunded or canceled upon anti-fraud reproval.
captureOnErrorDetermines if a transaction must be captured in the case of an error being returned by the anti-fraud provider.
refundOnErrorDetermines if a transaction must be refunded in the case of an error being returned by the anti-fraud provider.

Anti-fraud examples

To use anti-fraud analysis in your transactions, you must have an anti-fraud provider’s credentials set in your payment flow. From then on all you'll have to do is make sure to send the anti-fraud additional information.

Charge with Anti-fraud analysis approved example

After being pre authorized the charge will go through risk evaluation. If it's approved, it will be captured.

curl --location --request POST 'https://api.malga.io/v1/charges' \
--header 'x-client-id: <YOUR_CLIENT_ID>' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"merchantId": "5002bdcd-e816-4741-871c-6de4f31ea966",
"amount": 100,
"currency": "BRL",
"statementDescriptor": "Pedido #231 loja joão",
"capture": true,
"paymentMethod": {
"paymentType": "credit",
"installments": 1
},
"paymentSource": {
"sourceType": "card",
"card": {
"cardHolderName": "JOSE DAS NEVES",
"cardNumber": "4929564637987814",
"cardCvv": "120",
"cardExpirationDate": "12/2026"
}
},
"fraudAnalysis": {
"customer": {
"name": "Joao Torres",
"phone": "11 99329899",
"email": "joao@gmail.com",
"identity": "45762964851",
"identityType": "CPF",
"registrationDate": "2022-07-26T16:11:35.756Z",
"billingAddress": {
"street": "Rua Um",
"number": "200",
"zipCode": "02010010",
"country": "BR",
"state": "SP",
"district": "Jardim Paraiso",
"city": "Sao Paulo",
"complement": "ap 10"
},
"browser": {
"browserFingerprint": "074c1ee676ed4998ab66491013c565e2",
"cookiesAccepted": false,
"email": "comprador@test.com.br",
"hostName": "google.com",
"ipAddress": "127.0.0.1",
"type": "Chrome"
}
},
"cart": {
"items": [
{
"name": "ItemTeste1",
"quantity": 1,
"sku": "20170511",
"unitPrice": 100,
"risk": "High"
}
]
}
}
}'

< HTTP/2 201
< content-type: application/json; charset=utf-8
{
"id": "713d1e9d-3e05-4258-9c38-d5b474cdca7f",
"clientId": "<YOUR_CLIENT_ID>",
"merchantId": "5002bdcd-e816-4741-871c-6de4f31ea966",
"description": null,
"orderId": null,
"createdAt": "2022-08-25T20:56:37.265Z",
"amount": 100,
"originalAmount": 100,
"currency": "BRL",
"statementDescriptor": "Pedido #231 loja joão",
"capture": true,
"status": "authorized",
"paymentMethod": {
"installments": 1,
"paymentType": "credit"
},
"paymentSource": {
"sourceType": "card",
"cardId": "2aba421f-db81-4c2d-a6e8-3379c192a7c5"
},
"fraudAnalysisMetadata": {
"customer": {
"name": "Joao Torres",
"identity": "45762964851",
"identityType": "CPF",
"birthdate": null,
"phone": "11 99329899",
"billingAddress": {
"street": "Rua Um",
"number": "200",
"complement": "ap 10",
"zipCode": "02010010",
"city": "Sao Paulo",
"state": "SP",
"district": "Jardim Paraiso"
}
},
"cart": {
"items": [
{
"name": "ItemTeste1",
"quantity": 1,
"sku": "20170511",
"unitPrice": 100,
"risk": "High"
}
]
}
},
"transactionRequests": [
{
"id": "72e788f6-c767-4688-8b23-4f3c9313458f",
"createdAt": "2022-08-25T20:56:37.796Z",
"updatedAt": "2022-08-25T20:56:37.796Z",
"idempotencyKey": null,
"providerId": "5de239ec-b724-453a-96e1-229fe29cdedd",
"providerType": "SANDBOX",
"transactionId": "1737284",
"amount": 100,
"authorizationCode": "6076640",
"authorizationNsu": "3028818",
"requestStatus": "success",
"requestType": "capture",
"responseTs": "8ms",
"providerAuthorization": {
"networkAuthorizationCode": "7354551",
"networkResponseCode": "5759371"
}
},
{
"id": "f4c59668-c513-4e81-a5b2-9988866f3af4",
"createdAt": "2022-08-25T20:56:37.645Z",
"updatedAt": "2022-08-25T20:56:37.645Z",
"idempotencyKey": null,
"providerId": "5de239ec-b724-453a-96e1-229fe29cdedd",
"providerType": "SANDBOX",
"transactionId": "9475312",
"amount": 100,
"authorizationCode": null,
"authorizationNsu": null,
"requestStatus": "success",
"requestType": "anti_fraud",
"responseTs": "19ms",
"fraudAnalysis": {
"score": 85,
"status": "approved"
}
},
{
"id": "67a55426-defc-4f75-92d0-97f93ef55e39",
"createdAt": "2022-08-25T20:56:37.432Z",
"updatedAt": "2022-08-25T20:56:37.866Z",
"idempotencyKey": "97cfcd40-d9f0-469a-bc7f-b5cda1e2d8ac",
"providerId": "5de239ec-b724-453a-96e1-229fe29cdedd",
"providerType": "SANDBOX",
"transactionId": "6498444",
"amount": 100,
"authorizationCode": "3698706",
"authorizationNsu": "4897050",
"requestStatus": "success",
"requestType": "pre_authorization",
"responseTs": "36ms",
"providerAuthorization": {
"networkAuthorizationCode": "7376566",
"networkResponseCode": "2946159"
}
}
]
}

Charge with Anti-fraud analysis declined example

After being pre authorized, if the risk analysis is reproved, the charge is then declined and the pre authorization is automatically canceled.

curl --location --request POST 'https://api.malga.io/v1/charges/v1/charges' \
--header 'x-client-id: <YOUR_CLIENT_ID>' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"merchantId": "2f837bc1-9dc5-4683-9610-6e75ed9e5aa5",
"amount": 991,
"currency": "BRL",
"statementDescriptor": "Pedido #231 loja joão",
"capture": true,
"paymentMethod": {
"paymentType": "credit",
"installments": 1
},
"paymentSource": {
"sourceType": "card",
"card": {
"cardHolderName": "JOSE DAS NEVES",
"cardNumber": "4929564637987814",
"cardCvv": "120",
"cardExpirationDate": "12/2026"
}
},
"fraudAnalysis": {
"customer": {
"name": "João Neves",
"identity": "62871519005",
"identityType": "CPF",
"birthdate": null,
"phone": "219988776654",
"billingAddress": {
"street": "Rua CJ-14",
"number": "100",
"zipCode": "69314702",
"country": "BR",
"state": "PR",
"district": "Jardim Tropical",
"city": "Boa vista",
"complement": "ap 110"
},
"browser":{
"browserFingerprint":"074c1ee676ed4998ab66491013c565e2",
"cookiesAccepted":false,
"email":"comprador@test.com.br",
"hostName":"google.com",
"ipAddress":"127.0.0.1",
"type":"Chrome"
}
},
"cart": {
"items": [
{
"name": "ItemTeste1",
"quantity": 1,
"sku": "20170511",
"unitPrice": 991,
"risk": "High"
}
]
}
}
}'

< HTTP/2 201
< content-type: application/json; charset=utf-8
{
"id": "72dd8608-3741-48fd-9aab-5573408820fa",
"clientId": "<YOUR_CLIENT_ID>",
"merchantId": "2f837bc1-9dc5-4683-9610-6e75ed9e5aa5",
"description": null,
"orderId": null,
"createdAt": "2022-08-10T19:21:19.452Z",
"amount": 0,
"originalAmount": 991,
"currency": "BRL",
"statementDescriptor": "Pedido #231 loja joão",
"capture": true,
"status": "canceled",
"paymentMethod": {
"installments": 1,
"paymentType": "credit"
},
"paymentSource": {
"sourceType": "card",
"cardId": "4a986611-0534-4628-8c2e-2845a3f6d185"
},
"fraudAnalysisMetadata": {
"customer": {
"id": "c3eb8208-760d-4f21-b54f-70601db69aee",
"updatedAt": "2022-08-10T14:31:37.045Z",
"createdAt": "2022-08-10T14:31:37.045Z",
"idempotencyKey": null,
"requestId": null,
"name": "João Neves",
"identity": "62871519005",
"identityType": "CPF",
"birthdate": null,
"phone": "219988776654",
"billingAddress": {
"street": "Rua CJ-14",
"number": "100",
"zipCode": "69314702",
"country": "BR",
"state": "PR",
"district": "Jardim Tropical",
"city": "Boa vista",
"complement": "ap 110"
}
},
"cart": {
"items": [
{
"name": "ItemTeste1",
"quantity": 1,
"sku": "20170511",
"unitPrice": 991,
"risk": "High"
}
]
}
},
"transactionRequests": [
{
"id": "e03d2e8f-a279-4227-8753-ad7e248e242e",
"createdAt": "2022-08-10T19:21:21.910Z",
"updatedAt": "2022-08-10T19:21:21.910Z",
"idempotencyKey": null,
"providerId": "91d0191d-75fa-4abc-bc8b-f2c5d0170ebc",
"providerType": "PAGARME",
"transactionId": "17979806",
"amount": 991,
"authorizationCode": "386630",
"authorizationNsu": "17979806",
"requestStatus": "success",
"requestType": "void",
"responseTs": "333ms",
"providerAuthorization": {
"networkAuthorizationCode": "386630",
"networkResponseCode": "authorized"
}
},
{
"id": "9e15983b-eb1f-4407-b00f-e28c2a98bd51",
"createdAt": "2022-08-10T19:21:21.393Z",
"updatedAt": "2022-08-10T19:21:21.393Z",
"idempotencyKey": null,
"providerId": "8355537a-1d61-4426-aa8e-8905c15a2489",
"providerType": "CLEARSALE",
"transactionId": "0AE2DE127C8242579EF7D192DC4EAB16",
"amount": 991,
"authorizationCode": null,
"authorizationNsu": null,
"requestStatus": "success",
"requestType": "anti_fraud",
"responseTs": "1340ms",
"fraudAnalysis": {
"score": 97,
"status": "reproved"
}
},
{
"id": "f3e23e9e-52ff-40e4-b858-cffa32f10622",
"createdAt": "2022-08-10T19:21:19.532Z",
"updatedAt": "2022-08-10T19:21:21.982Z",
"idempotencyKey": "c9b417bd-fd21-42fc-9123-88dcb035449a",
"providerId": "91d0191d-75fa-4abc-bc8b-f2c5d0170ebc",
"providerType": "PAGARME",
"transactionId": "17979806",
"amount": 991,
"authorizationCode": "386630",
"authorizationNsu": "17979806",
"requestStatus": "success",
"requestType": "pre_authorization",
"responseTs": "418ms",
"providerAuthorization": {
"networkAuthorizationCode": "386630",
"networkResponseCode": "authorized"
}
}
]
}
caution

When a transaction is declined in anti-fraud analysis, the pre-authorization is going to be canceled. If this operation fails, the transaction will maintain pre_authorized status and can be canceled or captured manually, according to your preferences.

Charge with Anti-fraud provider error example

If an error is returned by the anti-fraud provider, the default behavior of the payment flow is to maintain the transaction in the pre authorized state.

curl --location --request POST 'https://api.malga.io/v1/charges' \
--header 'x-client-id: <YOUR_CLIENT_ID>' \
--header 'x-api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '{
"merchantId": "2f837bc1-9dc5-4683-9610-6e75ed9e5aa6",
"amount": 991,
"currency": "BRL",
"statementDescriptor": "Pedido #231 loja joão",
"capture": true,
"paymentMethod": {
"paymentType": "credit",
"installments": 1
},
"paymentSource": {
"sourceType": "card",
"card": {
"cardHolderName": "JOSE DAS NEVES",
"cardNumber": "4929564637987814",
"cardCvv": "120",
"cardExpirationDate": "12/2026"
}
},
"fraudAnalysis": {
"customer": {
"name": "João Neves",
"identity": "62871519005",
"identityType": "CPF",
"birthdate": null,
"phone": "219988776654",
"billingAddress": {
"street": "Rua CJ-14",
"number": "100",
"zipCode": "69314702",
"country": "BR",
"state": "PR",
"district": "Jardim Tropical",
"city": "Boa vista",
"complement": "ap 110"
}
},
"cart": {
"items": [
{
"name": "ItemTeste1",
"quantity": 1,
"sku": "20170511",
"unitPrice": 991,
"risk": "High"
}
]
}
}
}'

< HTTP/2 201
< content-type: application/json; charset=utf-8
{
"id": "9b7f2329-5f0b-417d-8e43-022a1057fded",
"clientId": "<YOUR_CLIENT_ID>",
"merchantId": "2f837bc1-9dc5-4683-9610-6e75ed9e5aa6",
"description": null,
"orderId": null,
"createdAt": "2022-08-10T19:26:55.701Z",
"amount": 991,
"originalAmount": 991,
"currency": "BRL",
"statementDescriptor": "Pedido #231 loja joão",
"capture": true,
"status": "pre_authorized",
"paymentMethod": {
"installments": 1,
"paymentType": "credit"
},
"paymentSource": {
"sourceType": "card",
"cardId": "d96fbcae-065e-4cd0-ac1e-b27714618c95"
},
"fraudAnalysisMetadata": {
"customer": {
"id": "c3eb8208-760d-4f21-b54f-70601db69aee",
"updatedAt": "2022-08-10T14:31:37.045Z",
"createdAt": "2022-08-10T14:31:37.045Z",
"idempotencyKey": null,
"requestId": null,
"name": "João Neves",
"identity": "62871519005",
"identityType": "CPF",
"birthdate": null,
"phone": "219988776654",
"billingAddress": {
"street": "Rua CJ-14",
"number": "100",
"zipCode": "69314702",
"country": "BR",
"state": "PR",
"district": "Jardim Tropical",
"city": "Boa vista",
"complement": "ap 110"
}
},
"cart": {
"items": [
{
"name": "ItemTeste1",
"quantity": 1,
"sku": "20170511",
"unitPrice": 991,
"risk": "High"
}
]
}
},
"transactionRequests": [
{
"id": "52efd018-c005-4b20-b28f-2cf390c794ef",
"createdAt": "2022-08-10T19:26:56.388Z",
"updatedAt": "2022-08-10T19:26:56.388Z",
"idempotencyKey": "11f4bd50-4110-43bf-91e7-28ae8d0d243b",
"providerId": "8355537a-1d61-4426-aa8e-8905c15a2489",
"providerType": "CLEARSALE",
"transactionId": null,
"amount": 991,
"authorizationCode": null,
"authorizationNsu": null,
"requestStatus": "timeout",
"requestType": "anti_fraud",
"responseTs": "9ms",
"providerError": {
"retryable": false,
"declinedCode": null,
"networkDeniedMessage": null,
"networkDeniedReason": null
}
},
{
"id": "65199fff-b961-473a-a75f-2b5717d73089",
"createdAt": "2022-08-10T19:26:55.802Z",
"updatedAt": "2022-08-10T19:26:56.412Z",
"idempotencyKey": "11f4bd50-4110-43bf-91e7-28ae8d0d243b",
"providerId": "91d0191d-75fa-4abc-bc8b-f2c5d0170ebc",
"providerType": "PAGARME",
"transactionId": "17981570",
"amount": 991,
"authorizationCode": "430210",
"authorizationNsu": "17981570",
"requestStatus": "success",
"requestType": "pre_authorization",
"responseTs": "467ms",
"providerAuthorization": {
"networkAuthorizationCode": "430210",
"networkResponseCode": "authorized"
}
}
]
}
caution

There are two settings to determine what to do with your transactions if the anti-fraud provider used in your payment flow undergoes stability issues.

  • captureOnError: Malga will attempt to capture the pre-authorization.
  • refundOnError: Malga will attempt to void the pre-authorization. It cannot be turned on at the same time as captureOnError.

In case when captureOnError and refundOnError are both false, the transaction is then returned as pre_authorized.

Testing Antifraud with Sandbox

It is possible to use Malga's sandbox provider to control each test transaction result you might encounter while using antifraud providers. To control these results you'll use the fraudAnalysis's customer's identity node to set the sandbox behavior.

The identity number can be generated using any available identity generator and respects the following rules:

IdentityApproved?Status
Ending in 1YESapproved
Ending in anything but 1NOreproved

In order to configure your sandbox anti-fraud provider you must create a merchant using both the "SANDBOX" transaction provider and the "SANDBOX_ANTIFRAUD" antifraud provider and set it's automatic anti-fraud behavior flags in the options object.

Sandbox Anti-fraud merchant creation example:

curl --location --request POST 'https://api.dev.malga.io/v1/merchants' \
--header 'X-Client-Id: <YOUR_CLIENT_ID>' \
--header 'X-Api-Key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data-raw '
{
"mcc": "4789",
"providers": [
{
"name": "sandbox",
"priority": 1,
"credentials": {
"type": "SANDBOX", // Sandbox transactions provider
"apiKey": "<YOUR_API_KEY>"
}
},
{
"name": "sandbox_antifraud",
"priority": 1,
"credentials": {
"type": "SANDBOX_ANTIFRAUD", // Sandbox anti-fraud provider
"apiKey": "<YOUR_API_KEY>"
},
"options": {
"type": "ANTIFRAUD",
"captureOnError": false,
"refundOnError": false,
"captureOnApproved": true,
"refundOnReproved": true
}
}
]
}'

Using Malga Checkout with anti-fraud

It's possible to use Malga Checkout and send anti-fraud parameters to the providers, besides that our checkout also can be combined with some anti-fraud provider SDK for a more complete solution.

Using Malga Checkout with Clearsale

To add Clearsale anti-fraud in payments made through Malga Checkout it's necessary to add Behavior Analytics SDK, it's from Clearsale itself, in your front-end application and uses sessionId provided by it to set up Malga Checkout.

After that, with Behavior Analytics SDK already implemented, just send the sessionId in the browserFingerprint field, like the example below:

info

The sessionId can be any UUID generated randomly for each new user session and sent to the Clearsale or be generated by its own SDK. Visit Behavior Analytics SDK FAQ to know more about it.

<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0"
/>
<script
type="module"
src="https://unpkg.com/@malga-checkout/core@latest/dist/malga-checkout/malga-checkout.esm.js"
></script>
<title>Malga Checkout Components</title>
</head>
<body>
<main>
<malga-checkout
sandbox="false"
public-key="<YOUR_PUBLIC_KEY>"
client-id="<YOUR_CLIENT_ID>"
merchant-id="<YOUR_MERCHANT_ID>"
></malga-checkout>
</main>

<script>
const malgaCheckout = document.querySelector('malga-checkout')
const fingerprint = '<YOUR-SESSION-ID>'

(function (a, b, c, d, e, f, g) {
a['CsdpObject'] = e; a[e] = a[e] || function () {
(a[e].q = a[e].q || []).push(arguments)
}, a[e].l = 1 * new Date(); f = b.createElement(c),
g = b.getElementsByTagName(c)[0]; f.async = 1; f.src = d; g.parentNode.insertBefore(f, g)
})(window, document, 'script', '//device.clearsale.com.br/p/fp.js', 'csdp');
csdp('app', 'seu_app');
csdp('sessionId', fingerprint);

malgaCheckout.paymentMethods = {
pix: {
expiresIn: 600
},
credit: {
installments: {
quantity: 1,
show: true,
},
showCreditCard: true
},
boleto: {
expiresDate: "2022-12-31",
instructions: "Boleto payment instructions",
interest: {
days: 1,
amount: 100,
},
fine: {
days: 2,
amount: 200,
}
}
}

malgaCheckout.transactionConfig = {
statementDescriptor: '#1 Demonstration Malga Checkout',
amount: 100,
description: '',
orderId: '',
customerId: '',
currency: 'BRL',
capture: false,
customerId: '6a9d59e7-afb4-4e17-a02e-36d82ed1c11c',
// Setting up anti-fraud object
fraudAnalysis: {
browserFingerprint: fingerprint,
cart: [
{
name: "",
quantity: 0,
sku: "",
unitPrice: 0,
risk: "Low"
}
],
}
}

malgaCheckout.dialogConfig={
show: true,
actionButtonLabel: 'Continue',
errorActionButtonLabel: 'Try again',
successActionButtonLabel: 'Continue',
successRedirectUrl: 'https://www.malga.io/',
pixFilledProgressBarColor: "#2FAC9B",
pixEmptyProgressBarColor: "#D8DFF0",
}

malgaCheckout.addEventListener('paymentSuccess', (data) => {
// Your specifications here
})

malgaCheckout.addEventListener('paymentFailed', (error) => {
// Your specifications here
})
</script>
</body>
</html>