Tích hợp SDK
Tổng quan
Thanh toán App-to-app, hay còn gọi là phương thức thanh toán trực tiếp qua Zalopay, là một cách thuận tiện để thanh toán đơn hàng bằng điện thoại thông minh. Khi người dùng chọn thanh toán đơn hàng trên ứng dụng Đối tác bằng phương thức "Thanh toán Zalopay", ứng dụng Đối tác sẽ điều hướng đến ứng dụng Zalopay và Zalopay sẽ tiến hành thanh toán. Việc tích hợp này cho phép thanh toán dễ dàng và nhanh chóng, cung cấp cách tích hợp các chương trình khuyến mãi, giảm nhu cầu tiếp xúc vật lý hoặc tiền mặt nhưng vẫn đảm bảo tính bảo mật khi thanh toán giữa các ứng dụng.
Ở các phần tiếp theo chúng tôi sẽ hướng dẫn bạn từng bước tích hợp Zalopay. Bạn có thể truy cập Github Repository của chúng tôi để tham khảo 4 ví dụ triển khai của chúng tôi (ứng dụng Android, ứng dụng iOS, ứng dụng React Native trên nền tảng Android/iOS và ứng dụng Flutter trên nền tảng Android/iOS).
Trước khi bắt đầu
Trước khi bạn bắt đầu, hãy đảm bảo các công việc sau được thực hiện để tích hợp suôn sẻ:
- Đã đăng ký tài khoản người bán thành công và có được
app_id
,mac_key
từ Merchant Portal. - Hiểu cách sử dụng và đặc điểm kỹ thuật của CreateOrder API và khái niệm về truyền dữ liệu an toàn.
- Môi trường phát triển của bạn đáp ứng các phiên bản dưới đây:
- Đối với nền tảng iOS:
- Phiên bản XCode 14.1
- Phiên bản Ruby 2.7.6
- Phiên bản Swift 5.7.1
- Đối với nền tảng Android:
- Phiên bản Gradle 7.5
- Phiên bản Android Gradle plugin 7.2.2
- Phiên bản JDK tối thiểu 11.0.13
- Đối với nền tảng iOS:
- Tải xuống
zpdk-swift-x.x.x.framework
(dành cho iOS) vàzpdk-release-vx.x.aar
(dành cho Android) tại đây nhằm hỗ trợ tích hợp ứng dụng Đối tác với ứng dụng Zalopay.
Cách hoạt động
Luồng thanh toán như sau:
- Đối tác thêm Zalopay làm phương thức thanh toán trong ứng dụng của họ, đồng thời khởi tạo ZPDK framework với
app_id
được cung cấp (ZPDK hỗ trợ thay đổiapp_id
cho Đối tác sử dụng nhiều id cho nhiều ứng dụng). - Người dùng lựa chọn Zalopay làm phương thức thanh toán rồi tiến hành thanh toán.
- Ứng dụng Đối tác gọi CreateOrder API để tạo đơn hàng thanh toán mới. Ứng dụng Đối tác sẽ nhận được
zpTransToken
trong response. - Ứng dụng Đối tác gọi hàm
payOrder
của ZPDK framework, vớizpTransToken
nhận được ở bước 3 làm tham số. - Ứng dụng Đối tác điều hướng đến màn hình tạo đơn hàng của ứng dụng Zalopay. Lưu ý: Đối tác nên xử lý ứng dụng của mình trong trường hợp người dùng chưa cài đặt ứng dụng Zalopay.
- Người dùng hoàn tất thanh toán trên ứng dụng Zalopay. Zalopay điều hướng quay lại ứng dụng Đối tác kèm theo response.
- Ứng dụng Đối tác xử lý response và hiển thị thông báo phù hợp cho người dùng.
Cụ thể, quy trình của chúng tôi như sau:
Tích hợp
Nền tảng iOS
Bước 1. Thêm và khởi tạo Zalopay SDK
- Thêm framework
ZPDK.framework
vào ứng dụng - Thay đổi cấu hình để cho phép khởi tạo Zalopay từ ứng dụng, bằng cách thêm zalo, Zalopay và Zalopay.api.v2 vào key LSApplicationQueriesSchemes. Đồng thời thêm url scheme của ứng dụng Đối tác (
merchant-deeplink
trong ví dụ này) vào key CFBundleURLSchemes để hỗ trợ điều hướng giữa các ứng dụng:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>zalo</string>
<string>Zalopay</string>
<string>Zalopay.api.v2</string>
</array>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>CFBundleURLSchemes</string>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>org.reactjs.native.example.demozpdk</string>
<key>CFBundleURLSchemes</key>
<array>
<string>merchant-deeplink</string>
</array>
</dict>
</array>
- Ở file AppDelegate, khởi tạo ZPDK để xử lý việc trao đổi dữ liệu giữa Zalopay và ứng dụng:
- Swift
- Objective C
// Gọi lại hàm này bất cứ khi nào bạn muốn khởi tạo lại ZPDK để cho phép thanh toán bằng app_id khác
//UriScheme giống như merchant-deeplink được cấu hình trong Info.plist ở trên
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ZalopaySDK.sharedInstance()?.initWithAppId(<appid>, uriScheme: "<merchant-deeplink>", environment: <ZPZPIEnvironment>)
return true
}
//Gọi ZPDK để xử lý việc trao đổi dữ liệu giữa Zalopay và ứng dụng. Gọi hàm này vì ZPDK hiện đang kiểm tra xem ứng dụng nguồn có phải là Ứng dụng Zalopay hay không.
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)
}
// Gọi lại hàm này bất cứ khi nào bạn muốn khởi tạo lại ZPDK để cho phép thanh toán bằng app_id khác
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[ZalopaySDK sharedInstance] initWithAppId:<appID> uriScheme:@"<uriScheme>" environment:<ZPZPIEnvironment>];
}
//Gọi ZPDK để xử lý việc trao đổi dữ liệu giữa Zalopay và ứng dụng. Gọi hàm này vì ZPDK hiện đang kiểm tra xem ứng dụng nguồn có phải là Ứng dụng Zalopay hay không.
- (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];
}
Bước 2. Gọi chức năng Thanh toán
- Gọi CreateOrder API. Đối tác sẽ nhận được
zpTransToken
sau khi gọi API thành công. - Gọi hàm Payment sử dụng
zpTransToken
ở trên:
- Swift
- Objective C
//Depend on where you handle ZPPaymentDelegate.
ZalopaySDK.sharedInstance()?.paymentDelegate = self
ZalopaySDK.sharedInstance()?.payOrder(zpTransToken.text)
// Phụ thuộc vào nơi bạn xử lý ZPPaymentDelegate.
[ZalopaySDK sharedInstance].paymentDelegate = self;
[[ZalopaySDK sharedInstance] payOrder:zpTransToken];
Bước 3. Xử lý kết quả trả về
ZPDK sẽ điều hướng quay lại ứng dụng Đối tác kèm theo response. Ứng dụng Đối tác cần xử lý kết quả trả về bằng cách sử dụng 3 callback sau:
- Swift
- Objective C
func paymentDidSucceeded(_ transactionId: String!, zpTranstoken: String!, appTransId: String!) {
//Xử lý trường hợp thanh toán thành công
}
func paymentDidCanceled(_ zpTranstoken: String!, appTransId: String!) {
//Xử lý trường hợp người dùng từ chối thanh toán
}
func paymentDidError(_ errorCode: ZPPaymentErrorCode, zpTranstoken : String!, appTransId: String!) {
//Xử lý trường hợp thanh toán lỗi
}
- (void)paymentDidSucceeded:(NSString *)transactionId zpTranstoken:(NSString *)zpTranstoken appTransId:(NSString *)appTransId {
//Xử lý trường hợp thanh toán thành công
}
- (void)paymentDidCanceled:(NSString *)zpTranstoken appTransId:(NSString *)appTransId {
//Xử lý trường hợp người dùng từ chối thanh toán
}
- (void)paymentDidError:(ZPPaymentErrorCode)errorCode zpTranstoken:(NSString *)zpTranstoken appTransId:(NSString *)appTransId {
//Xử lý trường hợp thanh toán lỗi
}
Bước 4. Xử lý trường hợp người dùng chưa cài đặt Zalopay
Để xử lý trường hợp người dùng chưa cài đặt Zalopay, trong hàm callback paymentDidError
kiểm tra xem errorCode trả về có bằng ZPPaymentErrorCode.appNotInstall
hay không. Nếu có, hãy gọi các hàm navigateToStore
của ZPDK:
- Swift
- Objective C
func paymentDidError(_ errorCode: ZPPaymentErrorCode, zpTranstoken : String!, appTransId: String!) {
if (errorCode == .appNotInstall) {
//Gọi hàm này để điều hướng đến tải ứng dụng Zalo trên AppStore
ZalopaySDK.sharedInstance()?.navigateToZaloStore();
//HOẶC gọi hàm này để điều hướng đến tải Ứng dụng Zalopay trên AppStore
ZalopaySDK.sharedInstance()?.navigateToZalopayStore();
return;
}
}
- (void)paymentDidError:(ZPPaymentErrorCode)errorCode zpTranstoken:(NSString *)zpTranstoken appTransId:(NSString *)appTransId {
if (errorCode == ZPPaymentErrorCode.appNotInstall) {
[[ZalopaySDK sharedInstance] navigateToZaloStore];
[[ZalopaySDK sharedInstance] navigateToZalopayStore];
return;
}
Nền tảng Android
Bước 1. Thêm và khởi tạo Zalopay SDK
- Trong Android Studio, chọn menu File -> New -> New module... -> Import .JAR/.AAR Package
- Chọn tệp zpdk-release-vx.x.aar, sau đó đặt tên cho module mới
- Kiểm tra xem bạn đã nhập module
zpdk
vào dự án của mình trong tệp build.gradle của thư mục ứng dụng chưa:
dependencies {
...
implementation(name:'zpdk-release-v3.1', ext:'aar')
}
- Thêm url scheme của ứng dụng Đối tác vào file
AndroidManifest.xml
:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="merchant-deeplink"
android:host="app" />
</intent-filter>
- Khởi tạo ZPDK ở hàm
onCreate
của Android Activity bạn muốn:
- Kotlin
- Java
override fun onCreate(savedInstanceState: Bundle?) {
...
ZalopaySDK.init(<appID>, <Environment>);
//Khởi tạo lại ZPDK nếu bạn muốn thanh toán bằng AppID khác
ZalopaySDK.tearDown();
ZalopaySDK.init(<appID>, Environment);
}
@Override
public void onCreate() {
...
ZalopaySDK.init(<appID>, <Environment>);
//Khởi tạo lại ZPDK nếu bạn muốn thanh toán bằng AppID khác
ZalopaySDK.tearDown();
ZalopaySDK.init(<appID>, <Environment>);
}
Bước 2. Gọi chức năng Thanh toán
Sau khi gọi CreateOrder API thành công và nhận được zpTransToken
, hãy gọi chức năng Thanh toán với zpTransToken
đó::
- Kotlin
- Java
//Cần phải hứng sự kiện OnNewIntent vì Zalopay App sẽ gọi deeplink tới ứng dụng Đối tác
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
ZalopaySDK.getInstance().onResult(intent)
}
ZalopaySDK.getInstance().payOrder(<Activity>, <Token>!!, "<MerchantApp Deeplink>", object: PayOrderListener {
...
})
//Cần phải hứng sự kiện OnNewIntent vì Zalopay App sẽ gọi deeplink tới ứng dụng Đối tác
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
ZalopaySDK.getInstance().onResult(intent);
}
ZalopaySDK.getInstance().payOrder(
<Activity>, <Token>, <YourAppUriScheme>, new MyZalopayListener()
);
Bước 3. Xử lý kết quả trả về
Triển khai PayOrderListener
và xử lý logic phù hợp với ứng dụng Đối tác trong các hàm tương ứng với trạng thái giao dịch: onPaymentSucceeded
, onPaymentCanceled
, onPaymentError
- Kotlin
- Java
ZalopaySDK.getInstance().payOrder(..., object: PayOrderListener {
override fun onPaymentCanceled(zpTransToken: String?, appTransID: String?) {
//Xử lý logic khi người dùng từ chối thanh toán
}
override fun onPaymentError(ZalopayErrorCode: ZalopayError?, zpTransToken: String?, appTransID: String?) {
//Xử lý logic khi thanh toán lỗi
}
override fun onPaymentSucceeded(transactionId: String, transToken: String, appTransID: String?) {
//Xử lý logic khi thanh toán thành công
}
})
private static class MyZalopayListener implements PayOrderListener {
@Override
public void onPaymentSucceeded(final String transactionId, final String transToken, final String appTransID) {
//Xử lý logic khi thanh toán thành công
}
@Override
public void onPaymentCanceled(String zpTransToken, String appTransID) {
//Xử lý logic khi người dùng từ chối thanh toán
}
@Override
public void onPaymentError(ZalopayError ZalopayError, String zpTransToken, String appTransID) {
//Xử lý logic khi thanh toán lỗi
}
}
Bước 4. Xử lý trường hợp người dùng chưa cài đặt Zalopay
Để xử lý trường hợp người dùng chưa cài đặt Zalopay, trong hàm onPaymentError
của PayOrderListener
, kiểm tra ZalopayError = ZalopayError.ZALO_PAY_NOT_INSTALLED (mã 1) và gọi những hàm của ZPDK để điều hướng đến Store:
- Kotlin
- Java
if (ZalopayError == ZalopayError.PAYMENT_APP_NOT_FOUND) {
ZalopaySDK.getInstance().navigateToZaloOnStore(getApplicationContext())
ZalopaySDK.getInstance().navigateToZalopayOnStore(getApplicationContext())
}
if (ZalopayError == ZalopayError.PAYMENT_APP_NOT_FOUND) {
ZalopaySDK.getInstance().navigateToZaloOnStore(getApplicationContext());
ZalopaySDK.getInstance().navigateToZalopayOnStore(getApplicationContext());
}
Ứng dụng React Native trên nền tảng iOS và Android
Bước 1. Thêm và khởi tạo Zalopay SDK
- Để tích hợp và khởi tạo ZPDK bằng React Native, chúng tôi thực hiện tương tự như ứng dụng iOS và Android ở trên
- Dùng các lớp Bridge cần thiết ở phía iOS và Android để giao tiếp hiệu quả với phía React Native
Bước 2. Gọi chức năng Thanh toán
- Ở phía iOS và Android, xuất một method cho React Native để gọi hàm
payOrder
của ZPDK:
RCT_EXPORT_METHOD(payOrder:
(NSString *)zpTransToken) {
[ZalopaySDK sharedInstance].paymentDelegate = self;
[[ZalopaySDK sharedInstance] payOrder:zpTransToken];
}
@ReactMethod
public void payOrder(String zpTransToken) {
Activity currentActivity = getCurrentActivity();
ZalopaySDK.getInstance().payOrder(currentActivity, zpTransToken, "demozpdk://app", payOrderListener);
}
- Ở phía React Native, sau khi gọi CreateOrder API thành công và nhận được
zpTransToken
, dùng native modulePayZaloBridge
và gọi phương thứcpayOrder
của nó:
import { NativeModules } from 'react-native';
const { PayZaloBridge } = NativeModules;
function payOrder() {
var payZP = NativeModules.PayZaloBridge;
payZP.payOrder(token);
}
Bước 3. Xử lý kết quả trả về
- Ở phía iOS, khai báo một sự kiện để React Native đăng ký. Sau đó, với mỗi callback được gọi, hãy gửi sự kiện đó đến phía React Native với dữ liệu tương ứng:
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventPayZalo"];
}
- (void)paymentDidSucceeded:(NSString *)transactionId
zpTranstoken:(NSString *)zpTranstoken
appTransId:(NSString *)appTransId {
[self sendEventWithName:@"EventPayZalo" body:@{@"returnCode": [NSString stringWithFormat:@"%ld", (long)1], @"transactionId":transactionId ? transactionId : @"", @"zpTranstoken": zpTranstoken ? zpTranstoken : @"", @"appTransId": appTransId ? appTransId : @""}];
}
- (void)paymentDidCanceled:(NSString *)zpTranstoken
appTransId:(NSString *)appTransId {
[self sendEventWithName:@"EventPayZalo" body:@{@"returnCode": [NSString stringWithFormat:@"%ld", (long)4], @"zpTranstoken":zpTranstoken ? zpTranstoken : @"", @"appTransId": appTransId ? appTransId : @""}];
}
- (void)paymentDidError:(ZPPaymentErrorCode)errorCode
zpTranstoken:(NSString *)zpTranstoken
appTransId:(NSString *)appTransId {
[self sendEventWithName:@"EventPayZalo" body:@{@"returnCode": [NSString stringWithFormat:@"%ld", (long)errorCode], @"zpTranstoken":zpTranstoken ? zpTranstoken : @"", @"appTransId":appTransId ? appTransId : @""}];
}
- Ở phía Android, khai báo một sự kiện để React Native đăng ký. Sau đó, với mỗi callback của
payOrderListener
được gọi, hãy gửi sự kiện đó đến phía React Native với dữ liệu tương ứng:
private ReactApplicationContext mReactContext;
private void sendEvent(ReactContext reactContext, String eventName, WritableMap params) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
PayOrderListener payOrderListener = new PayOrderListener() {
@Override
public void onPaymentSucceeded(String transactionId, String transToken, String appTransID) {
//Xử lý trường hợp thanh toán thành công
WritableMap params = Arguments.createMap();
params.putString("transactionId", transactionId);
params.putString("transToken", transToken);
params.putString("appTransID", appTransID);
params.putString("returnCode", PAYMENTSUCCESS);
sendEvent(mReactContext, "EventPayZalo", params);
}
@Override
public void onPaymentCanceled(String transToken, String appTransID) {
//Xử lý trường hợp người dùng từ chối thanh toán
WritableMap params = Arguments.createMap();
params.putString("returnCode", PAYMENTCANCELED);
params.putString("zpTranstoken", transToken);
params.putString("appTransID", appTransID);
sendEvent(mReactContext, "EventPayZalo", params);
}
@Override
public void onPaymentError(ZalopayError ZalopayError, String transToken, String appTransID) {
//Xử lý trường hợp thanh toán lỗi
WritableMap params = Arguments.createMap();
params.putString("returnCode", PAYMENTFAILED);
params.putString("zpTranstoken", transToken);
params.putString("appTransID", appTransID);
sendEvent(mReactContext, "EventPayZalo", params);
}
};
- Tại phía React Native, đăng ký sự kiện được khai báo ở trên và xử lý phù hợp:
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){
//Handle success case
} else{
//Handle other cases
}
}
);
}
componentWillUnmount() {
this.subscription.remove();
}
Bước 4. Xử lý trường hợp người dùng chưa cài đặt Zalopay
Chúng tôi xử lý tương tự như Bước 4 của ứng dụng iOS và Android ở trên
Ứng dụng Flutter trên nền tảng iOS và Android
Bước 1. Thêm và khởi tạo Zalopay SDK
Để tích hợp và cấu hình ZPDK, chúng ta thực hiện tương tự như Bước 1 của ứng dụng iOS và Android ở trên
Bước 2. Gọi chức năng Thanh toán
- Ở phía iOS, đăng ký Flutter Method Channel trong hàm
application
mà được sử dụng để khởi tạo ZPDK iOS:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// ...
let controller = window.rootViewController as? FlutterViewController
let nativeChannel = FlutterMethodChannel(name: "flutter.native/channelPayOrder",
binaryMessenger: controller!.binaryMessenger)
nativeChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
guard call.method == MethodNames.methodPayOrder else {
result(FlutterMethodNotImplemented)
return
}
let args = call.arguments as? [String: Any]
let _zptoken = args?["zptoken"] as? String
ZalopaySDK.sharedInstance()?.payOrder(_zptoken)
result("Processing...")
})
}
- Ở phía Android, dùng lớp
MainActivity
kế thừa lớpFlutterActivity
. Override phương thứcconfigureFlutterEngine
để đăng ký Flutter method channel:
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "flutter.native/channelPayOrder")
.setMethodCallHandler { call, result ->
if (call.method == "payOrder"){
val token = call.argument<String>("zptoken")
ZalopaySDK.getInstance().payOrder(this@MainActivity, token !!, "merchant-deeplink://app",object: PayOrderListener {
// ...
})
} else {
result.success("Method Not Implemented")
}
}
}
}
- Ở phía Flutter, tạo Flutter MethodChannel. Sau khi gọi CreateOrder API thành công và nhận được
zpTransToken
, hãy gọi hàm thanh toán vớizpTransToken
đó:
static const MethodChannel platform = MethodChannel('flutter.native/channelPayOrder');
final String result = await platform.invokeMethod('payOrder', {"zptoken": zpToken});
Bước 3. Xử lý kết quả trả về
- Ở phía iOS, cấu hình phần xử lý Flutter Event channel. Sau đó, gửi kết quả thanh toán tới Flutter bằng cách triển khai các chức năng liên quan đến từng mã kết quả:
// Khởi tạo FlutterEventChannel để xử lý các sự kiện
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// ...
let eventPayOrderChannel = FlutterEventChannel(name: "flutter.native/eventPayOrder",
binaryMessenger: controller!.binaryMessenger)
eventPayOrderChannel.setStreamHandler(self)
}
// Gửi sự kiện tới Flutter qua FlutterEventSink
private var eventSink: FlutterEventSink?
func paymentDidSucceeded(_ transactionId: String!, zpTranstoken: String!, appTransId: String!) {
guard let eventSink = eventSink else {
return
}
eventSink(["errorCode": 1, "zpTranstoken": zpTranstoken, "transactionId": transactionId, "appTransId": appTransId])
}
func paymentDidCanceled(_ zpTranstoken: String!, appTransId: String!) {
guard let eventSink = eventSink else {
return
}
eventSink(["errorCode": 4, "zpTranstoken": zpTranstoken, "appTransId": appTransId])
}
func paymentDidError(_ errorCode: ZPPaymentErrorCode, zpTranstoken: String!, appTransId: String!) {
guard let eventSink = eventSink else {
return
}
eventSink(["errorCode": errorCode, "zpTranstoken": zpTranstoken, "appTransId": appTransId])
}
- Ở phía Android, cấu hình xử lý Flutter Event channel. Sau đó, gửi kết quả thanh toán tới Flutter bằng cách triển khai các chức năng liên quan đến từng mã kết quả:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
// ...
EventChannel(flutterEngine.dartExecutor.binaryMessenger, "flutter.native/eventPayOrder")
.setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink) {
_eventSink = eventSink;
}
})
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelPayOrder)
.setMethodCallHandler { call, result ->
if (call.method == "payOrder") {
val tagSuccess = "[OnPaymentSucceeded]"
val tagError = "[onPaymentError]"
val tagCanel = "[onPaymentCancel]"
val token = call.argument<String>("zptoken")
ZalopaySDK.getInstance().payOrder(this@MainActivity, token !!, "merchant-deeplink://app",object: PayOrderListener {
override fun onPaymentCanceled(zpTransToken: String?, appTransID: String?) {
_eventSink?.success(mapOf(
"errorCode" to PAYMENTCANCELED, // code = 4
"zpTranstoken" to zpTransToken,
"appTransId" to appTransID,
))
}
override fun onPaymentError(ZalopayErrorCode: ZalopayError?, zpTransToken: String?, appTransID: String?) {
_eventSink?.success(mapOf(
"errorCode" to PAYMENTERROR,
"zpTranstoken" to zpTransToken,
"appTransId" to appTransID,
))
}
override fun onPaymentSucceeded(transactionId: String, transToken: String, appTransID: String?) {
_eventSink?.success(mapOf(
"errorCode" to PAYMENTCOMPLETE, // code = 1
"zpTranstoken" to transToken,
"transactionId" to transactionId,
"appTransId" to appTransID,
))
}
})
} else {
result.success("Method Not Implemented")
}
}
}
- Ở phía Flutter, đăng ký kênh sự kiện được tạo ở phía iOS và Android, sau đó xử lý các sự kiện tương ứng với từng mã kết quả:
const EventChannel eventChannel = EventChannel('flutter.native/eventPayOrder');
Future<void> subscribe() async {
eventChannel.receiveBroadcastStream().listen(
(data) {
var res = Map<String, dynamic>.from(data);
String message;
if (res["errorCode"] == 1) {
message = "Thanh toán thành công";
} else if (res["errorCode"] == 4) {
message = "User hủy thanh toán";
} else {
message = "Giao dịch thất bại";
}
resultCallback(message);
},
onError: (error) {
resultCallback(error.toString());
},
);
}
Bước 4. Xử lý trường hợp người dùng chưa cài đặt Zalopay
Chúng tôi xử lý tương tự như Bước 4 của ứng dụng iOS và Android ở trên
Kiểu dữ liệu kết quả trả về của ZPDK
Trường hợp thanh toán thành công - Xử lý hàm paymentDidSucceeded()
Tên dữ liệu | Kiểu dữ liệu | Mô tả |
---|---|---|
transactionId | string | Id của giao dịch hiện tại |
zpTranstoken | string | Token của đơn hàng hiện tại |
appTransId | string | app_trans_id của giao dịch hiện tại |
Trường hợp thanh toán bị hủy - Xử lý hàm paymentDidCanceled()
Tên dữ liệu | Kiểu dữ liệu | Mô tả |
---|---|---|
zpTranstoken | string | Token của đơn hàng hiện tại |
appTransId | string | app_trans_id của giao dịch hiện tại |
Trường hợp người dùng hủy thanh toán - Xử lý hàm paymentDidError()
Tên dữ liệu | Kiểu dữ liệu | Mô tả |
---|---|---|
errorCode | string | Mã lỗi trả về, là một trong các giá trị: UNKNOWN, PAYMENT_APP_NOT_FOUND, INPUT_IS_INVALID, EMPTY_RESULT, FAIL |
zpTranstoken | string | Token của đơn hàng hiện tại |
appTransId | string | app_trans_id của giao dịch hiện tại |
Xem thêm
Tiếp theo
- Đã cài đặt xong? Hãy kiểm thử kết quả tích hợp.