Android — SPayLater Widget Installation
This guide walks you through adding the SPayLater Promotional Widget to your Android app. Once installed, the widget automatically shows instalment pricing alongside your product prices, helping customers see that SPayLater is available at checkout.
What this does
The ShopeePay Merchant SDK adds a native Android view that displays "Buy Now, Pay Later with SPayLater" messaging on your Homepage, Category, and Product Detail Pages. Installation is a developer task — the steps below are written so you can hand them to your Android developer with everything they need.
Before you start
- Access Key — your unique SPayLater plugin key. Get it from your ShopeePay account manager if you don't have one yet.
- Store ID — the unique ID for your store in the ShopeePay system. Same source as above.
- An Android developer — the steps below require someone who can edit your app's
build.gradleand Kotlin/Java source files. - Market knowledge — know the country, currency, and language your app targets (e.g. Malaysia / MYR / EN) so the SDK is initialized correctly.
Merchant tip: Send your developer this page along with your Access Key and Store ID. That is everything they need to complete the installation.
Installation steps
Step 1 — Get the SDK file from your account manager
The SDK is distributed as an .aar file. It is not published to Maven Central or any public repository. Contact your ShopeePay account manager to receive the latest shopeepay-merchant-sdk.aar file.
Once you have the file, create a libs/ folder in your Android module directory (the same level as your src/ folder) and copy the .aar file there.
Step 2 — Add the SDK to your project
Open your module-level build.gradle and add the SDK as a file dependency:
dependencies {
implementation files("libs/shopeepay-merchant-sdk.aar")
}After saving the file, click Sync Project with Gradle Files in Android Studio to apply the change.
The SDK depends on the following third-party libraries. If your app already includes them, no changes are needed. If not, add them to the same dependencies block:
dependencies {
implementation "com.squareup.okhttp3:okhttp:3.12.1"
implementation "com.google.code.gson:gson:2.10.1"
implementation "com.github.bumptech.glide:glide:4.13.2"
implementation "androidx.core:core-ktx:1.10.1"
implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}Step 3 — Initialize the SDK
In your Application class (the class that extends android.app.Application), add the following inside onCreate(). Replace the placeholder values with your real credentials and target market settings:
val config = ShopeePayMerchantConfig.Builder()
.context(applicationContext)
.accessKey("YOUR_ACCESS_KEY")
.env(Environment.SANDBOX) // switch to Environment.LIVE for production
.country(Country.MY)
.currency(Currency.MYR)
.language(Language.EN)
.build()
ShopeePayMerchantSdk.init(config)Change Country, Currency, and Language to match your target market. Use Environment.LIVE when submitting your production build.
Step 4 — Place the widget on your pages
For each page where you want to show SPayLater messaging, add the view to your layout XML and call render() in the corresponding Activity or Fragment.
Layout XML — add this view wherever you want the widget to appear, typically just below the product price:
<com.shopeepay.merchant.sdk.biz.installment.ShopeePayMerchantView
android:id="@+id/shopeePayMerchantView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />Activity / Fragment code — call render() after the view is available, for example in onCreate() or onViewCreated():
merchantView.render(
storeExtId = "YOUR_STORE_ID",
productId = "product-id",
amount = 129900L, // price in smallest currency unit (e.g. cents)
pageType = ShopeePayMerchantPageType.PRODUCT_PAGE
)Category pages with RecyclerView — batch pre-fetch — if your category or listing page uses a RecyclerView, calling render() inside onBindViewHolder triggers a separate network request per item. To avoid this, call ShopeePayMerchantSdk.requestData() once with the full list of visible products before the list is bound:
ShopeePayMerchantSdk.requestData(
SPPMerchantInfoRequest(
storeExtId = "YOUR_STORE_ID",
pageType = ShopeePayMerchantPageType.CATEGORY_PAGE,
productInfoList = products.map { product ->
SPPMerchantInfo(
productId = product.id,
amount = product.price
)
}
)
)After requestData() completes, call render() in onBindViewHolder as normal — the SDK serves each item's data from its local cache, so the widget loads instantly without additional network calls.
Step 5 — Repeat for each page type
Repeat Step 4 for every page where you want to show SPayLater messaging. Change pageType to match the page you're working on: ShopeePayMerchantPageType.HOME_PAGE for your Homepage, ShopeePayMerchantPageType.CATEGORY_PAGE for listing pages, and ShopeePayMerchantPageType.PRODUCT_PAGE for Product Detail Pages. On the Homepage you do not need to pass productId or amount.
Developer note — exact SDK parameters and third-party dependencies
ShopeePayMerchantConfig.Builder() parameters
| Parameter | Type | Description |
|---|---|---|
accessKey | String | SPL plugin key provided by ShopeePay |
env | Environment | Environment.SANDBOX for testing; Environment.LIVE for production |
country | Country | Country enum value, e.g. Country.MY, Country.TH, Country.ID |
currency | Currency | Currency enum value, e.g. Currency.MYR, Currency.THB, Currency.IDR |
language | Language | Language enum value, e.g. Language.EN, Language.TH, Language.ID |
render() parameters
| Parameter | Type | Description |
|---|---|---|
storeExtId | String | Your Store ID from ShopeePay |
productId | String | Your product's SKU or ID; not required on the Homepage |
amount | Long | Product price in smallest currency unit (e.g. cents); not required on the Homepage |
pageType | ShopeePayMerchantPageType | HOME_PAGE, CATEGORY_PAGE, or PRODUCT_PAGE |
requestData() — SPPMerchantInfoRequest fields
| Field | Type | Description |
|---|---|---|
storeExtId | String | Your Store ID from ShopeePay |
pageType | ShopeePayMerchantPageType | Page context for the batch pre-fetch (e.g. CATEGORY_PAGE) |
productInfoList | List<SPPMerchantInfo> | List of products to pre-fetch; each entry takes productId (String) and amount (Long) |
The SDK depends on OkHttp, Gson, Glide, core-ktx, RecyclerView, and ConstraintLayout. If these are already in your app's build.gradle, no additional changes are needed. If not, add them as shown in Step 2. For full SDK documentation, refer to the Confluence developer guide provided by your ShopeePay account manager.
Configuration
| Setting | Where to set it | Notes |
|---|---|---|
| Access Key | accessKey() in Builder | Required. Provided by your ShopeePay account manager. |
| Environment | env() in Builder | Use SANDBOX for development and testing; switch to LIVE before your production release. |
| Country / Currency / Language | Builder enums | Must match the market your SPayLater agreement covers. Using a mismatched country will result in no widget being rendered. |
| Store ID | storeExtId in render() | Required on every page type. |
| Page placement | pageType in render() | Controls which variant of the widget is shown. Use the correct page type for each screen. |
| Styling | Not configurable | The widget renders with SPayLater's standard styling. Custom colors or fonts are not supported to maintain brand consistency. |
How to verify the installation
- Build and run your app in SANDBOX mode on a real device or emulator.
- Navigate to a page where you placed the widget (Homepage, Category, or Product page).
- Confirm the "Buy Now, Pay Later with SPayLater" messaging appears at the expected position — typically just below the product price.
- On a Product page, tap the ⓘ info icon next to the instalment line. A pop-up should appear listing the available instalment plans and monthly amounts.
- Once everything looks correct in SANDBOX, update the Builder to
Environment.LIVEand submit your production build.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Widget is blank / not visible | SDK not initialized before the Activity renders | Make sure ShopeePayMerchantSdk.init() is called in Application.onCreate(), not in an Activity or Fragment. |
| Build fails after adding the .aar | Gradle sync not run or file path incorrect | Confirm the shopeepay-merchant-sdk.aar file is in the libs/ folder and click Sync Project with Gradle Files. |
| Widget shows but no instalment price | Wrong country/currency settings or amount not passed | Double-check Country, Currency, and confirm you are passing amount in smallest currency units (e.g. cents not dollars). |
| Tenor pop-up does not open | pageType mismatch | The tenor pop-up only appears when pageType is set to PRODUCT_PAGE. Check you are not using HOME_PAGE or CATEGORY_PAGE on your PDP. |
| Widget visible in SANDBOX but not in LIVE | Merchant or store not yet live in ShopeePay's system | Contact your ShopeePay account manager to confirm your store is activated for LIVE. |
FAQ
Do I need to update the widget when prices change?
No. Just call render() with the current price each time the page loads. The widget calculates the instalment line dynamically based on the amount you pass.
What happens if SPayLater is unavailable in the customer's region?
The widget renders nothing and takes up no space. If the configured country does not have an active SPayLater program, the SDK view collapses to zero height automatically — no empty box will appear on your page.
Can I customize the widget's colors or fonts?
No. The widget uses SPayLater's standard visual style and cannot be themed. This is intentional — the consistent look is a trust signal for customers, and customization would require regulatory review of the modified messaging.
How do I switch from SANDBOX to LIVE for my production release?
Change env(Environment.SANDBOX) to env(Environment.LIVE) in your Builder configuration, rebuild, and submit. Your Access Key is the same across both environments — no new credentials are needed.
I have more than one store ID. Can the widget handle multiple stores?
The SDK is initialized once with a single configuration. If you need to show different store IDs on different screens, you can call render() with a different storeExtId per screen — the configuration set at initialization (Access Key, country, etc.) applies globally, but the Store ID is set per render call.