# Fraud Mitigation

Control AVS and CVV checks per transaction, overriding the portal-level defaults.

Source: https://developer.inoviopay.com/api/fraud-mitigation.html  
Markdown: https://developer.inoviopay.com/api/fraud-mitigation.md

Inovio provides built-in validation for Address Verification Service (AVS) and Card Security Code (CVV). By default, the gateway performs these checks but ignores the results unless specific flags are enabled. This can be maintained in the Inovio Portal settings.

If you want to manually control AVS and CVV settings or override the portal settings for specific transactions you can send the following parameters.

### Address Verification Service (AVS)

AVS verifies the billing address provided by the customer against the address on file at the issuing bank. It is generally supported in the US and several international markets.

| Parameter | Setting | Description |
|---|---|---|
| `CHKAVS` (optional) | `T` | **Enabled:** Transaction is approved only if the response matches the [AVSMatchSet](https://developer.inoviopay.com/reference/avs-codes.md). |
| `CHKAVS` (optional) | `F` | **Disabled:** Do not perform AVS check. |
| `CHKAVS` (optional) | `C` | **Conditional:** Check AVS, but ignore results if the CVV check is a match. |
| `AVSMATCHSET` (optional) | `[Codes]` | A custom string of AVS codes to accept (e.g., `ADRSTUVWZ`). If the bank returns a code not in this set, the transaction is declined. |

### Card Security Code (CVV)

The Card Security Code (CVV2/CVC2) is the 3 or 4-digit number on the card. This must be submitted in the `PMT_KEY` parameter.

| Parameter | Setting | Description |
|---|---|---|
| `CHKCVV` (optional) | `T` | **Enabled:** Transaction is approved only if the response matches the [CVVMATCHSET](https://developer.inoviopay.com/reference/cvv-codes.md). |
| `CHKCVV` (optional) | `F` | **Disabled:** Do not send CVV to the bank. |
| `CHKCVV` (optional) | `C` | **Conditional:** Check CVV, but ignore results if the AVS check is a match. |
| `CVVMATCHSET` (optional) | `[Codes]` | A custom string of CVV codes to accept (e.g., `MPSX`). Default positive response is `M` (Match). |

AVS and CVV enforcement is layered onto whatever request action you're already sending (`CCAUTHORIZE`, `CCAUTHCAP`), it does not require a separate SDK call, only additional parameters on the existing sale/authorize request.

All four SDKs model these as a `RiskOptions` block (`avs` / `cvv`, values `on` / `off` / `ignore` / `conditional`) on the transaction request, and expose the response as `avs.classification` / `cvv.classification` (`positive` / `partial` / `negative` / `neutral`, derived by the SDK from `AVS_RESPONSE` / `CVV_RESPONSE`), not just the raw letter code.

> **The SDKs currently send the wrong CHKAVS / CHKCVV values**
> The gateway compares `CHKAVS` and `CHKCVV` against the letter codes in the table above (`T`, `F`, `C`, default `I`); this is verified against the gateway's order processing. All four SDKs instead encode `RiskOptions.avs` / `.cvv` as `1` (on), `0` (off), `2` (ignore) and `3` (conditional), which the gateway does not recognise, so setting `RiskOptions` through an SDK today has no effect and the account's default AVS/CVV policy applies. Until the SDKs are corrected, enforce AVS and CVV by calling the API directly with the letter codes, as in the cURL tab.

**cURL**

```bash
curl -X POST "https://api.inoviopay.com/payment/pmt_service.cfm" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "request_action=CCAUTHCAP&req_username=api_user&req_password=P%40ssw0rd%21&site_id=12345&request_api_version=4.14&request_response_format=JSON&pmt_numb=4111111111111111&pmt_expiry=122026&pmt_key=123&request_currency=USD&li_value_1=49.99&xtl_order_id=INV-999&CHKAVS=T&CHKCVV=T"
```

**PHP**

```php
use Inovio\Gateway\{Credentials, InovioClient};
use Inovio\Gateway\Model\{LineItem, Money, PaymentMethods, RiskOptions};
use Inovio\Gateway\Request\TransactionRequest;

$client = new InovioClient(new Credentials('api_user', 'P@ssw0rd!', '12345'), 'SANDBOX');

$req = (new TransactionRequest(
    PaymentMethods::card('4111111111111111', '122026', '123'),
    [new LineItem('111205', 1, Money::of('49.99', 'USD'))]
))->withIdempotency('INV-999');

$req->risk = new RiskOptions();
$req->risk->avs = 'on';
$req->risk->cvv = 'on';

$result = $client->sale($req);

if ($result->avs !== null) {
    echo $result->avs->classification;   // positive | partial | negative | neutral
}
if ($result->cvv !== null) {
    echo $result->cvv->classification;
}
```

**Node**

```ts
import { InovioClient, Money, PaymentMethods } from '@inovio/gateway-sdk';

const client = new InovioClient(
  { reqUsername: 'api_user', reqPassword: 'P@ssw0rd!', siteId: '12345' },
  { environment: 'SANDBOX' }
);

const result = await client.sale({
  paymentMethod: PaymentMethods.card('4111111111111111', '122026', '123'),
  lineItems: [{ productId: '111205', count: 1, value: Money.of('49.99', 'USD') }],
  idempotency: { xtlOrderId: 'INV-999' },
  risk: { avs: 'on', cvv: 'on' },
});

console.log(result.avs?.classification);   // positive | partial | negative | neutral
console.log(result.cvv?.classification);
```

**Python**

```python
from inovio_gateway import Credentials, InovioClient, Money, PaymentMethods
from inovio_gateway.model import Idempotency, LineItem, RiskOptions
from inovio_gateway.request import TransactionRequest

client = InovioClient(Credentials("api_user", "P@ssw0rd!", site_id="12345"), environment="SANDBOX")

result = client.sale(TransactionRequest(
    payment_method=PaymentMethods.card("4111111111111111", "122026", "123"),
    line_items=[LineItem("111205", 1, Money.of("49.99", "USD"))],
    idempotency=Idempotency(xtl_order_id="INV-999"),
    risk=RiskOptions(avs="on", cvv="on"),
))

if result.avs:
    print(result.avs.classification)   # positive | partial | negative | neutral
if result.cvv:
    print(result.cvv.classification)
```

**Java**

```java
InovioClient client = new InovioClient(
    new InovioClient.Credentials("api_user", "P@ssw0rd!", "12345"));

TransactionRequest req = new TransactionRequest(
    PaymentMethods.card("4111111111111111", "122026", "123"),
    new LineItem("111205", 1, Money.of("49.99", "USD")))
    .idempotency("INV-999");

RequestParts.RiskOptions risk = new RequestParts.RiskOptions();
risk.avs = "on";
risk.cvv = "on";
req.risk = risk;

TransactionResult result = client.sale(req);

if (result.avs() != null) {
    System.out.println(result.avs().classification());   // positive | partial | negative | neutral
}
if (result.cvv() != null) {
    System.out.println(result.cvv().classification());
}
```

**Response**

```json
{
  "REQUEST_ACTION": "CCAUTHCAP",
  "REQ_ID": "84729110",
  "TRANS_STATUS_NAME": "APPROVED",
  "TRANS_VALUE": 3.15,
  "CURR_CODE_ALPHA": "USD",
  "TRANS_VALUE_SETTLED": 3.15,
  "CURR_CODE_ALPHA_SETTLED": "USD",
  "TRANS_EXCH_RATE": "",
  "TRANS_ID": 3948572124,
  "CUST_ID": 9827168,
  "XTL_CUST_ID": "xT883mP",
  "PO_ID": 99281743,
  "XTL_ORDER_ID": "",
  "BATCH_ID": 883930,
  "PROC_NAME": "Test Processor",
  "MERCH_ACCT_ID": 110203,
  "CARD_BRAND_NAME": "Visa",
  "CARD_TYPE": "VISA CLASSIC",
  "CARD_PREPAID": 1,
  "CARD_BANK": "BOFI FEDERAL BANK",
  "CARD_BALANCE": "",
  "PMT_L4": "2921",
  "PMT_ID": 8839214,
  "PMT_ID_XTL": "",
  "PROC_UDF01": "",
  "PROC_UDF02": "",
  "PROC_AUTH_RESPONSE": "TEST458",
  "PROC_RETRIEVAL_NUM": "930C79ED-E6D2-428B-A63EF36A9D769685",
  "PROC_REFERENCE_NUM": "TEST938316620",
  "PROC_REDIRECT_URL": "",
  "AVS_RESPONSE": "M",
  "CVV_RESPONSE": "M",
  "REQUEST_API_VERSION": "4.14",
  "P3DS_RESPONSE": "",
  "P3DS_VENDOR": "",
  "PO_LI_ID_1": "9928188",
  "PO_LI_COUNT_1": 1,
  "PO_LI_AMOUNT_1": "3.15",
  "PO_LI_PROD_ID_1": "111205",
  "MBSHP_ID_1": ""
}
```
