A guide for Partners
ShopeePay Integration Best Practices
By adhering to these guidelines, partners can significantly improve their ShopeePay integration leading to a smoother user experience (UX), higher payment success rate and reduced integration issue.
Common Integration Issues
- Callback Failures: Difficulty in receiving ShopeePay callbacks due to incorrect handling or IP address restrictions by partners or merchants
- Redirection Issues: Inability to successfully jump to Shopee or ShopeePay App during Checkout with Shopeepay OR Link&Pay process due to:
- Partners whitelist specific domains/IPs
- Partners opening redirect URLs within an embedded webview rather than an external browser
- Return URL Handling: Incorrect implementation of return URLs to redirect users back to merchant app/site after payment
Payment Process Overview
Checkout with ShopeePay
Redirection URLs:
- redirect_url_app: Uses a URL scheme (e.g., shopeepayid://...) designed to launch the Shopee or ShopeePay app directly. If the app isn't installed, the payment process will fail to continue.
- redirect_url_http: Uses a universal link/app link (e.g., https://app.shopeepay.co.id/...) provided by Shopee's Universal Link Service (ULS). This link follows a fallback sequence:
- Attempts to open via Universal/App Link
- Fallsback to URL scheme if step 1 fails
- Redirects to web if native app launch fails
- Recommendation: Merchants are strongly advised to use
redirect_url_http
because of its enhanced capabilities.redirect_url_http
ensures the best user experience, using universal links, which much more resilient thanredirect_url_app
- Example URLs:
EXAMPLE
"redirect_url_app": "shopeepayid://main?apprl=%2Frn%2FTRANSFER_PAGE%3Fnavigate_url%3Dhttps%253A%252F%252Fwsa. test.wallet.airpay.co.id%252Fwallet%252Fpay%253Fmedium_index% 253DdnFCUjNBdXRaOEx2KLa0HO9ZyY_EJjBsoyrYmfswUUciST05lDJXVib9x9QazK9-bUfhkQ%2526order_key%253D-RyfAzYY8APAkegc1j8PrXHNLXR59jRbH5SJGu-NkR5EHse9RO12iPHg3lul2LEp5KdvWx-3YduP7Q%2526order_sn% 253D158994047272681299%2526return_url%253DaHR0cHM6Ly9iYWlkdS5jb20% 25252FYW1vdW50PTEwMDAwMDAmY2xpZW50X2lkPTEwMTAwMzQ3JnJlZmVyZW5jZV9pZD1OZXdTeXN0ZW1fSnVtcEFwcF9jYzAxMTEmcmVzdWx0X2 NvZGU9MjAzJnNpZ25hdHVyZT14cUFZcVdteEIxYUhNeDA5V05ET1pMRDhZSHVGeU54ODdSY0VTaFg3d1owJTNE%2526source%253Dqr% 2526token%253DdnFCUjNBdXRaOEx2KLa0HO9ZyY_EJjBsoyrYmfswUUciST05lDJXVib9x9QazK9-bUfhkQ"
Copy
EXAMPLE
"redirect_url_http": "https://app.test.shopeepay.co.id/u/pay_checkout? type=start&mid=10100347&target_app=shopeepay&medium_index=dnFCUjNBdXRaOEx2KLa0HO9ZyY_EJjBsoyrYmfswUUciST05lDJXVi b9x9QazK9-bUfhkQ&order_key=-RyfAzYY8APAkegc1j8PrXHNLXR59jRbH5SJGu-NkR5EHse9RO12iPHg3lul2LEp5KdvWx-3YduP7Q&order_sn=158994047272681299&return_url=aHR0cHM6Ly9iYWlkdS5jb20% 2FYW1vdW50PTEwMDAwMDAmY2xpZW50X2lkPTEwMTAwMzQ3JnJlZmVyZW5jZV9pZD1OZXdTeXN0ZW1fSnVtcEFwcF9jYzAxMTEmcmVzdWx0X2NvZG U9MjAzJnNpZ25hdHVyZT14cUFZcVdteEIxYUhNeDA5V05ET1pMRDhZSHVGeU54ODdSY0VTaFg3d1owJTNE&source=web&token=dnFCUjNBdXRa OEx2KLa0HO9ZyY_EJjBsoyrYmfswUUciST05lDJXVib9x9QazK9-bUfhkQ"
Copy
- Deep Link Types:
- URL Scheme: scheme://host:port/path?query=xxxxxxx. The protocol, domain, and path are not fixed.
- Universal Link (iOS) / App Link (Android): https://host:port/path?query=xxxxxxx or http://host:port/path?query=xxxxxxx. The protocol must be HTTP or HTTPS. These are enhanced links that can trigger different behaviors.
Link&Pay (LnP)
- Redirection URL: The LnP process uses a single redirect_url which is opened in a web page (e.g., https://test.shopeepay.co.th/checkout/link-pay?...). It does not have the same deep link capabilities as the Checkout with ShopeePay process, and must open in a web page.
- Example URL:
EXAMPLE
"redirect_url":"https://test.shopeepay.co.th/checkout/link-pay? merchant_ticket=s3YLfqiyY9lgYLWGRy_yB_Dj3k2RKUB9pPnG7M0GWvO_5Pc43yYPJSvgGY4Dd1z6F2727ygpUzDNWw&return_url=https% 3A%2F%2Fapple.com%2Fsg%3Fresult%3D201"
Copy
Best Practices for Redirecting to ShopeePay
- Use External Browser: Always open redirect_url_http (CwS) or redirect_url (LnP) in the device's default browser rather than an embedded webview inside your app. This is crucial for triggering the native mechanism for universal links and deep linking.
- Whitelisting: If your app must use a webview for payment links, you need to:
- Add Shopee and ShopeePay app schemes to your app's whitelist settings
- Contact ShopeePay support to activate deeplinking features for your merchant account
- Shopee/ShopeePay App Schemes: The following app schemes should be whitelisted:
ID | MY | PH | SG | TH | VN | |
---|---|---|---|---|---|---|
Shopee App | shopeeid:// | shopeemy:// | shopeeph:// | shopeesg:// | shopeeth:// | shopeevn:// |
ShopeePay App | shopeepayid:// | / | / | / | shopeepayth:// | shopeepayth:// |
- Universal Links/App Links (Recommended): Use the provided universal links (e.g., https://app.shopeepay.co.id/xxxxx) in the redirect_url_http.
- This method uses the native OS capabilities to open the app directly.
- It improves the user experience by avoiding intermediary screens or manual app selection.
Region | Universal Link |
---|---|
ID | https://app.shopeepay.co.id/xxxxx |
TH | https://app.shopeepay.co.th/xxxxx |
VN | https://app.shopeepay.vn/xxxxx |
MY | https://app.shopeepay.com.my/xxxxx |
- URL Scheme (Fallback): As a fallback, you can use the URL schemes (e.g., shopeepayid://...). Note, however, that this method is less robust and may not always work as expected. Ensure the app schemes are properly configured in your app's info.plist (iOS) or AndroidManifest.xml (Android).
How to open the link via an external browser
iOS: Objective C
EXAMPLE
NSURL *url = [NSURL URLWithString:@"https://app.shopeepay.co.id/xxx"];if ([[UIApplication sharedApplication] canOpenURL:url]) {[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];}
Copy
iOS: Swift
EXAMPLE
if let url = URL(string: "https://app.shopeepay.co.id/xxx"), UIApplication.shared.canOpenURL(url) {UIApplication.shared.open(url, options: [:], completionHandler: nil)}
Copy
Android: Java
EXAMPLE
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://app.shopeepay.co.id/xxx"));//package name can get from here:https://confluence.shopee.io/display/ShopeePayFE/How+to+jump+to+ShopeePay+App#heading-AndroidPackageNamebrowserIntent.setPackage("com.shopeepay.id");startActivity(browserIntent);
Copy
Android: Kotlin
EXAMPLE
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("https://app.shopeepay.co.id/xxx"))//package name can get from here:https://confluence.shopee.io/display/ShopeePayFE/How+to+jump+to+ShopeePay+App#heading-AndroidPackageNamebrowserIntent.setPackage("com.shopeepay.id")startActivity(browserIntent)
Copy
React Native
EXAMPLE
import { Linking } from 'react-native';const openURL = async (url) => {const supported = await Linking.canOpenURL(url);if (supported) {await Linking.openURL(url);} else {console.error("Don't know how to open URL: " + url);}};openURL('https://app.shopeepay.co.id/xxx');
Copy
Flutter
1. Add url_launcher plugin
EXAMPLE
// yamldependencies:url_launcher: ^x.x.x
Copy
2. Use url_launcher to jump
EXAMPLE
import 'package:url_launcher/url_launcher.dart';void openURL(String url) async {if (await canLaunch(url)) {await launch(url);} else {throw 'Could not launch $url';}}openURL('https://app.shopeepay.co.id/xxx');
Copy
Web (Javascript)
Option 1: window.open
EXAMPLE
window.open("https://app.shopeepay.co.id/xxx", "_self");
Copy
Option 2: window.location
EXAMPLE
window.location.href = "https://app.shopeepay.co.id/xxx";
Copy
Option 3: Using a tag
EXAMPLE
<a href="https://app.shopeepay.co.id/xxx" target="_blank">Open Link</a>
Copy
How to open ShopeePay App by scheme URL
iOS:
Step 1: Config ShopeePay App schema in Third Part App info.plist
Step 2: Use Native OpenURL API to open ShopeePay App
EXAMPLE
NSURL *url = [NSURL URLWithString:@"shopeepayid://main?apprl=xxxx];if ([[UIApplication sharedApplication] canOpenURL:url]) {[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];} else {NSLog(@"Cannot open URL: %@", url);}
Copy
Android (Java)
EXAMPLE
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("shopeepayid://xxx"));//package name can get from here:https://confluence.shopee.io/display/ShopeePayFE/How+to+jump+to+ShopeePay+App#heading-AndroidPackageNamebrowserIntent.setPackage("com.shopeepay.id");startActivity(browserIntent);
Copy
Android (Kotlin)
EXAMPLE
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse("shopeepayid://xxx"))//package name can get from here:https://confluence.shopee.io/display/ShopeePayFE/How+to+jump+to+ShopeePay+App#heading-AndroidPackageNamebrowserIntent.setPackage("com.shopeepay.id")startActivity(browserIntent)
Copy
Android Package Name
Region | package name |
---|---|
ID | com.shopeepay.id |
TH | com.beeasy.airpay |
VN | com.beeasy.toppay |
MY | com.shopeepay.my |
Redirecting Back to Merchant App/Website after payment
CwS:
- Merchants must provide a return_url parameter when calling the "/v3/merchant-host/order/create" OR /v1.0/debit/payment-host-to-host endpoint.
- Upon completion or cancellation of the payment process, ShopeePay redirects back to this return_url.
- For example, if the user jumped from the partner app, the partner can utilize window.location.href = "{partner}://xxx" to open the partner's app by utilizing its own URL scheme.
LnP:
- LnP returns the payment result (success or failure) by appending a result parameter to the return_url.
- result=100 for successful payments.
- result=201 for failed payments.
- Example: https://apple.com/sg?result=201.
Refund
- ShopeePay Refunds: What you need to know:
- Refunds initiated between 12 AM and 5 AM might be temporarily blocked due to reconciliation processes on our end. This timeframe is reserved for essential system maintenance and financial balancing, which can impact the immediate processing of refund requests.
- ShopeePay refunds can only be processed if there's another ShopeePay transaction using the same checkout method on the same day. This is because refunds are sourced from new ShopeePay transactions.
- For off-us transactions, refunds can be processed via the ShopeePay Refund API, given that other e-wallet supports refund and the transaction is within the issuer's validity period.
Handling Invalid Token Error
Understanding the “Invalid Token Error” (401XX01)
Our system uses access tokens for authentication and authorization. These tokens have a limited lifespan and can be come invalid due to expiry or system issues. When it happens, API requests using invalid token will fail with with an “Invalid Token” Error (Response Code: 401XX01).
Sample Scenario to illustrate the flow:
- Token Generation: At 8.20 AM, you request a token by calling our access token endpoint. This token (token: ABC) is cached by our service.
- System downtime: Our token generation service experience downtime at 8.30 AM.
- Cache Token Usage: Partner can continue to use the cached token for subsequent API requests. During downtime, token validation is bypassed, allowing API request to proceed.
- System Recovery and Token Expiry: Our services resume at 8.45 AM. However, token ABC has now expired. Hence, when your system attempts to call our API, it receives an “invalid token” error
Action Required:
Do not ignore this invalid token error: Upon receiving an “invalid token” (401XX01) error, immediately request a new token by calling access token endpoint. This ensures that your system has a valid token for subsequent API Calls.
Best Practices:
- Proper Error Handling: Include an error handling logic in your integration to catch “invalid token” errors and trigger refresh token.
Check Transaction Status
Q: I received a '200xx00' response code after checking my transaction status. Does this mean my transaction is complete?
A: Not necessarily. While a '200xx00' response generally indicates a successful API call, the actual transaction might still be processing in the background.
To confirm the latest status of your transaction, we strongly recommend referring to the latestTransctionStatus field in the API response. This will provide the most up-to-date information.