Sherry L

[Projects] 迷你電商 X 串接第三方金流

snap

最近和 Ivy 一起做 side project,很喜歡買衣服的我們決定做一個迷你的服飾電商網站XD 也剛好把之前一直很想練習的購物車模型實際做出來。

因為缺乏前端隊友的關係,加上我們最近才開始各自學 React 和 Vue ,決定先用熟悉的全端方式(後端用 Node.js + Express,前端用 Handlebars 渲染)開發,並利用拆分 service 和 controller 的方式,一邊撰寫全端路由,一邊做 API server,這樣完成後至少會有一個全端作品,之後 React 或 Vue 學到一定程度後還可以回來串接這次寫好的 API ~

分工方式與開發流程

這次一樣是一起討論完所有路由與資料關聯,列出來後再進行分配。由於上次 Twitter 專案時,Ivy 負責所有基礎建設(資料庫 model 建置、Heroku 初始設定、使用者驗證等等)我負責功能開發,這次我們就互相調換:

  1. 我負責基礎建設 + 購物網站後台 control panel 與管理員權限(管理商品上架、訂單狀態處理等等)、種子資料
  2. Ivy 實作前台使用者功能(前台商品展示、商品加入購物車、結帳、查看訂單等等)
  3. 付款資訊與串接金流的我們都是第一次接觸,於是決定兩個人都各寫一版
  4. 換 Ivy 寫 swagger API,我寫 README

controlpanel

這次的分工方式我覺得滿有意思的,上次寫 twitter 時我就是等 Ivy 做完基礎建設後直接開發功能,該有的 table 都有了,撈資料都很直覺,該有的驗證也都做好了,直接打開 POSTMAN 無腦測試。

這次換我從 0 開始做,一開始真的有點手足無措,不知道要從哪裡開始XD 後來我們決定按照以下的開發流程,一步一步推動專案開發:

flow

還好有這次的練習機會,在建置 skeleton 時,我可以用比較宏觀的方式去設計這次的專案會需要用到哪些 module,利用清楚的 MVC 架構來設計等等。

mvc

技術新體驗 — 串接第三方金流服務

這次最重頭戲的技術非串接金流莫屬,平常網購結帳都很無腦,沒想到背後的流程這麼麻煩。

雖然做小型個人專案(前端)時經常會去串別人的 API,但通常都是用簡單的 axios request 附上一些 headers 參數就可以取得對方傳回來的資料。但串接金流因為涉及資料安全性的問題,以及需要傳送更多複雜的訂單資料給第三方平台商店驗證授權,所以實作難度與花費時間都提升許多。

blue

在這個專案裡,我使用藍新金流作為信用卡支付的平台,藍新金流提供測試平台及完整的技術手冊,研讀手冊可以得知取得支付頁面需要先傳送哪些資料,以及如何加密、雜湊,以及解密交易成功後的回傳資料,才能回來做我們的專案資料庫更新付款資訊的商業邏輯。整個串接過程可分為以下幾段:

準備付款頁面

按照技術文件,我們需要把訂單資訊打包起來,用 <form> POST 的方式將 data 傳送給平台。於是我先做一個含有 <form> 的頁面,利用 <input> 標籤及 handlebars 帶入變數的方式,把需要的資料 tradInfo 傳送給藍新。

code1

因為是使用 <input> 來帶入 value,想要對使用者隱藏這些資訊,但若加上 disabled 會造成表單無法 submit,所以就利用 hidden 屬性,將與使用者操作無關的欄位藏起來,只留下付款按鈕。

tradeInfo 中的必要參數有幾項:

MerchantID   // 申請的店家編號
TradeInfo   // 訂單資料,經過 AES 加密
TradeSha    // 利用 SHA256 來雜湊 AES 加密後的結果
Version  // 串接的軟體版本號

加密訂單資訊

code3

將加密資訊的邏輯拆成一個模組,放在 utils/ 下,再引入到 service 中使用,讓 service 不要太大包~

由於藍新技術文件中提供的加密程式碼只有 C#、VB、PHP 等語言撰寫的範例,為了實作加密與雜湊邏輯,只好去研究一下 crypto 這個 nodejs 原生的套件,裡面有一個 Cipher 的 class,用於加密:

code4

加密前必須先把訂單資訊改成類似 chain 字串的形式,才能開始進行加密~

code5

另一個需要傳送的參數是 經過 AES 加密後再 SHA256 雜湊過的 TradeSha,一樣用 crypto 內建方法就可以達成。有了這兩筆資料加上其他兩個參數後,就可以 POST 給金流平台,準備授權了~

但在這過程中,由於我使用的是測試帳號,本地開發時要連接藍新的付款服務還是需要使用 HTTPS 加密傳輸,因此需要下載反向代理工具 ngrok,把 localhost:3000 map 到一個 public 的網址,讓外面的服務可以用這個網址連到我的本機開發環境。

gif1

最後用測試信用卡號付款完成後,就會導回我們的前台訂單頁面~

解密平台回傳付款資訊,並更新資料庫

付款完成後我也加上「新增付款資訊」與「更新付款狀態」的邏輯,完成訂單/付款狀態的更新:

code6

這樣就大功告成了~研究技術文件其實就花了大半天,後面接收回傳資料時,因為日期與資料庫存入的格式不符,也是花了點時間解決,但整體來說很好玩!

協作體驗

或許有人會覺得這樣小規模的東西,為什麼不自己做一個就好?我想是因為我滿喜歡協作的感覺,繼上次和 Ivy 合作 Twitter 專案後端 API 開發,雖然分工很精細,但在每次 review PR 時都會互相討論用到的技術與實作方式,真的比一個人做全部還要充實、學到更多,看待問題、考慮如何實作的角度也不一樣。像是 Ivy 實作前台訂單完成時寄發通知信、購物車資訊存放於 session 等等,都是我覺得這次相對困難/新奇的技術。
前期的分工主要是前台/後台,成立訂單功能差不多完成後,我們決定兩個人都要練習到串接金流的部分,於是各自研究實作一版,review 完再推最終版本與 master branch 合併~

整體的協作經驗很好,大概因為人數變少了XD 遇到任何問題也都能夠先在 slack 提出,或到 trello 上開票,就可以迅速處理。雖然因為找工作的關係,這次專案時程拉得比較長,但我們總是能在約定驗收時間就快速通過,除了事前統一程式碼風格外,也已經培養相當的默契。

trello

整體開發心得

這次開發的過程有新技術,也有許多之前專案中已經碰過但沒有很熟的東西,例如以前我最害怕的 Sequelize migration 。

這次因為完善的事前規劃,加上對於查詢文件已經不陌生,整個過程都滿順的,遇到外鍵限制的問題也能快速調整設定解決。同時也發現設定 table association 的部分,真的要對專案所需的 data 彼此之間的關係很了解,也要對一對多、多對多的關係有一定的掌握度,因為我當初在設定關聯時,花了滿久的時間來釐清不同 table 間的關係,深怕設定錯誤而撈不到資料XD 感謝頭腦清楚的 Ivy 總是一句話點醒我其中的關聯 💙

另外在自己開發管理員後台時,也盡量靠自己的規劃去實現功能。實作 Google 與 Facebook 登入驗證時也碰到一些需要在 developer console 設定的問題,過程中也是泡在 stack overflow 一整天找答案,都是不錯的經驗。

而這次撰寫程式碼時,有刻意希望自己能夠把一些可複用的程式碼做模組化的打包,練習寫出簡潔的 service 、在變數命名上也訓練自己多使用語意化的命名方式。

雖然還有許多部分待優化(我們 trello 的 optimization 那欄好多東西),目前樣式上也稍微陽春了些,但這次的實作經驗讓我對於整個應用程式的規劃比較有概念了,也會刻意思考一些前台可能的狀況,撰寫錯誤訊息或設計對應的 handler 來排解。

這次雖然我們有試著用 mocha & chai 撰寫測試,用 TDD 方式來開發,這在前期建立資料 model 與基本的 CRUD request 時很有幫助。但後期功能越來越雜,加上對於測試框架尚不熟悉,比較可惜沒有繼續寫測試,希望之後有機會接觸更多測試相關的知識,好好實現 TDD~

希望以後有機會再做協作 side project 時實力已經提升了 💪🏻