Chương 12. Tích hợp dịch vụ bên ngoài
Back To BlogsChương 12. Tích hợp dịch vụ bên ngoài
📚 Mục lục sáchSản phẩm của bạn hiếm khi hoạt động một mình. Bạn sẽ cần cho khách đăng nhập bằng Google hoặc Facebook, tự động gửi email, nhận thanh toán qua cổng thanh toán, hoặc giao hàng và theo dõi vận đơn. EzyPlatform kết nối sẵn từng mảng việc này qua một plugin riêng — EzyLogin, EzyMail, EzyPayment, EzyDelivery — chương này giới thiệu từng plugin và nguyên tắc an toàn chung khi dùng chúng.
Đăng nhập bằng Google & Facebook với EzyLogin
Cài đặt thêm plugin EzyLogin (xem lại hướng dẫn cài đặt plugin cho EzyPlatform nếu cần) để cho phép khách đăng nhập bằng tài khoản Google hoặc Facebook thay vì phải đăng ký tài khoản mới — giúp khách vào thẳng trang mà không mất công điền form.
Toàn bộ quá trình diễn ra qua một vòng "chuyển hướng qua lại" giữa EzyPlatform và Google/Facebook, khách hàng không cần biết Client ID hay Redirect URI là gì — những thứ đó chỉ là phần bạn khai báo một lần lúc cấu hình:
flowchart LR
A["Khách bấm nút<br/>Đăng nhập bằng Google/Facebook"] --> B["EzyPlatform chuyển hướng<br/>sang trang đăng nhập của Google/Facebook"]
B --> C{"Khách đồng ý<br/>chia sẻ thông tin?"}
C -- "Đồng ý" --> D["Google/Facebook gọi ngược về<br/>Redirect URI đã khai báo"]
D --> E["EzyLogin xác thực,<br/>tạo hoặc cập nhật tài khoản"]
E --> F["Khách đăng nhập thành công"]
C -- "Từ chối" --> G["Quay lại trang đăng nhập,<br/>không tạo tài khoản mới"]
classDef action fill:#3b82f6,stroke:#1d4ed8,color:#ffffff;
classDef decision fill:#f59e0b,stroke:#b45309,color:#ffffff;
classDef success fill:#10b981,stroke:#047857,color:#ffffff;
classDef stop fill:#ef4444,stroke:#b91c1c,color:#ffffff;
class A,B,D,E action;
class C decision;
class F success;
class G stop;
linkStyle default stroke:#94a3b8,stroke-width:1.5px;
Với mỗi nhà cung cấp, bạn đăng ký một ứng dụng trên Google Cloud Console hoặc Facebook for Developers để lấy Client ID (hay App ID) và Client Secret, khai vào trang cài đặt EzyLogin trên trang quản trị. Khi đăng ký ứng dụng, nền tảng sẽ hỏi bạn Redirect URI (địa chỉ họ gọi ngược về sau khi khách đăng nhập xong) — luôn khai đúng theo mẫu {tên miền của bạn}/ezylogin/callback/{tên nhà cung cấp}:
| Nhà cung cấp | Redirect URI cần khai báo | Nơi lấy Client ID & Secret |
|---|---|---|
/ezylogin/callback/google |
Google Cloud Console | |
/ezylogin/callback/facebook |
Facebook for Developers |
Đây là hai nhà cung cấp EzyLogin hỗ trợ sẵn hiện nay. Sai một ký tự trong Redirect URI là nguyên nhân phổ biến nhất khiến nút "Đăng nhập bằng Google/Facebook" báo lỗi — nếu gặp lỗi này, việc đầu tiên nên kiểm tra là đối chiếu lại đúng địa chỉ đã khai trên Google/Facebook với địa chỉ website thật của bạn.
Gửi email tự động với EzyMail
EzyMail là plugin đứng sau mọi email tự động của EzyPlatform — kể cả các mẫu thư đơn hàng đã nhắc ở Chương 11. Chương trước nói về nội dung email (mẫu thư), còn phần này nói về đường truyền — email được gửi đi bằng cách nào. EzyMail hỗ trợ sáu phương thức gửi, bạn cấu hình tại trang cài đặt EzyMail trên trang quản trị và chỉ cần bật một phương thức đang thực sự dùng:
| Phương thức | Thông tin cần cấu hình |
|---|---|
| SMTP | Host, cổng, tài khoản, mật khẩu, bật xác thực, bật STARTTLS, email & tên người gửi mặc định. |
| Mailgun | Domain, API Key, endpoint, email & tên người gửi mặc định. |
| Amazon SES | Access Key ID, Secret Access Key, vùng (region), endpoint, email & tên người gửi mặc định. |
| Mailchimp (Transactional) | API Key, endpoint, email & tên người gửi mặc định. |
| Gmail API | Client ID, Client Secret (ứng dụng OAuth trên Google Cloud Console) — bấm nút kết nối trên trang cài đặt để đăng nhập Google một lần, EzyMail tự lưu lại và tự làm mới token sau đó. |
| Microsoft Graph API | Tenant ID, Client ID, Client Secret (ứng dụng đăng ký trên Microsoft Entra/Azure AD) — không cần đăng nhập tương tác, EzyMail tự lấy token bằng chính ứng dụng. |
Bốn phương thức đầu (SMTP, Mailgun, Amazon SES, Mailchimp) chỉ cần một khóa API tĩnh là gửi được ngay; riêng Gmail API và Microsoft Graph API cần một bước lấy token trước khi gửi, mỗi bên theo một cách khác nhau:
flowchart TD
A["Có email cần gửi<br/>(mẫu thư đơn hàng, marketing...)"] --> B["EzyMail đọc phương thức<br/>đang bật trong cài đặt"]
B --> C{"Phương thức nào?"}
C -- "SMTP / Mailgun /<br/>Amazon SES / Mailchimp" --> D["Gọi thẳng bằng<br/>khóa API đã khai"]
C -- "Gmail API" --> E["Dùng Refresh Token<br/>(lấy một lần qua màn hình kết nối Google)"]
E --> F["Tự làm mới Access Token<br/>khi sắp hết hạn"]
C -- "Microsoft Graph API" --> G["Tự lấy Access Token mới<br/>bằng Client ID/Secret, không cần đăng nhập"]
D --> H["Gửi email"]
F --> H
G --> H
classDef start fill:#3b82f6,stroke:#1d4ed8,color:#ffffff;
classDef decision fill:#f59e0b,stroke:#b45309,color:#ffffff;
classDef oauth fill:#8b5cf6,stroke:#6d28d9,color:#ffffff;
classDef success fill:#10b981,stroke:#047857,color:#ffffff;
class A,B,D start;
class C decision;
class E,F,G oauth;
class H success;
linkStyle default stroke:#94a3b8,stroke-width:1.5px;
Với Gmail API, khi bấm nút kết nối, EzyMail chuyển bạn sang trang đăng nhập Google rồi gọi ngược về đúng theo mẫu Redirect URI của EzyLogin ở trên: {tên miền của bạn}/ezymail/settings/mail-delivery-services/gmail-api/oauth2/callback — bạn cần khai đúng địa chỉ này khi đăng ký ứng dụng OAuth trên Google Cloud Console, tương tự bước làm với EzyLogin.
Cửa hàng bánh của tôi hiện gửi khoảng 50 email đơn hàng mỗi ngày, chưa có sẵn tài khoản email doanh nghiệp. Hãy so sánh giúp tôi ưu nhược điểm của SMTP, Mailgun và Amazon SES trong trường hợp này, và gợi ý phương thức nào phù hợp nhất để tôi bắt đầu.
Nhận thanh toán trực tuyến với EzyPayment
Cài đặt plugin EzyPayment để nhận thanh toán online. Năm cổng được hỗ trợ chia làm hai nhóm, khác nhau ở chỗ khách hàng thanh toán ở đâu và EzyPlatform biết tiền đã về bằng cách nào:
| Nhóm | Cổng | Trang thanh toán | Cách EzyPlatform biết đã thanh toán |
|---|---|---|---|
| Chuyển hướng sang cổng | VNPay | Trang do VNPay quản lý (thẻ ATM, thẻ quốc tế, QR) | VNPay gọi về /payment kèm chữ ký HMAC-SHA512 |
| PayPal | Trang do PayPal quản lý | Xác nhận qua API PayPal khi khách hoàn tất | |
| Chuyển khoản có xác nhận tự động | PayFS | /checkout/payfs (EzyPlatform tự hiển thị) |
Webhook PUT /api/v1/payfs/orders/{orderId}/bank-transferred kèm checksum |
| Pay2S | /checkout/pay2s |
Webhook PUT /api/v1/pay2s/orders/{orderId}/bank-transferred kèm checksum |
|
| SePay | /checkout/sepay |
Webhook PUT /api/v1/sepay/orders/{orderId}/bank-transferred kèm checksum |
Với nhóm "chuyển hướng sang cổng" (VNPay, PayPal), khách rời khỏi website của bạn để thanh toán, nên bạn không bao giờ chạm vào thông tin thẻ của khách. Với nhóm "chuyển khoản" (PayFS, Pay2S, SePay), EzyPlatform tự hiển thị trang riêng với thông tin chuyển khoản/mã QR ngân hàng — khách chuyển khoản thủ công, rồi đối tác đứng sau các cổng này tự gọi webhook báo "đã nhận tiền" khi phát hiện giao dịch khớp.
flowchart TD
A["Khách chọn cổng thanh toán<br/>lúc đặt hàng"] --> B{"Loại cổng?"}
B -- "VNPay / PayPal" --> C["Chuyển hướng khách<br/>sang trang do cổng quản lý"]
C --> D["Khách thanh toán trên trang của cổng"]
D --> E["Cổng gọi về /payment<br/>kèm chữ ký xác thực"]
B -- "PayFS / Pay2S / SePay" --> F["Hiển thị trang chuyển khoản/QR<br/>ngay trên website của bạn"]
F --> G["Khách chuyển khoản thủ công"]
G --> H["Đối tác gọi webhook<br/>.../bank-transferred kèm checksum"]
E --> I{"Chữ ký/checksum hợp lệ?"}
H --> I
I -- "Hợp lệ" --> J["Cập nhật đơn hàng: Đã thanh toán"]
I -- "Không hợp lệ" --> K["Từ chối, giữ nguyên trạng thái đơn"]
classDef action fill:#3b82f6,stroke:#1d4ed8,color:#ffffff;
classDef decision fill:#f59e0b,stroke:#b45309,color:#ffffff;
classDef success fill:#10b981,stroke:#047857,color:#ffffff;
classDef stop fill:#ef4444,stroke:#b91c1c,color:#ffffff;
class A,C,D,E,F,G,H action;
class B,I decision;
class J success;
class K stop;
linkStyle default stroke:#94a3b8,stroke-width:1.5px;
Việc xác thực callback — tính lại chữ ký/checksum, so khớp, chấp nhận hay từ chối — đều do EzyPayment xử lý sẵn cho cả năm cổng; bạn chỉ cần khai đúng Client Key/Secret Key mà từng cổng cấp cho bạn vào trang cài đặt EzyPayment trên trang quản trị.
Nguyên tắc an toàn: không bao giờ tự lưu trữ thông tin thẻ ngân hàng của khách hàng trên hệ thống của bạn. EzyPayment không có bất kỳ chỗ nào để lưu số thẻ hay mã CVV — toàn bộ luồng thanh toán đều đưa khách sang trang do cổng thanh toán host, hoặc chỉ hiển thị thông tin chuyển khoản công khai (số tài khoản, nội dung chuyển khoản) chứ không phải dữ liệu thẻ; vai trò của EzyPlatform chỉ là khởi tạo yêu cầu và xác minh kết quả trả về.
Cửa hàng bánh của tôi chủ yếu bán cho khách trong nước, chưa có tài khoản doanh nghiệp ở cổng thanh toán nào. Hãy so sánh giúp tôi giữa việc dùng VNPay (khách quẹt thẻ/QR trên trang VNPay) và Pay2S/SePay (khách chuyển khoản, hệ thống tự đối soát) — chi phí, thời gian thiết lập, và trải nghiệm khách hàng bên nào tiện hơn để tôi bắt đầu.
Giao hàng và theo dõi vận đơn với EzyDelivery
Nếu bạn bán hàng vật lý (như cửa hàng bánh xuyên suốt cuốn sách này), cài thêm plugin EzyDelivery để tạo vận đơn và theo dõi trạng thái giao hàng tự động, thay vì gọi điện hỏi đơn vị vận chuyển từng đơn. Hai đơn vị được hỗ trợ đầy đủ hiện nay là Giao Hàng Tiết Kiệm (GHTK) và Viettel Post:
| Đơn vị vận chuyển | Thông tin xác thực cần khai |
|---|---|
| Giao Hàng Tiết Kiệm (GHTK) | Một mã Token duy nhất do GHTK cấp cho tài khoản đối tác của bạn. |
| Viettel Post | Tài khoản (username/password) đã đăng ký với Viettel Post. |
Bạn khai những thông tin này tại trang cài đặt EzyDelivery trên trang quản trị. Sau khi tạo vận đơn, đơn vị vận chuyển sẽ tự động gọi webhook về EzyPlatform mỗi khi trạng thái đơn thay đổi, EzyDelivery cập nhật lại trạng thái tương ứng mà bạn không cần thao tác thủ công:
flowchart LR
A["Tạo vận đơn<br/>từ đơn hàng đã thanh toán"] --> B["Đã tiếp nhận<br/>(REQUEST_RECEIVED)"]
B --> C["Đã lấy hàng<br/>(PICKED_UP)"]
C --> D["Đang vận chuyển<br/>(IN_TRANSIT)"]
D --> E["Giao thành công<br/>(DELIVERED)"]
D -- "Giao không thành công" --> F["Không giao được<br/>(UNABLE_TO_DELIVER)"]
F -- "Giao lại" --> D
F -- "Không thể giao tiếp" --> G["Hoàn về người gửi<br/>(RETURNING_TO_SENDER)"]
classDef progress fill:#3b82f6,stroke:#1d4ed8,color:#ffffff;
classDef success fill:#10b981,stroke:#047857,color:#ffffff;
classDef fail fill:#ef4444,stroke:#b91c1c,color:#ffffff;
class A,B,C,D progress;
class E success;
class F,G fail;
linkStyle default stroke:#94a3b8,stroke-width:1.5px;
Đây là một luồng rút gọn — mỗi đơn vị vận chuyển thực tế trả về nhiều trạng thái chi tiết hơn (ví dụ GHTK có cả trạng thái "đang đối soát tiền COD", "hoãn lấy hàng"...), EzyDelivery quy đổi tất cả về một bộ trạng thái chung để bạn không cần tự xử lý sự khác biệt giữa các đơn vị. Khách hàng cũng có thể tự tra cứu vận đơn của mình ngay trên website (trang tra cứu vận đơn công khai) mà không cần đăng nhập.
Hãy viết giúp tôi phần chú thích ngắn gọn, thân thiện cho từng trạng thái vận đơn trên trang tra cứu đơn hàng của cửa hàng bánh: đã tiếp nhận, đã lấy hàng, đang vận chuyển, giao thành công, không giao được, hoàn về người gửi — để khách không quen thuật ngữ logistics vẫn hiểu đơn của mình đang ở đâu.
Webhook: cầu nối thông báo giữa các hệ thống
Webhook là cách một hệ thống bên ngoài tự động gửi thông báo về EzyPlatform ngay khi có sự kiện xảy ra, thay vì để EzyPlatform phải liên tục hỏi lại "có gì mới chưa?". Cả EzyPayment (khi khách thanh toán xong) lẫn EzyDelivery (khi trạng thái vận đơn thay đổi) đều hoạt động theo cơ chế này. Dù mỗi plugin gọi tên khác nhau, bản chất luồng xử lý bên dưới đều giống hệt nhau:
flowchart LR
A["Sự kiện xảy ra ở hệ thống ngoài<br/>(khách thanh toán, vận đơn đổi trạng thái...)"] --> B["Hệ thống ngoài gọi<br/>đến URL webhook đã đăng ký sẵn"]
B --> C["EzyPlatform nhận request<br/>tại endpoint tương ứng"]
C --> D{"Chữ ký/checksum<br/>hợp lệ?"}
D -- "Hợp lệ" --> E["Cập nhật dữ liệu tương ứng<br/>(đơn hàng, vận đơn...)"]
D -- "Không hợp lệ" --> F["Từ chối request,<br/>giữ nguyên dữ liệu cũ"]
classDef action fill:#3b82f6,stroke:#1d4ed8,color:#ffffff;
classDef decision fill:#f59e0b,stroke:#b45309,color:#ffffff;
classDef success fill:#10b981,stroke:#047857,color:#ffffff;
classDef fail fill:#ef4444,stroke:#b91c1c,color:#ffffff;
class A,B,C action;
class D decision;
class E success;
class F fail;
linkStyle default stroke:#94a3b8,stroke-width:1.5px;
Vì địa chỉ webhook là một URL công khai, ai cũng có thể gửi request giả tới đó để đánh lừa hệ thống — ví dụ giả vờ báo "đã thanh toán" cho một đơn hàng chưa hề được trả tiền. Đây là lý do mọi webhook trong EzyPayment và EzyDelivery đều đi kèm một bước xác minh chữ ký hoặc mã checksum, tính từ khóa bí mật chỉ bạn và đối tác biết, trước khi tin bất kỳ dữ liệu nào từ request gọi đến. Riêng webhook của EzyDelivery còn có thêm một lớp kiểm tra nữa: sau khi khóa bí mật hợp lệ, hệ thống đối chiếu tiếp mã vận đơn (tracking ID) trong request với mã đã lưu cho đúng đơn hàng đó — để một request hợp lệ về mặt khóa bí mật cũng không thể vô tình (hay cố ý) cập nhật nhầm sang đơn hàng khác. Bạn không cần tự viết logic xác thực này — chỉ cần khai đúng khóa bí mật ở bước cài đặt, phần còn lại EzyPlatform đã lo.
| Plugin | Sự kiện | Endpoint nhận webhook | Cách xác minh |
|---|---|---|---|
| EzyPayment — VNPay | Khách thanh toán hoàn tất | GET /payment |
Chữ ký HMAC-SHA512 |
| EzyPayment — PayFS / Pay2S / SePay | Đối tác xác nhận đã nhận chuyển khoản | PUT /api/v1/{tên cổng}/orders/{orderId}/bank-transferred |
Checksum |
| EzyDelivery — GHTK / Viettel Post | Trạng thái vận đơn thay đổi | POST /delivery/callback/{mã đơn vị vận chuyển} |
Khóa bí mật riêng từng đơn vị + đối chiếu mã vận đơn |
Những địa chỉ này chính là "Redirect URI" của EzyLogin nhìn từ một góc khác: cả hai đều là một URL bạn đăng ký sẵn để hệ thống bên ngoài gọi ngược về, chỉ khác ở chỗ Redirect URI phục vụ việc đăng nhập còn webhook phục vụ việc thông báo sự kiện. Khi tích hợp thêm một dịch vụ mới ngoài danh sách này, hãy tìm đúng endpoint tương ứng trong tài liệu của EzyPlatform và luôn kiểm tra bước xác minh chữ ký/checksum đã được bật, trước khi đưa vào vận hành thật.
Hãy giải thích ngắn gọn, dễ hiểu cho một người không chuyên kỹ thuật: tại sao webhook xác nhận thanh toán cần chữ ký/checksum, và điều gì sẽ xảy ra nếu bỏ qua bước xác minh này.
| Plugin | Dùng để làm gì | Nhà cung cấp hỗ trợ đầy đủ |
|---|---|---|
| EzyLogin | Cho khách đăng nhập bằng tài khoản mạng xã hội có sẵn | Google, Facebook |
| EzyMail | Gửi email tự động (đường truyền, không phải nội dung) | SMTP, Mailgun, Amazon SES, Mailchimp, Gmail API, Microsoft Graph API |
| EzyPayment | Nhận thanh toán trực tuyến an toàn | VNPay, PayPal (và PayFS, Pay2S, SePay dạng chuyển khoản) |
| EzyDelivery | Tạo vận đơn, theo dõi và cập nhật trạng thái giao hàng tự động | GHTK, Viettel Post |
📌 Tóm tắt chương
- EzyLogin cho khách đăng nhập bằng Google/Facebook — cần Client ID/Secret và khai đúng Redirect URI dạng
/ezylogin/callback/{tên nhà cung cấp}. - EzyMail lo phần đường truyền gửi email — SMTP, Mailgun, Amazon SES, Mailchimp, Gmail API hoặc Microsoft Graph API — tách biệt với nội dung mẫu thư đã học ở Chương 11.
- EzyPayment xử lý thanh toán qua VNPay, PayPal và các cổng chuyển khoản — không bao giờ tự lưu thông tin thẻ ngân hàng của khách.
- EzyDelivery tạo vận đơn và tự cập nhật trạng thái giao hàng qua GHTK, Viettel Post.
- Webhook là cơ chế chung giúp các dịch vụ bên ngoài tự thông báo cho EzyPlatform; luôn có bước xác minh chữ ký/checksum để chặn request giả mạo.
Young Monkeys - Founder