Node.js串接LinePay筆記

Joe Chang
Coding Hot Pot
Published in
Sep 24, 2022

本次練習使用的技術為 — 前端:React,後端 :Node.js + MongoDB,串接的LinePay版本為V3

近期在做side Project練習串接LinePay,順手將過程紀錄下來,這篇文章會著重在LinePay串接的流程,Node js和MongoDB的部分只會簡單帶過,因為本人也是後端初學者,文章裡的內容有些是自己摸索出來的,未必完全正確,如果有發現錯誤,歡迎留言告知我,萬分感謝!

讓我們先來看看LinePay官網提供的PC版流程圖吧!

PC付款頁面-付款完成

  1. 在LINE App的付款頁面,LINE Pay用戶選擇付款方式並輸入密碼。
  2. 在選擇付款方式後,點擊付款按鈕啟用付款
  3. LINE Pay用戶在LINE App確認付款資訊。
  4. 在PC環境的等待付款頁面一旦收到用戶付款狀態成功,將會轉導至商家系統的“confirmUrl”。
  5. 商家系統透過呼叫Confirm API來完成交易。

行動版的付款流程有些許差異,可以參考這裡

串接LinePay的前置作業

  1. 先建立sandBox帳號,👉這裡申請

2. 註冊成功後會收到信件,裡面會有帳號密碼的資訊

取得Channel ID & Secret Key

申請好帳號之後登入管理平台,點開選單內的管理連結金鑰的頁面,按下查詢,會寄送驗證碼到你的電子信箱,驗證成功即可取得金鑰

有了金鑰我們才能夠串接LinaPay的API,為了避免金鑰外洩,因此會把金鑰存放在env,至於LinaPay的版號和api url是否要放在env,就看大家的開發習慣了

白名單設置

為了提高安全性,必須將我們的後端server IP設為白名單,防範來路不明的請求(不過測試環境貌似可以不用設定,API也能打得過

建立一筆新訂單

點選購買的按鈕之後,前端會用POST的方式呼叫後端 /linepay這支API,後端收到請求後會先在資料庫建立一筆訂單,再呼叫LinePay的API請求付款網址

LinePay要求的訂單資訊如下(request body)

本次的練習是模擬使用者購買訂閱VIP的服務,因此商品內容和價錢都會由後端這邊固定寫死,依照LinePay規定的格式建立的訂單物件如下

不過除了LinePay本身要求的資料格式之外,還要滿足資料庫要求的必填欄位,像是訂單編號MerchantOrderNo,購買者user等等…, (這部分就看個人的資料庫欄位設計),因此新增訂單到資料庫的時候, 除了原本的資料還會多加上這幾個key

createOrder 的 controller

但也正是因為多帶了這幾個key的資料,打LinePay的API會得到 2102 JSON 資料格式的錯誤, 因此新增完資料庫的訂單之後,必須記得將非LinePay要求的key刪除,不然打API永遠都會失敗,除了訂單資訊,還要帶上重新導向的redirectUrls (confirmUrl & cancelUrl),目的是當訂單狀態變更為成功或失敗時,LinePay可以呼叫這兩隻API來通知後端 (config.callback為後端server的url)

header 資料格式

準備好了request body之後,接下來就是準備request header了,這裡會需要用加密的方式製做簽章(使用crypto-js套件),將LinePay規定的資料組合在一起,加密這邊有個小陷阱,看LinePay官方的文件是這樣寫的

但crypto-js的文件是這樣寫的

const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));

因此正確的順序應該是加密字串放在前面,secretKey要放在後面

製作簽章

取得跳轉網址

回傳跳轉網址

所有需要的資料都準備好了就可以打API了! 如果傳送的資料格式都正確的話,api的response的returnCode就會回應0000,而info.paymentUrl.web就是我們要取得的跳轉網址

Line Pay API回應結果

一開始想要用res.redirect的方式由後端直接導轉,但一直顯示cors error,搞了老半天都無法解決,只好換個方式,後端將web跳轉url吐給前端,由前端跳轉至Line Pay付款頁面 window.location.replace(…)

建立訂單並且取得付款網址

跳轉至付款頁面

確認訂單狀態

當使用者用app掃描畫面上的qrcode,就會看到以下畫面,不會真的扣款,可以放心按下去

成功付款之後,LinePay就會轉址到後端server的 /linpPay/confirm,並且在url後面帶上transactionId和orderId,通知後端使用者已經完成付款

掃碼付款成功流程
在後端log可以看到紀錄

不過為了安全性,我們必須再次詢問LinePay這筆訂單是否真的付款成功了,這裡的流程可以劃分成三個步驟:

  1. 根據剛剛LinePay帶在url上面的transactionId,後端再用POST的方式呼叫linePay的確認訂單api (${linePay}/payments/${transactionId}/confirm),一樣必須帶上加密簽章
後端詢問確認訂單是否成功
呼叫LinePay的confirm API

2.如果訂單成功,LinePay API的回應結果如下

LinePay確認訂單回傳結果

3.後端就可以跳轉到前端付款成功的頁面了(res.direct)

前端付款成功頁面

👉 實作程式碼,可參考linepay.route.js、linepay.controller.js、linepay.service.js這三隻檔案,主要邏輯都在linepay.service.js

--

--

Joe Chang
Coding Hot Pot

前端工程師,唯有非常努力,才能看起來毫不費力