fishman-activemerchant 1.18.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.
Files changed (188) hide show
  1. data/CHANGELOG +733 -0
  2. data/CONTRIBUTORS +257 -0
  3. data/MIT-LICENSE +20 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/active_merchant.rb +47 -0
  6. data/lib/active_merchant/billing.rb +9 -0
  7. data/lib/active_merchant/billing/avs_result.rb +98 -0
  8. data/lib/active_merchant/billing/base.rb +57 -0
  9. data/lib/active_merchant/billing/check.rb +68 -0
  10. data/lib/active_merchant/billing/credit_card.rb +260 -0
  11. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  12. data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
  13. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  14. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  15. data/lib/active_merchant/billing/gateway.rb +170 -0
  16. data/lib/active_merchant/billing/gateways.rb +18 -0
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +693 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +858 -0
  19. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +308 -0
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +139 -0
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +282 -0
  22. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  23. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  24. data/lib/active_merchant/billing/gateways/bogus.rb +142 -0
  25. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  26. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  27. data/lib/active_merchant/billing/gateways/braintree_blue.rb +303 -0
  28. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
  29. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  30. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  31. data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
  32. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  33. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  34. data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
  35. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  36. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  37. data/lib/active_merchant/billing/gateways/eway_managed.rb +264 -0
  38. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  39. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  40. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  41. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  42. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  43. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  44. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  45. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  46. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  47. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  48. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  49. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  50. data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
  51. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +156 -0
  52. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  53. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  54. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  55. data/lib/active_merchant/billing/gateways/moneris.rb +209 -0
  56. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  57. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  58. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  59. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  60. data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
  61. data/lib/active_merchant/billing/gateways/optimal_payment.rb +274 -0
  62. data/lib/active_merchant/billing/gateways/orbital.rb +321 -0
  63. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  64. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  65. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  66. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  67. data/lib/active_merchant/billing/gateways/payflow.rb +253 -0
  68. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  69. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  70. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  71. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  72. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  73. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  74. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  75. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  76. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +354 -0
  77. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  78. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  79. data/lib/active_merchant/billing/gateways/paypal_express.rb +184 -0
  80. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  81. data/lib/active_merchant/billing/gateways/paypal_express_de.rb +14 -0
  82. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  83. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  84. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  85. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  86. data/lib/active_merchant/billing/gateways/qbms.rb +297 -0
  87. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  88. data/lib/active_merchant/billing/gateways/quickpay.rb +297 -0
  89. data/lib/active_merchant/billing/gateways/realex.rb +311 -0
  90. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  91. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  92. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  93. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  94. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  95. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  96. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  97. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  98. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -0
  99. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  100. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  101. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  102. data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
  103. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  104. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  105. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  106. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  107. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  108. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  109. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  110. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  111. data/lib/active_merchant/billing/integrations.rb +17 -0
  112. data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
  113. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  114. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  115. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  116. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  117. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  118. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  119. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  120. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  121. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  122. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  123. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  124. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  125. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  126. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  127. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  128. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  129. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  130. data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
  131. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +28 -0
  132. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +50 -0
  133. data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
  134. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  135. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  136. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  137. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  138. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  139. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  140. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  141. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  142. data/lib/active_merchant/billing/integrations/helper.rb +96 -0
  143. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  144. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  145. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  146. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  147. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  148. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  149. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  150. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  151. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  152. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  153. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  154. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  155. data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
  156. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +58 -0
  157. data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
  158. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  159. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  160. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  161. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  162. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  163. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  164. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  165. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  166. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  167. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  168. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
  169. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  170. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  171. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  172. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  173. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  174. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  175. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  176. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  177. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  178. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  179. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  180. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  181. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  182. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  183. data/lib/active_merchant/billing/response.rb +32 -0
  184. data/lib/active_merchant/version.rb +3 -0
  185. data/lib/activemerchant.rb +1 -0
  186. data/lib/support/gateway_support.rb +58 -0
  187. data/lib/support/outbound_hosts.rb +25 -0
  188. metadata +335 -0
@@ -0,0 +1,207 @@
1
+ require 'iconv'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class PayboxDirectGateway < Gateway
6
+ TEST_URL = 'https://preprod-ppps.paybox.com/PPPS.php'
7
+ LIVE_URL = 'https://ppps.paybox.com/PPPS.php'
8
+ LIVE_URL_BACKUP = 'https://ppps1.paybox.com/PPPS.php'
9
+
10
+ # Payment API Version
11
+ API_VERSION = '00103'
12
+
13
+ # Transactions hash
14
+ TRANSACTIONS = {
15
+ :authorization => '00001',
16
+ :capture => '00002',
17
+ :purchase => '00003',
18
+ :unreferenced_credit => '00004',
19
+ :void => '00005',
20
+ :refund => '00014'
21
+ }
22
+
23
+ CURRENCY_CODES = {
24
+ "AUD"=> '036',
25
+ "CAD"=> '124',
26
+ "CZK"=> '203',
27
+ "DKK"=> '208',
28
+ "HKD"=> '344',
29
+ "ICK"=> '352',
30
+ "JPY"=> '392',
31
+ "NOK"=> '578',
32
+ "SGD"=> '702',
33
+ "SEK"=> '752',
34
+ "CHF"=> '756',
35
+ "GBP"=> '826',
36
+ "USD"=> '840',
37
+ "EUR"=> '978'
38
+ }
39
+
40
+ SUCCESS_CODES = ['00000']
41
+ UNAVAILABILITY_CODES = ['00001', '00097', '00098']
42
+ FRAUD_CODES = ['00102','00104','00105','00134','00138','00141','00143','00156','00157','00159']
43
+ SUCCESS_MESSAGE = 'The transaction was approved'
44
+ FAILURE_MESSAGE = 'The transaction failed'
45
+
46
+ # Money is referenced in cents
47
+ self.money_format = :cents
48
+ self.default_currency = 'EUR'
49
+
50
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
51
+ self.supported_countries = ['FR']
52
+
53
+ # The card types supported by the payment gateway
54
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
55
+
56
+ # The homepage URL of the gateway
57
+ self.homepage_url = 'http://www.paybox.com/'
58
+
59
+ # The name of the gateway
60
+ self.display_name = 'Paybox Direct'
61
+
62
+ def initialize(options = {})
63
+ requires!(options, :login, :password)
64
+ @options = options
65
+ super
66
+ end
67
+
68
+ def authorize(money, creditcard, options = {})
69
+ post = {}
70
+ add_invoice(post, options)
71
+ add_creditcard(post, creditcard)
72
+ commit('authorization', money, post)
73
+ end
74
+
75
+ def purchase(money, creditcard, options = {})
76
+ post = {}
77
+ add_invoice(post, options)
78
+ add_creditcard(post, creditcard)
79
+ commit('purchase', money, post)
80
+ end
81
+
82
+ def capture(money, authorization, options = {})
83
+ requires!(options, :order_id)
84
+ post = {}
85
+ add_invoice(post, options)
86
+ post[:numappel] = authorization[0,10]
87
+ post[:numtrans] = authorization[10,10]
88
+ commit('capture', money, post)
89
+ end
90
+
91
+ def void(identification, options = {})
92
+ requires!(options, :order_id, :amount)
93
+ post ={}
94
+ add_invoice(post, options)
95
+ add_reference(post, identification)
96
+ post[:porteur] = '000000000000000'
97
+ post[:dateval] = '0000'
98
+ commit('void', options[:amount], post)
99
+ end
100
+
101
+ def credit(money, identification, options = {})
102
+ deprecated CREDIT_DEPRECATION_MESSAGE
103
+ refund(money, identification, options)
104
+ end
105
+
106
+ def refund(money, identification, options = {})
107
+ post = {}
108
+ add_invoice(post, options)
109
+ add_reference(post, identification)
110
+ commit('refund', money, post)
111
+ end
112
+
113
+ def test?
114
+ @options[:test] || Base.gateway_mode == :test
115
+ end
116
+
117
+ private
118
+
119
+ def add_invoice(post, options)
120
+ post[:reference] = options[:order_id]
121
+ end
122
+
123
+ def add_creditcard(post, creditcard)
124
+ post[:porteur] = creditcard.number
125
+ post[:dateval] = expdate(creditcard)
126
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
127
+ end
128
+
129
+ def add_reference(post, identification)
130
+ post[:numappel] = identification[0,10]
131
+ post[:numtrans] = identification[10,10]
132
+ end
133
+
134
+ def parse(body)
135
+ body = Iconv.iconv("UTF-8","LATIN1", body.to_s).join
136
+ results = {}
137
+ body.split(/&/).each do |pair|
138
+ key,val = pair.split(/\=/)
139
+ results[key.downcase.to_sym] = CGI.unescape(val) if val
140
+ end
141
+ results
142
+ end
143
+
144
+ def commit(action, money = nil, parameters = nil)
145
+ parameters[:montant] = ('0000000000' + (money ? amount(money) : ''))[-10..-1]
146
+ parameters[:devise] = CURRENCY_CODES[options[:currency] || currency(money)]
147
+ request_data = post_data(action,parameters)
148
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request_data))
149
+ response = parse(ssl_post(LIVE_URL_BACKUP, request_data)) if service_unavailable?(response) && !test?
150
+ Response.new(success?(response), message_from(response), response.merge(
151
+ :timestamp => parameters[:dateq]),
152
+ :test => test?,
153
+ :authorization => response[:numappel].to_s + response[:numtrans].to_s,
154
+ :fraud_review => fraud_review?(response),
155
+ :sent_params => parameters.delete_if{|key,value| ['porteur','dateval','cvv'].include?(key.to_s)}
156
+ )
157
+ end
158
+
159
+ def success?(response)
160
+ SUCCESS_CODES.include?(response[:codereponse])
161
+ end
162
+
163
+ def fraud_review?(response)
164
+ FRAUD_CODES.include?(response[:codereponse])
165
+ end
166
+
167
+ def service_unavailable?(response)
168
+ UNAVAILABILITY_CODES.include?(response[:codereponse])
169
+ end
170
+
171
+ def message_from(response)
172
+ success?(response) ? SUCCESS_MESSAGE : (response[:commentaire] || FAILURE_MESSAGE)
173
+ end
174
+
175
+ def post_data(action, parameters = {})
176
+
177
+ parameters.update(
178
+ :version => API_VERSION,
179
+ :type => TRANSACTIONS[action.to_sym],
180
+ :dateq => Time.now.strftime('%d%m%Y%H%M%S'),
181
+ :numquestion => unique_id(parameters[:order_id]),
182
+ :site => @options[:login].to_s[0,7],
183
+ :rang => @options[:login].to_s[7..-1],
184
+ :cle => @options[:password],
185
+ :pays => '',
186
+ :archivage => parameters[:order_id]
187
+ )
188
+
189
+ parameters.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&")
190
+ end
191
+
192
+ def unique_id(seed = 0)
193
+ randkey = "#{seed}#{Time.now.usec}".to_i % 2147483647 # Max paybox value for the question number
194
+
195
+ "0000000000#{randkey}"[-10..-1]
196
+ end
197
+
198
+ def expdate(credit_card)
199
+ year = sprintf("%.4i", credit_card.year)
200
+ month = sprintf("%.2i", credit_card.month)
201
+
202
+ "#{month}#{year[-2..-1]}"
203
+ end
204
+
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,253 @@
1
+ require File.dirname(__FILE__) + '/payflow/payflow_common_api'
2
+ require File.dirname(__FILE__) + '/payflow/payflow_response'
3
+ require File.dirname(__FILE__) + '/payflow_express'
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ class PayflowGateway < Gateway
8
+ include PayflowCommonAPI
9
+
10
+ RECURRING_ACTIONS = Set.new([:add, :modify, :cancel, :inquiry, :reactivate, :payment])
11
+
12
+ self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover, :diners_club]
13
+ self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside'
14
+ self.display_name = 'PayPal Payflow Pro'
15
+
16
+ def authorize(money, credit_card_or_reference, options = {})
17
+ request = build_sale_or_authorization_request(:authorization, money, credit_card_or_reference, options)
18
+
19
+ commit(request, options)
20
+ end
21
+
22
+ def purchase(money, credit_card_or_reference, options = {})
23
+ request = build_sale_or_authorization_request(:purchase, money, credit_card_or_reference, options)
24
+
25
+ commit(request, options)
26
+ end
27
+
28
+ def credit(money, identification_or_credit_card, options = {})
29
+ if identification_or_credit_card.is_a?(String)
30
+ deprecated CREDIT_DEPRECATION_MESSAGE
31
+ # Perform referenced credit
32
+ refund(money, identification_or_credit_card, options)
33
+ else
34
+ # Perform non-referenced credit
35
+ request = build_credit_card_request(:credit, money, identification_or_credit_card, options)
36
+ commit(request, options)
37
+ end
38
+ end
39
+
40
+ def refund(money, reference, options = {})
41
+ commit(build_reference_request(:credit, money, reference, options), options)
42
+ end
43
+ # Adds or modifies a recurring Payflow profile. See the Payflow Pro Recurring Billing Guide for more details:
44
+ # https://www.paypal.com/en_US/pdf/PayflowPro_RecurringBilling_Guide.pdf
45
+ #
46
+ # Several options are available to customize the recurring profile:
47
+ #
48
+ # * <tt>profile_id</tt> - is only required for editing a recurring profile
49
+ # * <tt>starting_at</tt> - takes a Date, Time, or string in mmddyyyy format. The date must be in the future.
50
+ # * <tt>name</tt> - The name of the customer to be billed. If not specified, the name from the credit card is used.
51
+ # * <tt>periodicity</tt> - The frequency that the recurring payments will occur at. Can be one of
52
+ # :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly
53
+ # * <tt>payments</tt> - The term, or number of payments that will be made
54
+ # * <tt>comment</tt> - A comment associated with the profile
55
+ def recurring(money, credit_card, options = {})
56
+ options[:name] = credit_card.name if options[:name].blank? && credit_card
57
+ request = build_recurring_request(options[:profile_id] ? :modify : :add, money, options) do |xml|
58
+ add_credit_card(xml, credit_card) if credit_card
59
+ end
60
+ commit(request, options.merge(:request_type => :recurring))
61
+ end
62
+
63
+ def cancel_recurring(profile_id)
64
+ request = build_recurring_request(:cancel, 0, :profile_id => profile_id)
65
+ commit(request, options.merge(:request_type => :recurring))
66
+ end
67
+
68
+ def recurring_inquiry(profile_id, options = {})
69
+ request = build_recurring_request(:inquiry, nil, options.update( :profile_id => profile_id ))
70
+ commit(request, options.merge(:request_type => :recurring))
71
+ end
72
+
73
+ def express
74
+ @express ||= PayflowExpressGateway.new(@options)
75
+ end
76
+
77
+ private
78
+ def build_sale_or_authorization_request(action, money, credit_card_or_reference, options)
79
+ if credit_card_or_reference.is_a?(String)
80
+ build_reference_sale_or_authorization_request(action, money, credit_card_or_reference, options)
81
+ else
82
+ build_credit_card_request(action, money, credit_card_or_reference, options)
83
+ end
84
+ end
85
+
86
+ def build_reference_sale_or_authorization_request(action, money, reference, options)
87
+ xml = Builder::XmlMarkup.new
88
+ xml.tag! TRANSACTIONS[action] do
89
+ xml.tag! 'PayData' do
90
+ xml.tag! 'Invoice' do
91
+ # Fields accepted by PayFlow and recommended to be provided even for Reference Transaction, per Payflow docs.
92
+ xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
93
+ xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
94
+ xml.tag! 'Description', options[:description] unless options[:description].blank?
95
+ xml.tag! 'Comment', options[:comment] unless options[:comment].blank?
96
+ xml.tag!('ExtData', 'Name'=> 'COMMENT2', 'Value'=> options[:comment2]) unless options[:comment2].blank?
97
+
98
+ billing_address = options[:billing_address] || options[:address]
99
+ add_address(xml, 'BillTo', billing_address, options) if billing_address
100
+ add_address(xml, 'ShipTo', options[:shipping_address],options) if options[:shipping_address]
101
+
102
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
103
+ end
104
+ xml.tag! 'Tender' do
105
+ xml.tag! 'Card' do
106
+ xml.tag! 'ExtData', 'Name' => 'ORIGID', 'Value' => reference
107
+ end
108
+ end
109
+ end
110
+ end
111
+ xml.target!
112
+ end
113
+
114
+ def build_credit_card_request(action, money, credit_card, options)
115
+ xml = Builder::XmlMarkup.new
116
+ xml.tag! TRANSACTIONS[action] do
117
+ xml.tag! 'PayData' do
118
+ xml.tag! 'Invoice' do
119
+ xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
120
+ xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
121
+ xml.tag! 'Description', options[:description] unless options[:description].blank?
122
+ # Comment and Comment2 will show up in manager.paypal.com as Comment1 and Comment2
123
+ xml.tag! 'Comment', options[:comment] unless options[:comment].blank?
124
+ xml.tag!('ExtData', 'Name'=> 'COMMENT2', 'Value'=> options[:comment2]) unless options[:comment2].blank?
125
+
126
+ billing_address = options[:billing_address] || options[:address]
127
+ add_address(xml, 'BillTo', billing_address, options) if billing_address
128
+ add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
129
+
130
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
131
+ end
132
+
133
+ xml.tag! 'Tender' do
134
+ add_credit_card(xml, credit_card)
135
+ end
136
+ end
137
+ end
138
+ xml.target!
139
+ end
140
+
141
+ def add_credit_card(xml, credit_card)
142
+ xml.tag! 'Card' do
143
+ xml.tag! 'CardType', credit_card_type(credit_card)
144
+ xml.tag! 'CardNum', credit_card.number
145
+ xml.tag! 'ExpDate', expdate(credit_card)
146
+ xml.tag! 'NameOnCard', credit_card.first_name
147
+ xml.tag! 'CVNum', credit_card.verification_value if credit_card.verification_value?
148
+
149
+ if requires_start_date_or_issue_number?(credit_card)
150
+ xml.tag!('ExtData', 'Name' => 'CardStart', 'Value' => startdate(credit_card)) unless credit_card.start_month.blank? || credit_card.start_year.blank?
151
+ xml.tag!('ExtData', 'Name' => 'CardIssue', 'Value' => format(credit_card.issue_number, :two_digits)) unless credit_card.issue_number.blank?
152
+ end
153
+ xml.tag! 'ExtData', 'Name' => 'LASTNAME', 'Value' => credit_card.last_name
154
+ end
155
+ end
156
+
157
+ def credit_card_type(credit_card)
158
+ return '' if card_brand(credit_card).blank?
159
+
160
+ CARD_MAPPING[card_brand(credit_card).to_sym]
161
+ end
162
+
163
+ def expdate(creditcard)
164
+ year = sprintf("%.4i", creditcard.year)
165
+ month = sprintf("%.2i", creditcard.month)
166
+
167
+ "#{year}#{month}"
168
+ end
169
+
170
+ def startdate(creditcard)
171
+ year = format(creditcard.start_year, :two_digits)
172
+ month = format(creditcard.start_month, :two_digits)
173
+
174
+ "#{month}#{year}"
175
+ end
176
+
177
+ def build_recurring_request(action, money, options)
178
+ unless RECURRING_ACTIONS.include?(action)
179
+ raise StandardError, "Invalid Recurring Profile Action: #{action}"
180
+ end
181
+
182
+ xml = Builder::XmlMarkup.new
183
+ xml.tag! 'RecurringProfiles' do
184
+ xml.tag! 'RecurringProfile' do
185
+ xml.tag! action.to_s.capitalize do
186
+ unless [:cancel, :inquiry].include?(action)
187
+ xml.tag! 'RPData' do
188
+ xml.tag! 'Name', options[:name] unless options[:name].nil?
189
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
190
+ xml.tag! 'PayPeriod', get_pay_period(options)
191
+ xml.tag! 'Term', options[:payments] unless options[:payments].nil?
192
+ xml.tag! 'Comment', options[:comment] unless options[:comment].nil?
193
+
194
+
195
+ if initial_tx = options[:initial_transaction]
196
+ requires!(initial_tx, [:type, :authorization, :purchase])
197
+ requires!(initial_tx, :amount) if initial_tx[:type] == :purchase
198
+
199
+ xml.tag! 'OptionalTrans', TRANSACTIONS[initial_tx[:type]]
200
+ xml.tag! 'OptionalTransAmt', amount(initial_tx[:amount]) unless initial_tx[:amount].blank?
201
+ end
202
+
203
+ xml.tag! 'Start', format_rp_date(options[:starting_at] || Date.today + 1 )
204
+ xml.tag! 'EMail', options[:email] unless options[:email].nil?
205
+
206
+ billing_address = options[:billing_address] || options[:address]
207
+ add_address(xml, 'BillTo', billing_address, options) if billing_address
208
+ add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
209
+ end
210
+ xml.tag! 'Tender' do
211
+ yield xml
212
+ end
213
+ end
214
+ if action != :add
215
+ xml.tag! "ProfileID", options[:profile_id]
216
+ end
217
+ if action == :inquiry
218
+ xml.tag! "PaymentHistory", ( options[:history] ? 'Y' : 'N' )
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ def get_pay_period(options)
226
+ requires!(options, [:periodicity, :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly])
227
+ case options[:periodicity]
228
+ when :weekly then 'Weekly'
229
+ when :biweekly then 'Bi-weekly'
230
+ when :semimonthly then 'Semi-monthly'
231
+ when :quadweekly then 'Every four weeks'
232
+ when :monthly then 'Monthly'
233
+ when :quarterly then 'Quarterly'
234
+ when :semiyearly then 'Semi-yearly'
235
+ when :yearly then 'Yearly'
236
+ end
237
+ end
238
+
239
+ def format_rp_date(time)
240
+ case time
241
+ when Time, Date then time.strftime("%m%d%Y")
242
+ else
243
+ time.to_s
244
+ end
245
+ end
246
+
247
+ def build_response(success, message, response, options = {})
248
+ PayflowResponse.new(success, message, response, options)
249
+ end
250
+ end
251
+ end
252
+ end
253
+