文章目的只有練習串接requset
部分,不是實作。實作這樣搞,一定會出事。
products
、order
。建議安裝gem "figaro"
。
$ rails new project_name
$ rails g scaffold product name price:integer
$ rails g model order
$ rails g controller orders
#seed
Product.create(
name: "測試商品",
price: 500
)
$ rails db:create db:migrate db:seed
簡易設定路徑。
root "products#index"
resources :products
resources :orders
這邊直接在product#index
選數量送出
<%= form_tag orders_path, method: :post do %>
<%= hidden_field_tag(:name, @product.name) %>
<%= hidden_field_tag(:price, @product.price) %>
<%= select_tag(:quantity, options_for_select([*1..4])) %>
<%= submit_tag "送出", name: nil, class: "btn btn-primary" %>
<% end %>
Ruby
測試文件直接功能化。訂單body
部分。
def order_id
"order#{SecureRandom.uuid}" #建議自制能不重複且獨立的編號就好。
end
def packages_id
"package#{SecureRandom.uuid}" #建議自制能不重複且獨立的編號就好。
end
def amount
params[:quantity].to_i * params[:price].to_i
#因為訂單簡單化,所以body的兩個amount共用。
end
def body
@body = { amount: amount,
currency: "TWD",
orderId: order_id,
packages: [ { id: packages_id,
amount: amount,
products: [ {
name: params[:name],
quantity: params[:quantity].to_i,
price: params[:price].to_i } ] } ],
redirectUrls: { confirmUrl: "http://127.0.0.1:3000/confitmUrl",
cancelUrl: "http://127.0.0.1:3000/cancelUrl" } }
end
當然如果order
有開較多欄位,也可訂單建立後save,也可以重複使用資料,才是較好作法。
訂單header
部分。
private
def header_nonce
@nonce = SecureRandom.uuid
end
def header
get_signature()
@header = {"Content-Type": "application/json",
"X-LINE-ChannelId": ENV["line_pay_ChannelID"],
"X-LINE-Authorization-Nonce": @nonce,
"X-LINE-Authorization": @signature }
end
def get_signature
secrect = ENV["lines_pay_ChannelSecret"]
signature_uri = "/v3/payments/request"
message = "#{secrect}#{signature_uri}#{@body.to_json}#{@nonce}"
hash = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secrect, message)
@signature = Base64.strict_encode64(hash)
end
header_nonce
、body
、header
因為要確保加密資料都正確,所以這三項都是before_action
用實體變數固定。
before_action :header_nonce, only:[:create]
before_action :body, only:[:create]
before_action :header, only:[:create]
post
部分,其實跟昨天長的的幾乎一樣。def create
response = JSON.parse(get_response.body)
if response["returnMessage"] == "Success."
redirect_to response["info"]["paymentUrl"]["web"]
#這邊做直接轉址。
else
puts response
#這個沒意義,應該要做怎麼處理錯誤,這邊只做印出觀察錯誤資訊。
end
end
private
def get_response
uri = URI.parse("https://sandbox-api-pay.line.me/v3/payments/request")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri, @header)
request.body = @body.to_json
response = http.request(request)
end
基本上這樣就可以發出正確請求,取得如昨天的回傳訊息,自動轉址到付款畫面。
當然正確文件撰寫不會這樣操作,order是重要文件,不會什麼欄位都沒開,還有直接把邏輯都寫在controller
應該會被宰掉,但只要開頭會了,一切就都好說。建立request
一開始有功能細分好,後面的confirm
與其他都幾乎是照抄,注意body
的不同及回傳的重要訊息就好。
Line_pay_api簡單練習就到這邊啦!
回傳資料中transactionId
與regKey
等是一定要紀錄的,未來串接其他部分都會用到,另外sandbox
沒有regKey
回傳值。
request api
中body
有一個選填選項options.payment.capture
是讓你選擇confirm
時自動確認或要賣家手動確認,但確認完後流程一樣,但實作上就會是分歧點。我是賣家我當然設定自動確認啦!要退款等之後再說 XD!!!