activemerchant 1.49.0 → 1.50.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/CHANGELOG +47 -0
- data/CONTRIBUTORS +4 -0
- data/README.md +5 -1
- data/lib/active_merchant/billing/credit_card.rb +9 -0
- data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +17 -6
- data/lib/active_merchant/billing/gateways/beanstream.rb +4 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +0 -4
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +4 -0
- data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
- data/lib/active_merchant/billing/gateways/cashnet.rb +19 -8
- data/lib/active_merchant/billing/gateways/cenpos.rb +15 -29
- data/lib/active_merchant/billing/gateways/conekta.rb +3 -2
- data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +19 -12
- data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
- data/lib/active_merchant/billing/gateways/omise.rb +319 -0
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +5 -4
- data/lib/active_merchant/billing/gateways/orbital.rb +7 -0
- data/lib/active_merchant/billing/gateways/payu_in.rb +243 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +11 -357
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
- data/lib/active_merchant/billing/gateways/s5.rb +226 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +7 -1
- data/lib/active_merchant/billing/gateways/secure_net.rb +1 -1
- data/lib/active_merchant/billing/gateways/stripe.rb +8 -5
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +2 -2
- data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
- data/lib/active_merchant/connection.rb +3 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +15 -27
- checksums.yaml.gz.sig +0 -2
- data.tar.gz.sig +0 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +0 -209
- metadata.gz.sig +0 -1
@@ -0,0 +1,245 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class MerchantPartnersGateway < Gateway
|
6
|
+
self.display_name = "Merchant Partners"
|
7
|
+
self.homepage_url = "http://www.merchantpartners.com/"
|
8
|
+
|
9
|
+
self.live_url = "https://trans.merchantpartners.com/cgi-bin/ProcessXML.cgi"
|
10
|
+
|
11
|
+
self.supported_countries = ["US"]
|
12
|
+
self.default_currency = "USD"
|
13
|
+
self.money_format = :dollars
|
14
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
15
|
+
|
16
|
+
def initialize(options={})
|
17
|
+
requires!(options, :account_id, :merchant_pin)
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def purchase(amount, payment_method, options={})
|
22
|
+
post = {}
|
23
|
+
add_invoice(post, amount, options)
|
24
|
+
add_payment_method(post, payment_method)
|
25
|
+
add_customer_data(post, options)
|
26
|
+
|
27
|
+
commit(payment_method.is_a?(String) ? :stored_purchase : :purchase, post)
|
28
|
+
end
|
29
|
+
|
30
|
+
def authorize(amount, payment_method, options={})
|
31
|
+
post = {}
|
32
|
+
add_invoice(post, amount, options)
|
33
|
+
add_payment_method(post, payment_method)
|
34
|
+
add_customer_data(post, options)
|
35
|
+
|
36
|
+
commit(:authorize, post)
|
37
|
+
end
|
38
|
+
|
39
|
+
def capture(amount, authorization, options={})
|
40
|
+
post = {}
|
41
|
+
add_invoice(post, amount, options)
|
42
|
+
add_reference(post, authorization)
|
43
|
+
add_customer_data(post, options)
|
44
|
+
|
45
|
+
commit(:capture, post)
|
46
|
+
end
|
47
|
+
|
48
|
+
def void(authorization, options={})
|
49
|
+
post = {}
|
50
|
+
add_reference(post, authorization)
|
51
|
+
|
52
|
+
commit(:void, post)
|
53
|
+
end
|
54
|
+
|
55
|
+
def refund(amount, authorization, options={})
|
56
|
+
post = {}
|
57
|
+
add_invoice(post, amount, options)
|
58
|
+
add_reference(post, authorization)
|
59
|
+
add_customer_data(post, options)
|
60
|
+
|
61
|
+
commit(:refund, post)
|
62
|
+
end
|
63
|
+
|
64
|
+
def credit(amount, payment_method, options={})
|
65
|
+
post = {}
|
66
|
+
add_invoice(post, amount, options)
|
67
|
+
add_payment_method(post, payment_method)
|
68
|
+
|
69
|
+
commit(payment_method.is_a?(String) ? :stored_credit : :credit, post)
|
70
|
+
end
|
71
|
+
|
72
|
+
def verify(credit_card, options={})
|
73
|
+
MultiResponse.run(:use_first_response) do |r|
|
74
|
+
r.process { authorize(100, credit_card, options) }
|
75
|
+
r.process(:ignore_result) { void(r.authorization, options) }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def store(payment_method, options = {})
|
80
|
+
post = {}
|
81
|
+
add_payment_method(post, payment_method)
|
82
|
+
add_customer_data(post, options)
|
83
|
+
|
84
|
+
post[:profileactiontype] = options[:profileactiontype] || STORE_TX_TYPES[:store_only]
|
85
|
+
|
86
|
+
commit(:store, post)
|
87
|
+
end
|
88
|
+
|
89
|
+
def supports_scrubbing?
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
def scrub(transcript)
|
94
|
+
transcript.
|
95
|
+
gsub(%r((<ccnum>)[^<]+(<))i, '\1[FILTERED]\2').
|
96
|
+
gsub(%r((<cvv2>)[^<]+(<))i, '\1[FILTERED]\2').
|
97
|
+
gsub(%r((<merchantpin>)[^<]+(<))i, '\1[FILTERED]\2')
|
98
|
+
end
|
99
|
+
|
100
|
+
def test?
|
101
|
+
@options[:account_id].eql?('TEST0')
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def add_invoice(post, money, options)
|
107
|
+
post[:amount] = amount(money)
|
108
|
+
post[:merchantordernumber] = options[:order_id]
|
109
|
+
post[:currency] = options[:currency] || currency(money)
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_payment_method(post, payment_method)
|
113
|
+
if(payment_method.is_a?(String))
|
114
|
+
user_profile_id, last_4 = split_authorization(payment_method)
|
115
|
+
post[:userprofileid] = user_profile_id
|
116
|
+
post[:last4digits] = last_4
|
117
|
+
else
|
118
|
+
post[:ccname] = payment_method.name
|
119
|
+
post[:ccnum] = payment_method.number
|
120
|
+
post[:cvv2] = payment_method.verification_value
|
121
|
+
post[:expmon] = format(payment_method.month, :two_digits)
|
122
|
+
post[:expyear] = format(payment_method.year, :four_digits)
|
123
|
+
post[:swipedata] = payment_method.track_data if payment_method.track_data
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_customer_data(post, options)
|
128
|
+
post[:email] = options[:email] if options[:email]
|
129
|
+
post[:ipaddress] = options[:ip] if options[:ip]
|
130
|
+
if(billing_address = options[:billing_address])
|
131
|
+
post[:billaddr1] = billing_address[:address1]
|
132
|
+
post[:billaddr2] = billing_address[:address2]
|
133
|
+
post[:billcity] = billing_address[:city]
|
134
|
+
post[:billstate] = billing_address[:state]
|
135
|
+
post[:billcountry] = billing_address[:country]
|
136
|
+
post[:bilzip] = billing_address[:zip]
|
137
|
+
post[:phone] = billing_address[:phone]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def add_reference(post, authorization)
|
142
|
+
post[:historykeyid] = authorization
|
143
|
+
end
|
144
|
+
|
145
|
+
ACTIONS = {
|
146
|
+
purchase: "2",
|
147
|
+
authorize: "1",
|
148
|
+
capture: "3",
|
149
|
+
void: "5",
|
150
|
+
refund: "4",
|
151
|
+
credit: "6",
|
152
|
+
store: "7",
|
153
|
+
stored_purchase: "8",
|
154
|
+
stored_credit: "13"
|
155
|
+
}
|
156
|
+
|
157
|
+
STORE_TX_TYPES = {
|
158
|
+
store_only: "3"
|
159
|
+
}
|
160
|
+
|
161
|
+
def commit(action, post)
|
162
|
+
post[:acctid] = @options[:account_id]
|
163
|
+
post[:merchantpin] = @options[:merchant_pin]
|
164
|
+
post[:service] = ACTIONS[action] if ACTIONS[action]
|
165
|
+
|
166
|
+
data = build_request(post)
|
167
|
+
response_data = parse(ssl_post(live_url, data, headers))
|
168
|
+
succeeded = success_from(response_data)
|
169
|
+
|
170
|
+
Response.new(
|
171
|
+
succeeded,
|
172
|
+
message_from(succeeded, response_data),
|
173
|
+
response_data,
|
174
|
+
authorization: authorization_from(post, response_data),
|
175
|
+
:avs_result => AVSResult.new(code: response_data["avs_response"]),
|
176
|
+
:cvv_result => CVVResult.new(response_data["cvv2_response"]),
|
177
|
+
test: test?
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
def headers
|
182
|
+
{
|
183
|
+
"Content-Type" => "application/xml"
|
184
|
+
}
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_request(post)
|
188
|
+
Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
|
189
|
+
xml.interface_driver {
|
190
|
+
xml.trans_catalog {
|
191
|
+
xml.transaction(name: "creditcard") {
|
192
|
+
xml.inputs {
|
193
|
+
post.each do |field, value|
|
194
|
+
xml.send(field, value)
|
195
|
+
end
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}
|
199
|
+
}
|
200
|
+
end.to_xml
|
201
|
+
end
|
202
|
+
|
203
|
+
def parse(body)
|
204
|
+
response = {}
|
205
|
+
Nokogiri::XML(CGI.unescapeHTML(body)).xpath("//trans_catalog/transaction/outputs").children.each do |node|
|
206
|
+
parse_element(response, node)
|
207
|
+
end
|
208
|
+
response
|
209
|
+
end
|
210
|
+
|
211
|
+
def parse_element(response, node)
|
212
|
+
if node.elements.size == 0
|
213
|
+
response[node.name.downcase.underscore.to_sym] = node.text
|
214
|
+
else
|
215
|
+
node.elements.each{|element| parse_element(response, element) }
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def success_from(response)
|
220
|
+
response[:status] == "Approved"
|
221
|
+
end
|
222
|
+
|
223
|
+
def message_from(succeeded, response)
|
224
|
+
succeeded ? "Succeeded" : error_message_from(response)
|
225
|
+
end
|
226
|
+
|
227
|
+
def authorization_from(request, response)
|
228
|
+
request[:service] == ACTIONS[:store] ?
|
229
|
+
"#{response[:userprofileid]}|#{response[:last4digits]}" :
|
230
|
+
response[:historyid]
|
231
|
+
end
|
232
|
+
|
233
|
+
def split_authorization(authorization)
|
234
|
+
authorization.split("|")
|
235
|
+
end
|
236
|
+
|
237
|
+
def error_message_from(response)
|
238
|
+
if(response[:status] == "Declined")
|
239
|
+
match = response[:result].match(/DECLINED:\d{10}:(.+):/)
|
240
|
+
match[1] if match
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
@@ -31,6 +31,7 @@ module ActiveMerchant #:nodoc:
|
|
31
31
|
self.display_name = 'NETbilling'
|
32
32
|
self.homepage_url = 'http://www.netbilling.com'
|
33
33
|
self.supported_countries = ['US']
|
34
|
+
self.ssl_version = :TLSv1
|
34
35
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
|
35
36
|
|
36
37
|
def initialize(options = {})
|
@@ -0,0 +1,319 @@
|
|
1
|
+
require 'active_merchant/billing/rails'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class OmiseGateway < Gateway
|
6
|
+
API_VERSION = '1.0'
|
7
|
+
API_URL = 'https://api.omise.co/'
|
8
|
+
VAULT_URL = 'https://vault.omise.co/'
|
9
|
+
|
10
|
+
STANDARD_ERROR_CODE_MAPPING = {
|
11
|
+
'invalid_security_code' => STANDARD_ERROR_CODE[:invalid_cvc],
|
12
|
+
'failed_capture' => STANDARD_ERROR_CODE[:card_declined]
|
13
|
+
}
|
14
|
+
|
15
|
+
self.live_url = self.test_url = API_URL
|
16
|
+
|
17
|
+
# Currency supported by Omise
|
18
|
+
# * Thai Baht with Satang, ie. 9000 => 90 THB
|
19
|
+
self.default_currency = 'THB'
|
20
|
+
self.money_format = :cents
|
21
|
+
|
22
|
+
#Country supported by Omise
|
23
|
+
# * Thailand
|
24
|
+
self.supported_countries = %w( TH )
|
25
|
+
|
26
|
+
# Credit cards supported by Omise
|
27
|
+
# * VISA
|
28
|
+
# * MasterCard
|
29
|
+
self.supported_cardtypes = [:visa, :master]
|
30
|
+
|
31
|
+
# Omise main page
|
32
|
+
self.homepage_url = 'https://www.omise.co/'
|
33
|
+
self.display_name = 'Omise'
|
34
|
+
|
35
|
+
# Creates a new OmiseGateway.
|
36
|
+
#
|
37
|
+
# Omise requires public_key for token creation.
|
38
|
+
# And it requires secret_key for other transactions.
|
39
|
+
# These keys can be found in https://dashboard.omise.co/test/api-keys
|
40
|
+
#
|
41
|
+
# ==== Options
|
42
|
+
#
|
43
|
+
# * <tt>:public_key</tt> -- Omise's public key (REQUIRED).
|
44
|
+
# * <tt>:secret_key</tt> -- Omise's secret key (REQUIRED).
|
45
|
+
|
46
|
+
def initialize(options={})
|
47
|
+
requires!(options, :public_key, :secret_key)
|
48
|
+
@public_key = options[:public_key]
|
49
|
+
@secret_key = options[:secret_key]
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
# Perform a purchase (with auto capture)
|
54
|
+
#
|
55
|
+
# ==== Parameters
|
56
|
+
#
|
57
|
+
# * <tt>money</tt> -- The purchasing amount in Thai Baht Satang
|
58
|
+
# * <tt>payment_method</tt> -- The CreditCard object
|
59
|
+
# * <tt>options</tt> -- An optional parameters, such as token from Omise.js
|
60
|
+
#
|
61
|
+
# ==== Options
|
62
|
+
# * <tt>token_id</tt> -- token id, use Omise.js library to retrieve a token id
|
63
|
+
# if this is passed as an option, it will ignore tokenizing via Omisevaultgateway object
|
64
|
+
#
|
65
|
+
# === Example
|
66
|
+
# To create a charge on a card
|
67
|
+
#
|
68
|
+
# purchase(money, Creditcard_object)
|
69
|
+
#
|
70
|
+
# To create a charge on a token
|
71
|
+
#
|
72
|
+
# purchase(money, nil, { :token_id => token_id, ... })
|
73
|
+
#
|
74
|
+
# To create a charge on a customer
|
75
|
+
#
|
76
|
+
# purchase(money, nil, { :customer_id => customer_id })
|
77
|
+
|
78
|
+
def purchase(money, payment_method, options={})
|
79
|
+
create_charge(money, payment_method, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Authorize a charge.
|
83
|
+
#
|
84
|
+
# ==== Parameters
|
85
|
+
#
|
86
|
+
# * <tt>money</tt> -- The purchasing amount in Thai Baht Satang
|
87
|
+
# * <tt>payment_method</tt> -- The CreditCard object
|
88
|
+
# * <tt>options</tt> -- An optional parameters, such as token or capture
|
89
|
+
|
90
|
+
def authorize(money, payment_method, options={})
|
91
|
+
options[:capture] = 'false'
|
92
|
+
create_charge(money, payment_method, options)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Capture an authorized charge.
|
96
|
+
#
|
97
|
+
# ==== Parameters
|
98
|
+
#
|
99
|
+
# * <tt>money</tt> -- An amount in Thai Baht Satang
|
100
|
+
# * <tt>charge_id</tt> -- The CreditCard object
|
101
|
+
# * <tt>options</tt> -- An optional parameters, such as token or capture
|
102
|
+
|
103
|
+
def capture(money, charge_id, options={})
|
104
|
+
post = {}
|
105
|
+
add_amount(post, money, options)
|
106
|
+
commit(:post, "charges/#{CGI.escape(charge_id)}/capture", post, options)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Refund a charge.
|
110
|
+
#
|
111
|
+
# ==== Parameters
|
112
|
+
#
|
113
|
+
# * <tt>money</tt> -- An amount of money to charge in Satang.
|
114
|
+
# * <tt>charge_id</tt> -- The CreditCard object
|
115
|
+
# * <tt>options</tt> -- An optional parameters, such as token or capture
|
116
|
+
|
117
|
+
def refund(money, charge_id, options={})
|
118
|
+
options[:amount] = money if money
|
119
|
+
commit(:post, "charges/#{CGI.escape(charge_id)}/refunds", options)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Store a card details as customer
|
123
|
+
#
|
124
|
+
# ==== Parameters
|
125
|
+
#
|
126
|
+
# * <tt>payment_method</tt> -- The CreditCard.
|
127
|
+
# * <tt>options</tt> -- Optional Customer information:
|
128
|
+
# 'email' (A customer email)
|
129
|
+
# 'description' (A customer description)
|
130
|
+
|
131
|
+
def store(payment_method, options={})
|
132
|
+
post, card_params = {}, {}
|
133
|
+
add_customer_data(post, options)
|
134
|
+
add_token(card_params, payment_method, options)
|
135
|
+
commit(:post, 'customers', post.merge(card_params), options)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Delete a customer and all associated credit cards.
|
139
|
+
#
|
140
|
+
# ==== Parameters
|
141
|
+
#
|
142
|
+
# * <tt>customer_id</tt> -- The Customer identifier (REQUIRED).
|
143
|
+
|
144
|
+
def unstore(customer_id, options={})
|
145
|
+
commit(:delete, "customers/#{CGI.escape(customer_id)}")
|
146
|
+
end
|
147
|
+
|
148
|
+
# Enable scrubbling sensitive information
|
149
|
+
def supports_scrubbing?
|
150
|
+
true
|
151
|
+
end
|
152
|
+
|
153
|
+
# Scrub sensitive information out of HTTP transcripts
|
154
|
+
#
|
155
|
+
# ==== Parameters
|
156
|
+
#
|
157
|
+
# * <tt>transcript</tt> -- The HTTP transcripts
|
158
|
+
|
159
|
+
def scrub(transcript)
|
160
|
+
transcript.
|
161
|
+
gsub(/(Authorization: Basic )\w+/i, '\1[FILTERED]').
|
162
|
+
gsub(/(\\"number\\":)\\"\d+\\"/, '\1[FILTERED]').
|
163
|
+
gsub(/(\\"security_code\\":)\\"\d+\\"/,'\1[FILTERED]')
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def create_charge(money, payment_method, options)
|
169
|
+
post = {}
|
170
|
+
add_token(post, payment_method, options)
|
171
|
+
add_amount(post, money, options)
|
172
|
+
add_customer(post, options)
|
173
|
+
post[:capture] = options[:capture] if options[:capture]
|
174
|
+
commit(:post, 'charges', post, options)
|
175
|
+
end
|
176
|
+
|
177
|
+
def headers(options={})
|
178
|
+
key = options[:key] || @secret_key
|
179
|
+
{
|
180
|
+
'Content-Type' => 'application/json;utf-8',
|
181
|
+
'User-Agent' => "Omise/v#{API_VERSION} ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
|
182
|
+
'Authorization' => 'Basic ' + Base64.encode64(key.to_s + ':').strip,
|
183
|
+
'Accept-Encoding' => 'utf-8'
|
184
|
+
}
|
185
|
+
end
|
186
|
+
|
187
|
+
def url_for(endpoint)
|
188
|
+
(endpoint == 'tokens' ? VAULT_URL : API_URL) + endpoint
|
189
|
+
end
|
190
|
+
|
191
|
+
def post_data(parameters)
|
192
|
+
parameters.present? ? parameters.to_json : nil
|
193
|
+
end
|
194
|
+
|
195
|
+
def https_request(method, endpoint, parameters=nil, options={})
|
196
|
+
raw_response = response = nil
|
197
|
+
begin
|
198
|
+
raw_response = ssl_request(method, url_for(endpoint), post_data(parameters), headers(options))
|
199
|
+
response = parse(raw_response)
|
200
|
+
rescue ResponseError => e
|
201
|
+
raw_response = e.response.body
|
202
|
+
response = parse(raw_response)
|
203
|
+
rescue JSON::ParserError
|
204
|
+
response = json_error(raw_response)
|
205
|
+
end
|
206
|
+
response
|
207
|
+
end
|
208
|
+
|
209
|
+
def parse(body)
|
210
|
+
JSON.parse(body)
|
211
|
+
end
|
212
|
+
|
213
|
+
def json_error(raw_response)
|
214
|
+
msg = "Invalid response received from Omise API. Please contact support@omise.co if you continue to receive this message."
|
215
|
+
msg += "The raw response returned by the API was #{raw_response.inspect})"
|
216
|
+
{ message: msg }
|
217
|
+
end
|
218
|
+
|
219
|
+
def commit(method, endpoint, params=nil, options={})
|
220
|
+
response = https_request(method, endpoint, params, options)
|
221
|
+
Response.new(
|
222
|
+
successful?(response),
|
223
|
+
message_from(response),
|
224
|
+
response,
|
225
|
+
{
|
226
|
+
authorization: authorization_from(response),
|
227
|
+
test: test?,
|
228
|
+
error_code: successful?(response) ? nil : standard_error_code_mapping(response)
|
229
|
+
}
|
230
|
+
)
|
231
|
+
end
|
232
|
+
|
233
|
+
def standard_error_code_mapping(response)
|
234
|
+
STANDARD_ERROR_CODE_MAPPING[error_code_from(response)] || message_to_standard_error_code_from(response)
|
235
|
+
end
|
236
|
+
|
237
|
+
def error_code_from(response)
|
238
|
+
error?(response) ? response['code'] : response['failure_code']
|
239
|
+
end
|
240
|
+
|
241
|
+
def message_to_standard_error_code_from(response)
|
242
|
+
message = response['message'] if response['code'] == 'invalid_card'
|
243
|
+
case message
|
244
|
+
when /brand not supported/
|
245
|
+
STANDARD_ERROR_CODE[:invalid_number]
|
246
|
+
when /number is invalid/
|
247
|
+
STANDARD_ERROR_CODE[:incorrect_number]
|
248
|
+
when /expiration date cannot be in the past/
|
249
|
+
STANDARD_ERROR_CODE[:expired_card]
|
250
|
+
when /expiration \w+ is invalid/
|
251
|
+
STANDARD_ERROR_CODE[:invalid_expiry_date]
|
252
|
+
else
|
253
|
+
STANDARD_ERROR_CODE[:processing_error]
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def message_from(response)
|
258
|
+
if successful?(response)
|
259
|
+
'Success'
|
260
|
+
else
|
261
|
+
(response['message'] ? response['message'] : response['failure_message'])
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def authorization_from(response)
|
266
|
+
response['id'] if successful?(response)
|
267
|
+
end
|
268
|
+
|
269
|
+
def successful?(response)
|
270
|
+
!error?(response) && response['failure_code'].nil?
|
271
|
+
end
|
272
|
+
|
273
|
+
def error?(response)
|
274
|
+
response.key?('object') && (response['object'] == 'error')
|
275
|
+
end
|
276
|
+
|
277
|
+
def get_token(post, credit_card)
|
278
|
+
add_creditcard(post, credit_card) if credit_card
|
279
|
+
commit(:post, 'tokens', post, { key: @public_key })
|
280
|
+
end
|
281
|
+
|
282
|
+
def add_token(post, credit_card, options={})
|
283
|
+
if options[:token_id].present?
|
284
|
+
post[:card] = options[:token_id]
|
285
|
+
else
|
286
|
+
response = get_token(post, credit_card)
|
287
|
+
response.authorization ? (post[:card] = response.authorization) : response
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def add_creditcard(post, payment_method)
|
292
|
+
card = {
|
293
|
+
number: payment_method.number,
|
294
|
+
name: payment_method.name,
|
295
|
+
security_code: payment_method.verification_value,
|
296
|
+
expiration_month: payment_method.month,
|
297
|
+
expiration_year: payment_method.year
|
298
|
+
}
|
299
|
+
post[:card] = card
|
300
|
+
end
|
301
|
+
|
302
|
+
def add_customer(post, options={})
|
303
|
+
post[:customer] = options[:customer_id] if options[:customer_id]
|
304
|
+
end
|
305
|
+
|
306
|
+
def add_customer_data(post, options={})
|
307
|
+
post[:description] = options[:description] if options[:description]
|
308
|
+
post[:email] = options[:email] if options[:email]
|
309
|
+
end
|
310
|
+
|
311
|
+
def add_amount(post, money, options)
|
312
|
+
post[:amount] = amount(money)
|
313
|
+
post[:currency] = (options[:currency] || currency(money))
|
314
|
+
post[:description] = options[:description] if options.key?(:description)
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|