johnreitano-activemerchant 1.5.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.
Files changed (131) hide show
  1. data/CHANGELOG +508 -0
  2. data/CONTRIBUTORS +134 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +136 -0
  5. data/gem-public_cert.pem +20 -0
  6. data/lib/active_merchant/billing/avs_result.rb +98 -0
  7. data/lib/active_merchant/billing/base.rb +57 -0
  8. data/lib/active_merchant/billing/check.rb +68 -0
  9. data/lib/active_merchant/billing/credit_card.rb +159 -0
  10. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  11. data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
  12. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  13. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  14. data/lib/active_merchant/billing/gateway.rb +163 -0
  15. data/lib/active_merchant/billing/gateways/authorize_net.rb +654 -0
  16. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +736 -0
  17. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +244 -0
  18. data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
  19. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  20. data/lib/active_merchant/billing/gateways/bogus.rb +98 -0
  21. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  22. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  23. data/lib/active_merchant/billing/gateways/cyber_source.rb +594 -0
  24. data/lib/active_merchant/billing/gateways/data_cash.rb +593 -0
  25. data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
  26. data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
  27. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  28. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  29. data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
  30. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  31. data/lib/active_merchant/billing/gateways/jetpay.rb +270 -0
  32. data/lib/active_merchant/billing/gateways/linkpoint.rb +449 -0
  33. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
  34. data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
  35. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  36. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  37. data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
  38. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  39. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  40. data/lib/active_merchant/billing/gateways/ogone.rb +279 -0
  41. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  42. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  43. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  44. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  45. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  46. data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
  47. data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
  48. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  49. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  50. data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
  51. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +326 -0
  52. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
  53. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  54. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  55. data/lib/active_merchant/billing/gateways/paypal_express.rb +130 -0
  56. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
  57. data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
  58. data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
  59. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  60. data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
  61. data/lib/active_merchant/billing/gateways/realex.rb +200 -0
  62. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  63. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  64. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  65. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  66. data/lib/active_merchant/billing/gateways/sage_pay.rb +309 -0
  67. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  68. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  69. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
  70. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  71. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  72. data/lib/active_merchant/billing/gateways/smart_ps.rb +265 -0
  73. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  74. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  75. data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
  76. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  77. data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
  78. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  79. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  80. data/lib/active_merchant/billing/gateways.rb +18 -0
  81. data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
  82. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  83. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  84. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  85. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  86. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  87. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  88. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  89. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  90. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  91. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  92. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  93. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  94. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  95. data/lib/active_merchant/billing/integrations/helper.rb +93 -0
  96. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  97. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  98. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  99. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  100. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  101. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  102. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  103. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  104. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  105. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  106. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  107. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  108. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  109. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  110. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  111. data/lib/active_merchant/billing/integrations/quickpay.rb +17 -0
  112. data/lib/active_merchant/billing/integrations/return.rb +35 -0
  113. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  114. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  115. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  116. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  117. data/lib/active_merchant/billing/integrations.rb +29 -0
  118. data/lib/active_merchant/billing/response.rb +32 -0
  119. data/lib/active_merchant/billing.rb +9 -0
  120. data/lib/active_merchant/lib/connection.rb +170 -0
  121. data/lib/active_merchant/lib/country.rb +319 -0
  122. data/lib/active_merchant/lib/error.rb +4 -0
  123. data/lib/active_merchant/lib/post_data.rb +22 -0
  124. data/lib/active_merchant/lib/posts_data.rb +47 -0
  125. data/lib/active_merchant/lib/requires_parameters.rb +16 -0
  126. data/lib/active_merchant/lib/utils.rb +18 -0
  127. data/lib/active_merchant/lib/validateable.rb +76 -0
  128. data/lib/active_merchant.rb +46 -0
  129. data/lib/certs/cacert.pem +7815 -0
  130. data/lib/support/gateway_support.rb +58 -0
  131. metadata +218 -0
@@ -0,0 +1,318 @@
1
+ require 'base64'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class WirecardGateway < Gateway
6
+ # Test server location
7
+ TEST_URL = 'https://c3-test.wirecard.com/secure/ssl-gateway'
8
+
9
+ # Live server location
10
+ LIVE_URL = 'https://c3.wirecard.com/secure/ssl-gateway'
11
+
12
+ # The Namespaces are not really needed, because it just tells the System, that there's actually no namespace used.
13
+ # It's just specified here for completeness.
14
+ ENVELOPE_NAMESPACES = {
15
+ 'xmlns:xsi' => 'http://www.w3.org/1999/XMLSchema-instance',
16
+ 'xsi:noNamespaceSchemaLocation' => 'wirecard.xsd'
17
+ }
18
+
19
+ PERMITTED_TRANSACTIONS = %w[ AUTHORIZATION CAPTURE_AUTHORIZATION PURCHASE ]
20
+
21
+ RETURN_CODES = %w[ ACK NOK ]
22
+
23
+ # Wirecard only allows phone numbers with a format like this: +xxx(yyy)zzz-zzzz-ppp, where:
24
+ # xxx = Country code
25
+ # yyy = Area or city code
26
+ # zzz-zzzz = Local number
27
+ # ppp = PBX extension
28
+ # For example, a typical U.S. or Canadian number would be "+1(202)555-1234-739" indicating PBX extension 739 at phone
29
+ # number 5551234 within area code 202 (country code 1).
30
+ VALID_PHONE_FORMAT = /\+\d{1,3}(\(?\d{3}\)?)?\d{3}-\d{4}-\d{3}/
31
+
32
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
33
+ # TODO: Check supported countries
34
+ self.supported_countries = ['DE']
35
+
36
+ # Wirecard supports all major credit and debit cards:
37
+ # Visa, Mastercard, American Express, Diners Club,
38
+ # JCB, Switch, VISA Carte Bancaire, Visa Electron and UATP cards.
39
+ # They also support the latest anti-fraud systems such as Verified by Visa or Master Secure Code.
40
+ self.supported_cardtypes = [
41
+ :visa, :master, :american_express, :diners_club, :jcb, :switch
42
+ ]
43
+
44
+ # The homepage URL of the gateway
45
+ self.homepage_url = 'http://www.wirecard.com'
46
+
47
+ # The name of the gateway
48
+ self.display_name = 'Wirecard'
49
+
50
+ # The currency should normally be EUROs
51
+ self.default_currency = 'EUR'
52
+
53
+ # 100 is 1.00 Euro
54
+ self.money_format = :cents
55
+
56
+ def initialize(options = {})
57
+ # verify that username and password are supplied
58
+ requires!(options, :login, :password)
59
+ # unfortunately Wirecard also requires a BusinessCaseSignature in the XML request
60
+ requires!(options, :signature)
61
+ @options = options
62
+ super
63
+ end
64
+
65
+ # Should run against the test servers or not?
66
+ def test?
67
+ @options[:test] || super
68
+ end
69
+
70
+ # Authorization
71
+ def authorize(money, creditcard, options = {})
72
+ prepare_options_hash(options)
73
+ @options[:credit_card] = creditcard
74
+ request = build_request(:authorization, money, @options)
75
+ commit(request)
76
+ end
77
+
78
+
79
+ # Capture Authorization
80
+ def capture(money, authorization, options = {})
81
+ prepare_options_hash(options)
82
+ @options[:authorization] = authorization
83
+ request = build_request(:capture_authorization, money, @options)
84
+ commit(request)
85
+ end
86
+
87
+
88
+ # Purchase
89
+ def purchase(money, creditcard, options = {})
90
+ prepare_options_hash(options)
91
+ @options[:credit_card] = creditcard
92
+ request = build_request(:purchase, money, @options)
93
+ commit(request)
94
+ end
95
+
96
+ private
97
+
98
+ def prepare_options_hash(options)
99
+ @options.update(options)
100
+ setup_address_hash!(options)
101
+ end
102
+
103
+ # Create all address hash key value pairs so that
104
+ # it still works if only provided with one or two of them
105
+ def setup_address_hash!(options)
106
+ options[:billing_address] = options[:billing_address] || options[:address] || {}
107
+ options[:shipping_address] = options[:shipping_address] || {}
108
+ # Include Email in address-hash from options-hash
109
+ options[:billing_address][:email] = options[:email] if options[:email]
110
+ end
111
+
112
+ # Contact WireCard, make the XML request, and parse the
113
+ # reply into a Response object
114
+ def commit(request)
115
+ headers = { 'Content-Type' => 'text/xml',
116
+ 'Authorization' => encoded_credentials }
117
+
118
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request, headers))
119
+ # Pending Status also means Acknowledged (as stated in their specification)
120
+ success = response[:FunctionResult] == "ACK" || response[:FunctionResult] == "PENDING"
121
+ message = response[:Message]
122
+ authorization = (success && @options[:action] == :authorization) ? response[:GuWID] : nil
123
+
124
+ Response.new(success, message, response,
125
+ :test => test?,
126
+ :authorization => authorization,
127
+ :avs_result => { :code => response[:avsCode] },
128
+ :cvv_result => response[:cvCode]
129
+ )
130
+ end
131
+
132
+ # Generates the complete xml-message, that gets sent to the gateway
133
+ def build_request(action, money, options = {})
134
+ xml = Builder::XmlMarkup.new :indent => 2
135
+ xml.instruct!
136
+ xml.tag! 'WIRECARD_BXML' do
137
+ xml.tag! 'W_REQUEST' do
138
+ xml.tag! 'W_JOB' do
139
+ # TODO: OPTIONAL, check what value needs to be insert here
140
+ xml.tag! 'JobID', 'test dummy data'
141
+ # UserID for this transaction
142
+ xml.tag! 'BusinessCaseSignature', options[:signature] || options[:login]
143
+ # Create the whole rest of the message
144
+ add_transaction_data(xml, action, money, options)
145
+ end
146
+ end
147
+ end
148
+ xml.target!
149
+ end
150
+
151
+ # Includes the whole transaction data (payment, creditcard, address)
152
+ def add_transaction_data(xml, action, money, options = {})
153
+ options[:action] = action
154
+ # TODO: require order_id instead of auto-generating it if not supplied
155
+ options[:order_id] ||= generate_unique_id
156
+ transaction_type = action.to_s.upcase
157
+
158
+ xml.tag! "FNC_CC_#{transaction_type}" do
159
+ # TODO: OPTIONAL, check which param should be used here
160
+ xml.tag! 'FunctionID', options[:description] || 'Test dummy FunctionID'
161
+
162
+ xml.tag! 'CC_TRANSACTION' do
163
+ xml.tag! 'TransactionID', options[:order_id]
164
+ if [:authorization, :purchase].include?(action)
165
+ add_invoice(xml, money, options)
166
+ add_creditcard(xml, options[:credit_card])
167
+ add_address(xml, options[:billing_address])
168
+ elsif action == :capture_authorization
169
+ xml.tag! 'GuWID', options[:authorization] if options[:authorization]
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+ # Includes the payment (amount, currency, country) to the transaction-xml
176
+ def add_invoice(xml, money, options)
177
+ xml.tag! 'Amount', amount(money)
178
+ xml.tag! 'Currency', options[:currency] || currency(money)
179
+ xml.tag! 'CountryCode', options[:billing_address][:country]
180
+ xml.tag! 'RECURRING_TRANSACTION' do
181
+ xml.tag! 'Type', options[:recurring] || 'Single'
182
+ end
183
+ end
184
+
185
+ # Includes the credit-card data to the transaction-xml
186
+ def add_creditcard(xml, creditcard)
187
+ raise "Creditcard must be supplied!" if creditcard.nil?
188
+ xml.tag! 'CREDIT_CARD_DATA' do
189
+ xml.tag! 'CreditCardNumber', creditcard.number
190
+ xml.tag! 'CVC2', creditcard.verification_value
191
+ xml.tag! 'ExpirationYear', creditcard.year
192
+ xml.tag! 'ExpirationMonth', format(creditcard.month, :two_digits)
193
+ xml.tag! 'CardHolderName', [creditcard.first_name, creditcard.last_name].join(' ')
194
+ end
195
+ end
196
+
197
+ # Includes the IP address of the customer to the transaction-xml
198
+ def add_customer_data(xml, options)
199
+ return unless options[:ip]
200
+ xml.tag! 'CONTACT_DATA' do
201
+ xml.tag! 'IPAddress', options[:ip]
202
+ end
203
+ end
204
+
205
+ # Includes the address to the transaction-xml
206
+ def add_address(xml, address)
207
+ return if address.nil?
208
+ xml.tag! 'CORPTRUSTCENTER_DATA' do
209
+ xml.tag! 'ADDRESS' do
210
+ xml.tag! 'Address1', address[:address1]
211
+ xml.tag! 'Address2', address[:address2] if address[:address2]
212
+ xml.tag! 'City', address[:city]
213
+ xml.tag! 'ZipCode', address[:zip]
214
+
215
+ if address[:state] =~ /[A-Za-z]{2}/ && address[:country] =~ /^(us|ca)$/i
216
+ xml.tag! 'State', address[:state].upcase
217
+ end
218
+
219
+ xml.tag! 'Country', address[:country]
220
+ xml.tag! 'Phone', address[:phone] if address[:phone] =~ VALID_PHONE_FORMAT
221
+ xml.tag! 'Email', address[:email]
222
+ end
223
+ end
224
+ end
225
+
226
+
227
+ # Read the XML message from the gateway and check if it was successful,
228
+ # and also extract required return values from the response.
229
+ def parse(xml)
230
+ basepath = '/WIRECARD_BXML/W_RESPONSE'
231
+ response = {}
232
+
233
+ xml = REXML::Document.new(xml)
234
+ if root = REXML::XPath.first(xml, "#{basepath}/W_JOB")
235
+ parse_response(response, root)
236
+ elsif root = REXML::XPath.first(xml, "//ERROR")
237
+ parse_error(response, root)
238
+ else
239
+ response[:Message] = "No valid XML response message received. \
240
+ Propably wrong credentials supplied with HTTP header."
241
+ end
242
+
243
+ response
244
+ end
245
+
246
+ # Parse the <ProcessingStatus> Element which containts all important information
247
+ def parse_response(response, root)
248
+ status = nil
249
+ # get the root element for this Transaction
250
+ root.elements.to_a.each do |node|
251
+ if node.name =~ /FNC_CC_/
252
+ status = REXML::XPath.first(node, "CC_TRANSACTION/PROCESSING_STATUS")
253
+ end
254
+ end
255
+ message = ""
256
+ if status
257
+ if info = status.elements['Info']
258
+ message << info.text
259
+ end
260
+ # Get basic response information
261
+ status.elements.to_a.each do |node|
262
+ response[node.name.to_sym] = (node.text || '').strip
263
+ end
264
+ end
265
+ parse_error(root, message)
266
+ response[:Message] = message
267
+ end
268
+
269
+ # Parse a generic error response from the gateway
270
+ def parse_error(root, message = "")
271
+ # Get errors if available and append them to the message
272
+ errors = errors_to_string(root)
273
+ unless errors.strip.blank?
274
+ message << ' - ' unless message.strip.blank?
275
+ message << errors
276
+ end
277
+ message
278
+ end
279
+
280
+ # Parses all <ERROR> elements in the response and converts the information
281
+ # to a single string
282
+ def errors_to_string(root)
283
+ # Get context error messages (can be 0..*)
284
+ errors = []
285
+ REXML::XPath.each(root, "//ERROR") do |error_elem|
286
+ error = {}
287
+ error[:Advice] = []
288
+ error[:Message] = error_elem.elements['Message'].text
289
+ error_elem.elements.each('Advice') do |advice|
290
+ error[:Advice] << advice.text
291
+ end
292
+ errors << error
293
+ end
294
+ # Convert all messages to a single string
295
+ string = ''
296
+ errors.each do |error|
297
+ string << error[:Message]
298
+ error[:Advice].each_with_index do |advice, index|
299
+ string << ' (' if index == 0
300
+ string << "#{index+1}. #{advice}"
301
+ string << ' and ' if index < error[:Advice].size - 1
302
+ string << ')' if index == error[:Advice].size - 1
303
+ end
304
+ end
305
+ string
306
+ end
307
+
308
+ # Encode login and password in Base64 to supply as HTTP header
309
+ # (for http basic authentication)
310
+ def encoded_credentials
311
+ credentials = [@options[:login], @options[:password]].join(':')
312
+ "Basic " << Base64.encode64(credentials).strip
313
+ end
314
+
315
+ end
316
+ end
317
+ end
318
+
@@ -0,0 +1,18 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ autoload :Gateway, 'active_merchant/billing/gateway'
4
+
5
+ Dir[File.dirname(__FILE__) + '/gateways/**/*.rb'].each do |f|
6
+
7
+ # Get camelized class name
8
+ filename = File.basename(f, '.rb')
9
+ # Add _gateway suffix
10
+ gateway_name = filename + '_gateway'
11
+ # Camelize the string to get the class name
12
+ gateway_class = gateway_name.camelize
13
+
14
+ # Register for autoloading
15
+ autoload gateway_class, f
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,79 @@
1
+ require_library_or_gem 'action_pack'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module ActionViewHelper
7
+ # This helper allows the usage of different payment integrations
8
+ # through a single form helper. Payment integrations are the
9
+ # type of service where the user is redirected to the secure
10
+ # site of the service, like Paypal or Chronopay.
11
+ #
12
+ # The helper creates a scope around a payment service helper
13
+ # which provides the specific mapping for that service.
14
+ #
15
+ # <% payment_service_for 1000, 'paypalemail@mystore.com',
16
+ # :amount => 50.00,
17
+ # :currency => 'CAD',
18
+ # :service => :paypal,
19
+ # :html => { :id => 'payment-form' } do |service| %>
20
+ #
21
+ # <% service.customer :first_name => 'Cody',
22
+ # :last_name => 'Fauser',
23
+ # :phone => '(555)555-5555',
24
+ # :email => 'codyfauser@gmail.com' %>
25
+ #
26
+ # <% service.billing_address :city => 'Ottawa',
27
+ # :address1 => '21 Snowy Brook Lane',
28
+ # :address2 => 'Apt. 36',
29
+ # :state => 'ON',
30
+ # :country => 'CA',
31
+ # :zip => 'K1J1E5' %>
32
+ #
33
+ # <% service.invoice '#1000' %>
34
+ # <% service.shipping '0.00' %>
35
+ # <% service.tax '0.00' %>
36
+ #
37
+ # <% service.notify_url url_for(:only_path => false, :action => 'notify') %>
38
+ # <% service.return_url url_for(:only_path => false, :action => 'done') %>
39
+ # <% service.cancel_return_url 'http://mystore.com' %>
40
+ # <% end %>
41
+ #
42
+ def payment_service_for(order, account, options = {}, &proc)
43
+ raise ArgumentError, "Missing block" unless block_given?
44
+
45
+ integration_module = ActiveMerchant::Billing::Integrations.const_get(options.delete(:service).to_s.classify)
46
+
47
+ if ignore_binding?
48
+ concat(form_tag(integration_module.service_url, options.delete(:html) || {}))
49
+ else
50
+ concat(form_tag(integration_module.service_url, options.delete(:html) || {}), proc.binding)
51
+ end
52
+ result = "\n"
53
+
54
+ service_class = integration_module.const_get('Helper')
55
+ service = service_class.new(order, account, options)
56
+ yield service
57
+
58
+ result << service.form_fields.collect do |field, value|
59
+ hidden_field_tag(field, value)
60
+ end.join("\n")
61
+
62
+ result << "\n"
63
+ result << '</form>'
64
+
65
+ if ignore_binding?
66
+ concat(result)
67
+ else
68
+ concat(result, proc.binding)
69
+ end
70
+ end
71
+
72
+ private
73
+ def ignore_binding?
74
+ ActionPack::VERSION::MAJOR >= 2 && ActionPack::VERSION::MINOR >= 2
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Bogus
5
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
6
+ mapping :account, 'account'
7
+ mapping :order, 'order'
8
+ mapping :amount, 'amount'
9
+ mapping :currency, 'currency'
10
+ mapping :customer, :first_name => 'first_name',
11
+ :last_name => 'last_name'
12
+
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Bogus
5
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
6
+
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Bogus
5
+ class Return < ActiveMerchant::Billing::Integrations::Return
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module ActiveMerchant #:nodoc:
3
+ module Billing #:nodoc:
4
+ module Integrations #:nodoc:
5
+ module Bogus
6
+ autoload :Return, 'active_merchant/billing/integrations/bogus/return.rb'
7
+ autoload :Helper, 'active_merchant/billing/integrations/bogus/helper.rb'
8
+ autoload :Notification, 'active_merchant/billing/integrations/bogus/notification.rb'
9
+
10
+ mattr_accessor :service_url
11
+ self.service_url = 'http://www.bogus.com'
12
+
13
+ def self.notification(post)
14
+ Notification.new(post)
15
+ end
16
+
17
+ def self.return(query_string)
18
+ Return.new(query_string)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,120 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Chronopay
5
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
6
+ # All currently supported checkout languages:
7
+ # es (Spanish)
8
+ # en (English)
9
+ # de (German)
10
+ # pt (Portuguese)
11
+ # lv (Latvian)
12
+ # cn1 (Chinese Version 1)
13
+ # cn2 (Chinese version 2)
14
+ # nl (Dutch)
15
+ # ru (Russian)
16
+ COUNTRIES_FOR_LANG = {
17
+ 'ES' => %w( AR BO CL CO CR CU DO EC SV GQ GT HN MX NI PA PY PE ES UY VE),
18
+ 'DE' => %w( DE AT CH LI ),
19
+ 'PT' => %w( AO BR CV GW MZ PT ST TL),
20
+ 'RU' => %w( BY KG KZ RU ),
21
+ 'LV' => 'LV',
22
+ 'CN1' => 'CN',
23
+ 'NL' => 'NL'
24
+ }
25
+
26
+ LANG_FOR_COUNTRY = COUNTRIES_FOR_LANG.inject(Hash.new("EN")) do |memo, (lang, countries)|
27
+ countries.each do |code|
28
+ memo[code] = lang
29
+ end
30
+ memo
31
+ end
32
+
33
+
34
+ self.country_format = :alpha3
35
+
36
+ def initialize(order, account, options = {})
37
+ super
38
+ add_field('cb_type', 'p')
39
+ end
40
+
41
+ # product_id
42
+ mapping :account, 'product_id'
43
+ # product_name
44
+ mapping :invoice, 'product_name'
45
+ # product_price
46
+ mapping :amount, 'product_price'
47
+ # product_price_currency
48
+ mapping :currency, 'product_price_currency'
49
+
50
+ # f_name
51
+ # s_name
52
+ # email
53
+ mapping :customer, :first_name => 'f_name',
54
+ :last_name => 's_name',
55
+ :phone => 'phone',
56
+ :email => 'email'
57
+
58
+ # city
59
+ # street
60
+ # state
61
+ # zip
62
+ # country - The country must be a 3 digit country code
63
+ # phone
64
+
65
+ mapping :billing_address, :city => 'city',
66
+ :address1 => 'street',
67
+ :state => 'state',
68
+ :zip => 'zip',
69
+ :country => 'country'
70
+
71
+ def billing_address(mapping = {})
72
+ # Gets the country code in the appropriate format or returns what we were given
73
+ # The appropriate format for Chronopay is the alpha 3 country code
74
+ country_code = lookup_country_code(mapping.delete(:country))
75
+ add_field(mappings[:billing_address][:country], country_code)
76
+
77
+ countries_with_supported_states = ['USA', 'CAN']
78
+ if !countries_with_supported_states.include?(country_code)
79
+ mapping.delete(:state)
80
+ add_field(mappings[:billing_address][:state], 'XX')
81
+ end
82
+ mapping.each do |k, v|
83
+ field = mappings[:billing_address][k]
84
+ add_field(field, v) unless field.nil?
85
+ end
86
+ add_field('language', checkout_language_from_country(country_code))
87
+ end
88
+
89
+ # card_no
90
+ # exp_month
91
+ # exp_year
92
+ mapping :credit_card, :number => 'card_no',
93
+ :expiry_month => 'exp_month',
94
+ :expiry_year => 'exp_year'
95
+
96
+ # cb_url
97
+ mapping :notify_url, 'cb_url'
98
+
99
+ # cs1
100
+ mapping :order, 'cs1'
101
+
102
+ # cs2
103
+ # cs3
104
+ # decline_url
105
+
106
+
107
+ private
108
+
109
+ def checkout_language_from_country(country_code)
110
+ country = Country.find(country_code)
111
+ short_code = country.code(:alpha2).to_s
112
+ LANG_FOR_COUNTRY[short_code]
113
+ rescue InvalidCountryCodeError
114
+ 'EN'
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end