Bin Discount is a feature on XPay that allows merchants to configure discounts based on card BINs (the first 6 or 8 digits of a card). Merchants can apply discounts for specific BINs using either a fixed value or a percentage of the order price.

The Bin Discount module supports multiple configurable options, including:

How It Works

You need to pass apply_bin_discount: true in the payment intent create API payload, the system could process the bin discount based on the configurations in the store.

If a merchant has configured bin discounts on the XPay portal, then when a user enters their card in the SDK:

Using these details, you need to apply the discount to the order.


BIN Discount & Pre-calculation Requirement

If you want to use the BIN discount feature and enable pre-calculation, you must pass the piClientSecret while initializing the XPay SDK. BIN discount and pre-calculation features are supported only in XPay SDK v4.1 versions.

Vanilla JavaScript

const xpayy = new window.Xpay({
  publishableKey: xpay?.publishableKey,
  accountId: xpay?.accountId,
  email: xpay?.email || null,
  customerName: xpay?.customerName || null,
  piClientSecret: xpay?.piClientSecret || null,
});

React

<xpay
  xpay={{
    publishableKey: storePK,
    accountId: user_id,
    customerName: customer?.name || null,
    email: customer?.email || null,
    piClientSecret: pi_client_secret,
  }}
>
  <PaymentElement
    onBinDiscount={(data) => console.log("discount event data", data)}
  />
</xpay>;

How to Listen for the Event

Vanilla JavaScript (binDiscount Event)

In Vanilla JavaScript, you can listen for the binDiscount event using the xpay.on() method:

xpay.on('binDiscount', function (event) {
    console.log(event, 'bin discount event');
    // Apply the discount based on event data
});

React.js (onBinDiscount Event)

In React.js, you can listen for the event using the onBinDiscount prop inside the <PaymentElement /> component:

<PaymentElement
    onBinDiscount={(data)=> console.log("discount event data", data)}
/>

Event Response Example

If you pass payment intent secret before SDK load and bin discount is applicable, you will get pre-calculated discount details in the event in the following format:

{
	"bin": 512345,
	"bank_name": "Bank ALafalah (MPGS)",
	"account_id": "0ddb82950784f875",
	"store_id": "65ccc486e9c7cd07445f6d28",
	"bank_acronym": "BAFL",
	"bank_logo": "<https://xstak-pay-admin.s3.us-east-2.amazonaws.com/assets/bank-logos/HBL.png>",
	"discount_type": "percentage",
	"discount_value": 10,
	"discount_limit": 1,
	"active_days": "monday,tuesday",
	"max_daily_usage": 1,
	"max_monthly_usage": 3,
	"on_discounted_items": false,
	"rule_enabled": true,
	"id": "d0b80c34-7bc1-4f02-8f25-9fbbef6f4208",
	"_id": "6a0318717eacae338fe7379b",
	"createdAt": "2026-05-12T12:09:21.729Z",
	"updatedAt": "2026-05-12T12:09:21.729Z",
	"__v": 0,
	"discount_applicable": true,
	"discount_details": {
    "discount_amount": 10,
    "amount_after_discounted": 990,
    "original_amount": 1000,
  },
	"hash": "42a56aa1413773ab1652a04e1e170adeec5b9e359900ba8ebeaa904a84aa8069"
}

When a bin discount is applied and payment intent secret is not passed before SDK load, the event will return a response in the following format:

{
  "account_id": "0ddb82950784f875",
  "bank_acronym": "HBL",
  "bank_logo": "<https://js.xstak.com/assets/logos/HBL.png>",
  "bank_name": "Habib Bank Limited",
  "bin": 512345,
  "createdAt": "2025-01-06T09:53:45.148Z",
  "discount_type": "percentage",
  "discount_value": 70,
  "hash": "df49774ea1bcf4ff15ab18af6a989fc84e2e821b19700fb8bc9aa9577d57abe4",
  "id": "d1dffc51-7b7c-4af0-b306-a8cf76c344d4",
  "on_discounted_items": false,
  "rule_enabled": true,
  "store_id": "64f06b2fcabbf492b6d3a1e1",
  "updatedAt": "2025-01-06T09:53:45.148Z",
  "__v": 0,
  "_id": "677ba829b48208d8392c7633"
}

Webhook Response Example

When the order payment is captured, you will receive a webhook response containing the transaction details, including the unique hash for tracking discounts.

{
  "type": "PAYMENT_INTENT_NOTIFICATION",
  "payment_intent_id": "xpay_pi_1f4ebd77fe08624ee1216d4138d6f29227556a85473f2e7c128a622c2be56d2b",
  "refund_id": null,
  "amount": 9999,
  "currency": "PKR",
  "status": "succeeded",
  "customer": {
    "name": "Guest User",
    "email": "[email protected]",
    "phone": "03415682456"
  },
  "shipping": {
    "address1": "Gulberg",
    "city": "Lahore",
    "country": "Pakistan",
    "province": "Punjab",
    "zip": "65191",
    "shipping_method": "Standard"
  },
  "payment_method_types": "card",
  "product": {},
  "transaction_details": {
    "_id": "6a045b5d088c8840474298c7",
    "order": {
      "customer": {
        "name": "Guest User",
        "email": "[email protected]",
        "phone": "03415682456"
      },
      "name": "b2b-pl-02",
      "type": "headless"
    },
    "status": "CAPTURED",
    "secure": "3DS2",
    "refunded_amount": 0,
    "gateway": "bank-alfalah",
    "response_from_bank": "The payment was completed successfully",
    "status_message_from_bank": "PAYMENT_CAPTURED",
    "activity": [
      {
        "status": "AUTHENTICATION_SUCCESSFUL",
        "amount": 9999,
        "timestamp": "2026-05-13T11:07:11.348Z",
        "createdAt": "2026-05-13T11:07:13.300Z",
        "token": "",
        "card": {
          "bin": "512345",
          "last4digits": "2346",
          "name": "Guest User",
          "funding_method": "DEBIT",
          "type": "MASTERCARD",
          "issuer_details": {
            "card_issuer": "Habib Bank Limited",
            "card_network": "VISA",
            "card_type": "DEBIT"
          }
        },
        "3ds": { "authorization_code": "", "secure": "3DS2", "eci": "02" },
        "processing": { "acquirer_transaction_id": "trans-MHdo1pHUgK" }
      },
      {
        "status": "CAPTURED",
        "amount": 9999,
        "timestamp": "2026-05-13T11:07:12.478Z",
        "createdAt": "2026-05-13T11:07:13.300Z",
        "token": "",
        "card": {
          "hash": "42a56aa1413773ab1652a04e1e170adeec5b9e359900ba8ebeaa904a84aa8069",
          "bin": "512345",
          "last4digits": "2346",
          "name": "Guest User",
          "funding_method": "DEBIT",
          "type": "MASTERCARD",
          "issuer_details": {
            "card_issuer": "Habib Bank Limited",
            "card_network": "VISA",
            "card_type": "DEBIT"
          }
        },
        "3ds": {
          "authorization_code": "134697",
          "secure": "3DS2",
          "eci": "02"
        },
        "processing": { "acquirer_transaction_id": "trans-XSVwnVKIG5" }
      }
    ]
  },
  "metadata": { "order_reference": "b2b-pl-02" },
  "store_id": "65ccc486e9c7cd07445f6d28",
  "mode": "test",
  "account_id": "0ddb82950784f875",
  "discount_details": {
    "bin": 51234567,
    "binId": "6a0318717eacae338fe7379b",
    "type": "percentage",
    "limit": 1,
    "value": 10,
    "acronym": "BAFL",
    "max_daily_usage": 1,
    "max_monthly_usage": 3,
    "minimum_order_value": null,
    "active_days": null
  }
}

How to Track Discounts Against a Card

If you have configured bin discounts, the event will return a unique hash corresponding to the user's card:

When the order payment is captured, you will receive the same hash in the webhook data for the transaction captured status event.

Example Use Case: Restricting Discounts Per Day

If you want to allow only one discount per day for a card, follow these steps:

  1. The event (onBinDiscount in React, binDiscount in Vanilla JS) will return a unique hash for the card.
  2. When the order is captured, the same unique hash will be received in the webhook captured activity details.
  3. Save this hash in your system.
  4. On the next order, before applying the discount, check if the hash already exists. If it does, you can decide whether to allow the discount again.

This ensures that discounts are applied according to your business logic while preventing multiple discounts for the same card within a specified period.

APIs

Create Bin Discount Configuration

POST /bin/config/create/:store_id

Creates a new BIN discount configuration for a specific store

Request Payload

{
"bin": 437585,
"discount_type": "percentage",
"discount_value": 300,
"minimum_order_value": 1000,
"active_days": "monday,thursday,friday",
"max_daily_usage": 1,
"max_monthly_usage": 3,
"rule_enabled": true
}
Field Type Required Description
bin Number Yes Card BIN number. Must be exactly 6 or 8 digits
discount_type String Yes Type of discount. Allowed values: percentage, value
discount_value Number Yes Discount amount/value to apply
minimum_order_value Number No Minimum transaction amount required to apply discount
active_days String No Comma-separated weekdays when discount is active
max_daily_usage Number No Maximum number of discount usages allowed per day
max_monthly_usage Number No Maximum number of discount usages allowed per month
rule_enabled Boolean No Enables or disables the discount rule
discount_limit Number No Maximum discount amount allowed
rule_status String No Allowed values: TRUE, FALSE
id String No Optional custom identifier

Response

{
"success": true,
"responseStatus": "OK",
"message": "Request processed successfully.",
"data": {
"_id": "69ddec858da4120a0355d13c",
"bin": 51234567,
"bank_name": "Bank Alfalah Limited",
"account_id": "xxxb8295xxxxf875",
"store_id": "670cc16c5x5x5xe748916396",
"bank_acronym": "BAFL",
"bank_logo": "",
"discount_type": "percentage",
"discount_value": 10,
"discount_limit": 5,
"on_discounted_items": false,
"rule_enabled": true,
"id": "",
"createdAt": "2026-04-14T07:28:05.954Z",
"updatedAt": "2026-05-13T08:10:48.424Z",
"__v": 0,
"active_days": null,
"max_daily_usage": 1,
"max_monthly_usage": 3,
"minimum_order_value": null
}
}

Update Bin Discount Configuration

PUT /bin/config/create/:store_id

Updates a new BIN discount configuration for a specific store

Request Payload

{
"_id": "6a0318717eacae338fe7379b"
"bin": 437585,
"discount_type": "percentage",
"discount_value": 300,
"minimum_order_value": 1000,
"active_days": "monday,thursday,friday",
"max_daily_usage": 1,
"max_monthly_usage": 3,
"rule_enabled": true
}

Response

{
"success": true,
"responseStatus": "OK",
"message": "Request processed successfully.",
"data": {
"_id": "69ddec858da4120a0355d13c",
"bin": 51234567,
"bank_name": "Bank Alfalah Limited",
"account_id": "xxxb8295xxxxf875",
"store_id": "670cc16c5x5x5xe748916396",
"bank_acronym": "BAFL",
"bank_logo": "",
"discount_type": "percentage",
"discount_value": 10,
"discount_limit": 5,
"on_discounted_items": false,
"rule_enabled": true,
"id": "",
"createdAt": "2026-04-14T07:28:05.954Z",
"updatedAt": "2026-05-13T08:10:48.424Z",
"__v": 0,
"active_days": null,
"max_daily_usage": 1,
"max_monthly_usage": 3,
"minimum_order_value": null
}
}

Get Bin Discount Configuration Details

POST /bin/config

Request Payload

{
	"bin": 123456    // 123456 or 12345678
}

Response

{
"success": true,
"responseStatus": "OK",
"message": "Request processed successfully.",
"data": {
"_id": "69ddec858da4120a0355d13c",
"bin": 51234567,
"bank_name": "Bank Alfalah Limited",
"account_id": "xxxb8295xxxxf875",
"store_id": "670cc16c5x5x5xe748916396",
"bank_acronym": "BAFL",
"bank_logo": "",
"discount_type": "percentage",
"discount_value": 10,
"discount_limit": 5,
"on_discounted_items": false,
"rule_enabled": true,
"id": "",
"createdAt": "2026-04-14T07:28:05.954Z",
"updatedAt": "2026-05-13T08:10:48.424Z",
"__v": 0,
"active_days": null,
"max_daily_usage": 1,
"max_monthly_usage": 3,
"minimum_order_value": null
}
}

Delete Bin Discount Configuration

DELETE /bin/config/:store_id/:id

The bin discount configuration against _id will be deleted from the store.