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.api.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 {}
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")
}
})
}
}
Parameter | Datatype | Description |
---|---|---|
transactionId |
string | Transaction ID |
zpTranstoken |
string | ZPTranstoken from ZPDK send to ZaloPay to discern orders |
appTransId |
string | Order's transaction code |
Parameter | Datatype | Description |
---|---|---|
zpTranstoken |
string | ZPTranstoken from ZPDK send to ZaloPay to discern orders |
appTransId |
string | Order's transaction code |
Parameter | Datatype | Description |
---|---|---|
errorCode |
number | Error code |
zpTranstoken |
string | ZPTranstoken from ZPDK send to ZaloPay to discern orders |
appTransId |
string | Order's transaction code |
Note: If user has not installed ZaloPay or the Zalo app, response error code: -1. Merchant creates navigation to App Store/Google Play for user to download app
Example
{
if errorCode == ZPPaymentErrorCode.appNotInstall {
ZaloPaySDK.sharedInstance()?.navigateToZaloStore(); // navigator to Zalo App
// ZaloPaySDK.sharedInstance()?.navigateToZaloPayStore(); // navigator to ZaloPay App
return;
}
}