iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
自我挑戰組

初級紅寶石魔法師心得分享。系列 第 28

D-2.Line_pay_api 串接(三) Rails 串接

文章目的只有練習串接requset部分,不是實作。
實作這樣搞,一定會出事。

1.建立專案及productsorder

建議安裝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

2.建立訂單。

這邊直接在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_noncebodyheader因為要確保加密資料都正確,所以這三項都是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簡單練習就到這邊啦!

  • 回傳資料中transactionIdregKey等是一定要紀錄的,未來串接其他部分都會用到,另外sandbox沒有regKey回傳值。

  • request apibody有一個選填選項options.payment.capture是讓你選擇confirm時自動確認或要賣家手動確認,但確認完後流程一樣,但實作上就會是分歧點。
    我是賣家我當然設定自動確認啦!要退款等之後再說 XD!!!


上一篇
D-3.Line_pay_api 串接(二) V3 Request API
下一篇
D-1, length、size & count
系列文
初級紅寶石魔法師心得分享。30

尚未有邦友留言

立即登入留言