allpay_client 1.0.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +16 -9
- data/examples/server.rb +3 -7
- data/examples/views/index.erb +3 -17
- data/lib/allpay.rb +2 -2
- data/lib/allpay/client.rb +50 -15
- data/lib/allpay/core_ext/hash.rb +9 -0
- data/lib/allpay/errors.rb +6 -0
- data/lib/allpay/version.rb +1 -1
- data/spec/allpay_spec.rb +2 -18
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 289f14a5eea78b627c25e2ba352b8db3fefc0085
|
4
|
+
data.tar.gz: 33a5f66099a93de19b3a2d0fded4d3642bf195d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53a307012b9805ee5bd2c2f284d7eeaa6455b71d0b877d5ce00d1dc2bdf8e75910771e3dcc3a7c5d616c5fd3f7acab547d340c5a9061a02296b4f46f449fa952
|
7
|
+
data.tar.gz: c1e186805948c1339029b4bab674f2aa506687d7be994a41d07f69157de9f8c3a880eb71cf878dc05a77db55f14cc88af15c155a0315853e33007f3a4c530613
|
data/README.md
CHANGED
@@ -4,6 +4,10 @@
|
|
4
4
|
|
5
5
|
這是歐付寶 API 的 Ruby 包裝,更多資訊參考他們的[官方文件](https://www.allpay.com.tw/Content/files/%E5%85%A8%E6%96%B9%E4%BD%8D%E9%87%91%E6%B5%81%E4%BB%8B%E6%8E%A5%E6%8A%80%E8%A1%93%E6%96%87%E4%BB%B6.pdf)。
|
6
6
|
|
7
|
+
- 這不是 Rails 插件,只是個 API 包裝。
|
8
|
+
- 使用時只需要傳送需要的參數即可,不用產生檢查碼,`allpay_client` 會自己產生。
|
9
|
+
- 錯誤代碼太多且會不斷增加,筆者不另行撰寫,官方也建議查網站上的代碼清單。
|
10
|
+
|
7
11
|
## 安裝
|
8
12
|
|
9
13
|
```bash
|
@@ -13,13 +17,14 @@ gem install allpay_client
|
|
13
17
|
## 使用
|
14
18
|
|
15
19
|
```ruby
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
test_client = Allpay::Client.new(mode: :test)
|
21
|
+
production_client = Allpay::Client.new({
|
22
|
+
merchant_id: 'MERCHANT_ID',
|
23
|
+
hash_key: 'HASH_KEY',
|
24
|
+
hash_iv: 'HASH_IV'
|
21
25
|
})
|
22
|
-
|
26
|
+
|
27
|
+
test_client.request '/Cashier/QueryTradeInfo',
|
23
28
|
MerchantTradeNo: '0457ce27',
|
24
29
|
TimeStamp: Time.now.to_i
|
25
30
|
```
|
@@ -32,10 +37,10 @@ client.request '/Cashier/QueryTradeInfo',
|
|
32
37
|
- /CreditDetail/DoAction
|
33
38
|
- /Cashier/AioChargeback
|
34
39
|
|
35
|
-
每個 API
|
40
|
+
每個 API 有哪些參數建議直接參考歐付寶文件,注意幾點:
|
36
41
|
|
37
|
-
-
|
38
|
-
- `/Cashier/AioCheckOut` 回傳的內容是 HTML,這個請求應該是交給瀏覽器發送的,所以不應該寫出 `client.request '/Cashier/AioCheckOut'
|
42
|
+
- 使用時不用煩惱 `MerchantID` 與 `CheckMacValue`,正如上述範例一樣。
|
43
|
+
- `/Cashier/AioCheckOut` 回傳的內容是 HTML,這個請求應該是交給瀏覽器發送的,所以不應該寫出 `client.request '/Cashier/AioCheckOut'` 這樣的內容。
|
39
44
|
|
40
45
|
## Allpay::Client
|
41
46
|
|
@@ -43,8 +48,10 @@ client.request '/Cashier/QueryTradeInfo',
|
|
43
48
|
--- | --- | ---
|
44
49
|
`request(path, **params)` | `Net::HTTPResponse` | 發送 API 請求
|
45
50
|
`make_mac(**params)` | `String` | 用於產生 `CheckMacValue`,單純做加密,`params` 需要完整包含到 `MerchantID`
|
51
|
+
`verify_mac(**params)` | `Boolean` | 會於檢查收到的參數,其檢查碼是否正確,這用在歐付寶物的 `ReturnURL` 與 `PeriodReturnURL` 參數上。
|
46
52
|
`query_trade_info(merchant_trade_number, platform = nil)` | `Hash` | `/Cashier/QueryTradeInfo` 的捷徑方法,將 `TimeStamp` 設定為當前時間
|
47
53
|
`query_period_credit_card_trade_info(merchant_trade_number)` | `Hash` | `/Cashier/QueryPeriodCreditCardTradeInfo` 的捷徑方法,將 `TimeStamp` 設定為當前時間
|
54
|
+
`generate_checkout_params` | `Hash` | 用於產生 `/Cashier/AioCheckOut` 表單需要的參數,`MerchantTradeDate`、`MerchantTradeNo`、`PaymentType`,可省略。
|
48
55
|
|
49
56
|
## 使用範例
|
50
57
|
|
data/examples/server.rb
CHANGED
@@ -4,12 +4,9 @@ require 'sinatra'
|
|
4
4
|
require 'allpay'
|
5
5
|
|
6
6
|
get '/' do
|
7
|
-
client = Allpay::Client.new(
|
8
|
-
@params = {
|
9
|
-
MerchantID: client.merchant_id,
|
7
|
+
client = Allpay::Client.new(mode: :test)
|
8
|
+
@params = client.generate_checkout_params({
|
10
9
|
MerchantTradeNo: SecureRandom.hex(4),
|
11
|
-
MerchantTradeDate: Time.now.strftime('%Y/%m/%d %H:%M:%S'),
|
12
|
-
PaymentType: 'aio',
|
13
10
|
TotalAmount: 1000,
|
14
11
|
TradeDesc: '腦袋有動工作室',
|
15
12
|
ItemName: '物品一#物品二',
|
@@ -21,7 +18,6 @@ get '/' do
|
|
21
18
|
Frequency: 1,
|
22
19
|
ExecTimes: 12,
|
23
20
|
PeriodReturnURL: 'http://requestb.in/158bu8e1'
|
24
|
-
}
|
25
|
-
@mac = client.make_mac(@params)
|
21
|
+
})
|
26
22
|
erb :index
|
27
23
|
end
|
data/examples/views/index.erb
CHANGED
@@ -6,23 +6,9 @@
|
|
6
6
|
</head>
|
7
7
|
<body>
|
8
8
|
<form action="http://payment-stage.allpay.com.tw/Cashier/AioCheckOut" method="post">
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<input type="text" name="PaymentType" value="<%= @params[:PaymentType] %>">
|
13
|
-
<input type="text" name="TotalAmount" value="<%= @params[:TotalAmount] %>">
|
14
|
-
<input type="text" name="TradeDesc" value="<%= @params[:TradeDesc] %>">
|
15
|
-
<input type="text" name="ItemName" value="<%= @params[:ItemName] %>">
|
16
|
-
<input type="text" name="ReturnURL" value="<%= @params[:ReturnURL] %>">
|
17
|
-
<input type="text" name="ClientBackURL" value="<%= @params[:ClientBackURL] %>">
|
18
|
-
<input type="text" name="ChoosePayment" value="<%= @params[:ChoosePayment] %>">
|
19
|
-
<input type="text" name="PeriodAmount" value="<%= @params[:PeriodAmount] %>">
|
20
|
-
<input type="text" name="PeriodType" value="<%= @params[:PeriodType] %>">
|
21
|
-
<input type="text" name="Frequency" value="<%= @params[:Frequency] %>">
|
22
|
-
<input type="text" name="ExecTimes" value="<%= @params[:ExecTimes] %>">
|
23
|
-
<input type="text" name="PeriodReturnURL" value="<%= @params[:PeriodReturnURL] %>">
|
24
|
-
|
25
|
-
<input type="text" name="CheckMacValue" value="<%= @mac %>">
|
9
|
+
<% @params.each do |k, v| %>
|
10
|
+
<input type="text" name="<%= k %>" value="<%= v %>">
|
11
|
+
<% end %>
|
26
12
|
<input type="submit">
|
27
13
|
</form>
|
28
14
|
</body>
|
data/lib/allpay.rb
CHANGED
data/lib/allpay/client.rb
CHANGED
@@ -1,46 +1,73 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'json'
|
3
|
+
require 'cgi'
|
4
|
+
require 'digest'
|
5
|
+
require 'allpay/errors'
|
6
|
+
require 'allpay/core_ext/hash'
|
3
7
|
|
4
8
|
module Allpay
|
5
9
|
class Client
|
6
10
|
PRODUCTION_API_HOST = 'https://payment.allpay.com.tw'.freeze
|
7
11
|
TEST_API_HOST = 'http://payment-stage.allpay.com.tw'.freeze
|
12
|
+
TEST_OPTIONS = {
|
13
|
+
merchant_id: '2000132',
|
14
|
+
hash_key: '5294y06JbISpM5x9',
|
15
|
+
hash_iv: 'v77hoKGq4kWxNNIS'
|
16
|
+
}.freeze
|
8
17
|
|
9
|
-
|
18
|
+
attr_reader :options
|
10
19
|
|
11
|
-
def initialize
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
20
|
+
def initialize options = {}
|
21
|
+
@options = {mode: :production}.merge!(options)
|
22
|
+
case @options[:mode]
|
23
|
+
when :production
|
24
|
+
option_required! :merchant_id, :hash_key, :hash_iv
|
25
|
+
when :test
|
26
|
+
@options = TEST_OPTIONS.merge(options)
|
27
|
+
else
|
28
|
+
raise InvalidMode, %Q{option :mode is either :test or :production}
|
29
|
+
end
|
30
|
+
@options.freeze
|
17
31
|
end
|
18
32
|
|
19
33
|
def api_host
|
20
|
-
case mode
|
34
|
+
case @options[:mode]
|
21
35
|
when :production then PRODUCTION_API_HOST
|
22
36
|
when :test then TEST_API_HOST
|
23
|
-
else raise '`mode` is either :test or :production (default)'
|
24
37
|
end
|
25
38
|
end
|
26
39
|
|
27
40
|
def make_mac params = {}
|
28
41
|
raw = params.sort.map!{|k,v| "#{k}=#{v}"}.join('&')
|
29
|
-
padded = "HashKey=#{@hash_key}&#{raw}&HashIV=#{@hash_iv}"
|
42
|
+
padded = "HashKey=#{@options[:hash_key]}&#{raw}&HashIV=#{@options[:hash_iv]}"
|
30
43
|
url_encoded = CGI.escape(padded).downcase!
|
31
44
|
Digest::MD5.hexdigest(url_encoded).upcase!
|
32
45
|
end
|
33
46
|
|
34
47
|
def verify_mac params = {}
|
35
|
-
|
36
|
-
|
48
|
+
stringified_keys = params.stringify_keys
|
49
|
+
check_mac_value = stringified_keys.delete('CheckMacValue')
|
50
|
+
make_mac(stringified_keys) == check_mac_value
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_params overwrite_params = {}
|
54
|
+
result = overwrite_params.clone
|
55
|
+
result[:MerchantID] = @options[:merchant_id]
|
56
|
+
result[:CheckMacValue] = make_mac(result)
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
def generate_checkout_params overwrite_params = {}
|
61
|
+
generate_params({
|
62
|
+
MerchantTradeDate: Time.now.strftime('%Y/%m/%d %H:%M:%S'),
|
63
|
+
MerchantTradeNo: SecureRandom.hex(4),
|
64
|
+
PaymentType: 'aio'
|
65
|
+
}.merge!(overwrite_params))
|
37
66
|
end
|
38
67
|
|
39
68
|
def request path, params = {}
|
40
|
-
params[:MerchantID] = @merchant_id
|
41
|
-
params[:CheckMacValue] = make_mac(params)
|
42
69
|
api_url = URI.join(api_host, path)
|
43
|
-
Net::HTTP.post_form api_url, params
|
70
|
+
Net::HTTP.post_form api_url, generate_params(params)
|
44
71
|
end
|
45
72
|
|
46
73
|
def query_trade_info merchant_trade_number, platform = nil
|
@@ -60,5 +87,13 @@ module Allpay
|
|
60
87
|
TimeStamp: Time.now.to_i
|
61
88
|
JSON.parse(res.body)
|
62
89
|
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def option_required! *option_names
|
94
|
+
option_names.each do |option_name|
|
95
|
+
raise MissingOption, %Q{option "#{option_name}" is required.} if @options[:option_name].nil?
|
96
|
+
end
|
97
|
+
end
|
63
98
|
end
|
64
99
|
end
|
data/lib/allpay/version.rb
CHANGED
data/spec/allpay_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
require 'securerandom'
|
4
4
|
describe Allpay::Client do
|
5
5
|
before :all do
|
6
|
-
@client = Allpay::Client.new(
|
6
|
+
@client = Allpay::Client.new(mode: :test)
|
7
7
|
end
|
8
8
|
|
9
9
|
it '#api /Cashier/AioCheckOut' do
|
@@ -41,7 +41,7 @@ describe Allpay::Client do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it '#make_mac' do
|
44
|
-
client = Allpay::Client.new(merchant_id: '12345678', hash_key: 'xdfaefasdfasdfa32d', hash_iv: 'sdfxfafaeafwexfe')
|
44
|
+
client = Allpay::Client.new(merchant_id: '12345678', hash_key: 'xdfaefasdfasdfa32d', hash_iv: 'sdfxfafaeafwexfe', mode: :test)
|
45
45
|
mac = client.make_mac({
|
46
46
|
ItemName: 'sdfasdfa',
|
47
47
|
MerchantID: '12345678',
|
@@ -70,20 +70,4 @@ describe Allpay::Client do
|
|
70
70
|
MerchantTradeNo: '355313'
|
71
71
|
expect(result).to eq true
|
72
72
|
end
|
73
|
-
|
74
|
-
it '#verify_mac with string hash' do
|
75
|
-
result = @client.verify_mac 'RtnCode' => '1',
|
76
|
-
'PaymentType' => 'Credit_CreditCard',
|
77
|
-
'TradeAmt' => '700',
|
78
|
-
'PaymentTypeChargeFee' => '14',
|
79
|
-
'PaymentDate' => '2015/02/07 14:21:00',
|
80
|
-
'SimulatePaid' => '0',
|
81
|
-
'CheckMacValue' => '3AF270CCCFA58CA0349F4FD462E21643',
|
82
|
-
'TradeDate' => '2015/02/07 14:20:47',
|
83
|
-
'MerchantID' => '2000132',
|
84
|
-
'TradeNo' => '1502071420478656',
|
85
|
-
'RtnMsg' => '交易成功',
|
86
|
-
'MerchantTradeNo' => '355313'
|
87
|
-
expect(result).to eq true
|
88
|
-
end
|
89
73
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: allpay_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jian Weihang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -85,6 +85,8 @@ files:
|
|
85
85
|
- examples/views/index.erb
|
86
86
|
- lib/allpay.rb
|
87
87
|
- lib/allpay/client.rb
|
88
|
+
- lib/allpay/core_ext/hash.rb
|
89
|
+
- lib/allpay/errors.rb
|
88
90
|
- lib/allpay/version.rb
|
89
91
|
- lib/allpay_client.rb
|
90
92
|
- spec/allpay_spec.rb
|