在我們花了不少時間終於完整的完成ATM付款並成功架設Heroku網站後取回PayToken,更新付款資訊。有了這些基礎後,我們在實作信用卡的部份基本上都可以用走到飛的狀態來進行。
有興趣可以參考從Day12開始到Day17的文章,Day17基本上已將完整的流程與架構做了完成度很高的鋪墊。
以上為永豐規格書中提供的信用卡刷卡內容,和ATM的流程稍有不同就是在於PayToken的取得方式,下面來說明。
按照先前的ATM付款流程,信用卡的流程差在沒有中間的BackendURL的等待呼叫過程,整個流程從我們的電商平台到取得信用卡刷卡位置轉址,再轉回來,流程是銜接在一起的。
/order/create_card_order
)
create_new_card_order
CreateOrder
)
CreditCardMessage
類別物件 (繼承至ApiMessage
)set_shop_data()
設定訂單相關資料
ReturnURL
網址,待刷卡完成後導回網頁,並處理由永豐回傳的PayToken
。create_new_order()
方法進行各種所需流程之資料準備(加密、運算簽章等),最後叫用APIResponseCard
類別物件取回回傳值,最重要的是CardPayURL
。 (繼承至ResponseMessage
)ReturnURL
網址將頁面導回/order/card_return
)取回PayToken值
OrderPayQuery
)
QueryByPaytokenMessage
類別物件 (繼承至ApiMessage
)set_paytoken_json()
設定PayToken所需相關資料send_query()
方法進行各種所需流程之資料準備(加密、運算簽章等),最後叫用APIResponsePayToken
類別物件取回回傳值 (繼承至ResponseMessage
)和先前流程一樣,因為我們已經建立了兩套共用的父類別(ApiMessage
、ResponseMessage
),分別可從中繼承擴充新的Message呼叫方法以及擴充取回的response內容。
所以我們就新增一個CreditCardMessage
(繼承ApiMessage
),以及ResponseCard
(繼承ResponseMessage
),因此更新一下我們的物件架構圖。
class CreditCardMessage(ApiMessage):
return_url = "https://kummyshop.herokuapp.com/order/card_return"
def __init__(self):
super().__init__("OrderCreate")
self.shop_data = None
def set_shop_data(self, will_paid=True, amount=100, auto_billing="Y"):
self.shop_data = CreditCardMessage.gen_default_shop_data(self.shop_no, will_paid, amount)
self.shop_data["PayType"] = "C"
self.shop_data["CardParam"]["AutoBilling"] = auto_billing
self.shop_data["ReturnURL"] = CreditCardMessage.return_url
self.shop_data["BackendURL"] = SinopacUtil.backend_url
print("- shop_data: {}".format(self.shop_data))
super()._set_plain_msg_to_proc_msg_sign(self.shop_data)
def create_new_order(self):
print("Send API...")
return super()._send_api()
@staticmethod
def gen_default_shop_data(shop_no, will_paid=True, amount=100):
tmp_data = ApiMessage._gen_temp_shop_data()
tmp_data["ShopNo"] = shop_no
tmp_data["OrderNo"] = SinopacUtil.gen_order_no(will_paid)
tmp_data["Amount"] = amount * 100
tmp_data["PrdtName"] = "信用卡訂單"
return tmp_data
這邊和ATM基本上很像,差異僅在ATMParam與CardParam的部份,至於PrdtName則僅作個註記用途,沒有太實際的功能性。主要還是初始化後,設定shop_data後,就可以進行Send API的流程。
另外就是我們需要準備好ReturnURL
給永豐API,屆時刷卡完成後會再導回我們的網頁。
實際流程當然相當複雜,只是我們先前將Code經過整理後,目前只要有新的作法就可以疊加在已架構好的程式架構上進行叫用,無需每次都要重覆複製貼上一堆八、九成都一樣的的程式碼,這就是實踐程式碼的DRY(Don't repeat yourself)精神。
至於其他程式段,請參閱Day17的部份,在此就不再貼過來佔版面。
class ResponseCard(ResponseMessage):
def __init__(self, resp_json, hash_id):
super().__init__(resp_json, hash_id)
self.orderno = self.dec_resp_json["OrderNo"]
self.amount = self.dec_resp_json["Amount"]
self.tsno = self.dec_resp_json["TSNo"]
self.status = self.dec_resp_json["Status"]
self.desc = self.dec_resp_json["Description"]
self.card_pay_url = self.dec_resp_json["CardParam"]["CardPayURL"]
這裡就是針對CardPayURL
進行處理,簡單來說,就是我們既然要提供顧客刷卡服務,且透過永豐API,那我們要作的其實是建立訂單後請永豐給我們一個信卡用刷卡的金流網址,我們收到後就可以將客戶導入後刷卡,待刷卡完成後會再導回我們的頁面 (我們先前提供的ReturnURL
要用在這裡)。而導回我們的頁面,另一個要點是要處理PayToken
。
待我們將程式碼佈署上Heroku後,就可以馬上來試用。
建立新訂單,取回信用卡刷卡位置,點選導入刷卡網址:
進行刷卡,雖然永豐開發規格書上有提供測試用的刷卡卡號,但畢竟不是完全的公開資料,不確定被有心人士拿去亂使用會不會造成相關單位困擾,所以還是馬賽克一下。
在刷卡成功後,網頁回來是回來了,但卻發生了以下的錯誤。
500 Internal Server Error
原先因為Heroku上面我使用另一組production_settings設定檔,上面DEBUG是False,導致看不出原因。
以下是永豐的文件說提到,無論是ReturnURL或BackendURL都是以下面方式將PayToken傳入:
後來使用了F12
大法,透過Network方式查看Request的內容,發現如下內容。
於是解讀了一下,原先在ATM的BackendURL中,我是使用POST中將JSON內容從Raw Data方法取回,但一樣的方式會出現錯誤。
另外我再將DEBUG Mode打開後,確認他是透過POST Form
的方式回傳PayToken,而非JSON。
以此可證實,透過ReturnURL
回傳的PayToken值,是需要使用POST Form去抓取的。
(這部份永豐的開發規格書可能要註明一下)
上方的PayToken的值會和我等會兒下面頁面截圖上的值不同,因為頁面是後來全部修正完後重新上版跑過,所以兩者值不一樣是可想而知。
def card_return(request):
pay_token_dic = {"PayToken": request.POST.get("PayToken"), "ShopNo": request.POST.get("ShopNo")}
print(" --- PayToken: {}, ShopNo: {}".format(pay_token_dic["PayToken"], pay_token_dic["ShopNo"]))
create_new_paytoken(pay_token_dic["PayToken"])
update_order_by_paytoken(pay_token_dic)
return HttpResponse("PayToken: {}<br />ShopNo: {}".format(pay_token_dic["PayToken"], pay_token_dic["ShopNo"]))
首先,我們先直接從POST中取資料,而非先前的request.body
。取得後,一樣是需要將PayToken拿去重新經過一連串的加密包裝後取回付款狀態,並且更新。先前都寫好包裝好的程式碼,這時候就可以1分鐘內實作完成。
再看一下頁面,果然可以了!
當然,實際的電商頁面不會是這樣把PayToken印在畫面上,一切都是為了測試API的流程與驗證而已。真正要做的是將由PayToken問回來的付款結果,更新在畫面上,告知顧客他刷卡成功了。這部份就交給各位來實作了。
一樣的我們回到pgAdmin中看一下資料的更新狀態,也都符合我們的預期。!
這樣總算是將豐收款的兩大功能:ATM虛擬帳戶付款
與信用卡付款服務
完成了!