September 06, 2017

Cô hồn tiki - Phần 2

UPDATED 2: Tiki đã cập nhật kết quả nha :)

UPDATED 1: Sau khi xong thì có vẻ kết quả cô hồn hơi bị nhiều :( tiki nhận được hơi bị đau, chửi nát bét và quan trọng hơn là app bị rate 1*… :(

Vậy cũng 3 năm từ cái bài Cô hồn tiki, chủ yếu là 2 năm vừa rồi không có thời gian để “móc” chơi. Năm 2015 thì đang ở Phú Quốc, còn 2016 thì lại bị kẹt ở Úc do máy bay bị hỏng động cơ. Năm nay mới quay trở lại, chủ yếu là vì vui thôi, dĩ nhiên còn lý do cá nhân khác nữa. Tính ra thì năm nay hệ thống dzựt cô hồn của Tiki có vẻ đã ổn định và không có sự thay đổi đáng kể nào nếu nhìn từ bên ngoài… trừ việc cắt luôn phần dzựt trên web… cũng dễ hiểu mà, tránh bị dòm ngó nhiều vì web quá dễ truy cập theo dõi các request.

Rồi bây giờ coi năm nay Dzựt cô hồn Tiki có những gì:

  • API server chạy trên AWS (chạy EC2 hay gì thì mình không biết được)

  • Dùng S3

  • App Tiki trên iOS và Android

  • … và phần app Dzựt cô hồn (dch) được viết bằng React Native

Theo như thông tin mình có được thì kiến trúc như vậy đã có từ năm ngoái vì file bundle vẫn ghi name là “MobileDzut16” và hình như năm ngoái là lần đầu thử nghiệm trên app Tiki thì phải. Cách làm như vậy tiện lợi ở chỗ app Tiki chỉ cần update một lần để thêm phần dch vào và phần này vẫn có update mỗi lần người dùng click vào cái icon con ma. File bundle này được lưu trên S3 nên tải là vô hạn… trừ khi đứt cáp nặng quá thôi =]].

Rồi về cái API dzựt thì mình không bàn, vì đã xem phần trình bày của bạn Khôi năm ngoái, và theo mình gần như… tối ưu, chắc cũng chẳng có lo ngại gì về tải. Rồi vậy còn gì để nói về các dch này nhỉ? Dĩ nhiên là về mặt tổng quan thì ok rồi, còn thực tế thì vẫn có những điểm có thể gây rắc rối.

JWT

Dch và tiki.vn là 2 hệ thống riêng biệt, trong đó dch yêu cầu phải đăng nhập bằng tài khoản của tiki.vn. Về phần web thì mình thấy có cập nhật thông tin, nhưng 2 cái site sử dụng chung cookie của domain .tiki.vn nên chắc cũng không thành vấn đề. Về phần app thì khi đăng nhập app tiki nhận được 2 token dạng JWT. Một dành cho app tiki bán hàng và cái còn lại dành cho dch, tên quá rõ ràng luôn access_token_dzut. Ok, chắc là token này dùng cho dch (chắc thế, vì chưa đến giờ dzựt lúc mình viết bài này). Vậy xem coi cái token này có gì trong đó:

{
  "customer_id": "[tiki customer id]",
  "email": "[email]",
  "is_tikier": false,
  "created_at": "2017-09-04 hh:mm:ss"
}

Đến hôm nay mới biết tiki id của mình cũng đẹp đẹp ghê :v, is_tikier là gì nhỉ? Nghe cũng vui vui nhưng chắc liên quan đến test dev này nọ thôi. Cái token thiếu exp điều này nghĩa là sao? Một khả năng lớn là dch server chỉ check là cái này có phải do tiki.vn cấp thôi chứ không kiểm tra nó có hạn đến khi nào? Mặc dù có created_at nhưng mình nghĩ nếu tính đến chuyện kiểm tra hết hạn thì chắc đã có exp rồi. Mặt khác, cũng là suy từ bụng ta ra bụng người thôi là dch cũng không request lại đến tiki.vn để check lại lần nữa, vì thực sự cũng chẳng cần thiết với thêm nặng tải thôi.

REACT NATIVE

Lúc đầu nghĩ là, ồ năm nay cho dzựt trên app để tránh chạy script trên browser, chắc thế. Nên quất liền file APK mới nhất mà có được lúc đó là 3.30.0 thì phải. Dùng apktool để extract ra… Ok, tìm thấy được 1 cái namespace, à quên java chắc gọi là package nhỉ vn.tiki.dzut2017. Hehe, chắc source nằm ở trong đây… mở lên 1 đống file kiểu như asm… thiệt mình không rành Android nên cũng chả biết sao… nhưng search thấy có cái class Api gì đó, xong kiếm được 1 cái link json. Ok, cứ vô thử coi có gì trong đó… ra là URL tới cái file bundle react native. Mỗi lần tap vào con ma cái nó load file này về mà mình bắt request không để ý. Nếu biết trước thì đâu tốn công đục cái app =]]

Rồi vậy dễ rồi, react native, mặc dù mình cũng không rành, nhưng được cái viết bằng js, mình có thể ráng đọc được. Lúc đầu còn ngu ngu, cái file bundle mình tưởng là file… nén gì đó =]], google quài, hỏi thằng em ở fb (tiếc là nó làm ở mảng quảng cáo) không biết cách để đọc file này… xong kéo nó vào VSCode đọc thử… hóa ra là file text thôi. Cái tội ngu nè, bảo học react bao nhiêu lần rồi không chịu học. Đống js trong đây bị min, ugligy này nọ rồi, nhưng dễ mà cứ jsbeautifier thôi. Dĩ nhiên là tên biến không còn như xưa mà toàn a, b, c, x, y, z… À, sau đó mới để ý họ không xóa mấy file bundle cũ trên S3 =]], thử download build 1 vẫn được.

Trước khi đục app thì đã đục web và thấy là dzut api lại sử dụng JWT lần nữa, nhưng đến 2 lớp. Một để kiểm tra tài khoản tiki.vn (1), và một để gói toàn bộ request khi người dùng dzựt một sản phẩm (2). Cái token (1) thì dễ rồi, chắc xài cái ở trễn. Còn cái request dzựt có dạng như vậy:

{ 
  "access_token": "[access_token_dzut]",
  "region_id": 2,
  "period_id": 1,
  "product_id": "xxxxxx",
  "t": "1504666496.533" }

Cái token (1) thì lại y chang, vậy là dch sử dụng tới 2 chỗ. Một trên header X-ACCESS-TOKEN và mã hóa một lần nữa vào body. À nhắc tới header, họ không sử dụng header Authorization + Bearer như… thiên hạ (ừ thì đa số á) vẫn dùng, nhưng dùng gì cũng được, miễn giao thức nội bộ tự thỏa thuận với nhau mà. region_id thì chắc là dùng để test và production với danh sách sản phẩm khác nhau, product_id thì không cần nói, period_id là đợt dzựt, còn t là timestamp dạng giây, lẻ 3 số do JS lấy tới ms, họ lấy chia 1000 thôi.

Cuối cùng là token (2) được sign bởi một secret mà phải được thỏa thuận bởi cả app và server. Mục tiêu ban đầu mình đục app là để biết cái secret đó là gì. Cuối cùng sau khi lần mò đống biến abcxyz, require tùm lum thì cũng ra được dch dùng… User-Agent header làm secret, user agent của dch thì cũng tựa tựa như browser thôi “Tiki/dch… (ios)”. Rồi vậy là đủ, còn lại họ còn trap nào không thì mình không biết, vì còn một đoạn đổi token dzut gì tùm lum mình đọc quài chưa hiểu :)