智付通金流整合
今年初用 rails 做了個系統與智付通的金流整合。整合過程其實蠻單純的,稍微將實做整合的過程記錄在這邊。
當初整合智付通的流程是,使用者在我站挑選要購買的商品後,到結帳頁面輸入送貨地址,是否要開索取發票,是否使用折價卷或點數扣抵等等資訊。後。將使用者與確認完整的購買資訊 POST 到智付通的付款頁面。待使用者付款完成後,智付通會將使用者再導回我站,並且傳回付款結果等資訊告知我站是否已成功付款;同時背景也會呼叫我站的 Notify URL。
大概整合內容如上,很簡單。
幾個整合的重點:
- 跳轉到智付通的頁面要用 Form POST 把玩家導過去,要整頁導過去。智付通文件有說明放 iframe 裡導頁會有問題。
- 智付通回饋付款結果有兩個
- ReturnURL (前景) 讓使用者在付款完後(不管成功失敗) 導回 ReturnURL
- NotifyURL (背景) 會在背景把支付完後的資訊打給 NotifyURL
- 加解密的方式
這邊遇到一點問題的就是加解密,所以說明一下。其他頁面跳轉大部分的金流好像都差不多。
加解密的方式
整個加密重點在這段,智付通的 API 文件上提供 mcrypt_encrypt(CRYPT_RIJNDAEL_128, key, CRYPT_MODE_CBC, iv)
(PHP) 與 RijndaelManaged()
(.NET) 的 AES 加密範例可參考。
用 ruby 有遇到一點麻煩,因為先參考了mcrypt 的範例,一開始就直接用 OpenSSL 來加密,但是 encrypt 出的字串與智富通的不合。參考這篇 Stack Overflow 的答案 可知,在 ruby 裡用 OpenSSL::Cipher 與 mcrypt 執行起來的行為是不一樣的。將 256 bit 的 key 傳入 mcrypt( ) 他會自己改為 rijndael-256 的編碼,而 OpenSSL::Cipher 只會拿前 128 bits 。
而智付通給的key 是 256 bits 的
權衡之下,還是用了 php-mcrypt ….讓 mcrypt 自己去調整編碼方式
# 這個 hash 轉成 QUERY STRING 涵式是這邊抄來的:
# https://justanothercoder.wordpress.com/2009/04/24/converting-a-hash-to-a-query-string-in-ruby/
payload_str = Common::hash_to_querystring(@payload)# 加密 payload
crypto = Mcrypt.new(:rijndael_128, :cbc, key, iv, :pkcs)
ciphertext = crypto.encrypt(payload_str)ciphertext.unpack("H*").join()
最後,組出單向的核對字串:
def trade_sha(tradeInfo)
key = Settings.payment.spgateway.key
iv = Settings.payment.spgateway.iv Digest::SHA256.hexdigest("HashKey=#{key}&#{tradeInfo}&HashIV=#{iv}").upcase
end
在智付通把使用者導回 ReturnURL 的時後同時也會送來一串交易結果的 payload,這個 payload 的解密方式如下
def decrypt
key = Settings.payment.spgateway.key
iv = Settings.payment.spgateway.iv crypto = Mcrypt.new(:rijndael_128, :cbc, key, iv)
plaintext = crypto.decrypt([@payload].pack('H*')) # 移除解密後多出來的 padding
# 因為知道加密的內容是 JSON 所以可以用這樣的懶惰方式移除 padding...
plaintext[0, plaintext.rindex('}') + 1]
end
記得好像就醬,目前好像開立電子發票,信用卡請款等等都可用上述的方式加解密。整合來說並不算太複雜。
複雜的反而是開電子發票後如果客人要退貨,依照相關法規要退發票重新申報這些。如果可以直接進智付通後台操作那就還好…不然靠 API 要弄電子發票真的很繁雜….