pagarme 0.11

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,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ *.swp
15
+ vimsession
16
+
17
+ # YARD artifacts
18
+ .yardoc
19
+ _yardoc
20
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pagarme.gemspec
4
+ gemspec
@@ -0,0 +1 @@
1
+ Pagar.me's API in Ruby.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+L/5UB2xen6FnMjpQo7
3
+ ZOfoeYd4DFW7OtdQKqGRXdI4JYctZlbBbU5OoNH5clIZxUYi9sG15g8iieYxc77E
4
+ ZLSJFx+H7NuzeOBBQuCT7liYFiCm7LH0iyqPnFYQOoYHvibB+zVEm9/H5+qE3i1i
5
+ ZBuvT/5v0o4iemVLNzIGJs360atEHHnKjfqhpobzXQ0+BdqYu2VWEsCzhFRDt+yp
6
+ O8ZBcI+Fd0+SZYjOw0tyE1NousG5TvnST1SApucb44bD2PEIQ1RzTNRzhc+NVoTu
7
+ LYvotLGCm/SxJUkX/0RIMw6VJq1gXAGUdKE/W1ScFkGBbtyoqWvtlvvg9gQdmFLC
8
+ XwIDAQAB
9
+ -----END PUBLIC KEY-----
@@ -0,0 +1,48 @@
1
+ require File.join(File.dirname(__FILE__), '.', 'pagarme/transaction')
2
+ require File.join(File.dirname(__FILE__), '.', 'pagarme/request')
3
+ require File.join(File.dirname(__FILE__), '.', 'pagarme/errors')
4
+
5
+ module PagarMe
6
+
7
+ @@api_key = nil
8
+ @@api_endpoint = 'https://0.0.0.0:3001'
9
+ @@api_version = '1'
10
+ @@live = true
11
+ @@api_card_encryption_public_key = File.join(File.dirname(__FILE__), '..', 'certs/public_key.pem')
12
+
13
+ def self.api_key=(api_key)
14
+ @@api_key = api_key
15
+ end
16
+
17
+ def self.api_key
18
+ @@api_key
19
+ end
20
+
21
+ def self.api_card_encryption_public_key
22
+ @@api_card_encryption_public_key
23
+ end
24
+
25
+ def self.full_api_url(relative_path)
26
+ "#{@@api_endpoint}/#{@@api_version}#{relative_path}"
27
+ end
28
+
29
+ def self.live
30
+ @@live
31
+ end
32
+
33
+ def self.live=(live)
34
+ @@live = live
35
+ end
36
+
37
+ # def self.request(method, url, parameters)
38
+ # request_options = {
39
+ # :method => method,
40
+ # :url => self.full_api_url(url)
41
+ # :headers => nil,
42
+ # :open_timeout => 30,
43
+ # :payload => payload,
44
+ # :timeout => 80,
45
+ # }
46
+ # end
47
+
48
+ end
@@ -0,0 +1,24 @@
1
+ module PagarMe
2
+ class PagarMeError < StandardError
3
+ attr_reader :message
4
+ attr_reader :original_error
5
+
6
+ def initialize(message=nil, original_error=nil)
7
+ @message = message
8
+ @original_error = original_error
9
+ end
10
+
11
+ def to_s
12
+ "#{self.class.to_s} - #{message}"
13
+ end
14
+ end
15
+
16
+ class TransactionError < PagarMeError
17
+ end
18
+
19
+ class ConnectionError < PagarMeError
20
+ end
21
+
22
+ class ResponseError < PagarMeError
23
+ end
24
+ end
@@ -0,0 +1,80 @@
1
+ require 'uri'
2
+ require 'rest_client'
3
+ require 'multi_json'
4
+ require File.join(File.dirname(__FILE__), '.', 'utils')
5
+ require File.join(File.dirname(__FILE__), '.', 'errors')
6
+
7
+ module PagarMe
8
+ class Request
9
+ attr_accessor :path, :method, :parameters, :headers, :live
10
+
11
+ def initialize(path, method, live=PagarMe.live)
12
+ self.path = path
13
+ self.method = method
14
+ self.live = live
15
+ self.parameters = {}
16
+ self.headers = {}
17
+ end
18
+
19
+ def run
20
+ unless PagarMe.api_key
21
+ raise PagarMeError.new("You need to configure a API key before performing requests.")
22
+ end
23
+
24
+ parameters = self.parameters.merge({
25
+ :api_key => PagarMe.api_key,
26
+ :live => (self.live ? "1" : "0")
27
+ })
28
+
29
+ error = nil
30
+
31
+ begin
32
+ response = RestClient::Request.execute({
33
+ :method => self.method,
34
+ :url => PagarMe.full_api_url(self.path),
35
+ :headers => self.headers,
36
+ :open_timeout => 30,
37
+ :payload => parameters.to_params,
38
+ :timeout => 90,
39
+ :verify_ssl => false # TODO: change to verify SSL
40
+ })
41
+ rescue SocketError => e
42
+ error = "Error connecting to server (#{e.message})."
43
+ rescue NoMethodError => e
44
+ if e.message =~ /\WRequestFailed\W/
45
+ raise ResponseError.new("Unexpected response code (#{e.inspect}).")
46
+ else
47
+ raise
48
+ end
49
+ rescue RestClient::ExceptionWithResponse => e
50
+ if e.http_code and e.http_body
51
+ parsed_error = parse_json_response(e.http_body)
52
+ if parsed_error['error']
53
+ error = "HTTP error #{e.http_code}: #{parsed_error['error']}"
54
+ else
55
+ error = "Invalid response code (#{e.http_code})."
56
+ end
57
+ else
58
+ error = "Unexpected response code (#{e.message} - #{e.http_code})"
59
+ end
60
+ raise ResponseError.new(error)
61
+ rescue RestClient::Exception, Errno::ECONNREFUSED => e
62
+ error = "Error connecting to server: connection refused"
63
+ end
64
+
65
+ raise ConnectionError.new(error) if error
66
+
67
+ parse_json_response(response.body)
68
+ end
69
+
70
+ private
71
+
72
+ def parse_json_response(response)
73
+ begin
74
+ MultiJson.load(response)
75
+ rescue MultiJson::LoadError => e
76
+ raise ResponseError.new("Server response is not a valid JSON.")
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,156 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+ require File.join(File.dirname(__FILE__), '..', 'pagarme')
4
+ require File.join(File.dirname(__FILE__), '.', 'utils')
5
+ require File.join(File.dirname(__FILE__), '.', 'errors')
6
+
7
+ module PagarMe
8
+ class Transaction
9
+ attr_accessor :amount, :card_number, :card_holder_name, :card_expiracy_month, :card_expiracy_year, :card_cvv, :live, :card_hash, :installments
10
+
11
+ # initializers
12
+
13
+ def initialize(first_parameter = nil, server_response = nil)
14
+ @statuses_codes = { :local => 0, :approved => 1, :processing => 2, :refused => 3, :chargebacked => 4 }
15
+ @date_created = nil
16
+ @id = nil
17
+ self.status = :local
18
+ self.live = PagarMe.live
19
+ self.installments = 1
20
+
21
+ self.card_number = self.card_holder_name = self.card_expiracy_month = self.card_expiracy_year = self.card_cvv = ""
22
+ self.amount = 0
23
+
24
+ # First parameter can be a hash with transaction parameters
25
+ # or a encrypted card_hash that came from client.
26
+ if first_parameter.class == String
27
+ self.card_hash = first_parameter
28
+ elsif first_parameter.class == Hash
29
+ self.amount = first_parameter[:amount]
30
+ self.card_number = first_parameter[:card_number]
31
+ self.card_holder_name = first_parameter[:card_holder_name]
32
+ self.card_expiracy_month = first_parameter[:card_expiracy_month]
33
+ self.card_expiracy_year = first_parameter[:card_expiracy_year]
34
+ self.card_cvv = first_parameter[:card_cvv]
35
+ self.installments = first_parameter[:installments]
36
+ self.live = first_parameter[:live]
37
+ self.live = PagarMe.live unless self.live
38
+ end
39
+
40
+ update_fields_from_response(server_response) if server_response
41
+ end
42
+
43
+ def self.find_by_id(id)
44
+ request = PagarMe::Request.new("/transactions/#{id}", 'GET')
45
+ response = request.run
46
+ PagarMe::Transaction.new(nil, response)
47
+ end
48
+
49
+ def self.all(page = 1, count = 10)
50
+ raise TransactionError.new("Invalid page count") if page < 1 or count < 1
51
+
52
+ request = PagarMe::Request.new('/transactions', 'GET')
53
+ request.parameters = {
54
+ :page => page,
55
+ :count => count
56
+ }
57
+
58
+ response = request.run
59
+ response.map { |transaction_response| PagarMe::Transaction.new(nil, transaction_response) }
60
+ end
61
+
62
+ # getters
63
+
64
+ def status
65
+ @statuses_codes.key(@status)
66
+ end
67
+
68
+ def date_created
69
+ @date_created
70
+ end
71
+
72
+ def id
73
+ @id
74
+ end
75
+
76
+ # server requests methods
77
+
78
+ def charge
79
+ validation_error = self.card_hash ? nil : error_in_transaction
80
+ raise TransactionError.new(validation_error) if validation_error
81
+ raise TransactionError.new("Transaction already charged!") if self.status != :local
82
+
83
+ request = PagarMe::Request.new('/transactions', 'POST', self.live)
84
+ request.parameters = {
85
+ :amount => self.amount.to_s,
86
+ :installments => self.installments.to_i,
87
+ :card_hash => (self.card_hash ? self.card_hash : generate_card_hash)
88
+ }
89
+
90
+ response = request.run
91
+ update_fields_from_response(response)
92
+ end
93
+
94
+ def chargeback
95
+ raise TransactionError.new("Transaction already chargebacked!") if self.status == :chargebacked
96
+ raise TransactionError.new("Transaction needs to be approved to be chargebacked") if self.status != :approved
97
+
98
+ request = PagarMe::Request.new("/transactions/#{self.id}/chargeback/", 'POST', self.live)
99
+ response = request.run
100
+ update_fields_from_response(response)
101
+ end
102
+
103
+
104
+ private
105
+
106
+
107
+ def status=(status)
108
+ @status = @statuses_codes[status]
109
+ end
110
+
111
+ def update_fields_from_response(response)
112
+ @status = @statuses_codes[response['status'].to_sym]
113
+ @date_created = response['date_created']
114
+ self.amount = response['amount']
115
+ self.live = response['live']
116
+ self.card_holder_name = response['costumer_name']
117
+ self.installments = (!response['installments'] ? 1 : response['installments'].to_i)
118
+ @id = response['id']
119
+ end
120
+
121
+ def error_in_transaction
122
+ if self.card_number.length < 16 || self.card_number.length > 20
123
+ "Invalid card number."
124
+ elsif self.card_holder_name.length == 0
125
+ "Invalid card holder name."
126
+ elsif self.card_expiracy_month.to_i <= 0 || self.card_expiracy_month.to_i > 12
127
+ "Invalid expiracy date month."
128
+ elsif self.card_expiracy_year.to_i <= 0
129
+ "Invalid expiracy date year."
130
+ elsif self.card_cvv.length < 3 || self.card_cvv.length > 4
131
+ "Invalid card security code."
132
+ elsif self.amount <= 0
133
+ "Invalid amount."
134
+ else
135
+ nil
136
+ end
137
+ end
138
+
139
+ def card_data_parameters
140
+ {
141
+ :card_number => self.card_number,
142
+ :card_holder_name => self.card_holder_name,
143
+ :card_expiracy_date => "#{self.card_expiracy_month}#{self.card_expiracy_year}",
144
+ :card_cvv => self.card_cvv
145
+ }
146
+ end
147
+
148
+ def generate_card_hash
149
+ request = PagarMe::Request.new("/transactions/card_hash_key", 'GET', self.live)
150
+ response = request.run
151
+
152
+ public_key = OpenSSL::PKey::RSA.new(response['public_key'])
153
+ "#{response['id']}_#{Base64.strict_encode64(public_key.public_encrypt(card_data_parameters.to_params))}"
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,5 @@
1
+ class Hash
2
+ def to_params
3
+ self.collect{ |key, value| "#{key}=#{value}" }.join('&')
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "pagarme"
7
+ spec.version = 0.11
8
+ spec.authors = ["Pedro Franceschi"]
9
+ spec.email = ["pedrohfranceschi@gmail.com"]
10
+ spec.description = %q{Gem do pagar.me para Ruby}
11
+ spec.summary = %q{Permite a integração com a API do pagar.me por Ruby.}
12
+ spec.homepage = "http://pagar.me/"
13
+
14
+ spec.files = `git ls-files`.split($/)
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.3"
20
+ spec.add_development_dependency "rake"
21
+
22
+ spec.add_dependency "rest-client"
23
+ spec.add_dependency "multi_json"
24
+ end
@@ -0,0 +1,43 @@
1
+ require File.join(File.dirname(__FILE__), '.', 'lib/pagarme')
2
+
3
+ PagarMe.api_key = "4f0907cdfaf855b83a5d4a83a247772f"
4
+ PagarMe.live = true
5
+
6
+ begin
7
+ transaction = PagarMe::Transaction.new
8
+ transaction.card_number = "0000000000000000"
9
+ transaction.card_holder_name = "Test User"
10
+ transaction.card_expiracy_month = "12"
11
+ transaction.card_expiracy_year = "15"
12
+ transaction.card_cvv = "314"
13
+ transaction.amount = 1000
14
+ transaction.charge
15
+ transaction.chargeback
16
+
17
+ chargebacked_transaction = PagarMe::Transaction.find_by_id(transaction.id)
18
+ puts chargebacked_transaction.id == transaction.id
19
+ puts chargebacked_transaction.status == transaction.status
20
+ puts chargebacked_transaction.inspect
21
+
22
+ puts "\n\n"
23
+
24
+ hash_transaction = PagarMe::Transaction.new({
25
+ :card_number => "0000000000000000",
26
+ :card_holder_name => "Test User",
27
+ :card_expiracy_month => "12",
28
+ :card_expiracy_year => "13",
29
+ :card_cvv => "314",
30
+ :amount => 10000,
31
+ :installments => 5
32
+ })
33
+ hash_transaction.charge
34
+ puts hash_transaction.inspect
35
+ puts hash_transaction.status
36
+
37
+ puts "\n\n"
38
+
39
+ transactions = PagarMe::Transaction.all
40
+ puts transactions.inspect
41
+ rescue PagarMe::PagarMeError => e
42
+ puts "Error: #{e}"
43
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pagarme
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.11'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pedro Franceschi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &70206974487420 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70206974487420
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70206974486660 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70206974486660
36
+ - !ruby/object:Gem::Dependency
37
+ name: rest-client
38
+ requirement: &70206974485840 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70206974485840
47
+ - !ruby/object:Gem::Dependency
48
+ name: multi_json
49
+ requirement: &70206974485320 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70206974485320
58
+ description: Gem do pagar.me para Ruby
59
+ email:
60
+ - pedrohfranceschi@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - README.md
68
+ - Rakefile
69
+ - certs/public_key.pem
70
+ - lib/pagarme.rb
71
+ - lib/pagarme/errors.rb
72
+ - lib/pagarme/request.rb
73
+ - lib/pagarme/transaction.rb
74
+ - lib/pagarme/utils.rb
75
+ - pagarme.gemspec
76
+ - pagarme.rb
77
+ homepage: http://pagar.me/
78
+ licenses: []
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.10
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Permite a integração com a API do pagar.me por Ruby.
101
+ test_files: []