Kết nối store Shopify để nhận order tự động
Mỗi store Shopify cần một app tạo trên Shopify Dev Dashboard (dev.shopify.com) và cài vào store đó. Web chỉ cần 3 thông tin: Shop domain, Client ID, Client secret. Code tự xin Access Token (hạn 24h) bằng Client Credentials, tự làm mới trước khi hết hạn, và dùng chính Client secret để kiểm tra chữ ký webhook. Làm theo 3 bước dưới đây cho mỗi store mới.
Bước 1 — Tạo store trên web này
- Vào Settings → Create New Store.
- Nhập tên store (ví dụ
leafela), chọn Platform = Shopify → Create. - Chọn store vừa tạo ở ô chọn store. Card Shopify sẽ hiện ra.
Bước 2 — Tạo app trên Dev Dashboard và cài vào store
- Vào dev.shopify.com → Dashboard → Create app (có thể tạo từ Dashboard, không cần CLI). Đặt tên ví dụ
NCE Fulfillment - leafela. - Trong app → Configuration (hoặc Settings → Access scopes): khai báo quyền Admin API:
Bắt buộc:
read_orders,read_products
Bắt buộc để đẩy tracking lên Shopify (fulfill đơn):read_merchant_managed_fulfillment_orders,write_merchant_managed_fulfillment_orders
Nên thêm:read_customers(lấy email/tên khách),read_all_orders(sync đơn cũ hơn 60 ngày; Shopify có thể yêu cầu duyệt),read_third_party_fulfillment_orders+write_third_party_fulfillment_orders(chỉ cần nếu đơn được Shopify giao cho location của một app fulfillment bên thứ ba)
Lưu ý: khi đổi scopes phải Release phiên bản mới của app, sau đó bấm Test Connection lại trên web để token nhận scopes mới. - Cài app vào store: mục Distribution (hoặc nút Install app / Select store) → chọn đúng store (ví dụ leafela) → Install. App dạng này chỉ cài được vào store cùng tổ chức (hoặc dev store), đúng với nhu cầu nội bộ.
- Vào Settings của app → mục Client credentials: copy Client ID và Client secret (bấm Reveal). Không cần lấy Access Token thủ công — web sẽ tự xin.
Bước 3 — Nhập vào web và đăng ký webhook
- Ô Shop domain: nhập domain dạng
tenstore.myshopify.com(xem trên URL Admin:admin.shopify.com/store/tenstorethì domain làtenstore.myshopify.com). Nhập domain riêng (ví dụleafela.com) cũng được: web tự tra ra domain .myshopify.com thật (lưu ý domain thật có thể là dạng ngẫu nhiên nhưiikxj0-f9.myshopify.com, không phảileafela.myshopify.com). - Dán Client ID và Client secret → bấm Save Credentials.
- Bấm Test Connection. Web sẽ xin token lần đầu rồi gọi thử API. Thấy Connected to "Tên shop" kèm hạn token và scopes là đúng. Ô Access token hiện trạng thái "Active, valid until …, auto-renewed".
- Bấm Register Webhooks. Web sẽ tự tạo 3 webhook trên Shopify trỏ về URL hiện ở ô Webhook URL:
orders/create → đơn mới vào tab Mapping orders/updated → cập nhật địa chỉ / ghi chú cho đơn còn ở Mapping orders/cancelled → đánh dấu lỗi "Cancelled on Shopify"
Danh sách webhook đã đăng ký hiện ngay dưới các nút. Dấu ✓ xanh = đúng URL server này. - (Tuỳ chọn) Bấm Sync Orders để kéo các đơn đang mở & chưa fulfill trong 30 ngày gần nhất vào Mapping ngay, không cần chờ đơn mới.
Đơn vào web như thế nào
- Mỗi line item của đơn Shopify là 1 dòng trong tab Mapping (giống TikTok).
order_idlà số đơn Shopify (ví dụ1001từ#1001),order_item_idlà ID line item (dùng để chống trùng). - SKU lấy từ SKU của variant trên Shopify. Nếu SKU khớp rule variant trong Product Base, đơn được auto-map sang tab Order luôn.
- Personalization: các thuộc tính line item (line item properties, ví dụ từ app Personalizer) và Order note hiện trong tab Customization. Thuộc tính ẩn bắt đầu bằng
_bị bỏ qua. - Ảnh sản phẩm được lấy từ ảnh variant/product trên Shopify (cần quyền
read_products). - Sản phẩm không cần ship (digital, tip) bị bỏ qua. Đơn đã cancel không được import.
Đẩy tracking ngược lên Shopify (fulfill đơn)
- Khi một dòng đơn của store Shopify nhận được tracking number (sync/webhook từ Lenful, Flashship, Printway, Printbelle, Printify, Merchize, Dreamship, import tracking hoặc nhập tay), web sẽ tạo fulfillment trên Shopify cho đúng line item đó kèm tracking number, tên carrier và link tracking. Shopify tự gửi email "Your order has shipped" cho khách.
- Job chạy tự động mỗi ngày 1 lần lúc 09:00 (giờ Việt Nam) cho mọi store Shopify đã kết nối. Muốn đẩy ngay: Settings → store → bấm ⬆ Push Tracking. Kết quả ghi vào lịch sử đơn (action
shopify_fulfillment). - Nhiều line item cùng đơn, cùng tracking → gộp thành 1 fulfillment (khách chỉ nhận 1 email). Line item đã được fulfill tay trên Shopify trước đó → bỏ qua, không đẩy đè.
- Dòng đẩy lỗi sẽ được thử lại tối đa 6 lần rồi dừng; bấm Push Tracking để thử lại tất cả. Lỗi hiện trong thông báo sau khi bấm.
- Cần làm trên Shopify:
- dev.shopify.com → app → Configuration / Access scopes: thêm
read_merchant_managed_fulfillment_ordersvàwrite_merchant_managed_fulfillment_orders→ Release phiên bản mới. - Nếu Shopify báo app cần cập nhật quyền: vào Shopify Admin → Apps → app này → chấp nhận quyền mới (hoặc Install lại từ Dev Dashboard).
- Trên web: Save Credentials (xoá token cũ) → Test Connection → trong dòng kết quả phải thấy scopes có
write_merchant_managed_fulfillment_orders. - Shopify Admin → Settings → Locations: sản phẩm phải thuộc location do shop tự quản lý (mặc định). Nếu shop dùng app fulfillment bên thứ ba quản lý location thì cần thêm cặp scope
*_third_party_fulfillment_orders. - (Tuỳ chọn) Shopify Admin → Settings → Notifications → Shipping confirmation để chỉnh mẫu email khách nhận khi có tracking.
- dev.shopify.com → app → Configuration / Access scopes: thêm
Kiểm tra & xử lý sự cố
| Hiện tượng | Nguyên nhân / cách xử lý |
|---|---|
Test Connection báo Shopify token request failed (400/401) | Sai Client ID / Client secret, sai shop domain, hoặc app chưa được cài vào store này. Kiểm tra lại trên Dev Dashboard (mục Distribution / Install) rồi Save và Test lại. |
Test OK nhưng Register Webhooks hoặc Sync báo 403 | Thiếu scope read_orders / read_products. Thêm scope trên Dev Dashboard, Release phiên bản mới, cài lại nếu Shopify yêu cầu, rồi Save Credentials (xoá token cũ) và Test Connection lại. |
Push Tracking báo "App thiếu quyền fulfillment" / Access denied for fulfillmentOrders | Chưa thêm scope read_merchant_managed_fulfillment_orders + write_merchant_managed_fulfillment_orders, hoặc đã thêm nhưng chưa Release / chưa chấp nhận quyền mới trong Shopify Admin. Làm theo mục "Đẩy tracking ngược lên Shopify" rồi Save Credentials + Test Connection. |
| Push Tracking báo "Line item not found in an open fulfillment order" | Line item trên Shopify đang ON_HOLD (ví dụ chờ thanh toán / fraud review) hoặc đã bị xoá/refund. Mở đơn trên Shopify Admin, release hold rồi bấm Push Tracking lại. |
| Token hết hạn? | Token Client Credentials sống 24h. Web tự xin token mới khi còn dưới 2h, và có job chạy mỗi giờ làm mới trước các token sắp hết hạn trong 3h. Nếu Shopify trả 401 giữa chừng, web tự xin lại 1 lần rồi gọi lại. |
| Register báo "requires an https webhook URL" | Settings → Server Public URL phải là https (hiện tại là https://fulfillment.nceglobal.net). |
| Đơn mới trên Shopify không vào web | Bấm Check Webhooks xem còn 3 webhook ✓ không. Xem log server: grep Shopify /root/webff/webhook.log | tail. Nếu thấy HMAC verification FAILED → Client secret nhập sai (phải là secret của đúng app đã cài vào store, không phải của app khác). Nếu bạn vừa Rotate Client secret trên Dev Dashboard thì phải dán secret mới vào web. |
| Shopify tự xoá webhook | Shopify huỷ đăng ký nếu server trả lỗi liên tục ~48h. Bấm Register Webhooks để tạo lại. |
| Muốn ngắt kết nối | Bấm Remove Webhooks (xoá webhook trên Shopify), hoặc Uninstall app trong Shopify Admin. |
Ghi chú kỹ thuật
- Lấy token:
POST https://<shop>.myshopify.com/admin/oauth/access_tokenvớigrant_type=client_credentials,client_id,client_secret. Token và hạn lưu trong cộtshopify_access_token/shopify_token_expire_at. - Endpoint nhận webhook:
POST /api/webhooks/shopify/<store_id>/orders, xác thực headerX-Shopify-Hmac-Sha256bằng Client secret của store, đồng thời đối chiếuX-Shopify-Shop-Domainvới Shop domain đã lưu. - API version dùng:
2026-01(đổi bằng biến môi trườngSHOPIFY_API_VERSIONnếu Shopify ngừng hỗ trợ). - Credentials lưu theo từng store trong bảng
stores(cộtshopify_domain,shopify_client_id,shopify_client_secret,shopify_access_token,shopify_token_expire_at,shopify_webhooks).