start_activemerchant 1.50.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 (218) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1769 -0
  3. data/CONTRIBUTORS +540 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +226 -0
  6. data/lib/active_merchant.rb +67 -0
  7. data/lib/active_merchant/billing.rb +15 -0
  8. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +72 -0
  11. data/lib/active_merchant/billing/check.rb +76 -0
  12. data/lib/active_merchant/billing/compatibility.rb +120 -0
  13. data/lib/active_merchant/billing/credit_card.rb +404 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +195 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +291 -0
  18. data/lib/active_merchant/billing/gateways.rb +14 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
  20. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net.rb +510 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
  24. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  25. data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
  28. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
  29. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
  30. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  31. data/lib/active_merchant/billing/gateways/beanstream.rb +192 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +58 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
  35. data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
  36. data/lib/active_merchant/billing/gateways/borgun.rb +211 -0
  37. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  40. data/lib/active_merchant/billing/gateways/braintree_blue.rb +574 -0
  41. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  42. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  43. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +238 -0
  45. data/lib/active_merchant/billing/gateways/cashnet.rb +202 -0
  46. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  47. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  48. data/lib/active_merchant/billing/gateways/cenpos.rb +262 -0
  49. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  50. data/lib/active_merchant/billing/gateways/checkout.rb +216 -0
  51. data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
  52. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  53. data/lib/active_merchant/billing/gateways/conekta.rb +210 -0
  54. data/lib/active_merchant/billing/gateways/cyber_source.rb +720 -0
  55. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  56. data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
  57. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  58. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  59. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  60. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  61. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  62. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  63. data/lib/active_merchant/billing/gateways/eway_rapid.rb +522 -0
  64. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  65. data/lib/active_merchant/billing/gateways/ezic.rb +206 -0
  66. data/lib/active_merchant/billing/gateways/fat_zebra.rb +213 -0
  67. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  68. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  69. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  70. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  71. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +413 -0
  72. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  73. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  74. data/lib/active_merchant/billing/gateways/garanti.rb +261 -0
  75. data/lib/active_merchant/billing/gateways/global_transport.rb +179 -0
  76. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  77. data/lib/active_merchant/billing/gateways/hps.rb +287 -0
  78. data/lib/active_merchant/billing/gateways/iats_payments.rb +277 -0
  79. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  80. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  81. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  82. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  83. data/lib/active_merchant/billing/gateways/inspire.rb +219 -0
  84. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  85. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  86. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  87. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  88. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  89. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  90. data/lib/active_merchant/billing/gateways/litle.rb +345 -0
  91. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  92. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  93. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  94. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  95. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  96. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  97. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  98. data/lib/active_merchant/billing/gateways/mercury.rb +326 -0
  99. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  100. data/lib/active_merchant/billing/gateways/migs.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  102. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  103. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  104. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  105. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  106. data/lib/active_merchant/billing/gateways/moneris_us.rb +298 -0
  107. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  108. data/lib/active_merchant/billing/gateways/nab_transact.rb +290 -0
  109. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  110. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  111. data/lib/active_merchant/billing/gateways/netbilling.rb +224 -0
  112. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  113. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  114. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  115. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  116. data/lib/active_merchant/billing/gateways/omise.rb +319 -0
  117. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  118. data/lib/active_merchant/billing/gateways/optimal_payment.rb +314 -0
  119. data/lib/active_merchant/billing/gateways/orbital.rb +834 -0
  120. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  121. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  122. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  123. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  124. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  125. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  126. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  127. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  128. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  129. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  130. data/lib/active_merchant/billing/gateways/payflow.rb +308 -0
  131. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +220 -0
  132. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  133. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  134. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  135. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  136. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  137. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  138. data/lib/active_merchant/billing/gateways/paymill.rb +282 -0
  139. data/lib/active_merchant/billing/gateways/paypal.rb +129 -0
  140. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +679 -0
  141. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  142. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  143. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  144. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  145. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  146. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  147. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  148. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  149. data/lib/active_merchant/billing/gateways/payu_in.rb +247 -0
  150. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  151. data/lib/active_merchant/billing/gateways/pin.rb +207 -0
  152. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  153. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  154. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  155. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  156. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  157. data/lib/active_merchant/billing/gateways/quickbooks.rb +280 -0
  158. data/lib/active_merchant/billing/gateways/quickpay.rb +26 -0
  159. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
  160. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
  161. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
  162. data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
  163. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  164. data/lib/active_merchant/billing/gateways/redsys.rb +406 -0
  165. data/lib/active_merchant/billing/gateways/s5.rb +226 -0
  166. data/lib/active_merchant/billing/gateways/sage.rb +173 -0
  167. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +89 -0
  168. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
  169. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  170. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  171. data/lib/active_merchant/billing/gateways/sage_pay.rb +399 -0
  172. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  173. data/lib/active_merchant/billing/gateways/secure_net.rb +263 -0
  174. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  175. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  176. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  177. data/lib/active_merchant/billing/gateways/skip_jack.rb +451 -0
  178. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  179. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  180. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  181. data/lib/active_merchant/billing/gateways/stripe.rb +489 -0
  182. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  183. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  184. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  185. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  186. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  187. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  188. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  189. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  190. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +259 -0
  191. data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
  192. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  193. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  194. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  195. data/lib/active_merchant/billing/gateways/wepay.rb +205 -0
  196. data/lib/active_merchant/billing/gateways/wirecard.rb +420 -0
  197. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  198. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +204 -0
  199. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  200. data/lib/active_merchant/billing/model.rb +30 -0
  201. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +24 -0
  202. data/lib/active_merchant/billing/payment_token.rb +21 -0
  203. data/lib/active_merchant/billing/rails.rb +3 -0
  204. data/lib/active_merchant/billing/response.rb +92 -0
  205. data/lib/active_merchant/connection.rb +172 -0
  206. data/lib/active_merchant/country.rb +332 -0
  207. data/lib/active_merchant/empty.rb +20 -0
  208. data/lib/active_merchant/errors.rb +35 -0
  209. data/lib/active_merchant/network_connection_retries.rb +79 -0
  210. data/lib/active_merchant/post_data.rb +24 -0
  211. data/lib/active_merchant/posts_data.rb +84 -0
  212. data/lib/active_merchant/version.rb +3 -0
  213. data/lib/activemerchant.rb +1 -0
  214. data/lib/certs/cacert.pem +3866 -0
  215. data/lib/support/gateway_support.rb +71 -0
  216. data/lib/support/outbound_hosts.rb +28 -0
  217. data/lib/support/ssl_verify.rb +93 -0
  218. metadata +387 -0
@@ -0,0 +1,280 @@
1
+ require 'active_merchant/billing/gateways/migs/migs_codes'
2
+
3
+ require 'digest/md5' # Used in add_secure_hash
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ class MigsGateway < Gateway
8
+ include MigsCodes
9
+
10
+ API_VERSION = 1
11
+
12
+ class_attribute :server_hosted_url, :merchant_hosted_url
13
+
14
+ self.server_hosted_url = 'https://migs.mastercard.com.au/vpcpay'
15
+ self.merchant_hosted_url = 'https://migs.mastercard.com.au/vpcdps'
16
+
17
+ self.live_url = self.server_hosted_url
18
+
19
+ # MiGS is supported throughout Asia Pacific, Middle East and Africa
20
+ # MiGS is used in Australia (AU) by ANZ (eGate), CBA (CommWeb) and more
21
+ # Source of Country List: http://www.scribd.com/doc/17811923
22
+ self.supported_countries = %w(AU AE BD BN EG HK ID IN JO KW LB LK MU MV MY NZ OM PH QA SA SG TT VN)
23
+
24
+ # The card types supported by the payment gateway
25
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
26
+
27
+ self.money_format = :cents
28
+
29
+ # The homepage URL of the gateway
30
+ self.homepage_url = 'http://mastercard.com/mastercardsps'
31
+
32
+ # The name of the gateway
33
+ self.display_name = 'MasterCard Internet Gateway Service (MiGS)'
34
+
35
+ # Creates a new MigsGateway
36
+ # The advanced_login/advanced_password fields are needed for
37
+ # advanced methods such as the capture, refund and status methods
38
+ #
39
+ # ==== Options
40
+ #
41
+ # * <tt>:login</tt> -- The MiGS Merchant ID (REQUIRED)
42
+ # * <tt>:password</tt> -- The MiGS Access Code (REQUIRED)
43
+ # * <tt>:secure_hash</tt> -- The MiGS Secure Hash
44
+ # (Required for Server Hosted payments)
45
+ # * <tt>:advanced_login</tt> -- The MiGS AMA User
46
+ # * <tt>:advanced_password</tt> -- The MiGS AMA User's password
47
+ def initialize(options = {})
48
+ requires!(options, :login, :password)
49
+ super
50
+ end
51
+
52
+ # ==== Options
53
+ #
54
+ # * <tt>:order_id</tt> -- A reference for tracking the order (REQUIRED)
55
+ # * <tt>:unique_id</tt> -- A unique id for this request (Max 40 chars).
56
+ # If not supplied one will be generated.
57
+ def purchase(money, creditcard, options = {})
58
+ requires!(options, :order_id)
59
+
60
+ post = {}
61
+
62
+ add_amount(post, money, options)
63
+ add_invoice(post, options)
64
+ add_creditcard(post, creditcard)
65
+ add_standard_parameters('pay', post, options[:unique_id])
66
+
67
+ commit(post)
68
+ end
69
+
70
+ # MiGS works by merchants being either purchase only or authorize/capture
71
+ # So authorize is the same as purchase when in authorize mode
72
+ alias_method :authorize, :purchase
73
+
74
+ # ==== Options
75
+ #
76
+ # * <tt>:unique_id</tt> -- A unique id for this request (Max 40 chars).
77
+ # If not supplied one will be generated.
78
+ def capture(money, authorization, options = {})
79
+ requires!(@options, :advanced_login, :advanced_password)
80
+
81
+ post = options.merge(:TransNo => authorization)
82
+
83
+ add_amount(post, money, options)
84
+ add_advanced_user(post)
85
+ add_standard_parameters('capture', post, options[:unique_id])
86
+
87
+ commit(post)
88
+ end
89
+
90
+ # ==== Options
91
+ #
92
+ # * <tt>:unique_id</tt> -- A unique id for this request (Max 40 chars).
93
+ # If not supplied one will be generated.
94
+ def refund(money, authorization, options = {})
95
+ requires!(@options, :advanced_login, :advanced_password)
96
+
97
+ post = options.merge(:TransNo => authorization)
98
+
99
+ add_amount(post, money, options)
100
+ add_advanced_user(post)
101
+ add_standard_parameters('refund', post, options[:unique_id])
102
+
103
+ commit(post)
104
+ end
105
+
106
+ def credit(money, authorization, options = {})
107
+ ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
108
+ refund(money, authorization, options)
109
+ end
110
+
111
+ # Checks the status of a previous transaction
112
+ # This can be useful when a response is not received due to network issues
113
+ #
114
+ # ==== Parameters
115
+ #
116
+ # * <tt>unique_id</tt> -- Unique id of transaction to find.
117
+ # This is the value of the option supplied in other methods or
118
+ # if not supplied is returned with key :MerchTxnRef
119
+ def status(unique_id)
120
+ requires!(@options, :advanced_login, :advanced_password)
121
+
122
+ post = {}
123
+ add_advanced_user(post)
124
+ add_standard_parameters('queryDR', post, unique_id)
125
+
126
+ commit(post)
127
+ end
128
+
129
+ # Generates a URL to redirect user to MiGS to process payment
130
+ # Once user is finished MiGS will redirect back to specified URL
131
+ # With a response hash which can be turned into a Response object
132
+ # with purchase_offsite_response
133
+ #
134
+ # ==== Options
135
+ #
136
+ # * <tt>:order_id</tt> -- A reference for tracking the order (REQUIRED)
137
+ # * <tt>:locale</tt> -- Change the language of the redirected page
138
+ # Values are 2 digit locale, e.g. en, es
139
+ # * <tt>:return_url</tt> -- the URL to return to once the payment is complete
140
+ # * <tt>:card_type</tt> -- Providing this skips the card type step.
141
+ # Values are ActiveMerchant formats: e.g. master, visa, american_express, diners_club
142
+ # * <tt>:unique_id</tt> -- Unique id of transaction to find.
143
+ # If not supplied one will be generated.
144
+ def purchase_offsite_url(money, options = {})
145
+ requires!(options, :order_id, :return_url)
146
+ requires!(@options, :secure_hash)
147
+
148
+ post = {}
149
+
150
+ add_amount(post, money, options)
151
+ add_invoice(post, options)
152
+ add_creditcard_type(post, options[:card_type]) if options[:card_type]
153
+
154
+ post.merge!(
155
+ :Locale => options[:locale] || 'en',
156
+ :ReturnURL => options[:return_url]
157
+ )
158
+
159
+ add_standard_parameters('pay', post, options[:unique_id])
160
+
161
+ add_secure_hash(post)
162
+
163
+ self.server_hosted_url + '?' + post_data(post)
164
+ end
165
+
166
+ # Parses a response from purchase_offsite_url once user is redirected back
167
+ #
168
+ # ==== Parameters
169
+ #
170
+ # * <tt>data</tt> -- All params when offsite payment returns
171
+ # e.g. returns to http://company.com/return?a=1&b=2, then input "a=1&b=2"
172
+ def purchase_offsite_response(data)
173
+ requires!(@options, :secure_hash)
174
+
175
+ response_hash = parse(data)
176
+
177
+ expected_secure_hash = calculate_secure_hash(response_hash.reject{|k, v| k == :SecureHash}, @options[:secure_hash])
178
+ unless response_hash[:SecureHash] == expected_secure_hash
179
+ raise SecurityError, "Secure Hash mismatch, response may be tampered with"
180
+ end
181
+
182
+ response_object(response_hash)
183
+ end
184
+
185
+ def test?
186
+ @options[:login].start_with?('TEST')
187
+ end
188
+
189
+ private
190
+
191
+ def add_amount(post, money, options)
192
+ post[:Amount] = amount(money)
193
+ post[:Currency] = options[:currency] if options[:currency]
194
+ end
195
+
196
+ def add_advanced_user(post)
197
+ post[:User] = @options[:advanced_login]
198
+ post[:Password] = @options[:advanced_password]
199
+ end
200
+
201
+ def add_invoice(post, options)
202
+ post[:OrderInfo] = options[:order_id]
203
+ end
204
+
205
+ def add_creditcard(post, creditcard)
206
+ post[:CardNum] = creditcard.number
207
+ post[:CardSecurityCode] = creditcard.verification_value if creditcard.verification_value?
208
+ post[:CardExp] = format(creditcard.year, :two_digits) + format(creditcard.month, :two_digits)
209
+ end
210
+
211
+ def add_creditcard_type(post, card_type)
212
+ post[:Gateway] = 'ssl'
213
+ post[:card] = CARD_TYPES.detect{|ct| ct.am_code == card_type}.migs_long_code
214
+ end
215
+
216
+ def parse(body)
217
+ params = CGI::parse(body)
218
+ hash = {}
219
+ params.each do |key, value|
220
+ hash[key.gsub('vpc_', '').to_sym] = value[0]
221
+ end
222
+ hash
223
+ end
224
+
225
+ def commit(post)
226
+ data = ssl_post self.merchant_hosted_url, post_data(post)
227
+ response_hash = parse(data)
228
+ response_object(response_hash)
229
+ end
230
+
231
+ def response_object(response)
232
+ avs_response_code = response[:AVSResultCode]
233
+ avs_response_code = 'S' if avs_response_code == "Unsupported"
234
+
235
+ cvv_result_code = response[:CSCResultCode]
236
+ cvv_result_code = 'P' if cvv_result_code == "Unsupported"
237
+
238
+ Response.new(success?(response), response[:Message], response,
239
+ :test => test?,
240
+ :authorization => response[:TransactionNo],
241
+ :fraud_review => fraud_review?(response),
242
+ :avs_result => { :code => avs_response_code },
243
+ :cvv_result => cvv_result_code
244
+ )
245
+ end
246
+
247
+ def success?(response)
248
+ response[:TxnResponseCode] == '0'
249
+ end
250
+
251
+ def fraud_review?(response)
252
+ ISSUER_RESPONSE_CODES[response[:AcqResponseCode]] == 'Suspected Fraud'
253
+ end
254
+
255
+ def add_standard_parameters(action, post, unique_id = nil)
256
+ post.merge!(
257
+ :Version => API_VERSION,
258
+ :Merchant => @options[:login],
259
+ :AccessCode => @options[:password],
260
+ :Command => action,
261
+ :MerchTxnRef => unique_id || generate_unique_id.slice(0, 40)
262
+ )
263
+ end
264
+
265
+ def post_data(post)
266
+ post.collect { |key, value| "vpc_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
267
+ end
268
+
269
+ def add_secure_hash(post)
270
+ post[:SecureHash] = calculate_secure_hash(post, @options[:secure_hash])
271
+ end
272
+
273
+ def calculate_secure_hash(post, secure_hash)
274
+ sorted_values = post.sort_by(&:to_s).map(&:last)
275
+ input = secure_hash + sorted_values.join
276
+ Digest::MD5.hexdigest(input).upcase
277
+ end
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,100 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ module MigsCodes
4
+ TXN_RESPONSE_CODES = {
5
+ '?' => 'Response Unknown',
6
+ '0' => 'Transaction Successful',
7
+ '1' => 'Transaction Declined - Bank Error',
8
+ '2' => 'Bank Declined Transaction',
9
+ '3' => 'Transaction Declined - No Reply from Bank',
10
+ '4' => 'Transaction Declined - Expired Card',
11
+ '5' => 'Transaction Declined - Insufficient funds',
12
+ '6' => 'Transaction Declined - Error Communicating with Bank',
13
+ '7' => 'Payment Server Processing Error - Typically caused by invalid input data such as an invalid credit card number. Processing errors can also occur',
14
+ '8' => 'Transaction Declined - Transaction Type Not Supported',
15
+ '9' => 'Bank Declined Transaction (Do not contact Bank)',
16
+ 'A' => 'Transaction Aborted',
17
+ 'C' => 'Transaction Cancelled',
18
+ 'D' => 'Deferred Transaction',
19
+ 'E' => 'Issuer Returned a Referral Response',
20
+ 'F' => '3D Secure Authentication Failed',
21
+ 'I' => 'Card Security Code Failed',
22
+ 'L' => 'Shopping Transaction Locked (This indicates that there is another transaction taking place using the same shopping transaction number)',
23
+ 'N' => 'Cardholder is not enrolled in 3D Secure (Authentication Only)',
24
+ 'P' => 'Transaction is Pending',
25
+ 'R' => 'Retry Limits Exceeded, Transaction Not Processed',
26
+ 'S' => 'Duplicate OrderInfo used. (This is only relevant for Payment Servers that enforce the uniqueness of this field)',
27
+ 'U' => 'Card Security Code Failed'
28
+ }
29
+
30
+ ISSUER_RESPONSE_CODES = {
31
+ '00' => 'Approved',
32
+ '01' => 'Refer to Card Issuer',
33
+ '02' => 'Refer to Card Issuer',
34
+ '03' => 'Invalid Merchant',
35
+ '04' => 'Pick Up Card',
36
+ '05' => 'Do Not Honor',
37
+ '07' => 'Pick Up Card',
38
+ '12' => 'Invalid Transaction',
39
+ '14' => 'Invalid Card Number (No such Number)',
40
+ '15' => 'No Such Issuer',
41
+ '33' => 'Expired Card',
42
+ '34' => 'Suspected Fraud',
43
+ '36' => 'Restricted Card',
44
+ '39' => 'No Credit Account',
45
+ '41' => 'Card Reported Lost',
46
+ '43' => 'Stolen Card',
47
+ '51' => 'Insufficient Funds',
48
+ '54' => 'Expired Card',
49
+ '57' => 'Transaction Not Permitted',
50
+ '59' => 'Suspected Fraud',
51
+ '62' => 'Restricted Card',
52
+ '65' => 'Exceeds withdrawal frequency limit',
53
+ '91' => 'Cannot Contact Issuer'
54
+ }
55
+
56
+ VERIFIED_3D_CODES = {
57
+ 'Y' => 'The cardholder was successfully authenticated.',
58
+ 'E' => 'The cardholder is not enrolled.',
59
+ 'N' => 'The cardholder was not verified.',
60
+ 'U' => 'The cardholder\'s Issuer was unable to authenticate due to a system error at the Issuer.',
61
+ 'F' => 'An error exists in the format of the request from the merchant. For example, the request did not contain all required fields, or the format of some fields was invalid.',
62
+ 'A' => 'Authentication of your Merchant ID and Password to the Directory Server Failed (see "What does a Payment Authentication Status of "A" mean?" on page 85).',
63
+ 'D' => 'Error communicating with the Directory Server, for example, the Payment Server could not connect to the directory server or there was a versioning mismatch.',
64
+ 'C' => 'The card type is not supported for authentication.',
65
+ 'M' => 'This indicates that attempts processing was used. Verification is marked with status M - ACS attempts processing used. Payment is performed with authentication. Attempts is when a cardholder has successfully passed the directory server but decides not to continue with the authentication process and cancels.',
66
+ 'S' => 'The signature on the response received from the Issuer could not be validated. This should be considered a failure.',
67
+ 'T' => 'ACS timed out. The Issuer\'s ACS did not respond to the Authentication request within the time out period.',
68
+ 'P' => 'Error parsing input from Issuer.',
69
+ 'I' => 'Internal Payment Server system error. This could be caused by a temporary DB failure or an error in the security module or by some error in an internal system.'
70
+ }
71
+
72
+ class CreditCardType
73
+ attr_accessor :am_code, :migs_code, :migs_long_code, :name
74
+ def initialize(am_code, migs_code, migs_long_code, name)
75
+ @am_code = am_code
76
+ @migs_code = migs_code
77
+ @migs_long_code = migs_long_code
78
+ @name = name
79
+ end
80
+ end
81
+
82
+ CARD_TYPES = [
83
+ # The following are 4 different representations of credit card types
84
+ # am_code: The active merchant code
85
+ # migs_code: Used in response for purchase/authorize/status
86
+ # migs_long_code: Used to pre-select card for server_purchase_url
87
+ # name: The nice display name
88
+ %w(american_express AE Amex American\ Express),
89
+ %w(diners_club DC Dinersclub Diners\ Club),
90
+ %w(jcb JC JCB JCB\ Card),
91
+ %w(maestro MS Maestro Maestro\ Card),
92
+ %w(master MC Mastercard MasterCard),
93
+ %w(na PL PrivateLabelCard Private\ Label\ Card),
94
+ %w(visa VC Visa Visa\ Card')
95
+ ].map do |am_code, migs_code, migs_long_code, name|
96
+ CreditCardType.new(am_code, migs_code, migs_long_code, name)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,37 @@
1
+ require 'active_merchant/billing/gateways/modern_payments_cim'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class ModernPaymentsGateway < Gateway
6
+ self.supported_countries = ModernPaymentsCimGateway.supported_countries
7
+ self.supported_cardtypes = ModernPaymentsCimGateway.supported_cardtypes
8
+ self.homepage_url = ModernPaymentsCimGateway.homepage_url
9
+ self.display_name = ModernPaymentsCimGateway.display_name
10
+
11
+ self.abstract_class = true
12
+
13
+ def initialize(options = {})
14
+ requires!(options, :login, :password)
15
+ super
16
+ end
17
+
18
+ def purchase(money, credit_card, options = {})
19
+ customer_response = cim.create_customer(options)
20
+ return customer_response unless customer_response.success?
21
+
22
+ customer_id = customer_response.params["create_customer_result"]
23
+
24
+ card_response = cim.modify_customer_credit_card(customer_id, credit_card)
25
+ return card_response unless card_response.success?
26
+
27
+ cim.authorize_credit_card_payment(customer_id, money)
28
+ end
29
+
30
+ private
31
+ def cim
32
+ @cim ||= ModernPaymentsCimGateway.new(@options)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,219 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class ModernPaymentsCimGateway < Gateway #:nodoc:
4
+ self.test_url = "https://secure.modpay.com/netservices/test/ModpayTest.asmx"
5
+ self.live_url = 'https://secure.modpay.com/ws/modpay.asmx'
6
+
7
+ LIVE_XMLNS = "https://secure.modpay.com/ws/"
8
+ TEST_XMLNS = "https://secure.modpay.com/netservices/test/"
9
+
10
+ self.supported_countries = ['US']
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
12
+ self.homepage_url = 'http://www.modpay.com'
13
+ self.display_name = 'Modern Payments'
14
+
15
+ SUCCESS_MESSAGE = "Transaction accepted"
16
+ FAILURE_MESSAGE = "Transaction failed"
17
+ ERROR_MESSAGE = "Transaction error"
18
+
19
+ PAYMENT_METHOD = {
20
+ :check => 1,
21
+ :credit_card => 2
22
+ }
23
+
24
+ def initialize(options = {})
25
+ requires!(options, :login, :password)
26
+ super
27
+ end
28
+
29
+ def create_customer(options = {})
30
+ post = {}
31
+ add_customer_data(post, options)
32
+ add_address(post, options)
33
+
34
+ commit('CreateCustomer', post)
35
+ end
36
+
37
+ def modify_customer_credit_card(customer_id, credit_card)
38
+ raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
39
+
40
+ post = {}
41
+ add_customer_id(post, customer_id)
42
+ add_credit_card(post, credit_card)
43
+
44
+ commit('ModifyCustomerCreditCard', post)
45
+ end
46
+
47
+ def authorize_credit_card_payment(customer_id, amount)
48
+ raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
49
+
50
+ post = {}
51
+ add_customer_id(post, customer_id)
52
+ add_amount(post, amount)
53
+
54
+ commit('AuthorizeCreditCardPayment', post)
55
+ end
56
+
57
+ def create_payment(customer_id, amount, options = {})
58
+ raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
59
+
60
+ post = {}
61
+ add_customer_id(post, customer_id)
62
+ add_amount(post, amount)
63
+ add_payment_details(post, options)
64
+
65
+ commit('CreatePayment', post)
66
+ end
67
+
68
+ private
69
+ def add_payment_details(post, options)
70
+ post[:pmtDate] = (options[:payment_date] || Time.now.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
71
+ post[:pmtType] = PAYMENT_METHOD[options[:payment_method] || :credit_card]
72
+ end
73
+
74
+ def add_amount(post, money)
75
+ post[:pmtAmount] = amount(money)
76
+ end
77
+
78
+ def add_customer_id(post, customer_id)
79
+ post[:custId] = customer_id
80
+ end
81
+
82
+ def add_customer_data(post, options)
83
+ post[:acctNum] = options[:customer]
84
+ end
85
+
86
+ def add_address(post, options)
87
+ address = options[:billing_address] || options[:address] || {}
88
+
89
+ if name = address[:name]
90
+ segments = name.split(' ')
91
+ post[:lastName] = segments.pop
92
+ post[:firstName] = segments.join(' ')
93
+ else
94
+ post[:firstName] = address[:first_name]
95
+ post[:lastName] = address[:last_name]
96
+ end
97
+
98
+ post[:address] = address[:address1]
99
+ post[:city] = address[:city]
100
+ post[:state] = address[:state]
101
+ post[:zip] = address[:zip]
102
+ post[:phone] = address[:phone]
103
+ post[:fax] = address[:fax]
104
+ post[:email] = options[:email]
105
+ end
106
+
107
+ def add_credit_card(post, credit_card)
108
+ post[:ccName] = credit_card.name
109
+ post[:ccNum] = credit_card.number
110
+ post[:expMonth] = credit_card.month
111
+ post[:expYear] = credit_card.year
112
+ end
113
+
114
+ def build_request(action, params)
115
+ xml = Builder::XmlMarkup.new :indent => 2
116
+ xml.instruct!
117
+ xml.tag! 'env:Envelope',
118
+ { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
119
+ 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
120
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' } do
121
+
122
+ xml.tag! 'env:Body' do
123
+ xml.tag! action, { "xmlns" => xmlns(action) } do
124
+ xml.tag! "clientId", @options[:login]
125
+ xml.tag! "clientCode", @options[:password]
126
+ params.each {|key, value| xml.tag! key, value }
127
+ end
128
+ end
129
+ end
130
+ xml.target!
131
+ end
132
+
133
+ def xmlns(action)
134
+ if test? && action == 'AuthorizeCreditCardPayment'
135
+ TEST_XMLNS
136
+ else
137
+ LIVE_XMLNS
138
+ end
139
+ end
140
+
141
+ def url(action)
142
+ if test? && action == 'AuthorizeCreditCardPayment'
143
+ self.test_url
144
+ else
145
+ self.live_url
146
+ end
147
+ end
148
+
149
+ def commit(action, params)
150
+ data = ssl_post(url(action), build_request(action, params),
151
+ { 'Content-Type' =>'text/xml; charset=utf-8',
152
+ 'SOAPAction' => "#{xmlns(action)}#{action}" }
153
+ )
154
+
155
+ response = parse(action, data)
156
+ Response.new(successful?(action, response), message_from(action, response), response,
157
+ :test => test?,
158
+ :authorization => authorization_from(action, response),
159
+ :avs_result => { :code => response[:avs_code] }
160
+ )
161
+ end
162
+
163
+ def authorization_from(action, response)
164
+ response[authorization_key(action)]
165
+ end
166
+
167
+ def authorization_key(action)
168
+ action == "AuthorizeCreditCardPayment" ? :trans_id : "#{action.underscore}_result".to_sym
169
+ end
170
+
171
+ def successful?(action, response)
172
+ key = authorization_key(action)
173
+
174
+ if key == :trans_id
175
+ response[:approved] == "true"
176
+ else
177
+ response[key].to_i > 0
178
+ end
179
+ end
180
+
181
+ def message_from(action, response)
182
+ if response[:faultcode]
183
+ ERROR_MESSAGE
184
+ elsif successful?(action, response)
185
+ SUCCESS_MESSAGE
186
+ else
187
+ FAILURE_MESSAGE
188
+ end
189
+ end
190
+
191
+ def parse(action, xml)
192
+ response = {}
193
+ response[:action] = action
194
+
195
+ xml = REXML::Document.new(xml)
196
+ if root = REXML::XPath.first(xml, "//#{action}Response")
197
+ root.elements.to_a.each do |node|
198
+ parse_element(response, node)
199
+ end
200
+ elsif root = REXML::XPath.first(xml, "//soap:Fault")
201
+ root.elements.to_a.each do |node|
202
+ response[node.name.underscore.to_sym] = node.text
203
+ end
204
+ end
205
+
206
+ response
207
+ end
208
+
209
+ def parse_element(response, node)
210
+ if node.has_elements?
211
+ node.elements.each{|e| parse_element(response, e) }
212
+ else
213
+ response[node.name.underscore.to_sym] = node.text.to_s.strip
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
219
+