Stripe 是一間國際的金流支付公司,提供 client (Web / Android / iOS等)支付介面與 server-side API,用最短的時間就可以讓服務接上金流;
支援支付方式有Visa/Master Card等多間信用卡支付、Google Pay 、Apple Pay等等;
其中金流交易服務:
- 入門會員服務Payment(交易)、Billing(開立發票)、Connect(中間商,向A收錢並轉給B多少錢);
- 其他需要多花錢的加值服務:
Sigma(支援SQL產生報表)、Altas(美國開公司)、Radar(金融詐騙偵測,預設有支援但付費有進階功能) - 邀請制的加值服務:
Terminal(整合硬體Reader,限定持有該硬體才能交易)、Issuing(可以自己發卡,Stripe 提供虛擬卡與實體卡發送)
這次主要嘗試 Payment / Billing 的串接,內容參考自官方文件,包含 client-side(採用 React) 與 server-side(採用 Nodejs SDK),不得不說 Stripe對於開發者非常友善,文件非常好懂且各式語言與插件SDK都支援完整,所以只需要將SDK換掉我想以下的概念都是相同的。
2018/11: 全球地區都可以付款,只是要開通 stripe帳戶只有26個國家,目前不支援台灣
主要介紹 Payment / Billing 的概念,以及試圖理解 Stripe背後的運行機制
Payment
分成兩步驟,在client-side 置入 stripe 付費元件(如 html form),用戶輸入後會產生 token轉交給 server,接著 server 用此 token驗證並實際扣款
在Stripe 中,它定義很多物件,每個物件都有各自參數與封裝的用法,所以文件非常的 OOP,所以對開發者來說很好理解與上手
Checkout
Checkout 是一個 Stripe 提供簡化過後的 Payment方式, 開發者只要接上 Stripe 提供的 Client SDK,用戶的交易細節就會直接丟給 Stripe 處理並以 Token方式回傳,開發者再去 Server Side 拿 Token做後續的應用。
整合 Stripe Client-side有兩種模式 Simple
、Custom
Simple
用一個 <form/>
定義如何轉交給token給 server,接著內部嵌入 stripe script 並定義參數,最基本的幾個參數
|
|
對,就這麼簡單就完成了,接著就是到 form定義的 server api 收 token資料
Custom
如果希望有更細緻的用戶體驗,例如客製化自己的付費表單、顯示錯誤訊息等,就需要自己客製化,這部分也十分的簡單,用 vanilla js 也可以輕鬆完成
這部分程式碼可以參考文件
參數設定
以上的 Simple/Custome 就是一個基本的 Element,裡頭定義的 data-*
屬性則會決定產生的 Checkout 物件屬性,常見的屬性有
data-key [required]
當帳號成功激活後,會有兩組 key / secret 組合,分別是live / test
,對應就是正式機與測試機的概念token / source [required in custom mode]
這兩個對應 callback function,分別對應收到 Token / Source,Token主要是server可以取得用戶的部分信用卡資料,Source則是代表用戶的其他付款方式(這些資料的取得要透過後續的參數設定)data-name / data-description / data-image / data-locale / data-amount [highly recommend]
對應會顯示在 stripe 付費頁面的資訊,locale是設定表單語言data-zip-code / data-billing-address [highly recommend]
用戶的地址相關,Stripe推薦向用戶索取 zip-code,zip-code可以在後台設定當作 Radar的驗證條件,禁止可疑的Paymentdata-email / open / close [optional]
還有一些欄位可以定義就翻文件了,open / close則是 callback function會在表單開啟與關閉時候呼叫,同樣只用於 custom mode
特別注意,開發者完全不需要接觸到用戶的信用卡資料,在沒有謹慎評估之前,不要妄想儲存用戶信用卡資料!
因為如果要「合格」儲存用戶信用卡資料,必須過 PCI-DSS 國際信用卡組織聯合規範的支付安全認證,但這部分規範嚴格,而且必須定期做漏洞掃描
所以 Stripe 也提到他們為了讓開發者便利,所以信用卡資料都還是通過他們,僅回傳 Token形式供後續扣款使用,不用再多煩惱這些資安上的問題
Server-side
前端取得 Token 後,就可以往 server 丟,這個 Token是一次性扣款使用
,此外就等同於 Source的效力,也就是用於實際扣款的支付方式,後續會詳細介紹什麼是 Source
以上是最基本的 Checkout 信用卡付款,因為信用卡是立即扣款就能知道結果,但如果需要支援如銀行轉帳等其他需要用戶額外授權與支付的流程,就需要以下更複雜的設計
多元支付方式
Stripe透過產生 Source 物件代表不同的支付方式,支付概念上可以分成付款是同步與非同步完成(async vs sync) 錢如何從用戶轉出(push vs pull) 是否可重複使用(reusable)
例如說信用卡就是 sync + pull
,當用戶輸入信用卡後,就會立刻執行扣款動作(sync),就直接從用戶帳戶扣款或是產生支付紀錄(pull)
而像銀行產生虛擬帳號提供ATM付款是 async + push
,用戶可能在過幾天才去付款(async),而用戶本身需要主動去產生支付的動作(走到ATM前面,也就是 push)
其他還有多種地域性的支付方式,因為不熟悉就不再多敘述,可以參考文件
Source 物件建立初始化為 source.pending
,有 webhook 可以接收狀態的改變,當用戶授權後會觸發source.chargeable
、用戶拒絕授權source.failed
、過期source.canceled
Source 此時僅代表支付方式,實際的支付要透過 Source 建立 Charge 物件,Charge 物件同樣有幾個 webhook 可以串接,非同步支付初始化會是等待用戶支付charge.pending
、成功收到用戶支付charge.succeeded
、與支付失敗charge.failed
webhook 部分則是在後台設定。
以下擷取官方案例,僅作於理解使用
|
|
某些支付方式是可以多次扣款,例如信用卡,Stripe 提供 Customer 概念,也就是可以創建一個 Customer 代表用戶,接著將 Source 綁定到該用戶上,一個用戶可以綁定多個 Source,到時候如果要扣款可以從 Source中選擇其中一個,相當的方便
需注意 Source 必須是 chargable 才可以扣款
|
|
小結!
看到是不是有點暈頭轉向了呢,說好的 Stripe 很簡單呢?
或許這也是種 simplicity but not simple
,要提供多元的支付方式勢必帶來邏輯的複雜性,但是我覺得 Stripe 透過 OOP梳理整個金融支付的過程,帶來極棒的 Developer Experience與 User Experience,接過台灣的紅藍綠你就會知道Stripe 有多棒了
廢話不多說,讓我來重新整理一翻
最一開始提的 Checkout 信用卡支付取得的Token,算是 Source的簡化版,我猜目的是為了讓最快速接串好金流的作法,而且信用卡的支付行為算是最簡單的。
Billings
用於重複性扣款與開立發票
發票狀態流程
Invoice,代表發票的物件,一張發票可以多筆款項 InvoiceItems,因為不同的財務規劃而有比較多的狀態可以設
- 初始化為
draft
,此時發票的設定都還可以做調整,確定後或是預設一個小時後會變成open
;
刪除就變成deleted
open
則代表發票確認了,如果用戶付款了可以調整為paid
,可以選擇觸發後續的發票寄送等流程;
如果發現用戶破產之類無法支付,可以在後台將此筆發票設定為uncollectible
;
如果發票有誤需要作廢,則設為Void
一次性開立發票 one-off invoices
|
|
auto_advance 算是很重要的參數,Stripe 預設在 Invoice 創建之後會有自動化的動作,如一小時後自動轉成 open**,並會向用戶自動扣款 (預設 Source)接著轉成** paid
,並Email 發送 Receipt 與 Invoice;
如果不想要記得設為 false
在開立發票上 Stripe 靈活性頗高,每一筆 InvoiceItem 可以設定費用/折扣/稅率,InvoiceItem 可以指定所屬的 Invoice,或是預設歸類到該用戶的下筆 open 的Invoice中
訂閱制扣款服務 subscription
有些雲端服務都是以年或是月的訂閱收費制度,Stripe 中可以定義 Product 與 Plan,例如說有一個 Product 是 SaaS服務
|
|
針對這個 Product,可能會有許多的收費方式 Plan,可能是月繳/季繳/年繳或是有不同的適用期限、也可能有多種國家的不同定價等設定
|
|
Stripe 支援分層收費,可以指定多種模式,例如 當超過一個額度,每個商品變多少錢 / 又或是分多階層,超過部分算該價格的階梯形收費
當先前的 Custome想要購買時,會創建一個訂閱 Subscription 的物件,並決定要訂閱的 Plan,如果要一個訂閱多個 Plan,這些 Plan必須幣別相同且收費區間一致;
|
|
此外,還有Coupon 可以設定,支援一次性 / 永久性 / 每次扣款用,還有 %跟數量的設定,相當有彈性
|
|
建立 subscription 在沒有停止之前,Stripe 會自動依照時間定期扣款,並自動開立發票(可關閉),相當的方便。
升級或降級
如果用戶訂閱了普通版,在月中時突然想升級到專業版,該怎麼處理呢?
可以選擇將該用戶的 subscription 物件修改,更新訂閱的 Plan
|
|
更新容易,但是實際的扣款流程必須對應業務邏輯的處理,也就是收費的方式;
例如幾種案例
- 1/1開始訂閱 PlanA $30/mo,接著再 1/15 升級到 PlanB $45/mo
因為都是每月扣款,所以 Stripe 預設會在 2/1 開始收 PlanB 也就是 $45元,所以理論上應該在 2/1才將用戶升級到 PlanB的服務 - 同上,但是用戶希望 1/15就升級到PlanB
這時候有兩種做法
a. 自己手動開立 Invoice,開立Invoice當下就會扣款並產生發票
b. 設立 Proration,這是 Stripe 提供的方法,也就是在 update subscription 時指定proration_data
,Stripe 會在下一次收費時間多開立這部分的金額 - 如果用戶從月付費改成年付費,會立即扣款
- 如果1/1已經扣款 PlanA的錢,用戶 1/15取消,Stripe 預設不會退款;
也可以設定cancel_at_period_end
,讓用戶在月底才取消資格;
如果有額外產生的代付款項服,必須要手動清除 Invoice才不會在月底多扣款一次
小結二
同整一下 Invoice / Invoice Item / Product / Plan / Subscription 關係
總結
如果要一次性付費,則可以使用 Payment,且 Payment 不需要綁定 Customer,同樣會開立發票;
以下更複雜的扣款方式方式要先在 Stripe 建立 Customer,可以利用 Invoice,分次建立 Invoice Item,最後再一次開在一張 Invoice 下完成扣款;
又或是建立 Product 與對應的付費機制 Plan,並用 Customer 角色訂閱 Subscription, Stripe會處理定期扣款等機制;
結合 Coupon 可以提供彈性的折價機制。
總體上 Stripe 最讓我覺得方便的是 Dashboard 可以設定,這樣就可以少蓋一個後台自己麻煩,而且把Customer / Payment / Billing 等分門別類,以及個別子項目,非常好管理金流服務。