tbk 1.0.1 → 1.0.2
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/.gitignore +19 -0
- data/.travis.yml +12 -0
- data/.yardopts +5 -0
- data/Gemfile +18 -0
- data/LICENSE +20 -0
- data/README.md +115 -0
- data/Rakefile +6 -0
- data/lib/tbk.rb +12 -0
- data/lib/tbk/commerce.rb +69 -0
- data/lib/tbk/config.rb +43 -0
- data/lib/tbk/errors.rb +16 -0
- data/lib/tbk/keys.rb +5 -0
- data/lib/tbk/keys/test_commerce.pem +27 -0
- data/lib/tbk/keys/webpay.101.pem +14 -0
- data/lib/tbk/keys/webpay_test.101.pem +14 -0
- data/lib/tbk/version.rb +7 -0
- data/lib/tbk/webpay.rb +4 -0
- data/lib/tbk/webpay/confirmation.rb +122 -0
- data/lib/tbk/webpay/encryption.rb +75 -0
- data/lib/tbk/webpay/logger.rb +41 -0
- data/lib/tbk/webpay/logger/base_logger.rb +34 -0
- data/lib/tbk/webpay/logger/null_logger.rb +15 -0
- data/lib/tbk/webpay/logger/official_logger.rb +193 -0
- data/lib/tbk/webpay/payment.rb +169 -0
- data/spec/commerce_spec.rb +46 -0
- data/spec/config_spec.rb +54 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/syntax.rb +5 -0
- data/spec/support/test_commerce.rb +12 -0
- data/spec/webpay/confirmation_spec.rb +4 -0
- data/spec/webpay/encryption_spec.rb +4 -0
- data/spec/webpay/payment_spec.rb +1 -0
- data/tbk.gemspec +23 -0
- metadata +45 -4
@@ -0,0 +1,169 @@
|
|
1
|
+
module TBK
|
2
|
+
module Webpay
|
3
|
+
class Payment
|
4
|
+
attr_accessor :commerce
|
5
|
+
attr_accessor :request_ip
|
6
|
+
attr_accessor :amount
|
7
|
+
attr_accessor :order_id
|
8
|
+
attr_accessor :session_id
|
9
|
+
attr_accessor :confirmation_url
|
10
|
+
attr_accessor :success_url
|
11
|
+
attr_accessor :failure_url
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
self.commerce = options[:commerce] || TBK::Commerce.default_commerce
|
15
|
+
self.request_ip = options[:request_ip]
|
16
|
+
self.amount = options[:amount]
|
17
|
+
self.order_id = options[:order_id]
|
18
|
+
self.session_id = options[:session_id]
|
19
|
+
self.confirmation_url = options[:confirmation_url]
|
20
|
+
self.success_url = options[:success_url]
|
21
|
+
self.failure_url = options[:failure_url]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Transaction ids are generated randombly on the client side
|
25
|
+
def transaction_id
|
26
|
+
@transaction_id ||= (rand * 10000000000).to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
def redirect_url
|
30
|
+
"#{ self.process_url }?TBK_VERSION_KCC=#{ TBK::VERSION::KCC }&TBK_TOKEN=#{ self.token }"
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_html_form(options = {}, &block)
|
34
|
+
form = <<-EOF
|
35
|
+
<form method="POST"
|
36
|
+
class="#{ options[:class] || 'tbk_payment_form'}"
|
37
|
+
id="#{ options[:id] }"
|
38
|
+
action="#{ self.process_url }">
|
39
|
+
<input type="hidden" name="TBK_PARAM" value="#{ self.param }">
|
40
|
+
<input type="hidden" name="TBK_VERSION_KCC" value="#{ TBK::VERSION::KCC }">
|
41
|
+
<input type="hidden" name="TBK_CODIGO_COMERCIO" value="#{ self.commerce.id }">
|
42
|
+
<input type="hidden" name="TBK_KEY_ID" value="#{ self.commerce.webpay_key_id }">
|
43
|
+
#{ yield if block_given? }
|
44
|
+
</form>
|
45
|
+
EOF
|
46
|
+
|
47
|
+
form = form.html_safe if form.respond_to? :html_safe
|
48
|
+
|
49
|
+
form
|
50
|
+
end
|
51
|
+
|
52
|
+
def token
|
53
|
+
unless @token
|
54
|
+
@token = fetch_token
|
55
|
+
TBK::Webpay.logger.payment(self)
|
56
|
+
end
|
57
|
+
|
58
|
+
@token
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
def process_url
|
63
|
+
if self.commerce.test?
|
64
|
+
"https://certificacion.webpay.cl:6443/filtroUnificado/bp_revision.cgi"
|
65
|
+
else
|
66
|
+
"https://webpay.transbank.cl:443/filtroUnificado/bp_revision.cgi"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def validation_url
|
71
|
+
if self.commerce.test?
|
72
|
+
"https://certificacion.webpay.cl:6443/filtroUnificado/bp_validacion.cgi"
|
73
|
+
else
|
74
|
+
"https://webpay.transbank.cl:443/filtroUnificado/bp_validacion.cgi"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def fetch_token
|
79
|
+
uri = URI.parse( self.validation_url )
|
80
|
+
|
81
|
+
response = nil
|
82
|
+
until response && response['location'].nil?
|
83
|
+
uri = URI.parse( response.nil? ? self.validation_url : response['location'] )
|
84
|
+
|
85
|
+
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
|
86
|
+
post = Net::HTTP::Post.new uri.path
|
87
|
+
post["user-agent"] = "TBK/#{ TBK::VERSION::GEM } (Ruby/#{ RUBY_VERSION }; +#{ TBK::VERSION::WEBSITE })"
|
88
|
+
post.set_form_data({
|
89
|
+
'TBK_VERSION_KCC' => TBK::VERSION::KCC,
|
90
|
+
'TBK_CODIGO_COMERCIO' => self.commerce.id,
|
91
|
+
'TBK_KEY_ID' => self.commerce.webpay_key_id,
|
92
|
+
'TBK_PARAM' => self.param
|
93
|
+
})
|
94
|
+
|
95
|
+
# http.read_timeout = Webpay::Config.timeout
|
96
|
+
http.request post
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
unless response.code == "200"
|
101
|
+
raise TBK::Webpay::PaymentError, "Payment token generation failed"
|
102
|
+
end
|
103
|
+
|
104
|
+
response = self.commerce.webpay_decrypt(response.body)[:body]
|
105
|
+
|
106
|
+
unless /ERROR=([a-zA-Z0-9]+)/.match(response)[1] == "0"
|
107
|
+
raise TBK::Webpay::PaymentError, "Payment token generation failed"
|
108
|
+
end
|
109
|
+
|
110
|
+
/TOKEN=([a-zA-Z0-9]+)/.match(response)[1]
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def param
|
115
|
+
@param ||= begin
|
116
|
+
self.verify!
|
117
|
+
self.commerce.webpay_encrypt(raw_params)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def verify!
|
122
|
+
raise TBK::Webpay::PaymentError, "Commerce required" if self.commerce.nil?
|
123
|
+
raise TBK::Webpay::PaymentError, "Invalid amount (#{self.amount.inspect})" unless self.amount && self.amount > 0
|
124
|
+
raise TBK::Webpay::PaymentError, "Order ID required" if self.order_id.nil?
|
125
|
+
raise TBK::Webpay::PaymentError, "Success URL required" if self.success_url.nil?
|
126
|
+
raise TBK::Webpay::PaymentError, "Confirmation URL required" if self.confirmation_url.nil?
|
127
|
+
confirmation_uri = URI.parse(self.confirmation_url)
|
128
|
+
raise TBK::Webpay::PaymentError, "Confirmation URL host MUST be an IP address" unless /(\d{1,3}\.){3}\d{1,3}/.match(confirmation_uri.host)
|
129
|
+
raise TBK::Webpay::PaymentError, "Confirmation URL port MUST be 80 or 8080" unless [80, 8080].include?(confirmation_uri.port)
|
130
|
+
end
|
131
|
+
|
132
|
+
def raw_params(splitter="#", include_pseudomac=true)
|
133
|
+
params = []
|
134
|
+
|
135
|
+
params << "TBK_ORDEN_COMPRA=#{ self.order_id }"
|
136
|
+
params << "TBK_CODIGO_COMERCIO=#{ self.commerce.id }"
|
137
|
+
params << "TBK_ID_TRANSACCION=#{ self.transaction_id }"
|
138
|
+
|
139
|
+
uri = URI.parse(self.confirmation_url)
|
140
|
+
|
141
|
+
params << "TBK_URL_CGI_COMERCIO=#{ uri.path }"
|
142
|
+
params << "TBK_SERVIDOR_COMERCIO=#{ uri.host }"
|
143
|
+
params << "TBK_PUERTO_COMERCIO=#{ uri.port }"
|
144
|
+
|
145
|
+
params << "TBK_VERSION_KCC=#{ TBK::VERSION::KCC }"
|
146
|
+
params << "TBK_KEY_ID=#{ self.commerce.webpay_key_id }"
|
147
|
+
params << "PARAMVERIFCOM=1"
|
148
|
+
|
149
|
+
if include_pseudomac
|
150
|
+
# An old pseudo mac generation carried from an old implementation
|
151
|
+
digest = OpenSSL::Digest::MD5.new
|
152
|
+
digest << self.raw_params('&',false) << self.commerce.id.to_s << "webpay"
|
153
|
+
mac = digest.to_s
|
154
|
+
|
155
|
+
params << "TBK_MAC=#{ mac }"
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
params << "TBK_MONTO=#{ (self.amount * 100).to_i }"
|
160
|
+
params << "TBK_ID_SESION=#{ self.session_id }" if self.session_id
|
161
|
+
params << "TBK_URL_EXITO=#{ self.success_url }"
|
162
|
+
params << "TBK_URL_FRACASO=#{ self.failure_url || self.success_url }"
|
163
|
+
params << "TBK_TIPO_TRANSACCION=TR_NORMAL"
|
164
|
+
|
165
|
+
params.join(splitter)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TBK::Commerce do
|
4
|
+
context "creation" do
|
5
|
+
it "can be done with all it's arguments" do
|
6
|
+
@commerce = TBK::Commerce.new({
|
7
|
+
:id => 12345,
|
8
|
+
:key => TBK::Commerce::TEST_COMMERCE_KEY
|
9
|
+
})
|
10
|
+
|
11
|
+
expect(@commerce.id).to be_eql 12345
|
12
|
+
end
|
13
|
+
|
14
|
+
it "raises an exception if no id is given" do
|
15
|
+
expect{
|
16
|
+
TBK::Commerce.new({
|
17
|
+
:key => TBK::Commerce::TEST_COMMERCE_KEY
|
18
|
+
})
|
19
|
+
}.to raise_error TBK::CommerceError
|
20
|
+
end
|
21
|
+
|
22
|
+
it "raises an exception if no key is given" do
|
23
|
+
expect{
|
24
|
+
TBK::Commerce.new({
|
25
|
+
:id => 12345
|
26
|
+
})
|
27
|
+
}.to raise_error TBK::CommerceError
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
context "default_commerce" do
|
33
|
+
it "should be nil if no default is configured" do
|
34
|
+
TBK.config.should_receive(:commerce_id).and_return nil
|
35
|
+
expect(TBK::Commerce.default_commerce).to be_nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return a valid commerce if configured" do
|
39
|
+
TBK.config.should_receive(:commerce_id).at_least(:once).and_return 12345
|
40
|
+
TBK.config.should_receive(:commerce_key).at_least(:once).and_return TBK::Commerce::TEST_COMMERCE_KEY
|
41
|
+
|
42
|
+
expect(TBK::Commerce.default_commerce).not_to be_nil
|
43
|
+
expect(TBK::Commerce.default_commerce.id).to be_eql 12345
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TBK::Config do
|
4
|
+
|
5
|
+
it "should inject configuration methods on base module" do
|
6
|
+
|
7
|
+
expect(TBK).to respond_to :configure
|
8
|
+
expect(TBK).to respond_to :config
|
9
|
+
expect(TBK.config).to be_kind_of TBK::Config
|
10
|
+
|
11
|
+
TBK.configure do |config|
|
12
|
+
expect(config).to be_kind_of TBK::Config
|
13
|
+
expect(config).to be == TBK.config
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
context('#commerce_id') do
|
19
|
+
it "should be nil by default" do
|
20
|
+
expect(TBK.config.commerce_id).to be_nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should read it's default value from the environment" do
|
24
|
+
ENV.should_receive(:[]).with('TBK_COMMERCE_ID').and_return "12345"
|
25
|
+
|
26
|
+
expect(TBK.config.commerce_id).to be_eql "12345"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context('#commerce_key') do
|
31
|
+
it "should be nil by default" do
|
32
|
+
expect(TBK.config.commerce_key).to be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should read it's default value from the environment" do
|
36
|
+
ENV.should_receive(:[]).with('TBK_COMMERCE_KEY').and_return "PKEY"
|
37
|
+
|
38
|
+
expect(TBK.config.commerce_key).to be_eql "PKEY"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context('#environment') do
|
43
|
+
it "should be production by default" do
|
44
|
+
expect(TBK.config.environment).to be_eql :production
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should read it's default value from the environment" do
|
48
|
+
ENV.should_receive(:[]).with('TBK_COMMERCE_ENVIRONMENT').and_return "test"
|
49
|
+
|
50
|
+
expect(TBK.config.environment).to be_eql :test
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'spec_helper'
|
data/tbk.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tbk/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "tbk"
|
8
|
+
gem.version = TBK::VERSION::GEM
|
9
|
+
gem.authors = ["Seba Gamboa"]
|
10
|
+
gem.email = ["me@sagmor.com"]
|
11
|
+
gem.description = %q{Ruby implementation of Transbank's Webpay protocol}
|
12
|
+
gem.summary = "Pure Ruby implementation of Transbank's Webpay KCC #{TBK::VERSION::KCC}"
|
13
|
+
gem.homepage = TBK::VERSION::WEBSITE
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/).grep(%r{^(?!example)})
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency "tzinfo"
|
21
|
+
gem.add_development_dependency "rake"
|
22
|
+
gem.add_development_dependency "rspec"
|
23
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tbk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seba Gamboa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tzinfo
|
@@ -58,7 +58,40 @@ email:
|
|
58
58
|
executables: []
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
|
-
files:
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".travis.yml"
|
64
|
+
- ".yardopts"
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- lib/tbk.rb
|
70
|
+
- lib/tbk/commerce.rb
|
71
|
+
- lib/tbk/config.rb
|
72
|
+
- lib/tbk/errors.rb
|
73
|
+
- lib/tbk/keys.rb
|
74
|
+
- lib/tbk/keys/test_commerce.pem
|
75
|
+
- lib/tbk/keys/webpay.101.pem
|
76
|
+
- lib/tbk/keys/webpay_test.101.pem
|
77
|
+
- lib/tbk/version.rb
|
78
|
+
- lib/tbk/webpay.rb
|
79
|
+
- lib/tbk/webpay/confirmation.rb
|
80
|
+
- lib/tbk/webpay/encryption.rb
|
81
|
+
- lib/tbk/webpay/logger.rb
|
82
|
+
- lib/tbk/webpay/logger/base_logger.rb
|
83
|
+
- lib/tbk/webpay/logger/null_logger.rb
|
84
|
+
- lib/tbk/webpay/logger/official_logger.rb
|
85
|
+
- lib/tbk/webpay/payment.rb
|
86
|
+
- spec/commerce_spec.rb
|
87
|
+
- spec/config_spec.rb
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
- spec/support/syntax.rb
|
90
|
+
- spec/support/test_commerce.rb
|
91
|
+
- spec/webpay/confirmation_spec.rb
|
92
|
+
- spec/webpay/encryption_spec.rb
|
93
|
+
- spec/webpay/payment_spec.rb
|
94
|
+
- tbk.gemspec
|
62
95
|
homepage: http://sagmor.com/tbk/
|
63
96
|
licenses: []
|
64
97
|
metadata: {}
|
@@ -82,5 +115,13 @@ rubygems_version: 2.2.2
|
|
82
115
|
signing_key:
|
83
116
|
specification_version: 4
|
84
117
|
summary: Pure Ruby implementation of Transbank's Webpay KCC 6.0
|
85
|
-
test_files:
|
118
|
+
test_files:
|
119
|
+
- spec/commerce_spec.rb
|
120
|
+
- spec/config_spec.rb
|
121
|
+
- spec/spec_helper.rb
|
122
|
+
- spec/support/syntax.rb
|
123
|
+
- spec/support/test_commerce.rb
|
124
|
+
- spec/webpay/confirmation_spec.rb
|
125
|
+
- spec/webpay/encryption_spec.rb
|
126
|
+
- spec/webpay/payment_spec.rb
|
86
127
|
has_rdoc:
|