Skip to main content

Android callbacks and notifications

The Android SDK talks back to your app through callback interfaces. Some you pass as an anonymous object into a method call; others you implement on the Activity or Fragment that hosts the SDK, so the SDK can find them while it is on screen.

This page lists every interface, what it delivers, and when it fires — then covers push notifications, which sit outside the callback system entirely.

The interfaces at a glance

InterfaceImplemented onFires whenPayload
CHEGTopBannerCallBackAnonymous object at the call siteThe banner request completesBanner JSON
CHEGTopOfferCallBackAnonymous object at the call siteThe store request completesStore JSON
CHEGCashBackCallBackAnonymous object at the call siteThe points request completesPoints JSON
CHEGScratchCardCallBackAnonymous object at the call siteThe scratch card request completesCard JSON with a deep link
CHEGHeartBeatListenerThe calling Activity or FragmentThe user is active inside the SDKNothing
CHEGPaymentListenerSet on CHEGPaymentManagerThe SDK needs your app to collect a paymentBase64 payment data
CHEGscratchRevealCallBackThe calling ActivityA reward is revealed inside the SDKReveal data
Every data callback delivers a raw JSON string

onResponse receives a String, not a typed model. The SDK does no error mapping for you — a failed request may arrive as null, as an empty string, or as a body whose status is false. Guard all three before parsing.


Data callbacks

These four are structurally identical: one method, one nullable string, delivered when the network call this callback was passed to completes.

CHEGTopBannerCallBack

Delivered by getTopBannerDetails. Carries the banner creatives for a placement, keyed by placement id.

object : CHEGTopBannerCallBack {
override fun onResponse(responseString: String) {
if (responseString.isBlank()) return renderNoBanners()
val response = Gson().fromJson(responseString, BannerResponse::class.java)
renderCarousel(response.banners["01"].orEmpty())
}
}

Once you render a creative, fire its impression with CheggoutUtils.Companion.trackLink(href, virtualId). The callback firing is not an impression — display is.

CHEGTopOfferCallBack

Delivered by getTopStoreDetails. Carries an array of stores with storeId, title, href, logo, discountPercentage and category.

object : CHEGTopOfferCallBack {
override fun onResponse(responseString: String?) {
val stores = parseStores(responseString ?: return)
renderStoreRail(stores) // show name AND discount
}
}

CHEGCashBackCallBack

Delivered by getChegCashBackPoints. Carries { "cashbackPoints": "100", "deepLink": "deeplinkString" }. cashbackPoints is a string.

object : CHEGCashBackCallBack {
override fun onResponse(responseString: String?) {
val points = parsePoints(responseString) ?: return hideCoinBadge()
coinBadge.text = points.cashbackPoints
coinBadge.setOnClickListener { openDeepLink(points.deepLink) }
}
}

CHEGScratchCardCallBack

Delivered by getScratchCardDetails. Carries the card's status, banner, deepLink and the optional interstitial fields.

object : CHEGScratchCardCallBack {
override fun onResponse(responseString: String?) {
val card = parseCard(responseString) ?: return
if (!card.status) return // "not eligible" — a normal outcome
showCardBanner(card.banner) { launchWithDeepLink(card.deepLink) }
}
}

status: false means no card was issued. Treat it as a non-event and show nothing — not as an error worth surfacing to the user.


CHEGHeartBeatListener

Implemented on the Activity or Fragment that launches the SDK. The SDK calls onCheggoutHeartBeat() while the user is interacting inside Cheggout, so your app's inactivity timer does not expire a session that is in fact active.

class ShopActivity : AppCompatActivity(), CHEGHeartBeatListener {

override fun onCheggoutHeartBeat() {
sessionManager.recordActivity()
}
}

It only reaches you if you launch with the overload that takes the implementing instance:

// Activity: pass `this`. Fragment: pass `getActivity()`.
CheggoutApplication.Companion.launchCheggout(
this, virtualId, sessionId, payload, instanceOfActivity
)

This directly determines where the user lands when they come back: with an active session they return to your home page, without one they return to your login page. See Launching.

TBD The heartbeat interval is not documented. Do not assume a fixed cadence — treat each call as "activity happened recently" and reset your timer, rather than deriving elapsed time from the gap between calls.


CHEGPaymentListener

Used by the deep payment flow, where the user buys something inside Cheggout and your app collects the money. Set the callback on a CHEGPaymentManager instance:

val chegPaymentManager = CHEGPaymentManager()

chegPaymentManager.setCallback(object : CHEGPaymentListener {
override fun initPaymentCallFromCheggout(responseString: String?) {
val json = String(Base64.decode(responseString, Base64.DEFAULT))
val payment = parsePayment(json)
startPayment(payment)
}
})

responseString is Base64. Decoded, it looks like this:

{
"deepLink": "https://click.cheggout.com?type=pwa&id=<giftcard url>?token=tokenvalue/cheggoutRefNo=YOURCHANNEL123456/paymentType=YOURCHANNEL/amount=540.00/transactionId=bankTransactionID/status=bankStatus",
"cheggoutRefNo": "YOURCHANNEL123456",
"amount": "54000",
"responseCode": "COLLECTPAYMENT",
"virtualId": "pub_8f14e45fceea167a",
"merchantName": "Cheggout",
"merchantId": "REPLACE_WITH_MERCHANT_ID"
}
FieldMeaning
deepLinkUsed to relaunch the SDK after payment. Replace bankTransactionID with your payment's transaction ID and bankStatus with the payment status.
cheggoutRefNoUnique reference number generated by Cheggout for this transaction. Store it — it is your reconciliation key.
amountPayment amount in paisa. "54000" is ₹540.00.
responseCodeCOLLECTPAYMENT.
virtualIdThe user this payment belongs to.
merchantNameIdentifies the transaction source within Cheggout, for example Cheggout.
merchantIdA unique identifier per merchant name, issued by the bank during onboarding.
amount is in paisa

Every other amount in the Cheggout contract — GetReward, getScratchCardDetails — is in rupees to two decimals. This one is in paisa. Charging 54000 rupees instead of 540.00 is a real failure mode; convert explicitly and assert on the result.

After the payment completes, rebuild the payload with the updated deep link and relaunch:

val payload =
"{'Component':'CHEGGOUT','IsEmployee':'1','Language':'EN','DeeplinkInfo':'$deepLink'}"

CheggoutApplication.launchCheggout(this, virtualId, sessionId, payload)

Full flow in Deep payment.


CHEGscratchRevealCallBack

Implemented on the calling Activity. Fires when a reward is revealed inside the SDK, so your app can react — refresh a points balance, log an analytics event, or show your own confirmation.

class ShopActivity : AppCompatActivity(), CHEGscratchRevealCallBack {

override fun onReveal(onRevealData: String?) {
Log.d("Cheggout", "onReveal: $onRevealData")
rewardsRepository.refresh()
}
}

TBD The schema of onRevealData is not documented. Log it in UAT to see what your build delivers, and do not parse fields you have not observed. The iOS equivalent broadcasts a HandleDominosScDetails notification; see iOS callbacks.


Push notifications

Push sits outside the callback system: Cheggout needs to reach the user when your app is not running. There are two integration options, and you pick one during onboarding. They differ in who owns the delivery infrastructure.

Option 1 — Push via your Bank API

You already have a push service. Cheggout calls it.

  • You provide an API that sends a push notification to a user.
  • Cheggout calls it with the VirtualID — the same one your app passed when launching the SDK — and the message.
  • Cheggout includes deep-link information in that call. Your push service must carry the deep link through to the notification payload.
  • Your app, on notification tap, launches the SDK with that deep link in the payload's DeeplinkInfo.

This keeps device tokens and delivery entirely inside your infrastructure. It costs you an endpoint and the discipline of not dropping the deep-link field on the way through.

launchCheggout needs an Activity context, so a FirebaseMessagingService cannot make the call itself. Carry the deep link through to an Activity and launch from there.

// 1. In your FirebaseMessagingService — extract the deep link and hand it to an Activity.
class PushService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val deepLink = remoteMessage.data["deepLink"] ?: return
val intent = Intent(this, ShopActivity::class.java)
.putExtra("cheggoutDeepLink", deepLink)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// Attach this intent to your notification's PendingIntent, so the tap opens ShopActivity.
showNotification(remoteMessage, intent)
}
}
// 2. In the Activity the notification opens — launch the SDK with the deep link.
class ShopActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val deepLink = intent.getStringExtra("cheggoutDeepLink") ?: ""
val payload =
"{'Component':'CHEGGOUT','IsEmployee':'0','Language':'EN','DeeplinkInfo':'$deepLink'}"

// virtualId and sessionId come from your backend, as on any other launch.
CheggoutApplication.launchCheggout(
this, virtualId, sessionId, payload, this, "YOURCHANNEL"
)
}
}

Option 2 — Push managed by Cheggout

Cheggout sends directly to the device.

  • Your app communicates the FCM ID while launching the Cheggout SDK. TBD The pushnotificationID payload key is documented for iOS; the documented Android payload string is Component / IsEmployee / Language / DeeplinkInfo / customerId. Confirm with Cheggout how the FCM ID should be passed on Android.
  • You provide FCM API credentials to Cheggout so it can configure and send notifications.

This is less work in your codebase, but it means handing Firebase credentials to a third party and giving up visibility over what is sent. Most banks choose Option 1 for that reason.

Option 1 — your APIOption 2 — Cheggout sends
Who holds device tokensYouCheggout, via your FCM project
What you buildA send endpoint Cheggout can callPassing pushnotificationID at launch
What you hand overNothing sensitiveFCM API credentials
Deep-link handlingYou forward itCheggout embeds it
Visibility over sendsFullLimited
Details to settle at onboarding

TBD Neither option is fully specified in the integration document. The request contract for your Bank API endpoint, its authentication, the FCM credential handover process, and the notification payload shape all need to be agreed with Cheggout before you build. Raise them in your onboarding call and record the answers.

Never put a device token in documentation or a ticket

FCM device tokens are user identifiers. Keep them out of logs you export, out of support tickets, and out of anything shared outside your team.

Next

  • SDK methods — the calls these callbacks are passed into.
  • Launching — the payload, the exit handshake and the heartbeat overload.
  • Deep payment — the full payment round trip.