MenuPayU

Revenue attribution

PayU

Connect PayU India with your merchant key and salt so ProductLense records captured payments and refunds in INR, with PayU's fee and GST where reported.

ProductLense reads your PayU India transactions and their refunds. ProductLense only reads: it never initiates payments, refunds or cancellations.

What you need

FieldSecretWhere to find it
Merchant keyNoPayU Dashboard → Developers → Key and Salt.
Merchant saltYesThe salt shown with the key. PayU signs payment webhooks with it, so there is no separate webhook secret.
ModeNoproduction, or test for test keys.

Every plan includes one billing connection per site, Free too; Growth and Scale allow any number. See plans and limits.

Permissions

PayU keys are not scoped; ProductLense only reads with yours. Every call is a signed POST /merchant/postservice.php?form=2 command with the hash sha512(key|command|var1|salt). ProductLense uses two read commands: get_Transaction_Details (transactions between two dates) and getAllRefundsFromTxnIds (the refunds of one transaction).

Set up

  1. In the PayU Dashboard, open Developers → Key and Salt and copy both.
  2. In ProductLense, open your site's Settings → Billing connections → PayU, paste them, set the mode and click Connect and import history.
  3. Copy the webhook URL from the connection card.
  4. In PayU, open Developers → Webhooks and create a webhook for Successful and Failed payments, and another for Refund, both with that URL.

Webhook

URL: https://api.productlense.app/api/webhooks/payu/<connection-id> (ProductLense shows the exact URL after you save).

Events ProductLense uses: Successful, Failed and Refund.

Verification:

  • Payment webhooks are form posts carrying PayU's reverse hash, sha512(salt|status|udf10|…|udf1|email|firstname|productinfo|amount|txnid|key) (with additional_charges| in front when present). ProductLense recomputes it with your salt and checks the merchant key.
  • Refund webhooks are not signed by PayU. ProductLense records nothing from the notification itself: it fetches the refund from PayU with your key and salt and stores what PayU's API returns. A refund PayU does not know is refused.

PayU's payment webhooks carry no timestamp, so replays are recognised by the signed fields and body.

What ProductLense reads

  • Customers: PayU has no customer object, so ProductLense keys a payer by email, else phone number.
  • Subscriptions: not read. Recurring (SI) charges arrive as ordinary payments, so they count as revenue but do not appear in MRR.
  • Payments: captured transactions count as revenue. Failed, dropped, bounced and cancelled attempts are kept with status failed and add nothing to revenue. Authorised but uncaptured transactions are pending.
  • Refunds: every refund of each captured transaction, with its status.
  • History: the last 12 months on first connect, read in seven-day windows, then a nightly reconcile at 03:00 UTC from the last sync minus 48 hours. Refunds of older payments arrive through the refund webhook, so keep it on.

PayU India settles in INR. Amounts stay in INR and are also converted to USD at the European Central Bank rate for the payment's day.

How fees are derived

When PayU reports a fee on a transaction (mer_service_fee plus mer_service_tax), ProductLense uses it exactly. When PayU reports none, ProductLense subtracts an estimate of 2.36% (PayU's standard 2% plus 18% GST), shown as estimated on the connection card, where you can change it to your own rate. Payments recorded from a webhook get their exact fee at the next nightly reconcile.

Match payments to visitors

PayU has no free-form metadata, only the user-defined fields udf1 to udf10. ProductLense reads your user id from udf5 and a ProductLense visitor id from udf4. Use the same user id you pass to identify. Without them, ProductLense falls back to the payer's email, matched to the email trait sent with identify.

PayU payment request fields
// The fields you post to PayU. udf4 and udf5 are part of the request hash,
// so include them when you compute it.
const fields = {
  key, txnid, amount, productinfo, firstname, email, phone,
  udf4: visitorId, // ProductLense visitor id
  udf5: user.id,   // your user id
  surl, furl,
};

Limits

  • PayU's transaction list may not include every udf; when it does not, the payment matches by email until a webhook for it arrives.
  • Disputes and chargebacks are not read.
  • Up to 5,000 refund lookups run per backfill; refunds beyond that arrive by webhook.

See how payments are attributed.

    ↑ ↓ to move, Enter to open