ecpay_client 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 35baca5a0a7b13c148368c858ca735908ac24189
4
+ data.tar.gz: d42607f41d64c22d9fd471417d59ac5808083007
5
+ SHA512:
6
+ metadata.gz: 060bc9d3244e72df8f60a6cc239cdffb33476524a062f945457c1c4377eaa7b93315be121d6e7a2904bf1cc5b99c44f4cb36eb19e2c63d7614e0f1d6ff05761b
7
+ data.tar.gz: a0ad2bfb1f6bbdcb0c119b3bd8ec2c39f48aa0cf58c6358ce0cc8911ca85d291fe2fbb4e1c3580af71554ba01917ff40259cddb6d9f932a5bca6b4a5dd1b6a65
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+ Metrics:
4
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ before_install:
3
+ - gem update --system
4
+ - gem update bundler
5
+ rvm:
6
+ - 2.4.0
7
+ - 2.3.0
8
+ - 2.2.0
9
+ - 2.1.5
10
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 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.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ [![Gem Version](https://badge.fury.io/rb/ecpay_client.svg)](https://badge.fury.io/rb/ecpay_client)
2
+ [![Build Status](https://travis-ci.org/CalvertYang/ecpay.svg?branch=master)](https://travis-ci.org/CalvertYang/ecpay)
3
+
4
+ # Ecpay 綠界
5
+
6
+ 這是綠界 API 的 Ruby 包裝,更多資訊參考他們的[官方文件](https://www.ecpay.com.tw/Content/files/ecpay_011.pdf)。
7
+
8
+ - 這不是 Rails 插件,只是個 API 包裝。
9
+ - 使用時只需要傳送需要的參數即可,不用產生檢查碼,`ecpay_client` 會自己產生。
10
+ - 感謝[大兜](https://github.com/tonytonyjan)撰寫的 [allpay](https://github.com/tonytonyjan/allpay)
11
+
12
+ ## 安裝
13
+
14
+ ```bash
15
+ gem install ecpay_client
16
+ ```
17
+
18
+ ## 使用
19
+
20
+ ```ruby
21
+ test_client = Ecpay::Client.new(mode: :test)
22
+ production_client = Ecpay::Client.new({
23
+ merchant_id: 'MERCHANT_ID',
24
+ hash_key: 'HASH_KEY',
25
+ hash_iv: 'HASH_IV'
26
+ })
27
+
28
+ test_client.request(
29
+ '/Cashier/QueryTradeInfo',
30
+ MerchantTradeNo: '0457ce27',
31
+ TimeStamp: Time.now.to_i
32
+ )
33
+ ```
34
+
35
+ 本文件撰寫時,綠界共有 8 個 API (全方位金流介接技術文件 V2.0.6):
36
+
37
+ Endpoint | 說明
38
+ --- | ---
39
+ /Cashier/AioCheckOut/V2 | 產生訂單
40
+ /Cashier/QueryTradeInfo/V2 | 查詢訂單
41
+ /Cashier/QueryCreditCardPeriodInfo | 信用卡定期定額訂單查詢
42
+ /CreditDetail/DoAction | 信用卡關帳/退刷/取消/放棄
43
+ /Cashier/Capture | 合作特店申請撥款
44
+ /PaymentMedia/TradeNoAio | 下載合作特店對帳媒體檔
45
+ /CreditDetail/QueryTrade/V2 | 查詢信用卡單筆明細記錄
46
+ /CreditDetail/FundingReconDetail | 下載信用卡撥款對帳資料檔
47
+
48
+ 詳細 API 參數請參閱綠界金流介接技術文件,注意幾點:
49
+
50
+ - 使用時不用煩惱 `MerchantID` 與 `CheckMacValue`,正如上述範例一樣。
51
+ - `/Cashier/AioCheckOut/V2` 回傳的內容是 HTML,這個請求應該是交給瀏覽器發送的,所以不應該寫出 `client.request '/Cashier/AioCheckOut/V2'` 這樣的程式碼。
52
+
53
+ ## Ecpay::Client
54
+
55
+ 實體方法 | 回傳 | 說明
56
+ --- | --- | ---
57
+ `request(path, **params)` | `Net::HTTPResponse` | 發送 API 請求
58
+ `make_mac(**params)` | `String` | 用於產生 `CheckMacValue`,單純做加密,`params` 需要完整包含到 `MerchantID`
59
+ `verify_mac(**params)`                                       | `Boolean`           | 用於檢查收到的參數,其檢查碼是否正確,這用在綠界的 `ReturnURL` 與 `PeriodReturnURL` 參數上。
60
+ `query_trade_info(merchant_trade_number, platform = nil)` | `Hash` | `/Cashier/QueryTradeInfo/V2` 的捷徑方法,將 `TimeStamp` 設定為當前時間
61
+ `query_credit_card_period_info(merchant_trade_number)` | `Hash` | `/Cashier/QueryCreditCardPeriodInfo` 的捷徑方法,將 `TimeStamp` 設定為當前時間
62
+ `generate_checkout_params` | `Hash` | 用於產生 `/Cashier/AioCheckOut/V2` 表單需要的參數,`MerchantTradeDate`、`MerchantTradeNo`、`PaymentType`,可省略。
63
+
64
+ ## 使用範例
65
+
66
+ ```bash
67
+ git clone git@github.com:CalvertYang/ecpay.git
68
+ cd ecpay
69
+ bundle install
70
+ ruby examples/server.rb
71
+ ```
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ RuboCop::RakeTask.new
8
+
9
+ task default: [:rubocop, :spec]
data/ecpay.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'ecpay/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'ecpay_client'
9
+ spec.version = Ecpay::VERSION
10
+ spec.authors = ['Jian Weihang']
11
+ spec.email = ['tonytonyjan@gmail.com']
12
+ spec.summary = '綠界(Ecpay)API 包裝'
13
+ spec.description = '綠界(Ecpay)API 包裝'
14
+ spec.homepage = 'https://github.com/CalvertYang/ecpay'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
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 'rspec'
25
+ spec.add_development_dependency 'rubocop'
26
+ spec.add_development_dependency 'sinatra'
27
+ end
@@ -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,25 @@
1
+ # frozen_string_literal: true
2
+ $LOAD_PATH << File.expand_path('../../lib', __FILE__)
3
+ require 'bundler/setup'
4
+ require 'sinatra'
5
+ require 'ecpay'
6
+
7
+ get '/' do
8
+ @client = Ecpay::Client.new(mode: :test)
9
+ @params = @client.generate_checkout_params(
10
+ MerchantTradeNo: SecureRandom.hex(4),
11
+ TotalAmount: 1000,
12
+ TradeDesc: '交易測試',
13
+ ItemName: '物品一#物品二',
14
+ ReturnURL: 'https://requestb.in/127b0at1',
15
+ ClientBackURL: 'https://requestb.in/127b0at1?inspect',
16
+ ChoosePayment: 'Credit',
17
+ PeriodAmount: 1000,
18
+ PeriodType: 'D',
19
+ Frequency: 1,
20
+ ExecTimes: 12,
21
+ PeriodReturnURL: 'https://requestb.in/127b0at1'
22
+ )
23
+
24
+ erb :index
25
+ end
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>AIO Check Out</title>
6
+ <link rel="stylesheet" type="text/css" href="<%= url("/style.css")%>">
7
+ </head>
8
+ <body>
9
+ <form action="https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V2" method="post">
10
+ <table>
11
+ <caption>AIO Check Out</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>
22
+ <%= v %>
23
+ <input type="hidden" name="<%= k %>" value="<%= v %>">
24
+ </td>
25
+ </tr>
26
+ <% end %>
27
+ <tr>
28
+ <td colspan="2"><input type="submit"></td>
29
+ </tr>
30
+ </table>
31
+ </form>
32
+ </body>
33
+ </html>
data/lib/ecpay.rb ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ require 'ecpay/version'
3
+ require 'ecpay/client'
4
+
5
+ module Ecpay # :nodoc:
6
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'cgi'
5
+ require 'digest'
6
+ require 'ecpay/errors'
7
+ require 'ecpay/core_ext/hash'
8
+
9
+ module Ecpay
10
+ class Client # :nodoc:
11
+ PRODUCTION_API_HOST = 'https://payment.ecpay.com.tw'
12
+ TEST_API_HOST = 'https://payment-stage.ecpay.com.tw'
13
+ TEST_OPTIONS = {
14
+ merchant_id: '2000132',
15
+ hash_key: '5294y06JbISpM5x9',
16
+ hash_iv: 'v77hoKGq4kWxNNIS'
17
+ }.freeze
18
+
19
+ attr_reader :options
20
+
21
+ def initialize(options = {})
22
+ @options = { mode: :production }.merge!(options)
23
+ case @options[:mode]
24
+ when :production
25
+ option_required! :merchant_id, :hash_key, :hash_iv
26
+ when :test
27
+ @options = TEST_OPTIONS.merge(options)
28
+ else
29
+ raise InvalidMode, %(option :mode is either :test or :production)
30
+ end
31
+ @options.freeze
32
+ end
33
+
34
+ def api_host
35
+ case @options[:mode]
36
+ when :production then PRODUCTION_API_HOST
37
+ when :test then TEST_API_HOST
38
+ end
39
+ end
40
+
41
+ def make_mac(params = {})
42
+ raw = params.sort_by { |k, _v| k.downcase }.map! { |k, v| "#{k}=#{v}" }.join('&')
43
+ padded = "HashKey=#{@options[:hash_key]}&#{raw}&HashIV=#{@options[:hash_iv]}"
44
+ url_encoded = CGI.escape(padded).downcase!
45
+ Digest::SHA256.hexdigest(url_encoded).upcase!
46
+ end
47
+
48
+ def verify_mac(params = {})
49
+ stringified_keys = params.stringify_keys
50
+ check_mac_value = stringified_keys.delete('CheckMacValue')
51
+ make_mac(stringified_keys) == check_mac_value
52
+ end
53
+
54
+ def generate_params(overwrite_params = {})
55
+ result = overwrite_params.clone
56
+ result[:MerchantID] = @options[:merchant_id]
57
+ result[:CheckMacValue] = make_mac(result)
58
+ result
59
+ end
60
+
61
+ def generate_checkout_params(overwrite_params = {})
62
+ generate_params({
63
+ MerchantTradeNo: SecureRandom.hex(4),
64
+ MerchantTradeDate: Time.now.strftime('%Y/%m/%d %H:%M:%S'),
65
+ PaymentType: 'aio',
66
+ EncryptType: 1
67
+ }.merge!(overwrite_params))
68
+ end
69
+
70
+ def request(path, params = {})
71
+ api_url = URI.join(api_host, path)
72
+ Net::HTTP.post_form api_url, generate_params(params)
73
+ end
74
+
75
+ def query_trade_info(merchant_trade_number, platform = nil)
76
+ params = {
77
+ MerchantTradeNo: merchant_trade_number,
78
+ TimeStamp: Time.now.to_i,
79
+ PlatformID: platform
80
+ }
81
+ params.delete_if { |_k, v| v.nil? }
82
+ res = request('/Cashier/QueryTradeInfo/V2', params)
83
+
84
+ Hash[res.body.split('&').map! { |i| i.split('=') }]
85
+ end
86
+
87
+ def query_credit_card_period_info(merchant_trade_number)
88
+ res = request(
89
+ '/Cashier/QueryCreditCardPeriodInfo',
90
+ MerchantTradeNo: merchant_trade_number,
91
+ TimeStamp: Time.now.to_i
92
+ )
93
+
94
+ JSON.parse(res.body)
95
+ end
96
+
97
+ private
98
+
99
+ def option_required!(*option_names)
100
+ option_names.each do |option_name|
101
+ raise MissingOption, %(option "#{option_name}" is required.) if @options[option_name].nil?
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ class Hash # :nodoc:
3
+ def stringify_keys
4
+ result = self.class.new
5
+ each_key do |key|
6
+ result[key.to_s] = self[key]
7
+ end
8
+ result
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Ecpay
3
+ # Generic Ecpay exception class.
4
+ class EcpayError < StandardError; end
5
+ class MissingOption < EcpayError; end
6
+ class InvalidMode < EcpayError; end
7
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module Ecpay
3
+ VERSION = '1.0.0'
4
+ end
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require 'ecpay'
@@ -0,0 +1,146 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ require 'spec_helper'
4
+ require 'securerandom'
5
+
6
+ describe Ecpay::Client do
7
+ before :all do
8
+ @client = Ecpay::Client.new(mode: :test)
9
+ end
10
+
11
+ it '#api /Cashier/AioCheckOut/V2' do
12
+ res = @client.request(
13
+ '/Cashier/AioCheckOut/V2',
14
+ MerchantTradeNo: SecureRandom.hex(4),
15
+ MerchantTradeDate: Time.now.strftime('%Y/%m/%d %H:%M:%S'),
16
+ PaymentType: 'aio',
17
+ TotalAmount: 100,
18
+ TradeDesc: '交易測試',
19
+ ItemName: '物品一#物品二',
20
+ ReturnURL: 'https://requestb.in/127b0at1',
21
+ ClientBackURL: 'https://requestb.in/127b0at1?inspect',
22
+ ChoosePayment: 'Credit'
23
+ )
24
+
25
+ expect(res.code).to eq '200'
26
+ expect(res.body.force_encoding('UTF-8')).to include '物品一'
27
+ end
28
+
29
+ it '#api /Cashier/QueryTradeInfo/V2' do
30
+ res = @client.request(
31
+ '/Cashier/QueryTradeInfo/V2',
32
+ MerchantTradeNo: '0457ce27',
33
+ TimeStamp: Time.now.to_i
34
+ )
35
+
36
+ expect(res.code).to eq '200'
37
+ end
38
+
39
+ it '#query_trade_info' do
40
+ result_hash = @client.query_trade_info '0457ce27'
41
+ expect(result_hash.keys).to match_array %w(
42
+ HandlingCharge ItemName MerchantID MerchantTradeNo PaymentDate
43
+ PaymentType PaymentTypeChargeFee TradeAmt TradeDate TradeNo TradeStatus
44
+ CheckMacValue
45
+ )
46
+ end
47
+
48
+ it '#query_credit_card_period_info' do
49
+ result_hash = @client.query_credit_card_period_info '0457ce27'
50
+ expect(result_hash.keys).to match_array %w(
51
+ MerchantID MerchantTradeNo TradeNo RtnCode PeriodType Frequency
52
+ ExecTimes PeriodAmount amount gwsr process_date auth_code card4no
53
+ card6no TotalSuccessTimes TotalSuccessAmount ExecLog ExecStatus
54
+ )
55
+ end
56
+
57
+ it '#make_mac' do
58
+ client = Ecpay::Client.new(
59
+ merchant_id: '12345678',
60
+ hash_key: 'ejCk326UnaZWKisg',
61
+ hash_iv: 'q9jcZX8Ib9LM8wYk',
62
+ mode: :test
63
+ )
64
+
65
+ mac = client.make_mac(
66
+ ItemName: '商品',
67
+ MerchantID: '12345678',
68
+ MerchantTradeDate: '2017/02/22 12:00:00',
69
+ MerchantTradeNo: 'ecpay_1234',
70
+ PaymentType: 'ecpay',
71
+ ReturnURL: 'https://localhost',
72
+ TotalAmount: '500',
73
+ TradeDesc: '交易測試'
74
+ )
75
+
76
+ expect(mac).to eq 'FB41AEDA372FCE19E05A574CD635FE2DD31F4ADC75082ABB8C6B43FC15E74B7F'
77
+ end
78
+
79
+ it '#verify_mac' do
80
+ result = @client.verify_mac(
81
+ RtnCode: '1',
82
+ PaymentType: 'Credit_CreditCard',
83
+ TradeAmt: '700',
84
+ PaymentTypeChargeFee: '14',
85
+ PaymentDate: '2017/02/22 12:21:00',
86
+ SimulatePaid: '0',
87
+ CheckMacValue: '3CC2573905D6AC52B6A92E55E1A64FF32EF7F14B335C998A4A7EFFB94F5C7451',
88
+ TradeDate: '2017/02/22 12:20:00',
89
+ MerchantID: '2000132',
90
+ TradeNo: '1702221220478656',
91
+ RtnMsg: '交易成功',
92
+ MerchantTradeNo: '355313'
93
+ )
94
+
95
+ expect(result).to eq true
96
+ end
97
+
98
+ it '#verify_mac with more parameters' do
99
+ result = @client.verify_mac(
100
+ AlipayID: nil,
101
+ AlipayTradeNo: nil,
102
+ amount: '1290',
103
+ ATMAccBank: nil,
104
+ ATMAccNo: nil,
105
+ auth_code: '777777',
106
+ card4no: '2222',
107
+ card6no: '431195',
108
+ eci: '0',
109
+ ExecTimes: nil,
110
+ Frequency: nil,
111
+ gwsr: '12303658',
112
+ MerchantID: '2000132',
113
+ MerchantTradeNo: 'R9710358221432568191',
114
+ PayFrom: nil,
115
+ PaymentDate: '2017/02/22 14:37:42',
116
+ PaymentNo: nil,
117
+ PaymentType: 'Credit_CreditCard',
118
+ PaymentTypeChargeFee: '26',
119
+ PeriodAmount: nil,
120
+ PeriodType: nil,
121
+ process_date: '2017/02/22 14:37:42',
122
+ red_dan: '0',
123
+ red_de_amt: '0',
124
+ red_ok_amt: '0',
125
+ red_yet: '0',
126
+ RtnCode: '1',
127
+ RtnMsg: '交易成功',
128
+ SimulatePaid: '0',
129
+ staed: '0',
130
+ stage: '0',
131
+ stast: '0',
132
+ TenpayTradeNo: nil,
133
+ TotalSuccessAmount: nil,
134
+ TotalSuccessTimes: nil,
135
+ TradeAmt: '1290',
136
+ TradeDate: '2017/02/22 14:37:13',
137
+ TradeNo: '1702221437131701',
138
+ WebATMAccBank: nil,
139
+ WebATMAccNo: nil,
140
+ WebATMBankName: nil,
141
+ CheckMacValue: '16711032F02312916507EBE0E0F44FD9A549A5A70BBAED6343CD05FC5CC30C31'
142
+ )
143
+
144
+ expect(result).to eq true
145
+ end
146
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'ecpay'
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ecpay_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jian Weihang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-22 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: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
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: 綠界(Ecpay)API 包裝
84
+ email:
85
+ - tonytonyjan@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".rubocop.yml"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - ecpay.gemspec
99
+ - examples/public/style.css
100
+ - examples/server.rb
101
+ - examples/views/index.erb
102
+ - lib/ecpay.rb
103
+ - lib/ecpay/client.rb
104
+ - lib/ecpay/core_ext/hash.rb
105
+ - lib/ecpay/errors.rb
106
+ - lib/ecpay/version.rb
107
+ - lib/ecpay_client.rb
108
+ - spec/ecpay_spec.rb
109
+ - spec/spec_helper.rb
110
+ homepage: https://github.com/CalvertYang/ecpay
111
+ licenses:
112
+ - MIT
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.5.2
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: 綠界(Ecpay)API 包裝
134
+ test_files:
135
+ - spec/ecpay_spec.rb
136
+ - spec/spec_helper.rb