Bước 3 - Nhận kết quả trên Mini App
Khi người dùng hoàn thành quá trình thanh toán, Checkout SDK sẽ điều hướng người dùng về lại Mini App.
Tại Mini App, đối tác cần xây dựng cơ chế để lắng nghe sự kiện PaymentDone từ Checkout SDK.
Sau đó kiểm tra kết quả thanh toán bằng checkTransaction để điều hướng người dùng cho các trường hợp cụ thể như sau:
1- Thanh toán thành công0- Giao dịch đang được thực hiện hoặc chờ xử lý-1- Thanh toán thất bại-2- Người dùng không chọn phương thức thanh toán và thoát Checkout SDK
import { useEffect, useCallback } from "react";
import { events, EventName, CheckoutSDK, TransactionResult } from "zmp-sdk/apis";
import { useSnackbar, useNavigate } from "zmp-ui";
export function CheckoutPage() {
const { openSnackbar } = useSnackbar();
const navigate = useNavigate();
function handleClickCheckout() {
// Tạo đơn hàng trên hệ thống của bạn
const order = await yourService.initOrder()
// Khởi tạo đơn hàng & mở trang thanh toán với Checkout SDK
await CheckoutSDK.createOrder(order)
}
const handlePaymentDone = useCallback((data) => {
try {
// Sử dụng data trả về từ sự kiện PaymentDone để kiểm tra kết quả thanh toán
const result = await CheckoutSDK.checkTransaction({ data })
switch (result.resultCode) {
case 1:
// Giao dịch thành công
navigate("/result?status=success")
break;
case 0:
// Giao dịch đang chờ xử lý
navigate("/result?status=pending")
break;
case -1:
// Giao dịch không thành công
navigate("/result?status=fail")
break;
case -2:
// Người dùng không chọn phương thức thanh toán và thoát Checkout SDK
openSnackbar({
type: "info",
text: "Vui lòng chọn phương thức thanh toán",
});
break;
default:
openSnackbar({
type: "error",
text: result.msg || "Đã xảy ra lỗi, vui lòng thử lại sau",
});
// Giao dịch không hợp lệ, kiểm tra `result.err` & `result.msg` để biết thêm thông tin
console.error(result.msg);
break;
}
} catch (error) {
openSnackbar({
type: "error",
text: "Đã xảy ra lỗi, vui lòng thử lại sau",
});
}
}, [openSnackbar, navigate]);
useEffect(() => {
events.on(EventName.PaymentDone, handlePaymentDone);
return () => {
events.off(EventName.PaymentDone, handlePaymentDone);
};
}, [handlePaymentDone]);
return (
<div>
<Button onClick={handleClickCheckout}>Thanh toán</Button>
);
}
Tiếp theo
Bước này chỉ giúp bạn điều hướng và hiển thị kết quả cho người dùng ở trên giao diện Mini App.
Để hoàn tất quy trình thanh toán và đảm bảo thông tin được cập nhật chính xác, bạn cần Xử lý kết quả thanh toán ở phía Server.
Checkout SDK sẽ gửi dữ liệu kết quả thông qua Webhook đến Callback URL mà bạn đã cấu hình trước đó.
Dành cho ZMP SDK phiên bản dưới 2.45.0
Đối với các phiên bản ZMP SDK dưới 2.45.0, hoặc khi không lắng nghe sự kiện PaymentDone, bạn cần xử lý riêng biệt cho từng phương thức thanh toán như sau.
Đối với các phương thức ZaloPay, Momo, VNPay, Payme, COD
Đối tác cần xử lý lắng nghe những sự kiện sau:
- Sự kiện OpenApp
- Sự kiện PaymentClose
Sự kiện OpenApp
import { events, EventName } from "zmp-sdk/apis"; // Require: zmp-sdk >= 2.25.3
import { CheckoutSDK } from "zmp-sdk/apis";
events.on(EventName.OpenApp, (data) => {
const path = data?.path;
// kiểm tra path trả về từ giao dịch thanh toán
// RedirectPath: đã cung cấp tại trang khai báo phương thức
if (path.includes(RedirectPath)) {
// Nếu đúng với RedirectPath đã cũng cấp, thực hiện redirect tới path được nhận
// Kiểm tra giao dịch bằng API checkTransaction nếu muốn
CheckoutSDK.checkTransaction({
data: path,
success: (rs) => {
// Kết quả giao dịch khi gọi api thành công
const { orderId, resultCode, msg, transTime, createdAt } = rs;
},
fail: (err) => {
// Kết quả giao dịch khi gọi api thất bại
console.log(err);
},
});
}
});
Sự kiện PaymentClose
Sau khi đã chuyển qua trang thanh toán của đối tác thanh toán (như ZaloPay, Momo, VNPay,...), trong trường hợp người dùng không hoàn tất quá trình thanh toán và đóng trang thanh toán, Mini App sẽ gửi sự kiện PaymentClose về cho ứng dụng của bạn để xử lý.
import { events, EventName } from "zmp-sdk/apis"; // Require: zmp-sdk >= 2.36.0
import { CheckoutSDK } from "zmp-sdk/apis";
events.on(EventName.PaymentClose, (data) => {
const resultCode = data?.resultCode;
// kiểm tra resultCode trả về từ sự kiện PaymentClose
// 0: Đang xử lý
// 1: Thành công
// -1: Thất bại
//Nếu trạng thái đang thực hiện, kiểm tra giao dịch bằng API checkTransaction nếu muốn
if (resultCode === 0) {
CheckoutSDK.checkTransaction({
data: { zmpOrderId: data?.zmpOrderId },
success: (rs) => {
// Kết qu ả giao dịch khi gọi api thành công
const { orderId, resultCode, msg, transTime, createdAt } = rs;
},
fail: (err) => {
// Kết quả giao dịch khi gọi api thất bại
console.log(err);
},
});
} else {
// Xử lý kết quả thanh toán thành công hoặc thất bại
const { orderId, resultCode, msg, transTime, createdAt } = data;
}
});
Đối với phương thức chuyển khoản ngân hàng
Đối với phương thức chuyển khoản ngân hàng, lắng nghe sự kiện OnDataCallback và kiểm tra kết quả từ hệ thống thanh toán để xử lý.
| Property | Type | Description |
|---|---|---|
| eventType | String | Nhận giá trị "PAY_BY_BANK", thể hiện loại thanh toán bằng phương thức riêng |
| data | Object | { appTransId: mã giao dịch thanh toán} |
import { events, EventName } from "zmp-sdk/apis"; // Require: zmp-sdk >= 2.25.3
import { CheckoutSDK } from "zmp-sdk/apis";
events.on(EventName.OnDataCallback, (resp) => {
const { eventType, data } = resp;
if (eventType === "PAY_BY_BANK") {
if (data.appTransID) {
// gọi api checkTransaction để lấy thông tin giao dịch
CheckoutSDK.checkTransaction({
data,
success: (rs) => {
// Kết quả giao dịch khi gọi api thành công
const { id, resultCode, msg, transTime, createdAt } = rs;
},
fail: (err) => {
// Kết quả giao dịch khi gọi api thất bại
console.log(err);
},
});
}
}
});
Đối với phương thức thanh toán riêng
Đối với riêng phương thức thanh toán riêng, lắng nghe sự kiện OnDataCallback và kiểm tra kết quả từ hệ thống thanh toán để xử lý. Dữ liệu gửi thông qua sự kiện OnDataCallback như sau:
| Property | Type | Description |
|---|---|---|
| eventType | String | Nhận giá trị "PAY_BY_CUSTOM_METHOD", thể hiện loại thanh toán bằng phương thức riêng |
| data | Object | { method: Mã phương thức thanh toán, orderId: mã của đơn hàng thanh toán } |
Sau khi nhận dữ liệu từ sự kiện, đối tác chủ động thực hiện thanh toán với phương thức mà đối tác đã thiết lập.
Sample Code
import { events, EventName } from "zmp-sdk/apis"; // Require: zmp-sdk >= 2.25.3
import { CheckoutSDK } from "zmp-sdk/apis";
events.on(EventName.OnDataCallback, (resp) => {
const { eventType, data } = resp;
if (eventType === "PAY_BY_CUSTOM_METHOD") {
// method: mã phương thức thanh toán
// orderId: mã của đơn hàng thanh toán
const { method, orderId } = data;
// Xử lý thanh toán với phương thức riêng
}
});