Select the appropriate model of ZaloPay integration
When user use Merchant App to pay an order use ZaloPay Payment method on smartphone installed both Merchant app & ZaloPay app. Merchant app can send order's information to ZaloPay app directly through App-to-App method. After payment successfully, ZaloPay app will relaunch Merchant app to display payment result.
SDK AppToApp was distributed as libraries. Project need to be integrated with ZPDK's API following the instructions below in other to use it.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>zalo</string>
<string>zalopay</string>
<string>zalopay.guide.v2</string>
</array>
In the AppDelegate.m, add calling request to ZPDK to processing data transaction between ZaloPay and App.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[ZaloPaySDK sharedInstance] initWithAppId:<appID> uriScheme:@"<uriScheme>" environment:<ZPZPIEnvironment>]; //ZPDK Initialize
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
return [[ZaloPaySDK sharedInstance] application:app openURL:url sourceApplication:@"vn.com.vng.zalopay" annotation:nil]; //Calling request to ZPDK to process data transaction
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ZaloPaySDK.sharedInstance()?.initWithAppId(<appid>, uriScheme: "<uriScheme>", environment: <ZPZPIEnvironment>)
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return ZaloPaySDK.sharedInstance().application(app, open: url, sourceApplication:"vn.com.vng.zalopay", annotation: nil)
}
Notice: Call this function because ZPDK need to check if sourceApplication is belong to ZaloPay
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {}
Call payment function to process
[[ZaloPaySDK sharedInstance] initWithAppId:<appID> uriScheme:@"<uriScheme>" environment:<ZPZPIEnvironment>]; //Reinit ZPDK if you want to pay with another AppID
[ZaloPaySDK sharedInstance].paymentDelegate = self; //Depend on where you handle ZPPaymentDelegate.
[[ZaloPaySDK sharedInstance] payOrder:zpTransToken];
ZaloPaySDK.sharedInstance()?.initWithAppId(<appid>, uriScheme: "<uriScheme>", environment: <ZPZPIEnvironment>) //Reinit ZPDK if you want to pay with another AppID
ZaloPaySDK.sharedInstance()?.paymentDelegate = self //Depend on where you handle ZPPaymentDelegate.
ZaloPaySDK.sharedInstance()?.payOrder(zpTransToken.text)
Process responses
- (void)paymentDidSucceeded:(NSString *)transactionId zpTranstoken:(NSString *)zpTranstoken appTransId:(NSString *)appTransId {
//Handle Success
}
- (void)paymentDidCanceled:(NSString *)zpTranstoken appTransId:(NSString *)appTransId {
//Handle User Canceled
}
- (void)paymentDidError:(ZPPaymentErrorCode)errorCode zpTranstoken:(NSString *)zpTranstoken appTransId:(NSString *)appTransId {
//Redirect to Zalo/ZaloPay Store when errorCode == ZPPaymentErrorCode.appNotInstall
//Handle Error
}
func paymentDidSucceeded(_ transactionId: String!, zpTranstoken: String!, appTransId: String!) {
//Handle Success
}
func paymentDidCanceled(_ zpTranstoken: String!, appTransId: String!) {
//Handle User Canceled
}
func paymentDidError(_ errorCode: ZPPaymentErrorCode, zpTranstoken : String!, appTransId: String!) {
//Redirect to Zalo/ZaloPay Store when errorCode == ZPPaymentErrorCode.appNotInstall
//Handle Error
}
You have to following these intructions below to integrate ZPDK to Android Studio:
configurations.maybeCreate("default")
artifacts.add("default", file('zpdk-release.aar'))
Add ZPDK initializtion in Application's onCreate
function
@Override
public void onCreate() {
...
// ZPDK Initialize
ZaloPaySDK.init(<appID>, <Environment>);
}
override fun onCreate(savedInstanceState: Bundle?) {
..
ZaloPaySDK.init(<appID>, Environment);
}
//Need to catch OnNewIntent event because ZaloPay App will call deeplink to Merchant's app
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
ZaloPaySDK.getInstance().onResult(intent);
}
//Reinit ZPDK if you want to pay with another AppID
ZaloPaySDK.tearDown();
ZaloPaySDK.init(<appID>, <Environment>);
//Payment function
ZaloPaySDK.getInstance().payOrder(
<Activity>, <Token>, <YourAppUriScheme>, new MyZaloPayListener()
);
//Implement interface PayOrderListener to get payment result
private static class MyZaloPayListener implements PayOrderListener {
@Override
public void onPaymentSucceeded(final String transactionId, final String transToken, final String appTransID) {
//Handle Success
}
@Override
public void onPaymentCanceled(String zpTransToken, String appTransID) {
//Handle User Canceled
}
@Override
public void onPaymentError(ZaloPayError zaloPayError, String zpTransToken, String appTransID) {
//Redirect to Zalo/ZaloPay Store when zaloPayError == ZaloPayError.PAYMENT_APP_NOT_FOUND
//Handle Error
}
}
//Need to catch OnNewIntent event because ZaloPay App will call deeplink to Merchant's app
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
ZaloPaySDK.getInstance().onResult(intent)
}
//Reinit ZPDK if you want to pay with another AppID
ZaloPaySDK.tearDown();
ZaloPaySDK.init(<appID>, Environment);
//Payment function
ZaloPaySDK.getInstance().payOrder(<Activity>, <Token>!!, "<MerchantApp Deeplink>",object: PayOrderListener {
override fun onPaymentCanceled(zpTransToken: String?, appTransID: String?) {
//Handle User Canceled
}
override fun onPaymentError(zaloPayErrorCode: ZaloPayError?, zpTransToken: String?, appTransID: String?) {
//Redirect to Zalo/ZaloPay Store when zaloPayError == ZaloPayError.PAYMENT_APP_NOT_FOUND
//Handle Error
}
override fun onPaymentSucceeded(transactionId: String, transToken: String, appTransID: String?) {
//Handle Success
}
})
getPackages()
function, add new PayZaloBridge()
into Array.asList(...)
function like:
@Override
protected List<ReactPackage> getPackages() {
return Array.asList(
...,
new PayZaloBridge()
);
}
import {NativeModules, NativeEventEmitter} from 'react-native';
const { PayZaloBridge } = NativeModules;
const payZaloBridgeEmitter = new NativeEventEmitter(PayZaloBridge);
componentDidMount() {
this.subscription = payZaloBridgeEmitter.addListener(
'EventPayZalo',
(data) => {
if(data.returnCode == 1){
alert('Payment successully!');
} else{
alert('Payment failed!');
}
}
);
}
componentWillUnmount() {
this.subscription.remove();
}
let payZP = NativeModules.PayZaloBridge;
payZP.payOrder(zptranstoken);
static const MethodChannel platform = MethodChannel('flutter.native/channelPayOrder'); //Example of creating MethodChannel
final String result = await platform.invokeMethod('payOrder', {"zptoken": zpToken}); //Example of calling payOrder
static const EventChannel eventChannel = EventChannel('flutter.native/eventPayOrder');
@override
void initState() {
super.initState();
if (Platform.isIOS) {
eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError); //Listening for event
}
}
private var eventSink: FlutterEventSink?
func paymentDidSucceeded(_ transactionId: String!, zpTranstoken: String!, appTransId: String!) {
//Example of Handling Success
guard let eventSink = eventSink else {
return
}
eventSink(["errorCode": 1, "zpTranstoken": zpTranstoken, "transactionId": transactionId, "appTransId": appTransId])
}
func paymentDidCanceled(_ zpTranstoken: String!, appTransId: String!) {
//Example of Handling User Canceled
guard let eventSink = eventSink else {
return
}
eventSink(["errorCode": 4, "zpTranstoken": zpTranstoken, "appTransId": appTransId])
}
func paymentDidError(_ errorCode: ZPPaymentErrorCode, zpTranstoken: String!, appTransId: String!) {
//Example of Handling Error
guard let eventSink = eventSink else {
return
}
//Redirect to Zalo/ZaloPay Store when errorCode == ZPPaymentErrorCode.appNotInstall
eventSink(["errorCode": errorCode, "zpTranstoken": zpTranstoken, "appTransId": appTransId])
}
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelPayOrder)
.setMethodCallHandler { call, result ->
if (call.method == "payOrder"){
val token = call.argument<String>("zptoken")
ZaloPaySDK.getInstance().payOrder(this@MainActivity, token !!, "<UriScheme>",object: PayOrderListener {
override fun onPaymentCanceled(zpTransToken: String?, appTransID: String?) {
result.success("User Canceled")
}
override fun onPaymentError(zaloPayErrorCode: ZaloPayError?, zpTransToken: String?, appTransID: String?) {
//Redirect to Zalo/ZaloPay Store when zaloPayError == ZaloPayError.PAYMENT_APP_NOT_FOUND
result.success("Payment failed")
}
override fun onPaymentSucceeded(transactionId: String, transToken: String, appTransID: String?) {
result.success("Payment Success")
}
})
}
}
application/json
Parameter | Datatype | Description |
---|---|---|
errorCode |
int | Payment result. 1: transaction successfully #1: transaction failed, call API for more information |
transactionId |
String | Transaction ID |
zpTranstoken |
String | ZPTranstoken from ZPDK send to ZaloPay to discern orders |
appTransId |
String | Order's transaction code |