projectdx_activemerchant 1.7.1.20100817.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (140) hide show
  1. data/CHANGELOG +530 -0
  2. data/CONTRIBUTORS +142 -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 +102 -0
  21. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  22. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  23. data/lib/active_merchant/billing/gateways/braintree_blue.rb +210 -0
  24. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
  25. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  26. data/lib/active_merchant/billing/gateways/convenience_pay.rb +191 -0
  27. data/lib/active_merchant/billing/gateways/cyber_source.rb +406 -0
  28. data/lib/active_merchant/billing/gateways/data_cash.rb +593 -0
  29. data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
  30. data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
  31. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  32. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  33. data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
  34. data/lib/active_merchant/billing/gateways/garanti.rb +222 -0
  35. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  36. data/lib/active_merchant/billing/gateways/jetpay.rb +270 -0
  37. data/lib/active_merchant/billing/gateways/linkpoint.rb +449 -0
  38. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
  39. data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
  40. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  41. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  42. data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
  43. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  44. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  45. data/lib/active_merchant/billing/gateways/ogone.rb +279 -0
  46. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  47. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  48. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  49. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  50. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  51. data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
  52. data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
  53. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  54. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  55. data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
  56. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +326 -0
  57. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
  58. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  59. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  60. data/lib/active_merchant/billing/gateways/paypal_express.rb +135 -0
  61. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
  62. data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
  63. data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
  64. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  65. data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
  66. data/lib/active_merchant/billing/gateways/realex.rb +200 -0
  67. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  68. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  69. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  70. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  71. data/lib/active_merchant/billing/gateways/sage_pay.rb +309 -0
  72. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  73. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  74. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
  75. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  76. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  77. data/lib/active_merchant/billing/gateways/smart_ps.rb +265 -0
  78. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  79. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  80. data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
  81. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  82. data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
  83. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  84. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  85. data/lib/active_merchant/billing/gateways.rb +18 -0
  86. data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
  87. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  88. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  89. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  90. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  91. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  92. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  93. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  94. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  95. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  96. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  97. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  98. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  99. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  100. data/lib/active_merchant/billing/integrations/helper.rb +93 -0
  101. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  102. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  103. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  104. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  105. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  106. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  107. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  108. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  109. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  110. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  111. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  112. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  113. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  114. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  115. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  116. data/lib/active_merchant/billing/integrations/quickpay.rb +17 -0
  117. data/lib/active_merchant/billing/integrations/return.rb +35 -0
  118. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  119. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  120. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  121. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  122. data/lib/active_merchant/billing/integrations.rb +29 -0
  123. data/lib/active_merchant/billing/response.rb +32 -0
  124. data/lib/active_merchant/billing.rb +9 -0
  125. data/lib/active_merchant/common/connection.rb +172 -0
  126. data/lib/active_merchant/common/country.rb +319 -0
  127. data/lib/active_merchant/common/error.rb +26 -0
  128. data/lib/active_merchant/common/post_data.rb +24 -0
  129. data/lib/active_merchant/common/posts_data.rb +47 -0
  130. data/lib/active_merchant/common/requires_parameters.rb +16 -0
  131. data/lib/active_merchant/common/utils.rb +18 -0
  132. data/lib/active_merchant/common/validateable.rb +76 -0
  133. data/lib/active_merchant/common.rb +14 -0
  134. data/lib/active_merchant/version.rb +3 -0
  135. data/lib/active_merchant.rb +47 -0
  136. data/lib/activemerchant.rb +1 -0
  137. data/lib/certs/cacert.pem +7815 -0
  138. data/lib/support/gateway_support.rb +58 -0
  139. data/lib/support/outbound_hosts.rb +25 -0
  140. metadata +254 -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 >= 3 || (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' => %w( LV ),
22
+ 'CN1' => %w( CN ),
23
+ 'NL' => %w( 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