王琪驊 (Emily Wang)
--- 持續學習、自省
工作以來,持續透過下班時間學習軟體開發技能,勇於挑戰與嘗試新事物,做好當下的每一件事,不放棄任何機會。
平時參與技術社群活動,包含 React 培訓、GraphQL應用,後端讀書會,以及演算法讀書會。
專案簡介
鋼構設計流程自動化
曾在外部讀書會分享於此專案上應用 design pattern ,相關的說明與 sample code 請見此:Design pattern 在專案上的應用 (slides.com)
結構分析軟體
BIM 整合軟體
鋼接頭檢核軟體
Data Standardlization
Via API
ref:
https://bit.ly/3e58D9I; https://bit.ly/3gTVIJt; https://bit.ly/3aUQglT
專案簡介
Lodestar 內容商務系統
我在目前公司主要是做 SaaS 系統的功能擴充與開發,應用程式的核心架構分為前台、後台與後端,前端 repo 皆為開源專案
後端的部分,我參與了多個外部系統串接的需求,主要的架構設計為使用 class 封裝外部 api 的操作 (詳見下頁
class PaypalClient {
appId: string
dryRun: boolean
environment: any | null
constructor(appId: string) {
this.appId = appId
this.dryRun = Boolean(process.env.NODE_ENV !== 'production')
}
public setup = async () => {
// ...
}
public createOrder = async (orderDetails: CreateOrderRequestBody) => {
// ...
}
public captureOrder = async (paypalOrderId: string) => {
// ...
}
}跨境金流 PayPal 串接
// ...
const host = await getAppHost(appId)
const paypalClient = new PaypalClient(appId)
try {
await paypalClient.setup()
} catch (error) {
return res.redirect(`https://${host}/orders/${orderId}?code=E_SETUP_PAYPAL&error=${error.message}`)
}
// capture order
let capturedOrderResponse: OrderResponse | any
try {
capturedOrderResponse = await paypalClient.captureOrder(paymentId)
} catch (error) {
return res.redirect(`https://${host}/orders/${orderId}?code=E_PAYPAL_CAPTURE&error=${error.message}`)
}封裝外部 api 之 Client class
在 controller 內使用 client
外部 CRM 串接
class VitalClient {
appId: string
private _baseUri: string = ''
private _storeName: string = ''
private _apiKey: string = ''
private _apiBaseCaller: AxiosInstance = axios
constructor(appId: string) {
this.appId = appId
}
public init = async () => {
const appModules = await getAppModules(this.appId)
if (!appModules.includes('vital_crm')) {
throw new Error(`app: ${this.appId} did not support vital crm. Please add vital_crm module`)
}
// ...
this._baseUri = 'https://www.videgree.com/' + this._storeName
this._apiBaseCaller = axios.create({
headers: {
Authorization: `ApiKey ${this._apiKey}`,
},
baseURL: this._baseUri,
})
}
private _composeMemberData = (memberData: { email: string; name: string; id: string }) => {
// ...
}
private _composeOrderData = (orderData) => {
// ...
}
public insertMember = async (memberData: { [key: string]: any }) => {
// memberData to vital req.body
}
public updateMember = async (memberData: { [key: string]: any }) => {
// ...
}
public insertOrUpdateOrder = async (orderData) => {
// ...
}
}封裝外部 api 之 Client class
// ...
private static _handleMemberInsertOrUpdate = async (event: TriggerEvent) => {
// get app Id if there have vital_crm module
const appId = event.data.new?.app_id
const appModules = await getAppModules(appId)
if (!appModules.includes('vital_crm')) return
// get vitalClient
const vitalClient = new VitalClient(appId)
try {
await vitalClient.init()
} catch (error) {
throw new Error(`vital Client init failed: ${error.stack}`)
}
const newMemberData = event.data.new || {}
const vitalCustomerNo = newMemberData?.metadata?.vital?.CustomerNo
// insert
if (!vitalCustomerNo) {
await vitalClient.insertMember(newMemberData)
return
}
// update
await vitalClient.updateMember(newMemberData)
}外部 CRM 串接
在 event trigger 內使用 client
公司內部 code review,由我畫系統架構圖,並與 scrum team 講解目前的架構
Any Question?