iT邦幫忙

0

[不做怎麼知道系列之Android開發者的30天後端養成故事 Day27] - 可以付錢給我了! #串接第三方金流 #綠界 #ShowMeTheMoney

Sam 2020-03-10 22:15:0411631 瀏覽

https://ithelp.ithome.com.tw/upload/images/20200310/20124548on3wwPsugo.png

哈囉,我們又見面了,前幾天我們把 Line 的 ChatBot 番外篇 完成了,今天我們來試著串接「第三方金流」的服務,在開始之前必須先釐清一件事:「第三方金流行動支付電子支付差在哪裡?」

第三方金流 vs. 行動支付 vs. 電子支付

詳細可以參考 行動支付?第三方支付?電子支付?別搞混了它們三個都不一樣!| 電獺少女,第三方金流主要功能就是,先向顧客代收交易金額,等交易完全成功,例如是顧客收到貨品確認沒問題,才撥款給電商平台,而第三方金流也不是免費的,錢經過了它的手,怎麼有不收過路費的道理呢 XD,所以就有 手續費 的存在拉,關於手續費和服務內容,也就是各家第三方金流所競爭的關鍵。

https://ithelp.ithome.com.tw/upload/images/20200310/20124548DzzYp3O2nL.png

舉例來說

第三方金流就是你在電商網頁(博客來、蝦皮等等)上,進行結帳時會跳轉到一個要你輸入信用卡卡號的頁面,像下圖,要求你 填入卡號 或 選擇其他付款方式 的頁面,這就是第三方金流的服務。

https://ithelp.ithome.com.tw/upload/images/20200310/20124548mAGB2zhjuz.png

那我們就來試試看第三方金流的服務

今天我們要來嘗試的第三方金流廠商是 綠界,可以說是台灣最早的第三方金流廠商,除了綠界還有其他廠商,不過各家廠商的糾葛,就像連續劇一樣的情節了,我也不是很瞭解它們的關係 XD

綠界-台灣最早的第三方金流

有提供 Python SDK,支援以下支付方式

  • 信用卡(一次付清、分期付款)
  • 網路ATM
  • ATM櫃員機
  • 超商代碼
  • 超商條碼
  • Google Pay

除了支援 All in One 金流之外,還有提供 物流整合服務,包含超商(全家、7-11、萊爾富)取貨付款,還有黑貓、宅配通,還有提供 電子發票的服務,算是相當完整,但手續費也不低 XD,文章下面有 2020 年 3 月的手續費表格截圖供參考。

先來註冊綠界

https://ithelp.ithome.com.tw/upload/images/20200310/20124548X8nOHB1chQ.png

驗證完 → 填寫基本資料,到目前的步驟沒什麼問題,就是基本的註冊會員,下一步的收款設定比較麻煩

收款設定

這步驟需要決定,你是什麼商店、你賣哪些商品、提供身分或公司證明

https://ithelp.ithome.com.tw/upload/images/20200310/20124548NzcgZbKgZl.png

https://ithelp.ithome.com.tw/upload/images/20200310/20124548KbQjMJFXUI.png

因為我是個人戶,所以我放身分證正反面

https://ithelp.ithome.com.tw/upload/images/20200310/201245482bEvhEbvMN.png

到目前為止,已經可以接收非信用卡的收款了,如果要開通 接受信用卡收款 的功能、提領 的功能,需要另外由系統驗證證件,需要 2~3 個工作天的驗證流程,但實際上我提出之後在半小時左右就都驗證過了。

設定提領帳戶

https://ithelp.ithome.com.tw/upload/images/20200310/20124548SnmCxXjzwn.png

申請完成後,長這樣

https://ithelp.ithome.com.tw/upload/images/20200310/20124548QFHWZLayT8.png

https://ithelp.ithome.com.tw/upload/images/20200310/20124548kWmL0qkypV.png

建立收款連結

如果只是簡單的需要收款,可以直接透過「建立收款連結」,就可以產生一組 網址QR code,像是 https://p.ecpay.com.tw/3E441 這樣的一串網址,而你只要把這組網址 或 QR code,轉貼到顧客看的到的地方(可能是你的文章或者是個人網頁等等),顧客就可以點進去網址,使用刷卡或超商付款等等的方式,透過各種方式給你錢 !

實際建立收款連結的過程

進到綠界的管理後台,點建立收款連結,然後填資料,建立一個固定金額的商品,如果有很多項商品,就需要建立多筆連結,如果你有串 金流 SDK 就不用手動新增了,可以透過後端程式邏輯,把你原本就有的訂單系統結合 SDK,新增 商品 與 收款連結 的對應關係。

https://ithelp.ithome.com.tw/upload/images/20200310/20124548b06bxU2Hyv.png

https://ithelp.ithome.com.tw/upload/images/20200310/20124548o8xct8HuEW.png

因為各種付款方式有金額範圍限制,為了符合所有付款方式的最低限度,所以我才設 31 元這個奇怪的數字 XD

https://ithelp.ithome.com.tw/upload/images/20200310/20124548nnwDof9AIq.png

建立之後會得到一個連結、QR code,你只要把這串 網址 或 QR code 轉貼到 文章 或 私訊給你的顧客,他們就可以透過第三方金流來付款給你。

試著用「收款連結」來結帳看看

現在要模擬顧客刷卡的過程,自己結帳給自己 XD,點進去透過綠界產生的收款連結,就會跳轉到綠界的結帳頁面。

https://ithelp.ithome.com.tw/upload/images/20200310/20124548hW7qUg8ISC.png

點下一步→ 填付款人的基本資料

https://ithelp.ithome.com.tw/upload/images/20200310/20124548Ts3mzb7wYI.png

填完基本資料後,選擇付款方式,因為這筆訂單是 31元,符合各類付款方式的範圍,就可以選各種付款方式。

https://ithelp.ithome.com.tw/upload/images/20200310/20124548OUAgP1m68O.png

填完信用卡資訊後,就近到熟悉的手機驗證頁面,可以看到特約商店是 GreenWorld 綠界,相當於是我的信用卡付款給 綠界,由 綠界 代管,等整筆訂單交易成功,綠界 再把訂單的 31 元扣除手續費,再放到 綠界帳戶,需要的時候再申請 提領,將放在 綠界帳戶 的錢,匯款到個人/公司銀行帳戶。

https://ithelp.ithome.com.tw/upload/images/20200310/201245480U3TcMW8MQ.png

最後結帳成功

https://ithelp.ithome.com.tw/upload/images/20200310/20124548WGUzurz8gh.png

到綠界後台檢查訂單狀況

在綠界的後台可以查詢每一筆訂單,包括 消費者姓名手機email付款方式付款狀態等等,也可以決定是否 退款

https://ithelp.ithome.com.tw/upload/images/20200310/20124548iVtMFRrxTu.png

被扣了 5 元,在國內使用 信用卡一次付清 的手續費是 2.75%,因為 31 元的 2.75% 低於最低手續費 5 元,所以就被收了 5 元,對於小額收款的電商平台來說,這是一個很大的抽成。

以我這一筆 31 元的訂單來講,就相當於是 16% 的手續費,非常高。

https://ithelp.ithome.com.tw/upload/images/20200310/20124548jfgbMc6vPK.png

這張費率表是 2020-03-09 的截圖,不一定符合你現在觀看這篇文章時的手續費率。

在綠界後台也能處理取消訂單

因為是使用信用卡付款,還沒請款時,退款相對簡單,如果是已經請款了 或 客戶用的是別種結帳方式,那就要我們自己處理退款,也就是錢已經到綠界了,綠界是不會幫忙處理退款的,你需要用另外的帳戶來退款給顧客。

https://ithelp.ithome.com.tw/upload/images/20200310/20124548KX68xFSR77.png

https://ithelp.ithome.com.tw/upload/images/20200310/20124548193PB04sGw.png

到這邊,已經瞭解綠界的操作流程了,再來就是後端Server 串接 第三方金流SDK 的部分。


Python 串接 綠界 All in One 金流 SDK

綠界提供 PHP、Java、Ruby、Node.js、C#(.Net) 和 Python,六種的程式語言的 SDK,而我們這篇使用的 Python 的 All in One SDK,在官方提供的 Github 上,除了有 SDK 之外,還有數個 sample codes,我們這邊參考的是 sample_create_order_ALL.py 這個 sample code。

導入 SDK

首先需要先把 All in One SDK 放到 Django 專案底下

https://ithelp.ithome.com.tw/upload/images/20200310/201245483Gj5ZB4tUO.png

參考 sample code 來使用 SDK

原本 sample code 長這樣,落落長,而我們真的需要修改的地方,用註解的方法標註,真正的修改方法需要參考官方文件,我寫文章時所參考的文件版本是 5.1.47 (2020-02-10)

sample_create_order_ALL.py 複製下來,並重新命名為 ecpay_testing.py,放在 shop/ 底下 (和 views.py 同層級),且把整個用一個叫做 main 的 function 包起來。

import importlib.util

# 第一個需要修改的,就是 SDK 路徑
spec = importlib.util.spec_from_file_location(
    "ecpay_payment_sdk",    # SDK檔名不用改
    "/path/to/ecpay_payment_sdk.py"    # 改成 django app name/sdk name,
                                       # 以我把 SDK 放到 shop 為例,
                                       # 我就是改成 "shop/ecpay_payment_sdk.py"
)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
from datetime import datetime

def main():
	# 第二個需要修改的,商品資訊
	order_params = {
        'MerchantTradeNo': datetime.now().strftime("NO%Y%m%d%H%M%S"),
		'StoreID': '',
		'MerchantTradeDate': datetime.now().strftime("%Y/%m/%d %H:%M:%S"),
		'PaymentType': 'aio',
		'TotalAmount': 2000,         # 商品金額
		'TradeDesc': '訂單測試',      # 商品描述
		'ItemName': '商品1#商品2',    # 商品名稱,用井字號當分行
		'ReturnURL': 'https://www.ecpay.com.tw/return_url.php', # 顧客填完付款資料後的跳轉頁面
		'ChoosePayment': 'ALL',      # 顧客的付費方式
        
        # 結帳後,先導到 OrderResultURL,從綠界頁面跳回的頁面
        # 如果沒有參數才會跳轉到 ClientBackURL
		'ClientBackURL': 'https://www.ecpay.com.tw/client_back_url.php',
		'ItemURL': 'https://www.ecpay.com.tw/item_url.php',     # 商品資訊頁面
		'Remark': '交易備註',         # 備註文字
		'ChooseSubPayment': '',
        
        # 結帳成功/失敗後的結果頁面,告知顧客本次的結帳結果
        'OrderResultURL': 'https://www.ecpay.com.tw/order_result_url.php', 
		'NeedExtraPaidInfo': 'Y',
		'DeviceSource': '',
		'IgnorePayment': '',
		'PlatformID': '',
		'InvoiceMark': 'N',
		'CustomField1': '',
        'CustomField2': '',
		'CustomField3': '',
		'CustomField4': '',
		'EncryptType': 1,
    }
		
	extend_params_1 = {
		'ExpireDate': 7,    # 商品上架期限
		'PaymentInfoURL': 'https://www.ecpay.com.tw/payment_info_url.php',  #付款資訊頁面
		'ClientRedirectURL': '',  # 看完付款資訊,要重導到哪裡
	}
		
	extend_params_2 = {
		'StoreExpireDate': 15,
		'Desc_1': '',
		'Desc_2': '',
		'Desc_3': '',
		'Desc_4': '',
		'PaymentInfoURL': 'https://www.ecpay.com.tw/payment_info_url.php',
		'ClientRedirectURL': '',
    }
	
	extend_params_3 = {
        'BindingCard': 0,
		'MerchantMemberID': '',
    }
		
	extend_params_4 = {
		'Redeem': 'N',
		'UnionPay': 0,
    }
	
	# 發票資訊
	inv_params = {
		# 'RelateNumber': 'Tea0001', # 特店自訂編號
		# 'CustomerID': 'TEA_0000001', # 客戶編號
		# 'CustomerIdentifier': '53348111', # 統一編號
		# 'CustomerName': '客戶名稱',
		# 'CustomerAddr': '客戶地址',
		# 'CustomerPhone': '0912345678', # 客戶手機號碼
		# 'CustomerEmail': 'abc@ecpay.com.tw',
		# 'ClearanceMark': '2', # 通關方式
		# 'TaxType': '1', # 課稅類別
		# 'CarruerType': '', # 載具類別
		# 'CarruerNum': '', # 載具編號
		# 'Donation': '1', # 捐贈註記
		# 'LoveCode': '168001', # 捐贈碼
		# 'Print': '1',
		# 'InvoiceItemName': '測試商品1|測試商品2',
		# 'InvoiceItemCount': '2|3',
		# 'InvoiceItemWord': '個|包',
		# 'InvoiceItemPrice': '35|10',
		# 'InvoiceItemTaxType': '1|1',
		# 'InvoiceRemark': '測試商品1的說明|測試商品2的說明',
		# 'DelayDay': '0', # 延遲天數
        # 'InvType': '07', # 字軌類別
	}
		
	# 建立實體
	ecpay_payment_sdk = module.ECPayPaymentSdk(
        # 參考綠界後台->系統開發管理->系統界接設定,開發時有測試用的 商店ID
        MerchantID='2000132',
        
        # 參考綠界後台->系統開發管理->系統界接設定,開發時有測試用的 HashKey
        HashKey='5294y06JbISpM5x9',
        
        # 參考綠界後台->系統開發管理->系統界接設定,開發時有測試用的 HashIV
        HashIV='v77hoKGq4kWxNNIS'
	)
	
	# 合併延伸參數
	order_params.update(extend_params_1)
	order_params.update(extend_params_2)
	order_params.update(extend_params_3)
	order_params.update(extend_params_4)
		
	# 合併發票參數
	order_params.update(inv_params)
		
	try:
		# 產生綠界訂單所需參數
		final_order_params = ecpay_payment_sdk.create_order(order_params)
		
		# 產生 html 的 form 格式
		action_url = 'https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5'  # 測試環境
		# action_url = 'https://payment.ecpay.com.tw/Cashier/AioCheckOut/V5' # 正式環境
		html = ecpay_payment_sdk.gen_html_post_form(action_url, final_order_params)

		# 最後產出 html,回傳回去顯示此 html
		return html
	except Exception as error:
		print('An exception happened: ' + str(error))

views.py

導入 ecpay_testing.pymain()

from .ecpay_testing import main

@csrf_exempt
def ecpay_view(request):
    return HttpResponse(main())

urls.py

把這個測試頁面,綁在 ecpay/ 的網域底下,所以 urls.py 長這樣

urlpatterns = [
	...
    path('ecpay/', ecpay_view),
]

Djano 跑起來

$ python manage.py runserver

訪問 127.0.0.1:8000/ecpay/

進入到測試頁面

https://ithelp.ithome.com.tw/upload/images/20200310/20124548HIaKAhsHs8.png

在結帳前,還會告知目前是測試環境

https://ithelp.ithome.com.tw/upload/images/20200310/20124548hP2BDnwQiP.png

到目前為止,算是初次使用 綠界所提供的 All in One SDK,還沒有真正串接起來,因為中間還漏了 CheckMacValue 的驗證流程,在文件的第 43 頁有解釋驗證流程該怎麼進行,但我暫時還沒有要完整的接起來,就不浪費時間在確認驗證流程了,可以參考【Flask 教學】Python 綠界金流 API 信用卡串接 | Max行銷誌,雖然我用了它的方法還是驗證失敗 QQ

單日心得總結

串接 SDK 最麻煩的就是 驗證,尤其還有 加解密編碼 的問題,非常麻煩,需要一步一步核對文件所描述的步驟,去確認每一步的輸出都是正確的,非常耗時間跟腦力,尤其是邊做的時候,邊腦中出現一句話「接起來是應該的,接不起來是你太弱」,就會覺得心累 XD

我就帶大家走到這步,後續驗證的苦差事就交給各位自己解決了,尤其是 程式語言作業系統預設編碼不一致,非常容易出錯,就算我今天做出來了,放到不同的作業系統說不定又不行,所以必須把 收到的資料 和 送出的資料 的編碼寫清楚,確保每次進來和出去的編碼符合文件需求。

這系列終於要結束了,很期待下一個系列的到來,又可以替自己刷新一套世界觀了~

我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。


https://ithelp.ithome.com.tw/upload/images/20200219/20124548meDsnCPamL.png


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
chris
iT邦新手 5 級 ‧ 2022-10-17 17:55:17

不好意思,想問一下,當確認付款完後,到入以下頁面後
https://www.ecpay.com.tw/order_result_url.php#
出現以下錯誤訊息
Sorry! 很抱歉,目前網頁無回應,請重新整理或稍後再試!已通知相關人員協助處理。
想請問不知道樓主有沒有經驗,這個錯誤的原因呢

Sam iT邦新手 4 級 ‧ 2022-10-18 08:56:53 檢舉

嗨,

短答案

把建立訂單的 OrderResultURL 參數拿掉就好了


完整解釋

綠界的文件來看,在建立綠界訂單的時候,有幾個比較像的參數要注意:

  1. OrderResultURL: (選填)
    • 官方解釋:Client端回傳付款結果網址
    • 個人理解:與 ClientBackURL 只能擇一填,差別在於 ClientBackURL 不會帶付款結果,而 OrderResultURL 會帶付款結果
  2. ClientBackURL: (選填)
    • 官方解釋:Client端返回特店的按鈕連結
    • 個人理解:同上
  3. ReturnURL: (必填)
    • 官方解釋:付款完成通知回傳網址
    • 個人理解:Server 要多開一支 POST API 給綠界,當使用者付款完畢,或取消付款,綠界都會發付款結果給我們的 Server

這幾個真的很容易搞混,我自己每次要接的時候,都還要回來看文件QQ

所以以你的情況來說,只要把 OrderResultURL 拿掉,付款後就不會跳出你剛講的頁面

chris iT邦新手 5 級 ‧ 2022-10-19 10:44:27 檢舉

成功解決了!非常感謝您,原來是我還沒有完全理解他的code!!謝謝您的文章~

Sam iT邦新手 4 級 ‧ 2022-10-30 10:35:46 檢舉

不客氣~

順便推廣一下我自己哈哈哈,我還有自己的 YT 頻道,有興趣可以訂閱~

我要留言

立即登入留言