NAV

Mô hình tích hợp

Chọn mô hình tích hợp ZaloPay phù hợp

Mobile - App to App

Giới thiệu Demo Hướng dẫn tích hợp

Ngữ cảnh sử dụng

Khi người dùng sử dụng merchant apps để thanh toán một đơn hàng sử dụng phương thức thanh toán là ZaloPay trên điện thoại của người sử dụng có cài đặt đồng thời merchant app và ZaloPay App. Merchant App có thể gửi thông tin đơn hàng trực tiếp tới ZaloPay App thông qua đường App-to-App. Sau khi người dùng thực hiện thanh toán xong, ZaloPay App sẽ gọi lại merchant apps để thông báo kết quả giao dịch.

Luồng xử lý

Luồng xử lý chính

App to App Payment Flow

Trường hợp không có cài đặt ZaloPay

App to App Payment Flow

Tải về SDK AppToApp

Đối với iOS

Tích hợp SDK AppToApp

SDK AppToApp được phân phối dưới dạng thư viện, để sử dụng các API của ZPDK, cần tích hợp vào project theo các bước sau

  1. Thêm framework ZPDK.framework vào project
  2. Cấu hình cho phép khởi tạo ZaloPay từ app, bằng cách thêm  zalozalopay và zalopay.api.v2 vào key  LSApplicationQueriesSchemes
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>zalo</string>
    <string>zalopay</string>
    <string>zalopay.guide.v2</string>
</array>

Khởi tạo ZPDK

Trong AppDelegate.m, thêm lời gọi tới ZPDK để xử lý việc trao đổi dữ liệu giữa ZaloPay và app

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [[ZaloPaySDK sharedInstance] initWithAppId:<appID> uriScheme:@"<uriScheme>" environment:<ZPZPIEnvironment>]; //Khởi tạo ZPDK
}

- (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]; //gọi tới ZPDK để xử lý trao đổi dữ liệu giữa ZaloPay với app
}
  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)
  }

Lưu ý: Gọi hàm này vì ZPDK hiện đang check sourceApplication có đúng là của ZaloPay hay không.

- (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 {}

Gọi hàm thanh toán

Gọi hàm để bắt đầu thanh toán

  [[ZaloPaySDK sharedInstance] initWithAppId:<appID> uriScheme:@"<uriScheme>" environment:<ZPZPIEnvironment>]; //Reinit ZPDK nếu muốn thanh toán bằng một AppID khác
  [ZaloPaySDK sharedInstance].paymentDelegate = self; //Depend on where you handle ZPPaymentDelegate.
  [[ZaloPaySDK sharedInstance] payOrder:zpTransToken];
  ZaloPaySDK.sharedInstance()?.initWithAppId(<appid>, uriScheme: "<uriScheme>", environment: <ZPZPIEnvironment>) //Reinit ZPDK nếu muốn thanh toán bằng một AppID khác
  ZaloPaySDK.sharedInstance()?.paymentDelegate = self  //Depend on where you handle ZPPaymentDelegate. 
  ZaloPaySDK.sharedInstance()?.payOrder(zpTransToken.text)

Xử lý kết quả trả về

  - (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
  }

Đối với Android

Tích hợp SDK AppToApp

Để tích hợp SDK AppToApp vào Android Studio bạn thực hiện các bước sau:

configurations.maybeCreate("default")
artifacts.add("default", file('zpdk-release.aar'))

Khởi tạo ZPDK

Thêm lời khởi tạo ZPDK trong hàm onCreate của Application

@Override
public void onCreate() {
  ...
  // Khởi tạo ZPDK
  ZaloPaySDK.init(<appID>, <Environment>);
}
    override fun onCreate(savedInstanceState: Bundle?) {
      ..
      ZaloPaySDK.init(<appID>, Environment);
    }

Gọi hàm thanh toán từ ZPDK và nhận callback

//Cần bắt sự kiện OnNewIntent vì ZaloPay App sẽ gọi deeplink về app của Merchant
@Override
public void onNewIntent(Intent intent) {
  super.onNewIntent(intent);
  ZaloPaySDK.getInstance().onResult(intent);
}

//Reinit ZPDK nếu muốn thanh toán bằng một AppID khác
ZaloPaySDK.tearDown();
ZaloPaySDK.init(<appID>, <Environment>);

//Gọi hàm thanh toán
ZaloPaySDK.getInstance().payOrder(
  <Activity>, <Token>, <YourAppUriScheme>, new MyZaloPayListener()
);

//Implement interface PayOrderListener để nhận kết quả thanh toán 
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
  }
}
  //Cần bắt sự kiện OnNewIntent vì ZaloPay App sẽ gọi deeplink về app của Merchant
  override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    ZaloPaySDK.getInstance().onResult(intent)
  }

  //Reinit ZPDK nếu muốn thanh toán bằng một AppID khác
  ZaloPaySDK.tearDown();
  ZaloPaySDK.init(<appID>, Environment);

  //Gọi hàm thanh toán
  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
    }
  })

Đối với React Native

Tích hợp và khởi tạo ZPDK

iOS

Android

  1. Mở project android bên trong project React Native đang làm việc bằng android studio
  2. Thực hiện các bước tiếp theo tương tự như phần Android ở trên
  3. Trong hàm getPackages(), thêm new PayZaloBridge() bên trong hàm Array.asList(...) như sau:
@Override
protected List<ReactPackage> getPackages() {
  return Array.asList(
    ...,
    new PayZaloBridge()
  );
}

Gọi hàm thanh toán

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('Giao dịch thành công!');
      } else{
        alert('Giao dịch thất bại!');
      }
    }
  );
}

componentWillUnmount() {
  this.subscription.remove();
}

let payZP = NativeModules.PayZaloBridge;
payZP.payOrder(zptranstoken);

Đối với Flutter

Tích hợp ZPDK

iOS

Tạo MethodChannel để gọi hàm thanh toán ZaloPay

  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

Tạo EventChannel để nhận kết quả trả về từ ZaloPay

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
    }
  }

Gửi kết quả đến EventChannel

  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])
  }

Android

Dùng Method Channel để gọi đến hàm thanh toán và trả kết quả về Flutter

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")
            }
        })
    }
  }

Dữ liệu trả về của ZPDK

Tham số Kiểu dữ liệu Ý nghĩa
errorCode int

Kết quả giao dịch.

1: giao dịch thành công

#1: giao dịch thất bại, gọi thêm Api server để biết thêm thông tin

transactionId String Mã zp_trans_id của giao dịch
zpTranstoken String Mã zp_trans_token của đơn hàng thanh toán
appTransId String Mã app_trans_id của giao dịch
Không tìm thấy kết quả phù hợp