smulube-activemerchant 1.5.1 → 1.5.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/active_merchant/billing/gateways/payflow_nvp_uk.rb +320 -19
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
@@ -1,75 +1,376 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Billing #:nodoc:
|
3
3
|
class PayflowNvpUkGateway < Gateway
|
4
|
-
TEST_URL = 'https://
|
5
|
-
LIVE_URL = 'https://
|
4
|
+
TEST_URL = 'https://pilot-payflowpro.paypal.com'
|
5
|
+
LIVE_URL = 'https://payflowpro.paypal.com'
|
6
|
+
|
7
|
+
self.class_inheritable_accessor :partner
|
8
|
+
self.class_inheritable_accessor :timeout
|
9
|
+
|
10
|
+
# Enable safe retry of failed connections
|
11
|
+
# Payflow is safe to retry because retried transactions use the same
|
12
|
+
# X-VPS-Request-ID header. If a transaction is detected as a duplicate
|
13
|
+
# only the original transaction data will be used by Payflow, and the
|
14
|
+
# subsequent Responses will have a :duplicate parameter set in the params
|
15
|
+
# hash.
|
16
|
+
self.retry_safe = true
|
6
17
|
|
7
18
|
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
8
|
-
self.supported_countries = ['
|
19
|
+
self.supported_countries = ['GB']
|
9
20
|
|
10
21
|
# The card types supported by the payment gateway
|
11
|
-
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
22
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :solo, :switch]
|
12
23
|
|
13
24
|
# The homepage URL of the gateway
|
14
|
-
self.homepage_url = '
|
25
|
+
self.homepage_url = 'https://www.paypal.com/uk/cgi-bin/webscr?cmd=_wp-pro-overview-outside'
|
15
26
|
|
16
27
|
# The name of the gateway
|
17
|
-
self.display_name = '
|
28
|
+
self.display_name = 'PayPal Website Payments Pro (UK) [NVP API]'
|
18
29
|
|
30
|
+
self.default_currency = 'GBP'
|
31
|
+
self.partner = 'PayPalUk'
|
32
|
+
self.money_format = :dollars
|
33
|
+
|
34
|
+
TRANSACTIONS = {
|
35
|
+
:purchase => "S",
|
36
|
+
:authorization => "A",
|
37
|
+
:capture => "D",
|
38
|
+
:void => "V",
|
39
|
+
:credit => "C",
|
40
|
+
:recurring => "R"
|
41
|
+
}
|
42
|
+
|
43
|
+
PERIODS = {
|
44
|
+
:daily => "EDAY",
|
45
|
+
:weekly => "WEEK",
|
46
|
+
:biweekly => "BIWK",
|
47
|
+
:semimonthly => "SMMO",
|
48
|
+
:quadweekly => "FRWK",
|
49
|
+
:monthly => "MONT",
|
50
|
+
:quarterly => "QTER",
|
51
|
+
:semiyearly => "SMYR",
|
52
|
+
:yearly => "YEAR"
|
53
|
+
}
|
54
|
+
|
55
|
+
RECURRING_ACTIONS = {
|
56
|
+
:create => "A",
|
57
|
+
:modify => "M",
|
58
|
+
:deactivate => "C",
|
59
|
+
:reactivate => "R",
|
60
|
+
:inquiry => "I"
|
61
|
+
}
|
62
|
+
|
63
|
+
# Creates a new PayflowNvpUkGateway
|
64
|
+
#
|
65
|
+
# The gateway requires that a valid login and password be passed
|
66
|
+
# in the +options+ hash.
|
67
|
+
#
|
68
|
+
# ==== Parameters
|
69
|
+
#
|
70
|
+
# * <tt>options</tt>
|
71
|
+
# * <tt>:login</tt> - Your Payflow login
|
72
|
+
# * <tt>:password</tt> - Your Payflow password
|
19
73
|
def initialize(options = {})
|
20
|
-
|
74
|
+
requires!(options, :login, :password)
|
21
75
|
@options = options
|
76
|
+
@options[:partner] = partner if @options[:partner].blank?
|
22
77
|
super
|
23
|
-
end
|
24
|
-
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Is the gateway in test mode?
|
82
|
+
def test?
|
83
|
+
@options[:test] || super
|
84
|
+
end
|
85
|
+
|
86
|
+
# Performs an authorization transaction. This is required due to Visa and
|
87
|
+
# Mastercard restrictions, in that a customer's card cannot be charged
|
88
|
+
# until the goods have been dispatched. An authorization allows an amout
|
89
|
+
# to be reserved on a customer's card, bringing down the available
|
90
|
+
# balance or credit, but they are not actually charged until a subsequent
|
91
|
+
# capture step actually captures the funds.
|
92
|
+
#
|
93
|
+
# ==== Parameters
|
94
|
+
#
|
95
|
+
# * <tt>money</tt> - The amount to be charged as an integer value in cents.
|
96
|
+
# * <tt>creditcard</tt> - The CreditCard object to be used as a funding source for the transaction.
|
97
|
+
# * <tt>options</tt> - A hash of optional parameters
|
98
|
+
# * <tt>:order_id</tt> - A unique reference for this order (maximum of 127 characters).
|
99
|
+
# * <tt>:email</tt> - The customer's email address
|
100
|
+
# * <tt>:customer</tt> - A unique reference for the customer (maximum of 12 characters).
|
101
|
+
# * <tt>:ip</tt> - The customer's IP address
|
102
|
+
# * <tt>:currency</tt> - The currency of the transaction. If present must be one of { AUD, CAD, EUR, JPY, GBP or USD }. If omitted the default currency is used.
|
103
|
+
# * <tt>:billing_address</tt> - The customer's billing address as a hash of address information.
|
104
|
+
# * <tt>:address1</tt> - The billing address street
|
105
|
+
# * <tt>:city</tt> - The billing address city
|
106
|
+
# * <tt>:state</tt> - The billing address state
|
107
|
+
# * <tt>:country</tt> - The 2 digit ISO billing address country code
|
108
|
+
# * <tt>:zip</tt> - The billing address zip code
|
109
|
+
# * <tt>:shipping_address</tt> - The customer's shipping address as a hash of address information.
|
110
|
+
# * <tt>:address1</tt> - The shipping address street
|
111
|
+
# * <tt>:city</tt> - The shipping address city
|
112
|
+
# * <tt>:state</tt> - The shipping address state code
|
113
|
+
# * <tt>:country</tt> - The 2 digit ISO shipping address country code
|
114
|
+
# * <tt>:zip</tt> - The shipping address zip code
|
25
115
|
def authorize(money, creditcard, options = {})
|
26
116
|
post = {}
|
27
117
|
add_invoice(post, options)
|
28
118
|
add_creditcard(post, creditcard)
|
29
|
-
|
119
|
+
add_currency(post, money, options)
|
120
|
+
add_address(post, options[:billing_address] || options[:address])
|
121
|
+
add_address(post, options[:shipping_address], "shipto")
|
30
122
|
add_customer_data(post, options)
|
31
123
|
|
32
|
-
commit(
|
124
|
+
commit(TRANSACTIONS[:authorize], money, post)
|
33
125
|
end
|
34
126
|
|
127
|
+
# A purchase transaction authorizes and captures in a single hit. We can only
|
128
|
+
# do this for transactions where you provide immediate fulfillment of products or services.
|
129
|
+
#
|
130
|
+
# ==== Parameters
|
131
|
+
#
|
132
|
+
# * <tt>money</tt> - The amount to be charged as an integer value in cents.
|
133
|
+
# * <tt>creditcard</tt> - The CreditCard object to be used as a funding source for the transaction.
|
134
|
+
# * <tt>options</tt> - A hash of optional parameters
|
135
|
+
# * <tt>:order_id</tt> - A unique reference for this order (maximum of 127 characters).
|
136
|
+
# * <tt>:email</tt> - The customer's email address
|
137
|
+
# * <tt>:customer</tt> - A unique reference for the customer (maximum of 12 characters).
|
138
|
+
# * <tt>:ip</tt> - The customer's IP address
|
139
|
+
# * <tt>:currency</tt> - The currency of the transaction. If present must be one of { AUD, CAD, EUR, JPY, GBP or USD }. If ommitted the default currency is used.
|
140
|
+
# * <tt>:billing_address</tt> - The customer's billing address as a hash of address information.
|
141
|
+
# * <tt>:address1</tt> - The billing address street
|
142
|
+
# * <tt>:city</tt> - The billing address city
|
143
|
+
# * <tt>:state</tt> - The billing address state
|
144
|
+
# * <tt>:country</tt> - The 2 digit ISO billing address country code
|
145
|
+
# * <tt>:zip</tt> - The billing address zip code
|
146
|
+
# * <tt>:shipping_address</tt> - The customer's shipping address as a hash of address information.
|
147
|
+
# * <tt>:address1</tt> - The shipping address street
|
148
|
+
# * <tt>:city</tt> - The shipping address city
|
149
|
+
# * <tt>:state</tt> - The shipping address state code
|
150
|
+
# * <tt>:country</tt> - The 2 digit ISO shipping address country code
|
151
|
+
# * <tt>:zip</tt> - The shipping address zip code
|
35
152
|
def purchase(money, creditcard, options = {})
|
36
153
|
post = {}
|
37
154
|
add_invoice(post, options)
|
38
155
|
add_creditcard(post, creditcard)
|
39
|
-
|
156
|
+
add_currency(post, money, options)
|
157
|
+
add_address(post, options[:billing_address] || options[:address])
|
158
|
+
add_address(post, options[:shipping_address], "shipto")
|
40
159
|
add_customer_data(post, options)
|
41
160
|
|
42
|
-
commit(
|
161
|
+
commit(TRANSACTIONS[:purchase], money, post)
|
43
162
|
end
|
44
163
|
|
164
|
+
# Captures authorized funds.
|
165
|
+
#
|
166
|
+
# ==== Parameters
|
167
|
+
#
|
168
|
+
# * <tt>money</tt> - The amount to be authorized as an integer value in cents. Payflow does support changing the captured amount, so whatever is passed here will be captured.
|
169
|
+
# * <tt>authorization</tt> - The authorization reference string returned by the original transaction's Response#authorization.
|
170
|
+
# * <tt>options</tt> - not currently used.
|
45
171
|
def capture(money, authorization, options = {})
|
46
|
-
|
172
|
+
post = {}
|
173
|
+
post[:origid] = authorization
|
174
|
+
|
175
|
+
commit(TRANSACTIONS[:capture], money, post)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Voids an authorization or delayed capture
|
179
|
+
#
|
180
|
+
# ==== Parameters
|
181
|
+
#
|
182
|
+
# * <tt>authorization</tt> - The authorization reference string returned by the original transaction's Response#authorization.
|
183
|
+
# * <tt>options</tt> - Not currently used.
|
184
|
+
def void(authorization, options = {})
|
185
|
+
post = {}
|
186
|
+
post[:origid] = authorization
|
187
|
+
|
188
|
+
commit(TRANSACTIONS[:void], nil, post)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Process a refund to a customer.
|
192
|
+
#
|
193
|
+
# ==== Parameters
|
194
|
+
# * <tt>money</tt> - The amount to be credited as an integer value in cents.
|
195
|
+
# * <tt>authorization_or_card</tt> - The CreditCard you want to refund to OR the PayPal PNRef of a previous transaction. It depends on the settings in your PayPal account as to whether non referenced credits are permitted. The default is that they are not.
|
196
|
+
# * <tt>options</tt> - not currently used
|
197
|
+
def credit(money, authorization_or_card, options = {})
|
198
|
+
post = {}
|
199
|
+
|
200
|
+
if authorization_or_card.is_a?(String)
|
201
|
+
# perform a referenced credit
|
202
|
+
post[:origid] = authorization
|
203
|
+
else
|
204
|
+
# perform an unreferenced credit
|
205
|
+
add_creditcard(post, creditcard)
|
206
|
+
end
|
207
|
+
|
208
|
+
commit(TRANSACTIONS[:credit], money, post)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Create or modify a recurring profile.
|
212
|
+
#
|
213
|
+
# ==== Parameters
|
214
|
+
#
|
215
|
+
# * <tt>money</tt> - The amount that the recurring profile is to be set up for as an integer value in cents.
|
216
|
+
# * <tt>creditcard</tt> - The CreditCard object to be used as a funding source for the recurring profile.
|
217
|
+
# * <tt>options</tt> - A hash of parameters (some optional).
|
218
|
+
# * <tt>:profile_id</tt> - If present then we are modifying an existing profile, and this :profile_id identifies the profile we want to amend. If not present then we are creating a new recurring payments profile.
|
219
|
+
# * <tt>:starting_at</tt> - Takes a Date, Time or string in MMDDYYYY format. The date must be in the future.
|
220
|
+
# * <tt>:name</tt> - The name of the customer to be billed. If omitted the name from the creditcard is used.
|
221
|
+
# * <tt>:periodicity</tt> - The frequency that the recurring payments will occur at. Can be one of: [:daily, :weekly, :biweekly (every 2 weeks), :semimonthly (twice every month), :quadweekly (once every 4 weeks), :monthly (every month on the same date as the first payment), :quarterly (every 3 months on the same date as the first payment), :semiyearly (every 6 months on the same date as the first payment), :yearly.
|
222
|
+
# * <tt>:payments</tt> - Integer value describing the number of payments to be made.
|
223
|
+
# * <tt>:comment<tt> - Optional description of the goods or service being purchased
|
224
|
+
# * <tt>:max_failed_payments</tt> - The number of payments that are allowed to fail before PayPal suspends the profile. Defaults to 0 which means PayPal will never suspend the profile until the term is completed. PayPal will keep attempting to process failed payments.
|
225
|
+
# * <tt>:currency</tt> - The currency of the transaction. If present must be one of { AUD, CAD, EUR, JPY, GBP or USD }. If omitted the default currency is used.
|
226
|
+
def recurring(money, creditcard, options = {})
|
227
|
+
post = {}
|
228
|
+
add_creditcard(post, creditcard)
|
229
|
+
add_currency(post, money, options)
|
230
|
+
add_address(post, options[:billing_address] || options[:address])
|
231
|
+
add_address(post, options[:shipping_address], "shipto")
|
232
|
+
add_customer_data(post, options)
|
233
|
+
add_recurring_info(post, creditcard, options)
|
234
|
+
|
235
|
+
commit(TRANSACTIONS[:recurring], money, post)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Inquire about the status of a previously created recurring profile.
|
239
|
+
#
|
240
|
+
# ==== Parameters
|
241
|
+
#
|
242
|
+
# * <tt>profile_id</tt>
|
243
|
+
# * <tt>options</tt>
|
244
|
+
def recurring_inquiry(profile_id, options = {})
|
245
|
+
post = {}
|
246
|
+
|
247
|
+
post[:action] = RECURRING_ACTIONS[:inquiry]
|
248
|
+
post[:origprofileid] = profile_id.to_s
|
249
|
+
|
250
|
+
commit(TRANSACTIONS[:recurring], nil, options)
|
251
|
+
end
|
252
|
+
|
253
|
+
# Cancel a recurring profile.
|
254
|
+
#
|
255
|
+
# ==== Parameters
|
256
|
+
#
|
257
|
+
# * <tt>profile_id</tt>
|
258
|
+
def cancel_recurring(profile_id)
|
259
|
+
post = {}
|
260
|
+
|
261
|
+
post[:action] = RECURRING_ACTIONS[:deactivate]
|
262
|
+
post[:origprofileid] = profile_id.to_s
|
263
|
+
|
264
|
+
commit(TRANSACTIONS[:recurring], nil, nil)
|
47
265
|
end
|
48
266
|
|
49
267
|
private
|
50
268
|
|
51
269
|
def add_customer_data(post, options)
|
270
|
+
post[:email] = options[:email].to_s if options.has_key?(:email)
|
271
|
+
post[:custref] = options[:customer].to_s.slice(0,12) if options[:customer]
|
272
|
+
post[:custip] = options[:ip].to_s if options[:ip]
|
52
273
|
end
|
53
274
|
|
54
|
-
|
275
|
+
# NOTE : If you pass in any of the ship-to address parameters such as SHIPTOCITY or
|
276
|
+
# SHIPTOSTATE, you must pass in the complete set (that is, SHIPTOSTREET,
|
277
|
+
# SHIPTOCITY, SHIPTOSTATE, SHIPTOCOUNTRY, and SHIPTOZIP).
|
278
|
+
def add_address(post, address, prefix = '')
|
279
|
+
unless address.blank? or address.values.blank?
|
280
|
+
post[prefix+"street"] = address[:address1].to_s
|
281
|
+
post[prefix+"city"] = address[:city].to_s
|
282
|
+
post[prefix+"state"] = address[:state].blank? ? 'n/a' : address[:state]
|
283
|
+
post[prefix+"country"] = address[:country].to_s
|
284
|
+
post[prefix+"zip"] = address[:zip].to_s
|
285
|
+
end
|
55
286
|
end
|
56
287
|
|
57
288
|
def add_invoice(post, options)
|
289
|
+
post[:invnum] = options[:order_id].to_s.slice(0,127)
|
58
290
|
end
|
59
291
|
|
60
292
|
def add_creditcard(post, creditcard)
|
293
|
+
post[:acct] = creditcard.number
|
294
|
+
post[:cvv2] = creditcard.verification_value
|
295
|
+
post[:expdate] = expdate(creditcard)
|
296
|
+
post[:firstname] = creditcard.first_name
|
297
|
+
post[:lastname] = creditcard.last_name
|
61
298
|
end
|
62
299
|
|
300
|
+
def add_currency(post, money, options)
|
301
|
+
post[:currency] = options[:currency] || currency(money)
|
302
|
+
end
|
303
|
+
|
304
|
+
# need to add START, TERM, PAYPERIOD, ACTION
|
305
|
+
def add_recurring_info(post, creditcard, options)
|
306
|
+
post[:action] = options.has_key?(:profile_id) ? RECURRING_ACTIONS[:modify] : RECURRING_ACTIONS[:create]
|
307
|
+
post[:start] = format_date(options[:starting_at])
|
308
|
+
post[:term] = options[:payments] unless options[:payments].nil?
|
309
|
+
post[:payperiod] = PERIODS[options[:periodicity]]
|
310
|
+
post[:desc] = options[:comment] unless options[:comment].nil?
|
311
|
+
post[:maxfailedpayments] = options[:max_failed_payments] unless options[:max_failed_payments].nil?
|
312
|
+
post[:profilename] = (options[:name] || creditcard.name).to_s.slice(0,128)
|
313
|
+
end
|
314
|
+
|
315
|
+
def format_date(time)
|
316
|
+
case time
|
317
|
+
when Time, Date then time.strftime("%m%d%Y")
|
318
|
+
else
|
319
|
+
time.to_s
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def expdate(creditcard)
|
324
|
+
year = sprintf("%.04i", creditcard.year.to_i)
|
325
|
+
month = sprintf("%.02i", creditcard.month.to_i)
|
326
|
+
|
327
|
+
"#{month}#{year[-2..-1]}"
|
328
|
+
end
|
329
|
+
|
63
330
|
def parse(body)
|
331
|
+
results = {}
|
332
|
+
body.split(/&/).each do |pair|
|
333
|
+
key,val = pair.split(/=/)
|
334
|
+
results[key] = val
|
335
|
+
end
|
336
|
+
|
337
|
+
results
|
64
338
|
end
|
65
|
-
|
66
|
-
def
|
339
|
+
|
340
|
+
def build_request(parameters, action = nil)
|
341
|
+
post = {}
|
342
|
+
post[:user] = @options[:login]
|
343
|
+
post[:pwd] = @options[:password]
|
344
|
+
post[:trxtype] = action if action
|
345
|
+
|
346
|
+
request = post.merge(parameters).map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
347
|
+
request
|
67
348
|
end
|
68
349
|
|
69
|
-
def
|
350
|
+
def build_headers(content_length)
|
351
|
+
{
|
352
|
+
"Content-Type" => "text/namevalue",
|
353
|
+
"Content-Length" => content_length.to_s,
|
354
|
+
"X-VPS-Client-Timeout" => timeout.to_s,
|
355
|
+
"X-VPS-VIT-Integration-Product" => "ActiveMerchant",
|
356
|
+
"X-VPS-VIT-Runtime-Version" => RUBY_VERSION,
|
357
|
+
"X-VPS-Request-ID" => Utils.generate_unique_id
|
358
|
+
}
|
70
359
|
end
|
71
360
|
|
72
|
-
def
|
361
|
+
def commit(action, money, parameters)
|
362
|
+
request = build_request(parameters, action)
|
363
|
+
headers = build_headers(request.size)
|
364
|
+
|
365
|
+
parameters[:amount] = amount(money) if money
|
366
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request, headers))
|
367
|
+
Response.new(response["RESULT"] == "0", response["RESPMSG"], response,
|
368
|
+
:authorization => response["PNREF"],
|
369
|
+
:test => test?,
|
370
|
+
:cvv_result => response["CVV2MATCH"],
|
371
|
+
:avs_result => { :code => response["IAVS"] }
|
372
|
+
)
|
373
|
+
|
73
374
|
end
|
74
375
|
end
|
75
376
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -6,7 +6,8 @@ version: !ruby/object:Gem::Version
|
|
6
6
|
- 1
|
7
7
|
- 5
|
8
8
|
- 1
|
9
|
-
|
9
|
+
- 1
|
10
|
+
version: 1.5.1.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Tobias Luetke
|
@@ -35,7 +36,7 @@ cert_chain:
|
|
35
36
|
hPaSTyVU0yCSnw==
|
36
37
|
-----END CERTIFICATE-----
|
37
38
|
|
38
|
-
date: 2010-
|
39
|
+
date: 2010-04-06 00:00:00 +01:00
|
39
40
|
default_executable:
|
40
41
|
dependencies:
|
41
42
|
- !ruby/object:Gem::Dependency
|
metadata.gz.sig
CHANGED
Binary file
|