pay2go_client 1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 94c744431068dcfe778555adc0b846e716c240ec
4
+ data.tar.gz: 69ef98e01e9a55a5f49d993fff121bc4b667567f
5
+ SHA512:
6
+ metadata.gz: 5799cd9ec1151aa49c81d73b34a81b20d2c2119ddcf25065518d6b6ca8c2a19d7b46fb296f4ac68e019f9a7394fb6050b6ac940c4e4b4999958aa7cd751c241c
7
+ data.tar.gz: 11e7bcfbfb562ff6cd08b9f80213345ceef349cfd485dc806975459834696ed7aedaca441680b0c21ff3c75c689a282bdbd86a19bf746c07de9333d3ae01f836
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ - 2.2.0
5
+ - 2.1.5
6
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Calvert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,161 @@
1
+ [![Build Status](https://travis-ci.org/CalvertYang/pay2go.svg?branch=master)](https://travis-ci.org/CalvertYang/pay2go)
2
+
3
+ # 智付寶 Pay2go
4
+
5
+ 這是智付寶 API 的 Ruby 包裝,更多資訊請參閱 [API 文件專區](https://www.pay2go.com/info/site_description/api_description)。
6
+
7
+ - 這不是 Rails 插件,只是個 API 包裝。
8
+ - 使用時只需要傳送需要的參數即可,不用產生檢查碼,`pay2go_client` 會自己產生。
9
+ - 感謝[大兜](https://github.com/tonytonyjan)撰寫的 [allpay](https://github.com/tonytonyjan/allpay)
10
+
11
+ ## 安裝
12
+
13
+ ```bash
14
+ gem install pay2go_client
15
+ ```
16
+
17
+ ## 使用
18
+
19
+ ```ruby
20
+ test_client = Pay2go::Client.new({
21
+ merchant_id: 'MERCHANT_ID',
22
+ hash_key: 'HASH_KEY',
23
+ hash_iv: 'HASH_IV',
24
+ mode: :test
25
+ })
26
+
27
+ production_client = Pay2go::Client.new({
28
+ merchant_id: 'MERCHANT_ID',
29
+ hash_key: 'HASH_KEY',
30
+ hash_iv: 'HASH_IV'
31
+ })
32
+
33
+ test_client.query_trade_info({
34
+ MerchantOrderNo: '4e19cab1',
35
+ Amt: 100
36
+ })
37
+ ```
38
+
39
+ 本文件撰寫時,智付寶共有 5 個 API:
40
+
41
+ API 名稱 | 說明
42
+ --- | ---
43
+ MPG API | MPG(Multi Payment Gateway),單一串接多種支付方式。<br>透過 MPG API 可串接平台提供的所有支付方式。
44
+ 交易狀態查詢 API | 透過交易查詢 API 可自動化查核所有交易是否同步更新付款資訊。
45
+ 信用卡-取消授權模組 API | 透過取消授權 API,可進行信用卡交易授權取消,以返還持卡人及商店信用卡額度。
46
+ 信用卡-請退款模組 API | 透過請退款 API,可進行信用卡交易的請退款。
47
+ 信用卡-定期定額 API | 透過信用卡定期定額 API,可進行信用卡定期定額交易。
48
+
49
+ 詳細 API 參數請參閱智付寶技術串接手冊,注意幾點:
50
+
51
+ - 使用時不用煩惱 `MerchantID`、`RespondType`、`CheckValue`、`TimeStamp` 及 `Version`,正如上述範例一樣。
52
+ - MPG/信用卡-定期定額 API 回傳的內容是 HTML,這個請求應該是交給瀏覽器發送的。
53
+
54
+ ## Pay2go::Client
55
+
56
+ 實體方法 | 回傳 | 說明
57
+ --- | --- | ---
58
+ `verify_check_code(params)` | `Boolean` | 會於檢查收到的參數,其檢查碼是否正確,用於智付寶的 `NotifyURL` 參數及檢核資料回傳的合法性。
59
+ `generate_mpg_params(params)` | `Hash` | 用於產生 MPG API 表單需要的參數。
60
+ `query_trade_info(params)` | `Hash` | 用於查詢交易狀態。
61
+ `credit_card_deauthorize(params)` | `Hash` | 用於進行信用卡交易授權取消作業。
62
+ `credit_card_deauthorize_by_merchant_order_no(params)` | `Hash` | `credit_card_deauthorize` 的捷徑方法,將 `IndexType` 設為 1
63
+ `credit_card_deauthorize_by_trade_no(params)` | `Hash` | `credit_card_deauthorize` 的捷徑方法,將 `IndexType` 設為 2
64
+ `credit_card_collect_refund(params)` | `Hash` | 用於進行信用卡交易的請退款作業。
65
+ `credit_card_collect_refund_by_merchant_order_no(params)` | `Hash` | `credit_card_collect_refund` 的捷徑方法,將 `IndexType` 設為 1
66
+ `credit_card_collect_refund_by_trade_no(params)` | `Hash` | `credit_card_collect_refund` 的捷徑方法,將 `IndexType` 設為 2
67
+ `generate_credit_card_period_params(params)` | `Hash` | 用於產生信用卡-定期定額 API 表單需要的參數。
68
+
69
+ ## 使用範例
70
+
71
+ ##### MPG、信用卡-定期定額
72
+ ```bash
73
+ git clone git@github.com:CalvertYang/pay2go.git
74
+ cd pay2go
75
+ bundle install
76
+ ruby examples/server.rb
77
+ ```
78
+
79
+ - MPG(GET):http://localhost:4567/mpg
80
+ - 信用卡-定期定額(GET):http://localhost:4567/period
81
+ - 驗證資料合法性(POST):http://localhost:4567/validate
82
+
83
+ ##### 交易狀態查詢
84
+ ```ruby
85
+ result = test_client.query_trade_info({
86
+ MerchantOrderNo: '4e19cab1',
87
+ Amt: 100
88
+ })
89
+
90
+ puts "Result: #{result}"
91
+ puts "Valid?: #{@client.verify_check_code(result)}"
92
+ ```
93
+
94
+ ##### 信用卡-取消授權模組
95
+ ```ruby
96
+ result = test_client.credit_card_deauthorize({
97
+ TradeNo: '16010112345678901',
98
+ Amt: 100,
99
+ IndexType: 1
100
+ })
101
+
102
+ puts "Result: #{result}"
103
+ puts "Valid?: #{@client.verify_check_code(result)}"
104
+ ```
105
+
106
+ ```ruby
107
+ result = test_client.credit_card_deauthorize_by_merchant_order_no({
108
+ MerchantOrderNo: '4e19cab1',
109
+ Amt: 100
110
+ })
111
+
112
+ puts "Result: #{result}"
113
+ puts "Valid?: #{@client.verify_check_code(result)}"
114
+ ```
115
+
116
+ ```ruby
117
+ result = test_client.credit_card_deauthorize_by_trade_no({
118
+ TradeNo: '16010112345678901',
119
+ Amt: 100
120
+ })
121
+
122
+ puts "Result: #{result}"
123
+ puts "Valid?: #{@client.verify_check_code(result)}"
124
+ ```
125
+
126
+ ##### 信用卡-請退款模組
127
+ ```ruby
128
+ result = test_client.credit_card_collect_refund({
129
+ MerchantOrderNo: '4e19cab1',
130
+ Amt: 100,
131
+ CloseType: 2,
132
+ IndexType: 1
133
+ })
134
+
135
+ puts "Result: #{result}"
136
+ ```
137
+
138
+ ```ruby
139
+ result = test_client.credit_card_collect_refund_by_merchant_order_no({
140
+ MerchantOrderNo: '4e19cab1',
141
+ Amt: 100,
142
+ CloseType: 2
143
+ })
144
+
145
+ puts "Result: #{result}"
146
+ ```
147
+
148
+ ```ruby
149
+ result = test_client.credit_card_collect_refund_by_trade_no({
150
+ TradeNo: '16010112345678901',
151
+ Amt: 100,
152
+ CloseType: 2
153
+ })
154
+
155
+ puts "Result: #{result}"
156
+ ```
157
+
158
+ ## License
159
+ MIT
160
+
161
+ ![Analytics](https://ga-beacon.appspot.com/UA-44933497-3/CalvertYang/pay2go?pixel)
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = 'test/**/*_test.rb'
7
+ t.verbose = true
8
+ end
9
+
10
+ desc "Run tests"
11
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "pay2go_client"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,15 @@
1
+ table {
2
+ width: 100%;
3
+ }
4
+
5
+ table input {
6
+ width: 100%;
7
+ }
8
+
9
+ table .title {
10
+ width: 10%;
11
+ }
12
+
13
+ input[type="submit"] {
14
+ margin-top: 2em;
15
+ }
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ $: << File.expand_path('../lib')
3
+ require 'sinatra'
4
+ require 'pay2go'
5
+
6
+ client = Pay2go::Client.new({
7
+ merchant_id: '123456',
8
+ hash_key: '12345678901234567890123456789012',
9
+ hash_iv: '1234567890123456',
10
+ mode: :test
11
+ })
12
+
13
+ get '/mpg' do
14
+ @client_options = client.options
15
+ @params = client.generate_mpg_params({
16
+ MerchantOrderNo: SecureRandom.hex(4),
17
+ Amt: 200,
18
+ ItemDesc: '一般交易測試',
19
+ Email: 'hello@localhost.com',
20
+ EmailModify: 0,
21
+ LoginType: 0,
22
+ CREDIT: 1
23
+ })
24
+
25
+ erb :mpg
26
+ end
27
+
28
+ get '/period' do
29
+ @client_options = client.options
30
+ @params = client.generate_credit_card_period_params({
31
+ MerchantOrderNo: SecureRandom.hex(4),
32
+ ProdDesc: '定期定額交易測試',
33
+ PeriodAmt: 100,
34
+ PeriodAmtMode: 'Total',
35
+ PeriodType: 'M',
36
+ PeriodPoint: '01',
37
+ PeriodStartType: 1,
38
+ PeriodTimes: '5',
39
+ })
40
+
41
+ erb :period
42
+ end
43
+
44
+ post '/validate' do
45
+ client.verify_check_code(request.POST).to_s
46
+ end
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>MPG API</title>
6
+ <link rel="stylesheet" type="text/css" href="<%= url("/style.css")%>">
7
+ </head>
8
+ <body>
9
+ <form action="https://capi.pay2go.com/MPG/mpg_gateway" method="post">
10
+ <table>
11
+ <caption>MPG API</caption>
12
+ <% @client_options.each do |k, v| %>
13
+ <tr>
14
+ <th class="title"><%= k %></th>
15
+ <td><%= v %></td>
16
+ </tr>
17
+ <% end %>
18
+ <% @params.each do |k, v| %>
19
+ <tr>
20
+ <th class="title"><%= k %></th>
21
+ <td><input type="text" name="<%= k %>" value="<%= v %>"></td>
22
+ </tr>
23
+ <% end %>
24
+ <tr>
25
+ <td colspan="2"><input type="submit"></td>
26
+ </tr>
27
+ </table>
28
+ </form>
29
+ </body>
30
+ </html>
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>信用卡-定期定額 API</title>
6
+ <link rel="stylesheet" type="text/css" href="<%= url("/style.css")%>">
7
+ </head>
8
+ <body>
9
+ <form action="https://capi.pay2go.com/API/PeriodAPI" method="post">
10
+ <table>
11
+ <caption>信用卡-定期定額 API</caption>
12
+ <% @client_options.each do |k, v| %>
13
+ <tr>
14
+ <th class="title"><%= k %></th>
15
+ <td><%= v %></td>
16
+ </tr>
17
+ <% end %>
18
+ <% @params.each do |k, v| %>
19
+ <tr>
20
+ <th class="title"><%= k %></th>
21
+ <td><input type="text" name="<%= k %>" value="<%= v %>"></td>
22
+ </tr>
23
+ <% end %>
24
+ <tr>
25
+ <td colspan="2"><input type="submit"></td>
26
+ </tr>
27
+ </table>
28
+ </form>
29
+ </body>
30
+ </html>
@@ -0,0 +1,5 @@
1
+ require 'pay2go/version'
2
+ require 'pay2go/client'
3
+
4
+ module Pay2go
5
+ end
@@ -0,0 +1,245 @@
1
+ require 'net/http'
2
+ require 'cgi'
3
+ require 'digest'
4
+ require 'pay2go/errors'
5
+ require 'pay2go/core_ext/hash'
6
+
7
+ module Pay2go
8
+ class Client
9
+ TRANSACTION_API_ENDPOINTS = {
10
+ test: 'https://capi.pay2go.com/API/QueryTradeInfo',
11
+ production: 'https://api.pay2go.com/API/QueryTradeInfo'
12
+ }.freeze
13
+ CREDITCARD_COLLECT_REFUND_API_ENDPOINTS = {
14
+ test: 'https://cweb.pay2go.com/API/CreditCard/Close',
15
+ production: 'https://web.pay2go.com/API/CreditCard/Close'
16
+ }.freeze
17
+ CREDITCARD_DEAUTHORIZE_API_ENDPOINTS = {
18
+ test: 'https://cweb.pay2go.com/API/CreditCard/Cancel',
19
+ production: 'https://web.pay2go.com/API/CreditCard/Cancel'
20
+ }.freeze
21
+ NEED_CHECK_VALUE_APIS = [
22
+ :query_trade_info # Transaction API
23
+ ]
24
+
25
+ attr_reader :options
26
+
27
+ def initialize options = {}
28
+ @options = { mode: :production }.merge!(options)
29
+
30
+ case @options[:mode]
31
+ when :test, :production
32
+ option_required! :merchant_id, :hash_key, :hash_iv
33
+ else
34
+ raise InvalidMode, %Q{option :mode is either :test or :production}
35
+ end
36
+
37
+ @options.freeze
38
+ end
39
+
40
+ def verify_check_code params = {}
41
+ stringified_keys = params.stringify_keys
42
+ check_code = stringified_keys.delete('CheckCode')
43
+ make_check_code(stringified_keys) == check_code
44
+ end
45
+
46
+ def generate_mpg_params params = {}
47
+ param_required! params, [:MerchantOrderNo, :Amt, :ItemDesc, :Email, :LoginType]
48
+
49
+ post_params = {
50
+ RespondType: 'String',
51
+ TimeStamp: Time.now.to_i,
52
+ Version: '1.2'
53
+ }.merge!(params)
54
+
55
+ generate_params(:mpg, post_params)
56
+ end
57
+
58
+ def query_trade_info params = {}
59
+ param_required! params, [:MerchantOrderNo, :Amt]
60
+
61
+ post_params = {
62
+ Version: '1.1',
63
+ RespondType: 'String',
64
+ TimeStamp: Time.now.to_i
65
+ }.merge!(params)
66
+
67
+ res = request :query_trade_info, post_params
68
+ Hash[res.body.split('&').map!{|i| URI::decode(i).split('=')}]
69
+ end
70
+
71
+ def credit_card_deauthorize params = {}
72
+ param_required! params, [:Amt, :IndexType]
73
+
74
+ raise MissingOption, %Q{One of the following param is required: MerchantOrderNo, TradeNo} if params[:MerchantOrderNo].nil? and params[:TradeNo].nil?
75
+
76
+ post_params = {
77
+ RespondType: 'String',
78
+ Version: '1.0',
79
+ TimeStamp: Time.now.to_i
80
+ }.merge!(params)
81
+
82
+ post_params.delete_if { |key, value| value.nil? }
83
+
84
+ res = request :credit_card_deauthorize, post_params
85
+ Hash[res.body.split('&').map!{|i| URI::decode(i.force_encoding('ASCII-8BIT').force_encoding('UTF-8')).split('=')}]
86
+ end
87
+
88
+ def credit_card_deauthorize_by_merchant_order_no params = {}
89
+ param_required! params, [:Amt, :MerchantOrderNo]
90
+
91
+ post_params = {
92
+ IndexType: 1
93
+ }.merge!(params)
94
+
95
+ credit_card_deauthorize post_params
96
+ end
97
+
98
+ def credit_card_deauthorize_by_trade_no params = {}
99
+ param_required! params, [:Amt, :TradeNo]
100
+
101
+ post_params = {
102
+ IndexType: 2
103
+ }.merge!(params)
104
+
105
+ credit_card_deauthorize post_params
106
+ end
107
+
108
+ def credit_card_collect_refund params = {}
109
+ param_required! params, [:Amt, :IndexType, :CloseType]
110
+
111
+ raise MissingOption, %Q{One of the following param is required: MerchantOrderNo, TradeNo} if params[:MerchantOrderNo].nil? and params[:TradeNo].nil?
112
+
113
+ post_params = {
114
+ RespondType: 'String',
115
+ Version: '1.0',
116
+ TimeStamp: Time.now.to_i
117
+ }.merge!(params)
118
+
119
+ res = request :credit_card_collect_refund, post_params
120
+ Hash[res.body.split('&').map!{|i| URI::decode(i.force_encoding('ASCII-8BIT').force_encoding('UTF-8')).split('=')}]
121
+ end
122
+
123
+ def credit_card_collect_refund_by_merchant_order_no params = {}
124
+ param_required! params, [:Amt, :MerchantOrderNo, :CloseType]
125
+
126
+ post_params = {
127
+ IndexType: 1
128
+ }.merge!(params)
129
+
130
+ credit_card_collect_refund post_params
131
+ end
132
+
133
+ def credit_card_collect_refund_by_trade_no params = {}
134
+ param_required! params, [:Amt, :TradeNo, :CloseType]
135
+
136
+ post_params = {
137
+ IndexType: 1
138
+ }.merge!(params)
139
+
140
+ credit_card_collect_refund post_params
141
+ end
142
+
143
+ def generate_credit_card_period_params params = {}
144
+ param_required! params, [:MerchantOrderNo, :ProdDesc, :PeriodAmt, :PeriodAmtMode, :PeriodType, :PeriodPoint, :PeriodStartType, :PeriodTimes]
145
+
146
+ generate_params(:credit_card_period, {
147
+ RespondType: 'String',
148
+ TimeStamp: Time.now.to_i,
149
+ Version: '1.0'
150
+ }.merge!(params))
151
+ end
152
+
153
+ def make_check_value type, params = {}
154
+ case type
155
+ when :mpg
156
+ check_value_fields = [:Amt, :MerchantID, :MerchantOrderNo, :TimeStamp, :Version]
157
+ padded = "HashKey=#{@options[:hash_key]}&%s&HashIV=#{@options[:hash_iv]}"
158
+ when :query_trade_info
159
+ check_value_fields = [:Amt, :MerchantID, :MerchantOrderNo]
160
+ padded = "IV=#{@options[:hash_iv]}&%s&Key=#{@options[:hash_key]}"
161
+ when :credit_card_period
162
+ check_value_fields = [:MerchantID, :MerchantOrderNo, :PeriodAmt, :PeriodType, :TimeStamp]
163
+ padded = "HashKey=#{@options[:hash_key]}&%s&HashIV=#{@options[:hash_iv]}"
164
+ else
165
+ raise UnsupportedType, "Unsupported API type."
166
+ end
167
+
168
+ param_required! params, check_value_fields
169
+
170
+ raw = params.select { |key, value| key.to_s.match(/^(#{check_value_fields.join('|')})$/) }
171
+ .sort_by{ |k, v| k.downcase }.map!{ |k, v| "#{k}=#{v}" }.join('&')
172
+
173
+ padded = padded % raw
174
+
175
+ Digest::SHA256.hexdigest(padded).upcase!
176
+ end
177
+
178
+ def encode_post_data data
179
+ cipher = OpenSSL::Cipher::AES256.new(:CBC)
180
+ cipher.encrypt
181
+ cipher.padding = 0
182
+ cipher.key = @options[:hash_key]
183
+ cipher.iv = @options[:hash_iv]
184
+ data = add_padding(data)
185
+ encrypted = cipher.update(data) + cipher.final
186
+ encrypted.unpack('H*').first
187
+ end
188
+
189
+ private
190
+
191
+ def option_required! *option_names
192
+ option_names.each do |option_name|
193
+ raise MissingOption, %Q{option "#{option_name}" is required.} if @options[option_name].nil?
194
+ end
195
+ end
196
+
197
+ def param_required! params, param_names
198
+ param_names.each do |param_name|
199
+ raise MissingParameter, %Q{param "#{param_name}" is required.} if params[param_name].nil?
200
+ end
201
+ end
202
+
203
+ def make_check_code params = {}
204
+ raw = params.select { |key, value| key.to_s.match(/^(Amt|MerchantID|MerchantOrderNo|TradeNo)$/) }
205
+ .sort_by{ |k, v| k.downcase }.map!{ |k, v| "#{k}=#{v}" }.join('&')
206
+ padded = "HashIV=#{@options[:hash_iv]}&#{raw}&HashKey=#{@options[:hash_key]}"
207
+ Digest::SHA256.hexdigest(padded).upcase!
208
+ end
209
+
210
+ def generate_params type, overwrite_params = {}
211
+ result = overwrite_params.clone
212
+ result[:MerchantID] = @options[:merchant_id]
213
+ result[:CheckValue] = make_check_value(type, result)
214
+ result
215
+ end
216
+
217
+ def request type, params = {}
218
+ case type
219
+ when :query_trade_info
220
+ api_url = TRANSACTION_API_ENDPOINTS[@options[:mode]]
221
+ when :credit_card_deauthorize
222
+ api_url = CREDITCARD_DEAUTHORIZE_API_ENDPOINTS[@options[:mode]]
223
+ when :credit_card_collect_refund
224
+ api_url = CREDITCARD_COLLECT_REFUND_API_ENDPOINTS[@options[:mode]]
225
+ end
226
+
227
+ if NEED_CHECK_VALUE_APIS.include?(type)
228
+ post_params = generate_params(type, params)
229
+ else
230
+ post_params = {
231
+ MerchantID_: @options[:merchant_id],
232
+ PostData_: encode_post_data(URI.encode(params.map{ |key, value| "#{key}=#{value}" }.join("&")))
233
+ }
234
+ end
235
+
236
+ Net::HTTP.post_form URI(api_url), post_params
237
+ end
238
+
239
+ def add_padding text, size = 32
240
+ len = text.length
241
+ pad = size - (len % size)
242
+ text = text + (pad.chr * pad)
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,9 @@
1
+ class Hash
2
+ def stringify_keys
3
+ result = self.class.new
4
+ each_key do |key|
5
+ result[key.to_s] = self[key]
6
+ end
7
+ result
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Pay2go
2
+ # Generic Pay2Go exception class.
3
+ class Pay2goError < StandardError; end
4
+ class MissingOption < Pay2goError; end
5
+ class MissingParameter < Pay2goError; end
6
+ class InvalidMode < Pay2goError; end
7
+ class UnsupportedType < Pay2goError; end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Pay2go
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1 @@
1
+ require 'pay2go'
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pay2go/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pay2go_client"
8
+ spec.version = Pay2go::VERSION
9
+ spec.authors = ["Calvert"]
10
+ spec.email = [""]
11
+
12
+ spec.summary = %q{API client for pay2go}
13
+ spec.description = %q{API client for pay2go}
14
+ spec.homepage = "https://github.com/CalvertYang/pay2go"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "bin"
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "minitest", "~> 5.8"
25
+ spec.add_development_dependency "minitest-reporters", "~> 1.1"
26
+ spec.add_development_dependency "sinatra"
27
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pay2go_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Calvert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sinatra
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: API client for pay2go
84
+ email:
85
+ - ''
86
+ executables:
87
+ - console
88
+ - setup
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - examples/public/style.css
101
+ - examples/server.rb
102
+ - examples/views/mpg.erb
103
+ - examples/views/period.erb
104
+ - lib/pay2go.rb
105
+ - lib/pay2go/client.rb
106
+ - lib/pay2go/core_ext/hash.rb
107
+ - lib/pay2go/errors.rb
108
+ - lib/pay2go/version.rb
109
+ - lib/pay2go_client.rb
110
+ - pay2go.gemspec
111
+ homepage: https://github.com/CalvertYang/pay2go
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.5.1
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: API client for pay2go
135
+ test_files: []