Chọn mô hình tích hợp ZaloPay phù hợp
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.
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
<key>LSApplicationQueriesSchemes</key>
<array>
<string>zalo</string>
<string>zalopay</string>
<string>zalopay.guide.v2</string>
</array>
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 để 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
}
Để 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'))
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);
}
//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
}
})
getPackages()
, thêm new PayZaloBridge()
bên trong hàm Array.asList(...)
như sau:
@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('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);
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
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 |