Proteside Docs

Payment integrity and Pix

How the SDK validates Pix, boleto, crypto and card payments on your checkout, and how to register trusted recipients.

Besides watching scripts, the SDK checks that the payment details shown to the customer are your store's: the Pix copy-and-paste code, the boleto digit line, the crypto address and the amount. This page explains how it finds this data, what it validates and how to pin your trusted recipients.

How the SDK finds the payment

No special markup is needed. Once it starts, the SDK looks for payment codes on the page:

  1. in known selectors, such as [data-pix-code], #pix-code, .pix-copia-cola, [data-pix-qr], [data-crypto-address], #crypto-address, .wallet-address, [data-payment-value] and [data-qr-value];
  2. in all visible text in the <body> between 20 and 1,000 characters long;
  3. in page changes (for example, when the Pix code is inserted after the customer chooses Pix);
  4. every 2 seconds during the first minute, as a fallback.

Codes are recognized by format: Pix BRCode (EMV standard), boleto digit line (47 or 48 digits), Bitcoin and Ethereum addresses, UPI VPAs and EMV QR codes from other countries (PayNow, PromptPay, DuitNow, QR Ph, HK FPS, Transferencias 3.0, CoDi and QR wallets).

The code must be in the page's text

The SDK reads text, not form field values. A Pix copy-and-paste code shown only in <input readonly value="000201…"> is not detected, and the same goes for a <textarea> filled in by JavaScript. Show the code as text, for example <div id="pix-code">000201…</div>, or provide the recipient with Proteside.registerPaymentPayload().

Recommended: Pix code as text
<div class="pix">
  <img src="/qrcode/order-1234.png" alt="Pix QR code" />
  <div id="pix-code">00020126580014br.gov.bcb.pix0136…6304ABCD</div>
  <button type="button">Copy code</button>
</div>

Payment validation

The first valid reading of each method on the page becomes the reference for that page load. From then on:

  • if the displayed text changes to a different code that doesn't match the reference, the SDK emits the method's tampering event (PIX_TAMPERED, BOLETO_TAMPERED, CRYPTO_ADDRESS_SWAP, UPI_TAMPERED or QR_TAMPERED);
  • if the content copied to the clipboard is a code that differs from the reference, the SDK emits CLIPBOARD_HIJACK;
  • when the reading is valid, the SDK emits PAYMENT_VALIDATED, which feeds the dashboard's Payment Integrity page.

PAYMENT_VALIDATED is sent on the first detection, when the code changes to the same recipient (for example, a regenerated QR) and, at most, every 60 seconds while the customer is on the page. The event never carries the code or the key: only the method, whether the recipient was verified and the number of fields.

Card

The SDK doesn't read card data. It considers a card payment validated when:

  • it finds a known payment provider's iframe on the page (Stripe, Adyen, Braintree, Mercado Pago, Pagar.me, PagBank, Iugu, Cielo and others) and observes a successful response to a charge request; or
  • it found the iframe and, within 10 minutes, the customer reaches a confirmation page with obrigado, sucesso, thank-you, success, confirmacao or order-complete in the path.

For the second case to work, the snippet must also be on the confirmation page.

Trusted recipients (Pix Key Pinning)

Without a recipient list, a payment code tampered with from the moment it's first shown would become the reference, and nothing would look wrong. The trusted recipient list solves this: the SDK checks each code's recipient against the keys that belong to your store.

Open Payment protection

In the dashboard, go to Settings → Payment protection, Trusted recipients section. Only owners and admins can add recipients.

Enter the recipient

Choose the Method (Pix, Bitcoin, Ethereum, UPI or Boleto (bank)), fill in the Key and, optionally, a Label.

  • Pix: CPF, CNPJ, email, phone number (+55…) or random key.
  • Boleto: the issuing bank's code (3 digits) or the full digit line.

Click Add

The recipient is saved immediately and reaches the SDK through the remote configuration. The dashboard stores only the SHA-256 hash and a masked version of the key.

The SDK only receives the hashes. To compare, it normalizes the recipient it reads on the checkout (email in lowercase, phone number digits only, boleto by its first 3 digits) and computes the same hash.

SituationResult
The code's recipient is on the listThe code becomes the reference and PAYMENT_VALIDATED is sent with the recipient verified. The dashboard shows Recipient matches the trusted list.
The recipient is not on the listThe SDK emits the method's tampering event with the reason "untrusted recipient" and doesn't accept the code as the reference. In Block mode, the code's text is replaced with ⚠︎.
No recipient registered for the methodNo recipient verification. Only the comparison with the first reading applies.

Limits of neutralization in Block mode

The SDK only neutralizes the text it read. The QR code image, <input value> fields and other copies of the code on the page stay as they are, and a re-render of the checkout may restore the text. Treat the alert as an incident even with Block mode on.

Limitations

  • Dynamic Pix. A dynamic BRCode carries a charge URL instead of the recipient's key. With no key in the code, there's no recipient verification; the comparison with the first reading still applies.
  • Collection boletos (48-digit line, from utilities and taxes) have no bank code and get no recipient verification.
  • Pix in a form field isn't read (see the warning at the top of this page).
  • QR wallets and instant payments from other countries are recognized and validated, but don't accept a registered recipient.

Expected amount and session recipient

If your checkout knows the order's amount and key, pass them to the SDK with Proteside.expectPayment():

// Before showing the order's Pix code
Proteside.expectPayment({ method: 'pix', amount: '19,90', key: 'pix@mystore.com' })
  • amount enables AMOUNT_TAMPERED: if the code's amount differs from the expected one, the SDK alerts. It accepts 19.9, '19,90' or 'R$ 19,90', compared to two decimal places.
  • key adds a trusted recipient for this page only. Only the hash is kept in memory.

Call expectPayment before the code appears on the page and only after the SDK has finished starting up. See how to wait for the SDK.

Payment methods

In Payment protection → Payment methods you check the methods your store offers. In the browser, this list only defines what shows up in getStatus().paymentMethodsMonitored and when the SDK stops looking for codes.

Unchecking a method doesn't turn detection off

The screen says unchecking methods reduces noise and that, with no method checked, verification will be disabled. In the code, the SDK recognizes and validates every method, checked or not, and an empty list is treated as Pix and card.

Payment pages

Payment pages (URL patterns, with mode and methods per page) are registered through the API, not the dashboard. They're used to count payment page pageviews in your plan usage and for compliance reports.

The mode and methods set per page don't reach the SDK. The SDK behaves the same on every page where the snippet is installed, using the store's mode and methods.

In the dashboard

The Payment Integrity page shows one card per method with the status NOT CONFIGURED, WAITING (no payment observed yet), INTACT or TAMPERED, plus the recipient status. See Payment integrity.

Next steps

On this page