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,111 @@
1
+ require 'uri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module SagePayForm
7
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
8
+ include Encryption
9
+
10
+ mapping :credential2, 'EncryptKey'
11
+
12
+ mapping :account, 'Vendor'
13
+ mapping :amount, 'Amount'
14
+ mapping :currency, 'Currency'
15
+
16
+ mapping :order, 'VendorTxCode'
17
+
18
+ mapping :customer,
19
+ :first_name => 'BillingFirstnames',
20
+ :last_name => 'BillingSurname',
21
+ :email => 'CustomerEMail',
22
+ :phone => 'BillingPhone',
23
+ :send_email_confirmation => 'SendEmail'
24
+
25
+ mapping :billing_address,
26
+ :city => 'BillingCity',
27
+ :address1 => 'BillingAddress1',
28
+ :address2 => 'BillingAddress2',
29
+ :state => 'BillingState',
30
+ :zip => 'BillingPostCode',
31
+ :country => 'BillingCountry'
32
+
33
+ mapping :shipping_address,
34
+ :city => 'DeliveryCity',
35
+ :address1 => 'DeliveryAddress1',
36
+ :address2 => 'DeliveryAddress2',
37
+ :state => 'DeliveryState',
38
+ :zip => 'DeliveryPostCode',
39
+ :country => 'DeliveryCountry'
40
+
41
+ mapping :return_url, 'SuccessURL'
42
+ mapping :description, 'Description'
43
+
44
+ def form_fields
45
+ fields['DeliveryFirstnames'] ||= fields['BillingFirstnames']
46
+ fields['DeliverySurname'] ||= fields['BillingSurname']
47
+
48
+ fields['FailureURL'] ||= fields['SuccessURL']
49
+
50
+ crypt_skip = ['Vendor', 'EncryptKey', 'SendEmail']
51
+ crypt_skip << 'BillingState' unless fields['BillingCountry'] == 'US'
52
+ crypt_skip << 'DeliveryState' unless fields['DeliveryCountry'] == 'US'
53
+ crypt_skip << 'CustomerEMail' unless fields['SendEmail']
54
+
55
+ key = fields['EncryptKey']
56
+ @crypt ||= create_crypt_field(fields.except(*crypt_skip), key)
57
+
58
+ {
59
+ 'VPSProtocol' => '2.23',
60
+ 'TxType' => 'PAYMENT',
61
+ 'Vendor' => @fields['Vendor'],
62
+ 'Crypt' => @crypt
63
+ }
64
+ end
65
+
66
+ private
67
+
68
+ def create_crypt_field(fields, key)
69
+ parts = fields.map { |k, v| "#{k}=#{sanitize(k, v)}" unless v.nil? }.compact.shuffle
70
+ parts.unshift(sage_encrypt_salt(key.length, key.length * 2))
71
+ sage_encrypt(parts.join('&'), key)
72
+ end
73
+
74
+ def sanitize(key, value)
75
+ reject = exact = nil
76
+
77
+ case key
78
+ when /URL$/
79
+ # allow all
80
+ when 'VendorTxCode'
81
+ reject = /[^A-Za-z0-9{}._-]+/
82
+ when /[Nn]ames?$/
83
+ reject = %r{[^[:alpha:] /\\.'-]+}
84
+ when /(?:Address[12]|City)$/
85
+ reject = %r{[^[:alnum:] +'/\\:,.\n()-]+}
86
+ when /PostCode$/
87
+ reject = /[^A-Za-z0-9 -]+/
88
+ when /Phone$/
89
+ reject = /[^0-9A-Za-z+ ()-]+/
90
+ when 'Currency'
91
+ exact = /^[A-Z]{3}$/
92
+ when /State$/
93
+ exact = /^[A-Z]{2}$/
94
+ else
95
+ reject = /&+/
96
+ end
97
+
98
+ if exact
99
+ raise ArgumentError, "Invalid value for #{key}: #{value.inspect}" unless value =~ exact
100
+ value
101
+ elsif reject
102
+ value.gsub(reject, ' ')
103
+ else
104
+ value
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,210 @@
1
+ require 'net/http'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module SagePayForm
7
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
8
+ class CryptError < StandardError; end
9
+
10
+ include Encryption
11
+
12
+ def initialize(post_data, options)
13
+ super
14
+ load_crypt_params(params['crypt'], options[:credential2])
15
+ end
16
+
17
+ # Was the transaction complete?
18
+ def complete?
19
+ status_code == 'OK'
20
+ end
21
+
22
+ # Was the transaction cancelled?
23
+ # Unfortunately, we can't distinguish "user abort" from "idle too long".
24
+ def cancelled?
25
+ status_code == 'ABORT'
26
+ end
27
+
28
+ # Text version of #complete?, since we don't support Pending.
29
+ def status
30
+ complete? ? 'Completed' : 'Failed'
31
+ end
32
+
33
+ # Status of transaction. List of possible values:
34
+ # <tt>OK</tt>:: Transaction completed successfully.
35
+ # <tt>NOTAUTHED</tt>:: Incorrect card details / insufficient funds.
36
+ # <tt>MALFORMED</tt>:: Invalid input data.
37
+ # <tt>INVALID</tt>:: Valid input data, but some fields are incorrect.
38
+ # <tt>ABORT</tt>:: User hit cancel button or went idle for 15+ minutes.
39
+ # <tt>REJECTED</tt>:: Rejected by account fraud screening rules.
40
+ # <tt>AUTHENTICATED</tt>:: Authenticated card details secured at SagePay.
41
+ # <tt>REGISTERED</tt>:: Non-authenticated card details secured at SagePay.
42
+ # <tt>ERROR</tt>:: Problem internal to SagePay.
43
+ def status_code
44
+ params['Status']
45
+ end
46
+
47
+ # Check this if #completed? is false.
48
+ def message
49
+ params['StatusDetail']
50
+ end
51
+
52
+ # Vendor-supplied code (:order mapping).
53
+ def item_id
54
+ params['VendorTxCode']
55
+ end
56
+
57
+ # Internal SagePay code, typically "{LONG-UUID}".
58
+ def transaction_id
59
+ params['VPSTxId']
60
+ end
61
+
62
+ # Authorization number (only if #completed?).
63
+ def auth_id
64
+ params['TxAuthNo']
65
+ end
66
+
67
+ # Total amount (no fees).
68
+ def gross
69
+ params['Amount']
70
+ end
71
+
72
+ # AVS and CV2 check results. Possible values:
73
+ # <tt>ALL MATCH</tt>::
74
+ # <tt>SECURITY CODE MATCH ONLY</tt>::
75
+ # <tt>ADDRESS MATCH ONLY</tt>::
76
+ # <tt>NO DATA MATCHES</tt>::
77
+ # <tt>DATA NOT CHECKED</tt>::
78
+ def avs_cv2_result
79
+ params['AVSCV2']
80
+ end
81
+
82
+ # Numeric address check. Possible values:
83
+ # <tt>NOTPROVIDED</tt>::
84
+ # <tt>NOTCHECKED</tt>::
85
+ # <tt>MATCHED</tt>::
86
+ # <tt>NOTMATCHED</tt>::
87
+ def address_result
88
+ params['AddressResult']
89
+ end
90
+
91
+ # Post code check. Possible values:
92
+ # <tt>NOTPROVIDED</tt>::
93
+ # <tt>NOTCHECKED</tt>::
94
+ # <tt>MATCHED</tt>::
95
+ # <tt>NOTMATCHED</tt>::
96
+ def post_code_result
97
+ params['PostCodeResult']
98
+ end
99
+
100
+ # CV2 code check. Possible values:
101
+ # <tt>NOTPROVIDED</tt>::
102
+ # <tt>NOTCHECKED</tt>::
103
+ # <tt>MATCHED</tt>::
104
+ # <tt>NOTMATCHED</tt>::
105
+ def cv2_result
106
+ params['CV2Result']
107
+ end
108
+
109
+ # Was the Gift Aid box checked?
110
+ def gift_aid?
111
+ params['GiftAid'] == '1'
112
+ end
113
+
114
+ # Result of 3D Secure checks. Possible values:
115
+ # <tt>OK</tt>:: Authenticated correctly.
116
+ # <tt>NOTCHECKED</tt>:: Authentication not performed.
117
+ # <tt>NOTAVAILABLE</tt>:: Card not auth-capable, or auth is otherwise impossible.
118
+ # <tt>NOTAUTHED</tt>:: User failed authentication.
119
+ # <tt>INCOMPLETE</tt>:: Authentication unable to complete.
120
+ # <tt>ERROR</tt>:: Unable to attempt authentication due to data / service errors.
121
+ def buyer_auth_result
122
+ params['3DSecureStatus']
123
+ end
124
+
125
+ # Encoded 3D Secure result code.
126
+ def buyer_auth_result_code
127
+ params['CAVV']
128
+ end
129
+
130
+ # Address confirmation status. PayPal only. Possible values:
131
+ # <tt>NONE</tt>::
132
+ # <tt>CONFIRMED</tt>::
133
+ # <tt>UNCONFIRMED</tt>::
134
+ def address_status
135
+ params['AddressStatus']
136
+ end
137
+
138
+ # Payer verification. Undocumented.
139
+ def payer_verified?
140
+ params['PayerStatus'] == 'VERIFIED'
141
+ end
142
+
143
+ # Credit card type. Possible values:
144
+ # <tt>VISA</tt>:: Visa
145
+ # <tt>MC</tt>:: MasterCard
146
+ # <tt>DELTA</tt>:: Delta
147
+ # <tt>SOLO</tt>:: Solo
148
+ # <tt>MAESTRO</tt>:: Maestro (UK and International)
149
+ # <tt>UKE</tt>:: Visa Electron
150
+ # <tt>AMEX</tt>:: American Express
151
+ # <tt>DC</tt>:: Diners Club
152
+ # <tt>JCB</tt>:: JCB
153
+ # <tt>LASER</tt>:: Laser
154
+ # <tt>PAYPAL</tt>:: PayPal
155
+ def credit_card_type
156
+ params['CardType']
157
+ end
158
+
159
+ # Last four digits of credit card.
160
+ def credit_card_last_4_digits
161
+ params['Last4Digits']
162
+ end
163
+
164
+ # Used by composition methods, but not supplied by SagePay.
165
+ def currency
166
+ nil
167
+ end
168
+
169
+ def test?
170
+ false
171
+ end
172
+
173
+ def acknowledge
174
+ true
175
+ end
176
+
177
+ private
178
+
179
+ def load_crypt_params(crypt, key)
180
+ raise MissingCryptData if crypt.blank?
181
+ raise MissingCryptKey if key.blank?
182
+
183
+ crypt_data = sage_decrypt(crypt.gsub(' ', '+'), key)
184
+ raise InvalidCryptData unless crypt_data =~ /(^|&)Status=/
185
+
186
+ params.clear
187
+ parse(crypt_data)
188
+ end
189
+
190
+ class MissingCryptKey < CryptError
191
+ def message
192
+ 'No merchant decryption key supplied'
193
+ end
194
+ end
195
+ class MissingCryptData < CryptError
196
+ def message
197
+ 'No data received from SagePay'
198
+ end
199
+ end
200
+ class InvalidCryptData < CryptError
201
+ def message
202
+ 'Invalid data received from SagePay'
203
+ end
204
+ end
205
+
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,31 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module SagePayForm
5
+ class Return < ActiveMerchant::Billing::Integrations::Return
6
+
7
+ def initialize(query_string, options)
8
+ begin
9
+ @notification = Notification.new(query_string, options)
10
+ rescue Notification::CryptError => e
11
+ @message = e.message
12
+ end
13
+ end
14
+
15
+ def success?
16
+ @notification && @notification.complete?
17
+ end
18
+
19
+ def cancelled?
20
+ @notification && @notification.cancelled?
21
+ end
22
+
23
+ def message
24
+ @message || @notification.message
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module ActiveMerchant #:nodoc:
3
+ module Billing #:nodoc:
4
+ module Integrations #:nodoc:
5
+ module TwoCheckout
6
+ autoload 'Helper', File.dirname(__FILE__) + '/two_checkout/helper'
7
+ autoload 'Return', File.dirname(__FILE__) + '/two_checkout/return'
8
+ autoload 'Notification', File.dirname(__FILE__) + '/two_checkout/notification'
9
+
10
+ mattr_accessor :service_url
11
+ self.service_url = 'https://www.2checkout.com/2co/buyer/purchase'
12
+
13
+ def self.notification(post, options = {})
14
+ Notification.new(post)
15
+ end
16
+
17
+ def self.return(query_string, options = {})
18
+ Return.new(query_string)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module TwoCheckout
5
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
6
+ def initialize(order, account, options = {})
7
+ super
8
+ add_field('fixed', 'Y')
9
+
10
+ if ActiveMerchant::Billing::Base.integration_mode == :test || options[:test]
11
+ add_field('demo', 'Y')
12
+ end
13
+ end
14
+
15
+ # The 2checkout vendor account number
16
+ mapping :account, 'sid'
17
+
18
+ # he total amount to be billed, in decimal form, without a currency symbol. (8 characters, decimal, 2 characters: Example: 99999999.99)
19
+ mapping :amount, 'total'
20
+
21
+ # a unique order id from your program. (128 characters max)
22
+ mapping :order, 'cart_order_id'
23
+
24
+
25
+ mapping :customer, :email => 'email',
26
+ :phone => 'phone'
27
+
28
+ mapping :billing_address, :city => 'city',
29
+ :address1 => 'street_address',
30
+ :address2 => 'street_address2',
31
+ :state => 'state',
32
+ :zip => 'zip',
33
+ :country => 'country'
34
+
35
+ mapping :shipping_address, :city => 'ship_city',
36
+ :address1 => 'ship_street_address',
37
+ :state => 'ship_state',
38
+ :zip => 'ship_zip',
39
+ :country => 'ship_country'
40
+
41
+ mapping :invoice, 'merchant_order_id'
42
+
43
+ # Does nothing, since we've disabled the Continue Shopping button by using the fixed = Y field
44
+ mapping :return_url, 'return_url'
45
+
46
+ #mapping :description, ''
47
+ #mapping :tax, ''
48
+ #mapping :shipping, ''
49
+
50
+ def customer(params = {})
51
+ add_field(mappings[:customer][:email], params[:email])
52
+ add_field(mappings[:customer][:phone], params[:phone])
53
+ add_field('card_holder_name', "#{params[:first_name]} #{params[:last_name]}")
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,114 @@
1
+ require 'net/http'
2
+ require 'base64'
3
+ require 'digest/md5'
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ module Integrations #:nodoc:
8
+ module TwoCheckout
9
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
10
+ # order_number 2Checkout.com order number
11
+ # card_holder_name Card holder's name
12
+ # street_address Card holder's address
13
+ # city Card holder's city
14
+ # state Card holder's state
15
+ # zip Card holder's zip
16
+ # country Card holder's country
17
+ # email Card holder's email
18
+ # phone Card holder's phone
19
+ # credit_card_processed Y if successful, K if waiting for approval
20
+ # total Total purchase amount
21
+ # ship_name Shipping information
22
+ # ship_street_address Shipping information
23
+ # ship_city Shipping information
24
+ # ship_state Shipping information
25
+ # ship_zip Shipping information
26
+ # ship_country Shipping information
27
+ # product_id 2Checkout product ID for purchased items will append a number if more than one item.
28
+ # ex. product_id,product_id1,product_id2
29
+ # quantity quantity of corresponding product will append a number if more than one item.
30
+ # ex. quantity,quantity1,quantity2
31
+ # merchant_product_id your product ID for purchased items will append a number if more than one item.
32
+ # ex. merchant_product_id,merchant_product_id1,merchant_product_id2
33
+ # product_description your description for purchased items will append a number if more than one item.
34
+ # ex. product_description,product_description1,product_description2
35
+
36
+ def currency
37
+ 'USD'
38
+ end
39
+
40
+ def complete?
41
+ status == 'Completed'
42
+ end
43
+
44
+ def item_id
45
+ params['cart_order_id']
46
+ end
47
+
48
+ def transaction_id
49
+ params['order_number']
50
+ end
51
+
52
+ def received_at
53
+ params['']
54
+ end
55
+
56
+ def payer_email
57
+ params['email']
58
+ end
59
+
60
+ def receiver_email
61
+ params['']
62
+ end
63
+
64
+ # The MD5 Hash
65
+ def security_key
66
+ params['key']
67
+ end
68
+
69
+ # the money amount we received in X.2 decimal.
70
+ def gross
71
+ params['total']
72
+ end
73
+
74
+ # Was this a test transaction? # Use the hash
75
+ def test?
76
+ params['demo'] == 'Y'
77
+ end
78
+
79
+ def status
80
+ case params['credit_card_processed']
81
+ when 'Y'
82
+ 'Completed'
83
+ when 'K'
84
+ 'Pending'
85
+ else
86
+ 'Failed'
87
+ end
88
+ end
89
+
90
+ def secret
91
+ @options[:credential2]
92
+ end
93
+
94
+ def acknowledge
95
+ return false if security_key.blank?
96
+
97
+ Digest::MD5.hexdigest("#{secret}#{params['sid']}#{transaction_id}#{gross}").upcase == security_key.upcase
98
+ end
99
+
100
+ private
101
+
102
+ def parse(post)
103
+ @raw = post.to_s
104
+ for line in @raw.split('&')
105
+ key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
106
+ params[key] = CGI.unescape(value || '')
107
+ end
108
+ end
109
+
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end