yetanothernguyen-activemerchant 1.16.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 (192) hide show
  1. data/CHANGELOG +711 -0
  2. data/CONTRIBUTORS +245 -0
  3. data/MIT-LICENSE +20 -0
  4. data/gem-public_cert.pem +20 -0
  5. data/lib/active_merchant.rb +52 -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 +178 -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 +672 -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_stream.rb +230 -0
  30. data/lib/active_merchant/billing/gateways/cyber_source.rb +430 -0
  31. data/lib/active_merchant/billing/gateways/data_cash.rb +597 -0
  32. data/lib/active_merchant/billing/gateways/efsnet.rb +235 -0
  33. data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
  34. data/lib/active_merchant/billing/gateways/epay.rb +268 -0
  35. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  36. data/lib/active_merchant/billing/gateways/eway_managed.rb +231 -0
  37. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  38. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  39. data/lib/active_merchant/billing/gateways/first_pay.rb +177 -0
  40. data/lib/active_merchant/billing/gateways/garanti.rb +262 -0
  41. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  42. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  43. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  44. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  45. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  46. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  47. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  48. data/lib/active_merchant/billing/gateways/jetpay.rb +276 -0
  49. data/lib/active_merchant/billing/gateways/linkpoint.rb +454 -0
  50. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +156 -0
  51. data/lib/active_merchant/billing/gateways/merchant_ware.rb +289 -0
  52. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  53. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  54. data/lib/active_merchant/billing/gateways/moneris.rb +209 -0
  55. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  56. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  57. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  58. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  59. data/lib/active_merchant/billing/gateways/ogone.rb +292 -0
  60. data/lib/active_merchant/billing/gateways/orbital.rb +321 -0
  61. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  62. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  63. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  64. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  65. data/lib/active_merchant/billing/gateways/payflow.rb +253 -0
  66. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  67. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  68. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  69. data/lib/active_merchant/billing/gateways/payflow_express.rb +222 -0
  70. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  71. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  72. data/lib/active_merchant/billing/gateways/payment_express.rb +235 -0
  73. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  74. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +351 -0
  75. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +49 -0
  76. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  77. data/lib/active_merchant/billing/gateways/paypal_express.rb +177 -0
  78. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +25 -0
  79. data/lib/active_merchant/billing/gateways/paystation.rb +201 -0
  80. data/lib/active_merchant/billing/gateways/plugnpay.rb +298 -0
  81. data/lib/active_merchant/billing/gateways/psigate.rb +219 -0
  82. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  83. data/lib/active_merchant/billing/gateways/qbms.rb +293 -0
  84. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  85. data/lib/active_merchant/billing/gateways/quickpay.rb +223 -0
  86. data/lib/active_merchant/billing/gateways/realex.rb +311 -0
  87. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  88. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  89. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  90. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  91. data/lib/active_merchant/billing/gateways/sage_pay.rb +320 -0
  92. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  93. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  94. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  95. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +193 -0
  96. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  97. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  98. data/lib/active_merchant/billing/gateways/smart_ps.rb +271 -0
  99. data/lib/active_merchant/billing/gateways/stripe.rb +212 -0
  100. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  101. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  102. data/lib/active_merchant/billing/gateways/trust_commerce.rb +423 -0
  103. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  104. data/lib/active_merchant/billing/gateways/verifi.rb +233 -0
  105. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  106. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  107. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  108. data/lib/active_merchant/billing/integrations.rb +17 -0
  109. data/lib/active_merchant/billing/integrations/action_view_helper.rb +70 -0
  110. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  111. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  112. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  113. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  114. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  115. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  116. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  117. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  118. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  119. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  120. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  121. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  122. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  123. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  124. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  125. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  126. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  127. data/lib/active_merchant/billing/integrations/e_payment_plans.rb +48 -0
  128. data/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb +34 -0
  129. data/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb +84 -0
  130. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  131. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  132. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  133. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  134. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  135. data/lib/active_merchant/billing/integrations/helper.rb +96 -0
  136. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  137. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  138. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  139. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  140. data/lib/active_merchant/billing/integrations/migs.rb +22 -0
  141. data/lib/active_merchant/billing/integrations/migs/helper.rb +64 -0
  142. data/lib/active_merchant/billing/integrations/migs/return.rb +54 -0
  143. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  144. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  145. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  146. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  147. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  148. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  149. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  150. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  151. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  152. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  153. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  154. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  155. data/lib/active_merchant/billing/integrations/quickpay.rb +21 -0
  156. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  157. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  158. data/lib/active_merchant/billing/integrations/return.rb +42 -0
  159. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  160. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  161. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
  162. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  163. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  164. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  165. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  166. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  167. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  168. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  169. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  170. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  171. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +97 -0
  172. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  173. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  174. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  175. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  176. data/lib/active_merchant/billing/response.rb +32 -0
  177. data/lib/active_merchant/common.rb +14 -0
  178. data/lib/active_merchant/common/connection.rb +177 -0
  179. data/lib/active_merchant/common/country.rb +328 -0
  180. data/lib/active_merchant/common/error.rb +26 -0
  181. data/lib/active_merchant/common/post_data.rb +24 -0
  182. data/lib/active_merchant/common/posts_data.rb +63 -0
  183. data/lib/active_merchant/common/requires_parameters.rb +16 -0
  184. data/lib/active_merchant/common/utils.rb +22 -0
  185. data/lib/active_merchant/common/validateable.rb +81 -0
  186. data/lib/active_merchant/railtie.rb +9 -0
  187. data/lib/active_merchant/version.rb +3 -0
  188. data/lib/activemerchant.rb +1 -0
  189. data/lib/certs/cacert.pem +7815 -0
  190. data/lib/support/gateway_support.rb +58 -0
  191. data/lib/support/outbound_hosts.rb +25 -0
  192. metadata +281 -0
@@ -0,0 +1,49 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaypalExpressResponse < Response
4
+ def email
5
+ info['Payer']
6
+ end
7
+
8
+ def info
9
+ (@params['PayerInfo']||{})
10
+ end
11
+
12
+ def name
13
+ payer = (info['PayerName']||{})
14
+ [payer['FirstName'], payer['MiddleName'], payer['LastName']].compact.join(' ')
15
+ end
16
+
17
+ def token
18
+ @params['Token']
19
+ end
20
+
21
+ def payer_id
22
+ info['PayerID']
23
+ end
24
+
25
+ def payer_country
26
+ info['PayerCountry']
27
+ end
28
+
29
+ # PayPal returns a contact telephone number only if your Merchant account profile settings require that the buyer enter one.
30
+ def contact_phone
31
+ @params['ContactPhone']
32
+ end
33
+
34
+ def address
35
+ address = (@params['PaymentDetails']||{})['ShipToAddress']
36
+ { 'name' => address['Name'],
37
+ 'company' => info['PayerBusiness'],
38
+ 'address1' => address['Street1'],
39
+ 'address2' => address['Street2'],
40
+ 'city' => address['CityName'],
41
+ 'state' => address['StateOrProvince'],
42
+ 'country' => address['Country'],
43
+ 'zip' => address['PostalCode'],
44
+ 'phone' => (contact_phone || address['Phone'])
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/paypal'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ # The PayPal gateway for PayPal Website Payments Pro Canada only supports Visa and MasterCard
6
+ class PaypalCaGateway < PaypalGateway
7
+ self.supported_cardtypes = [:visa, :master]
8
+ self.supported_countries = ['CA']
9
+ self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside'
10
+ self.display_name = 'PayPal Website Payments Pro (CA)'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,177 @@
1
+ require File.dirname(__FILE__) + '/paypal/paypal_common_api'
2
+ require File.dirname(__FILE__) + '/paypal/paypal_express_response'
3
+ require File.dirname(__FILE__) + '/paypal_express_common'
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ class PaypalExpressGateway < Gateway
8
+ include PaypalCommonAPI
9
+ include PaypalExpressCommon
10
+
11
+ self.test_redirect_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
12
+ self.supported_countries = ['US']
13
+ self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside'
14
+ self.display_name = 'PayPal Express Checkout'
15
+
16
+ def setup_authorization(money, options = {})
17
+ requires!(options, :return_url, :cancel_return_url)
18
+
19
+ commit 'SetExpressCheckout', build_setup_request('Authorization', money, options)
20
+ end
21
+
22
+ def setup_purchase(money, options = {})
23
+ requires!(options, :return_url, :cancel_return_url)
24
+
25
+ commit 'SetExpressCheckout', build_setup_request('Sale', money, options)
26
+ end
27
+
28
+ def details_for(token)
29
+ commit 'GetExpressCheckoutDetails', build_get_details_request(token)
30
+ end
31
+
32
+ def authorize(money, options = {})
33
+ requires!(options, :token, :payer_id)
34
+
35
+ commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Authorization', money, options)
36
+ end
37
+
38
+ def purchase(money, options = {})
39
+ requires!(options, :token, :payer_id)
40
+
41
+ commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Sale', money, options)
42
+ end
43
+
44
+ private
45
+ def build_get_details_request(token)
46
+ xml = Builder::XmlMarkup.new :indent => 2
47
+ xml.tag! 'GetExpressCheckoutDetailsReq', 'xmlns' => PAYPAL_NAMESPACE do
48
+ xml.tag! 'GetExpressCheckoutDetailsRequest', 'xmlns:n2' => EBAY_NAMESPACE do
49
+ xml.tag! 'n2:Version', API_VERSION
50
+ xml.tag! 'Token', token
51
+ end
52
+ end
53
+
54
+ xml.target!
55
+ end
56
+
57
+ def build_sale_or_authorization_request(action, money, options)
58
+ currency_code = options[:currency] || currency(money)
59
+
60
+ xml = Builder::XmlMarkup.new :indent => 2
61
+ xml.tag! 'DoExpressCheckoutPaymentReq', 'xmlns' => PAYPAL_NAMESPACE do
62
+ xml.tag! 'DoExpressCheckoutPaymentRequest', 'xmlns:n2' => EBAY_NAMESPACE do
63
+ xml.tag! 'n2:Version', API_VERSION
64
+ xml.tag! 'n2:DoExpressCheckoutPaymentRequestDetails' do
65
+ xml.tag! 'n2:PaymentAction', action
66
+ xml.tag! 'n2:Token', options[:token]
67
+ xml.tag! 'n2:PayerID', options[:payer_id]
68
+ xml.tag! 'n2:PaymentDetails' do
69
+ xml.tag! 'n2:OrderTotal', localized_amount(money, currency_code), 'currencyID' => currency_code
70
+
71
+ # All of the values must be included together and add up to the order total
72
+ if [:subtotal, :shipping, :handling, :tax].all?{ |o| options.has_key?(o) }
73
+ xml.tag! 'n2:ItemTotal', localized_amount(options[:subtotal], currency_code), 'currencyID' => currency_code
74
+ xml.tag! 'n2:ShippingTotal', localized_amount(options[:shipping], currency_code),'currencyID' => currency_code
75
+ xml.tag! 'n2:HandlingTotal', localized_amount(options[:handling], currency_code),'currencyID' => currency_code
76
+ xml.tag! 'n2:TaxTotal', localized_amount(options[:tax], currency_code), 'currencyID' => currency_code
77
+ end
78
+
79
+ xml.tag! 'n2:NotifyURL', options[:notify_url]
80
+ xml.tag! 'n2:ButtonSource', application_id.to_s.slice(0,32) unless application_id.blank?
81
+ xml.tag! 'n2:InvoiceID', options[:order_id]
82
+ xml.tag! 'n2:OrderDescription', options[:description]
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ xml.target!
89
+ end
90
+
91
+ def build_setup_request(action, money, options)
92
+ currency_code = options[:currency] || currency(money)
93
+
94
+ xml = Builder::XmlMarkup.new :indent => 2
95
+ xml.tag! 'SetExpressCheckoutReq', 'xmlns' => PAYPAL_NAMESPACE do
96
+ xml.tag! 'SetExpressCheckoutRequest', 'xmlns:n2' => EBAY_NAMESPACE do
97
+ xml.tag! 'n2:Version', API_VERSION
98
+ xml.tag! 'n2:SetExpressCheckoutRequestDetails' do
99
+ if options[:max_amount]
100
+ xml.tag! 'n2:MaxAmount', localized_amount(options[:max_amount], currency_code), 'currencyID' => currency_code
101
+ end
102
+ if !options[:allow_note].nil?
103
+ xml.tag! 'n2:AllowNote', options[:allow_note] ? '1' : '0'
104
+ end
105
+ xml.tag! 'n2:PaymentDetails' do
106
+ xml.tag! 'n2:OrderTotal', amount(money).to_f.zero? ? localized_amount(100, currency_code) : localized_amount(money, currency_code), 'currencyID' => currency_code
107
+ # All of the values must be included together and add up to the order total
108
+ if [:subtotal, :shipping, :handling, :tax].all? { |o| options.has_key?(o) }
109
+ xml.tag! 'n2:ItemTotal', localized_amount(options[:subtotal], currency_code), 'currencyID' => currency_code
110
+ xml.tag! 'n2:ShippingTotal', localized_amount(options[:shipping], currency_code), 'currencyID' => currency_code
111
+ xml.tag! 'n2:HandlingTotal', localized_amount(options[:handling], currency_code), 'currencyID' => currency_code
112
+ xml.tag! 'n2:TaxTotal', localized_amount(options[:tax], currency_code), 'currencyID' => currency_code
113
+ end
114
+
115
+ xml.tag! 'n2:OrderDescription', options[:description]
116
+ xml.tag! 'n2:InvoiceID', options[:order_id]
117
+
118
+ if options[:items]
119
+ options[:items].each do |item|
120
+ xml.tag! 'n2:PaymentDetailsItem' do
121
+ xml.tag! 'n2:Name', item[:name]
122
+ xml.tag! 'n2:Number', item[:number]
123
+ xml.tag! 'n2:Quantity', item[:quantity]
124
+ if item[:amount]
125
+ xml.tag! 'n2:Amount', localized_amount(item[:amount], currency_code), 'currencyID' => currency_code
126
+ end
127
+ xml.tag! 'n2:Description', item[:description]
128
+ xml.tag! 'n2:ItemURL', item[:url]
129
+ end
130
+ end
131
+ end
132
+ add_address(xml, 'n2:ShipToAddress', options[:shipping_address] || options[:address])
133
+
134
+ xml.tag! 'n2:PaymentAction', action
135
+ end
136
+
137
+ xml.tag! 'n2:AddressOverride', options[:address_override] ? '1' : '0'
138
+ xml.tag! 'n2:NoShipping', options[:no_shipping] ? '1' : '0'
139
+ xml.tag! 'n2:ReturnURL', options[:return_url]
140
+ xml.tag! 'n2:CancelURL', options[:cancel_return_url]
141
+ xml.tag! 'n2:IPAddress', options[:ip] unless options[:ip].blank?
142
+ xml.tag! 'n2:BuyerEmail', options[:email] unless options[:email].blank?
143
+
144
+ if options[:billing_agreement]
145
+ xml.tag! 'n2:BillingAgreementDetails' do
146
+ xml.tag! 'n2:BillingType', options[:billing_agreement][:type]
147
+ xml.tag! 'n2:BillingAgreementDescription', options[:billing_agreement][:description]
148
+ xml.tag! 'n2:PaymentType', options[:billing_agreement][:payment_type] || 'InstantOnly'
149
+ end
150
+ end
151
+
152
+ # Customization of the payment page
153
+ xml.tag! 'n2:PageStyle', options[:page_style] unless options[:page_style].blank?
154
+ xml.tag! 'n2:cpp-header-image', options[:header_image] unless options[:header_image].blank?
155
+ xml.tag! 'n2:cpp-header-back-color', options[:header_background_color] unless options[:header_background_color].blank?
156
+ xml.tag! 'n2:cpp-header-border-color', options[:header_border_color] unless options[:header_border_color].blank?
157
+ xml.tag! 'n2:cpp-payflow-color', options[:background_color] unless options[:background_color].blank?
158
+
159
+ if options[:allow_guest_checkout]
160
+ xml.tag! 'n2:SolutionType', 'Sole'
161
+ xml.tag! 'n2:LandingPage', 'Billing'
162
+ end
163
+
164
+ xml.tag! 'n2:LocaleCode', options[:locale] unless options[:locale].blank?
165
+ end
166
+ end
167
+ end
168
+
169
+ xml.target!
170
+ end
171
+
172
+ def build_response(success, message, response, options = {})
173
+ PaypalExpressResponse.new(success, message, response, options)
174
+ end
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,25 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ module PaypalExpressCommon
4
+ def self.included(base)
5
+ base.cattr_accessor :test_redirect_url
6
+ base.cattr_accessor :live_redirect_url
7
+ base.live_redirect_url = 'https://www.paypal.com/cgibin/webscr'
8
+ end
9
+
10
+ def redirect_url
11
+ test? ? test_redirect_url : live_redirect_url
12
+ end
13
+
14
+ def redirect_url_for(token, options = {})
15
+ options = {:review => true, :mobile => false}.update(options)
16
+
17
+ cmd = options[:mobile] ? '_express-checkout-mobile' : '_express-checkout'
18
+ url = "#{redirect_url}?cmd=#{cmd}&token=#{token}"
19
+ url += '&useraction=commit' unless options[:review]
20
+
21
+ url
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,201 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaystationGateway < Gateway
4
+
5
+ URL = "https://www.paystation.co.nz/direct/paystation.dll"
6
+
7
+ # an "error code" of "0" means "No error - transaction successful"
8
+ SUCCESSFUL_RESPONSE_CODE = '0'
9
+
10
+ # an "error code" of "34" means "Future Payment Stored OK"
11
+ SUCCESSFUL_FUTURE_PAYMENT = '34'
12
+
13
+ # TODO: check this with paystation
14
+ self.supported_countries = ['NZ']
15
+
16
+ # TODO: check this with paystation (amex and diners need to be enabled)
17
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club ]
18
+
19
+ self.homepage_url = 'http://paystation.co.nz'
20
+ self.display_name = 'Paystation'
21
+
22
+ self.default_currency = 'NZD'
23
+ self.money_format = :cents
24
+
25
+ def initialize(options = {})
26
+ # You need to pass your Paystation ID and Gateway ID
27
+ requires!(options, :paystation_id, :gateway_id)
28
+ @options = options
29
+ super
30
+ end
31
+
32
+ def authorize(money, credit_card, options = {})
33
+ post = new_request
34
+
35
+ add_invoice(post, options)
36
+ add_amount(post, money, options)
37
+
38
+ add_credit_card(post, credit_card)
39
+
40
+ add_authorize_flag(post, options)
41
+
42
+ commit(post)
43
+ end
44
+
45
+ def capture(money, authorization_token, options = {})
46
+ post = new_request
47
+
48
+ add_invoice(post, options)
49
+ add_amount(post, money, options)
50
+
51
+ add_authorization_token(post, authorization_token, options[:credit_card_verification])
52
+
53
+ commit(post)
54
+ end
55
+
56
+ def purchase(money, payment_source, options = {})
57
+ post = new_request
58
+
59
+ add_invoice(post, options)
60
+ add_amount(post, money, options)
61
+
62
+ if payment_source.is_a?(String)
63
+ add_token(post, payment_source)
64
+ else
65
+ add_credit_card(post, payment_source)
66
+ end
67
+
68
+ add_customer_data(post, options) if options.has_key?(:customer)
69
+
70
+ commit(post)
71
+ end
72
+
73
+ def store(credit_card, options = {})
74
+ post = new_request
75
+
76
+ add_invoice(post, options)
77
+ add_credit_card(post, credit_card)
78
+ store_credit_card(post, options)
79
+
80
+ commit(post)
81
+ end
82
+
83
+ private
84
+
85
+ def new_request
86
+ {
87
+ :pi => @options[:paystation_id], # paystation account id
88
+ :gi => @options[:gateway_id], # paystation gateway id
89
+ "2p" => "t", # two-party transaction type
90
+ :nr => "t", # -- redirect??
91
+ :df => "yymm" # date format: optional sometimes, required others
92
+ }
93
+ end
94
+
95
+ def add_customer_data(post, options)
96
+ post[:mc] = options[:customer]
97
+ end
98
+
99
+ def add_invoice(post, options)
100
+ requires!(options, :order_id)
101
+
102
+ post[:ms] = options[:order_id] # "Merchant Session", must be unique per request
103
+ post[:mo] = options[:invoice] # "Order Details", displayed in Paystation Admin
104
+ post[:mr] = options[:description] # "Merchant Reference Code", seen from Paystation Admin
105
+ end
106
+
107
+ def add_credit_card(post, credit_card)
108
+
109
+ post[:cn] = credit_card.number
110
+ post[:ct] = credit_card.type
111
+ post[:ex] = format_date(credit_card.month, credit_card.year)
112
+ post[:cc] = credit_card.verification_value if credit_card.verification_value?
113
+
114
+ end
115
+
116
+ # bill a token (stored via "store") rather than a Credit Card
117
+ def add_token(post, token)
118
+ post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
119
+ post[:ft] = token
120
+ end
121
+
122
+ def store_credit_card(post, options)
123
+
124
+ post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
125
+ post[:fs] = "t" # tells paystation to store right now, not bill
126
+ post[:ft] = options[:token] if options[:token] # specify a token to use that, or let Paystation generate one
127
+
128
+ end
129
+
130
+ def add_authorize_flag(post, options)
131
+ post[:pa] = "t" # tells Paystation that this is a pre-auth authorisation payment (account must be in pre-auth mode)
132
+ end
133
+
134
+ def add_authorization_token(post, auth_token, verification_value = nil)
135
+ post[:cp] = "t" # Capture Payment flag – tells Paystation this transaction should be treated as a capture payment
136
+ post[:cx] = auth_token
137
+ post[:cc] = verification_value
138
+ end
139
+
140
+ def add_amount(post, money, options)
141
+
142
+ post[:am] = amount(money)
143
+ post[:cu] = options[:currency] || currency(money)
144
+
145
+ end
146
+
147
+ def parse(xml_response)
148
+ response = {}
149
+
150
+ xml = REXML::Document.new(xml_response)
151
+
152
+ # for normal payments, the root node is <Response>
153
+ # for "future payments", it's <PaystationFuturePaymentResponse>
154
+ xml.elements.each("#{xml.root.name}/*") do |element|
155
+ response[element.name.underscore.to_sym] = element.text
156
+ end
157
+
158
+ response
159
+ end
160
+
161
+ def commit(post)
162
+
163
+ post[:tm] = "T" if test? # test mode
164
+
165
+ pstn_prefix_params = post.collect { |key, value| "pstn_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
166
+
167
+ # need include paystation param as "initiator flag for payment engine"
168
+ data = ssl_post(URL, "#{pstn_prefix_params}&paystation=_empty")
169
+ response = parse(data)
170
+ message = message_from(response)
171
+
172
+ PaystationResponse.new(success?(response), message, response,
173
+ :test => (response[:tm] && response[:tm].downcase == "t"),
174
+ :authorization => response[:paystation_transaction_id]
175
+ )
176
+ end
177
+
178
+ def success?(response)
179
+ (response[:ec] == SUCCESSFUL_RESPONSE_CODE) || (response[:ec] == SUCCESSFUL_FUTURE_PAYMENT)
180
+ end
181
+
182
+ def message_from(response)
183
+ response[:em]
184
+ end
185
+
186
+ def format_date(month, year)
187
+ "#{format(year, :two_digits)}#{format(month, :two_digits)}"
188
+ end
189
+
190
+ end
191
+
192
+ class PaystationResponse < Response
193
+ # add a method to response so we can easily get the token
194
+ # for Validate transactions
195
+ def token
196
+ @params["future_payment_token"]
197
+ end
198
+ end
199
+ end
200
+ end
201
+