Skip to main content

Deep payment

When a customer buys something inside the Cheggout marketplace, your app can execute the payment rather than Cheggout. The SDK hands you the payment details, you collect the money with your own rails, and you relaunch the SDK with the result.

Available Android · Available iOS

Why you'd want this

For a bank or wallet, payments are the thing you do best. Keeping them in your own flow means the customer pays with the account and authentication they already trust, you keep the transaction on your rails, and the purchase appears in your statement rather than as an opaque third-party charge.

The flow

Receiving the request

Register a payment manager and implement the listener:

private lateinit var chegPaymentManager: CHEGPaymentManager

class CGMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

chegPaymentManager = CHEGPaymentManager()
chegPaymentManager.setCallback(object : CHEGPaymentListener {
override fun initPaymentCallFromCheggout(responseString: String?) {
val decoded = String(Base64.decode(responseString, Base64.DEFAULT))
val json = JSONObject(decoded)
val deepLink = json.optString("deepLink", "")

// Collect the payment with your own rails, then relaunch:
val payload =
"{'Component':'CHEGGOUT','IsEmployee':'1','Language':'EN','DeeplinkInfo':'$deepLink'}"
launchCheggout(this@CGMainActivity, virtualId, sessionId, payload)
finish()
}
})
}
}

The same decode, written out as a helper:

fun decodeBase64(value: String?): String {
val decodedBytes = Base64.decode(value, Base64.DEFAULT)
return String(decodedBytes, Charsets.UTF_8)
}

The payload

The response string is Base64. Decoded, it looks like this:

{
"deepLink": "https://click.cheggout.com?type=pwa&id=<destination>?token=tokenvalue/cheggoutRefNo=YOURCHANNEL1775814852490048/paymentType=YOURCHANNEL/amount=540.00/transactionId=bankTransactionID/status=bankStatus",
"cheggoutRefNo": "YOURCHANNEL1775814852490048",
"amount": "54000",
"responseCode": "COLLECTPAYMENT",
"virtualId": "pub_8f14e45fceea167a",
"merchantName": "Cheggout",
"merchantId": "REPLACE_MERCHANT_ID"
}
FieldMeaning
deepLinkUsed to relaunch the SDK. Substitute bankTransactionID with your transaction ID and bankStatus with the payment status.
cheggoutRefNoCheggout's unique reference for this transaction
amountThe payment amount, in paisa
responseCodeCOLLECTPAYMENT
virtualIdThe user
merchantNameIdentifies the transaction source within Cheggout
merchantIdUnique per merchant name, issued by the bank at onboarding
amount is in paisa

"54000" means ₹540.00. Charging the raw value as rupees overcharges by a hundred times. Convert explicitly and unit-test the conversion.

Relaunching

After the payment completes, relaunch the SDK with the deep link — with two substitutions made:

Placeholder in the deep linkReplace with
bankTransactionIDYour transaction identifier for this payment
bankStatusThe payment status

Pass the resulting deep link in the launch payload's DeeplinkInfo field. The SDK opens on the confirmation flow and settles the order with Cheggout.

Relaunch on both success and failure. A failed payment still needs to be reported so the order does not hang in a pending state.

The Client Status API

Cheggout may need to check a payment's status independently — for instance if your app was killed before it could relaunch. For that you expose an endpoint Cheggout calls:

GET https://<your-domain>/cheggout-txn-status?virtualId={{virtualId}}&orderId={{cheggoutRefNo}}&amount={{amount}}

With header Authorization: {{key}}.

It must work with either your transaction ID plus virtualId, or cheggoutRefNo plus virtualId — because in some scenarios Cheggout will not have received your transaction ID.

Parameters are encrypted and URL-encoded

Cheggout encrypts virtualId, cheggoutRefNo and amount before appending them, using AES with a shared secret converted to a 16-byte key. Your endpoint must decrypt before use.

TBD The secret-key exchange process is not documented. Agree it with Cheggout before implementing. See Client Status API.

Implementation checklist

  • Payment callback registered before the SDK can invoke it
  • Base64 decoding tested against a real payload
  • Amount converted from paisa and unit-tested
  • cheggoutRefNo stored against your transaction, for reconciliation
  • Deep link substitution correct for both bankTransactionID and bankStatus
  • Relaunch happens on success and on failure
  • Client Status API implemented, with decryption
  • Reconciliation matches your payments to cheggoutRefNo

Troubleshooting

SymptomLikely cause
Customer charged 100×amount treated as rupees rather than paisa
Order stuck pendingSDK not relaunched after payment, or placeholders not substituted
Relaunch opens the wrong screenDeep link not passed in DeeplinkInfo
Cheggout cannot verify a paymentClient Status API missing, or decryption failing

Next