From 08c3ec7dec024ae49e8b6d1bf51c27989295ac19 Mon Sep 17 00:00:00 2001 From: Skud Date: Fri, 31 May 2013 12:15:23 +1000 Subject: [PATCH] Vendored the activemerchant gem to help with testing We needed a bogus paypal gateway as per http://infotrope.net/2013/05/31/testing-paypal-express-with-activemerchants-bogusgateway-and-how-to-make-it-work/ Tests now pass usefully. --- Gemfile | 9 +- Gemfile.lock | 28 +- app/controllers/orders_controller.rb | 7 +- config/environments/test.rb | 4 +- spec/controllers/orders_controller_spec.rb | 11 + vendor/gems/active_utils-1.0.5/.gitignore | 5 + vendor/gems/active_utils-1.0.5/Gemfile | 3 + vendor/gems/active_utils-1.0.5/MIT-LICENSE | 20 + vendor/gems/active_utils-1.0.5/README.md | 15 + vendor/gems/active_utils-1.0.5/Rakefile | 13 + .../active_utils-1.0.5/active_utils.gemspec | 26 + .../active_utils-1.0.5/lib/active_utils.rb | 20 + .../lib/active_utils/common/connection.rb | 147 + .../lib/active_utils/common/country.rb | 328 + .../lib/active_utils/common/error.rb | 26 + .../common/network_connection_retries.rb | 58 + .../lib/active_utils/common/post_data.rb | 24 + .../lib/active_utils/common/posts_data.rb | 69 + .../common/requires_parameters.rb | 16 + .../lib/active_utils/common/utils.rb | 20 + .../lib/active_utils/common/validateable.rb | 81 + .../lib/active_utils/version.rb | 3 + .../active_utils-1.0.5/lib/certs/cacert.pem | 7815 +++++++++++++++++ .../active_utils-1.0.5/test/test_helper.rb | 12 + .../test/unit/connection_test.rb | 149 + .../test/unit/country_code_test.rb | 31 + .../test/unit/country_test.rb | 68 + .../unit/network_connection_retries_test.rb | 127 + .../test/unit/post_data_test.rb | 50 + .../test/unit/posts_data_test.rb | 35 + .../test/unit/utils_test.rb | 7 + .../test/unit/validateable_test.rb | 59 + vendor/gems/activemerchant-1.33.0/CHANGELOG | 1143 +++ .../gems/activemerchant-1.33.0/CONTRIBUTORS | 402 + vendor/gems/activemerchant-1.33.0/MIT-LICENSE | 20 + vendor/gems/activemerchant-1.33.0/README.md | 221 + .../activemerchant-1.33.0/gem-public_cert.pem | 20 + .../lib/active_merchant.rb | 63 + .../lib/active_merchant/billing.rb | 9 + .../lib/active_merchant/billing/avs_result.rb | 98 + .../lib/active_merchant/billing/base.rb | 56 + .../lib/active_merchant/billing/check.rb | 69 + .../active_merchant/billing/credit_card.rb | 278 + .../billing/credit_card_formatting.rb | 21 + .../billing/credit_card_methods.rb | 143 + .../lib/active_merchant/billing/cvv_result.rb | 38 + .../active_merchant/billing/expiry_date.rb | 34 + .../lib/active_merchant/billing/gateway.rb | 177 + .../lib/active_merchant/billing/gateways.rb | 17 + .../billing/gateways/authorize_net.rb | 724 ++ .../billing/gateways/authorize_net_cim.rb | 956 ++ .../billing/gateways/balanced.rb | 467 + .../billing/gateways/banwire.rb | 105 + .../billing/gateways/barclays_epdq.rb | 314 + .../billing/gateways/beanstream.rb | 169 + .../gateways/beanstream/beanstream_core.rb | 393 + .../billing/gateways/beanstream_interac.rb | 54 + .../billing/gateways/blue_pay.rb | 503 ++ .../active_merchant/billing/gateways/bogus.rb | 142 + .../billing/gateways/braintree.rb | 19 + .../gateways/braintree/braintree_common.rb | 9 + .../billing/gateways/braintree_blue.rb | 401 + .../billing/gateways/braintree_orange.rb | 19 + .../billing/gateways/card_save.rb | 23 + .../billing/gateways/card_stream.rb | 225 + .../billing/gateways/card_stream_modern.rb | 155 + .../active_merchant/billing/gateways/cc5.rb | 156 + .../billing/gateways/certo_direct.rb | 277 + .../billing/gateways/cyber_source.rb | 614 ++ .../billing/gateways/data_cash.rb | 591 ++ .../billing/gateways/efsnet.rb | 230 + .../billing/gateways/elavon.rb | 312 + .../active_merchant/billing/gateways/epay.rb | 275 + .../billing/gateways/evo_ca.rb | 308 + .../active_merchant/billing/gateways/eway.rb | 225 + .../billing/gateways/eway_managed.rb | 291 + .../billing/gateways/eway_rapid.rb | 300 + .../active_merchant/billing/gateways/exact.rb | 218 + .../billing/gateways/fat_zebra.rb | 152 + .../billing/gateways/federated_canada.rb | 167 + .../billing/gateways/finansbank.rb | 22 + .../billing/gateways/first_pay.rb | 176 + .../billing/gateways/firstdata_e4.rb | 314 + .../billing/gateways/garanti.rb | 257 + .../active_merchant/billing/gateways/hdfc.rb | 207 + .../billing/gateways/ideal/ideal_base.rb | 249 + .../billing/gateways/ideal/ideal_rabobank.pem | 13 + .../billing/gateways/ideal/ideal_response.rb | 29 + .../billing/gateways/ideal_rabobank.rb | 66 + .../billing/gateways/inspire.rb | 221 + .../billing/gateways/instapay.rb | 163 + .../billing/gateways/iridium.rb | 262 + .../billing/gateways/itransact.rb | 448 + .../billing/gateways/jetpay.rb | 275 + .../billing/gateways/linkpoint.rb | 447 + .../active_merchant/billing/gateways/litle.rb | 540 ++ .../billing/gateways/merchant_e_solutions.rb | 176 + .../billing/gateways/merchant_ware.rb | 323 + .../billing/gateways/merchant_warrior.rb | 190 + .../billing/gateways/mercury.rb | 272 + .../billing/gateways/metrics_global.rb | 322 + .../active_merchant/billing/gateways/migs.rb | 265 + .../billing/gateways/migs/migs_codes.rb | 100 + .../billing/gateways/modern_payments.rb | 37 + .../billing/gateways/modern_payments_cim.rb | 219 + .../billing/gateways/moneris.rb | 244 + .../billing/gateways/moneris_us.rb | 208 + .../billing/gateways/nab_transact.rb | 269 + .../billing/gateways/net_registry.rb | 193 + .../billing/gateways/netaxept.rb | 181 + .../billing/gateways/netbilling.rb | 197 + .../billing/gateways/netpay.rb | 223 + .../active_merchant/billing/gateways/nmi.rb | 13 + .../active_merchant/billing/gateways/ogone.rb | 424 + .../billing/gateways/optimal_payment.rb | 297 + .../billing/gateways/orbital.rb | 633 ++ .../billing/gateways/orbital/avs_result.rb | 93 + .../orbital/orbital_soft_descriptors.rb | 46 + .../billing/gateways/pay_gate_xml.rb | 261 + .../billing/gateways/pay_junction.rb | 396 + .../billing/gateways/pay_secure.rb | 119 + .../billing/gateways/paybox_direct.rb | 196 + .../billing/gateways/payflow.rb | 268 + .../gateways/payflow/payflow_common_api.rb | 210 + .../payflow/payflow_express_response.rb | 39 + .../gateways/payflow/payflow_response.rb | 13 + .../billing/gateways/payflow_express.rb | 224 + .../billing/gateways/payflow_express_uk.rb | 15 + .../billing/gateways/payflow_uk.rb | 21 + .../billing/gateways/payment_express.rb | 340 + .../billing/gateways/paymill.rb | 179 + .../billing/gateways/paypal.rb | 106 + .../gateways/paypal/paypal_common_api.rb | 654 ++ .../paypal/paypal_express_response.rb | 61 + .../gateways/paypal/paypal_recurring_api.rb | 248 + .../billing/gateways/paypal_bogus.rb | 53 + .../billing/gateways/paypal_ca.rb | 13 + .../billing/gateways/paypal_digital_goods.rb | 43 + .../billing/gateways/paypal_express.rb | 222 + .../billing/gateways/paypal_express_common.rb | 30 + .../billing/gateways/paystation.rb | 199 + .../billing/gateways/payway.rb | 207 + .../active_merchant/billing/gateways/pin.rb | 165 + .../billing/gateways/plugnpay.rb | 294 + .../billing/gateways/psigate.rb | 227 + .../billing/gateways/psl_card.rb | 303 + .../active_merchant/billing/gateways/qbms.rb | 292 + .../billing/gateways/quantum.rb | 276 + .../billing/gateways/quickpay.rb | 335 + .../billing/gateways/realex.rb | 303 + .../billing/gateways/redsys.rb | 394 + .../active_merchant/billing/gateways/sage.rb | 152 + .../billing/gateways/sage/sage_bankcard.rb | 93 + .../billing/gateways/sage/sage_core.rb | 114 + .../gateways/sage/sage_virtual_check.rb | 102 + .../billing/gateways/sage_pay.rb | 324 + .../billing/gateways/sallie_mae.rb | 143 + .../billing/gateways/samurai.rb | 118 + .../billing/gateways/secure_net.rb | 329 + .../billing/gateways/secure_pay.rb | 28 + .../billing/gateways/secure_pay_au.rb | 279 + .../billing/gateways/secure_pay_tech.rb | 112 + .../billing/gateways/skip_jack.rb | 453 + .../billing/gateways/smart_ps.rb | 272 + .../billing/gateways/spreedly_core.rb | 233 + .../billing/gateways/stripe.rb | 255 + .../billing/gateways/trans_first.rb | 126 + .../billing/gateways/transax.rb | 23 + .../billing/gateways/transnational.rb | 239 + .../billing/gateways/trust_commerce.rb | 421 + .../billing/gateways/usa_epay.rb | 25 + .../billing/gateways/usa_epay_advanced.rb | 1501 ++++ .../billing/gateways/usa_epay_transaction.rb | 201 + .../billing/gateways/verifi.rb | 232 + .../billing/gateways/viaklix.rb | 189 + .../billing/gateways/vindicia.rb | 361 + .../billing/gateways/webpay.rb | 53 + .../billing/gateways/wirecard.rb | 313 + .../billing/gateways/worldpay.rb | 302 + .../active_merchant/billing/integrations.rb | 17 + .../billing/integrations/a1agregator.rb | 26 + .../integrations/a1agregator/helper.rb | 31 + .../integrations/a1agregator/notification.rb | 186 + .../integrations/a1agregator/status.rb | 38 + .../integrations/action_view_helper.rb | 73 + .../billing/integrations/authorize_net_sim.rb | 38 + .../integrations/authorize_net_sim/helper.rb | 228 + .../authorize_net_sim/notification.rb | 340 + .../billing/integrations/bogus.rb | 23 + .../billing/integrations/bogus/helper.rb | 17 + .../integrations/bogus/notification.rb | 11 + .../billing/integrations/bogus/return.rb | 10 + .../billing/integrations/chronopay.rb | 23 + .../billing/integrations/chronopay/helper.rb | 120 + .../integrations/chronopay/notification.rb | 158 + .../billing/integrations/chronopay/return.rb | 10 + .../billing/integrations/direc_pay.rb | 41 + .../billing/integrations/direc_pay/helper.rb | 200 + .../integrations/direc_pay/notification.rb | 76 + .../billing/integrations/direc_pay/return.rb | 32 + .../billing/integrations/direc_pay/status.rb | 37 + .../billing/integrations/directebanking.rb | 47 + .../integrations/directebanking/helper.rb | 90 + .../directebanking/notification.rb | 120 + .../integrations/directebanking/return.rb | 11 + .../billing/integrations/dotpay.rb | 22 + .../billing/integrations/dotpay/helper.rb | 77 + .../integrations/dotpay/notification.rb | 86 + .../billing/integrations/dotpay/return.rb | 11 + .../billing/integrations/dwolla.rb | 23 + .../billing/integrations/dwolla/common.rb | 21 + .../billing/integrations/dwolla/helper.rb | 40 + .../integrations/dwolla/notification.rb | 60 + .../billing/integrations/dwolla/return.rb | 46 + .../billing/integrations/e_payment_plans.rb | 48 + .../integrations/e_payment_plans/helper.rb | 34 + .../e_payment_plans/notification.rb | 84 + .../billing/integrations/easy_pay.rb | 30 + .../billing/integrations/easy_pay/common.rb | 40 + .../billing/integrations/easy_pay/helper.rb | 36 + .../integrations/easy_pay/notification.rb | 59 + .../billing/integrations/epay.rb | 21 + .../billing/integrations/epay/helper.rb | 55 + .../billing/integrations/epay/notification.rb | 110 + .../billing/integrations/first_data.rb | 38 + .../billing/integrations/first_data/helper.rb | 63 + .../integrations/first_data/notification.rb | 56 + .../billing/integrations/gestpay.rb | 25 + .../billing/integrations/gestpay/common.rb | 42 + .../billing/integrations/gestpay/helper.rb | 70 + .../integrations/gestpay/notification.rb | 85 + .../billing/integrations/gestpay/return.rb | 10 + .../billing/integrations/helper.rb | 117 + .../billing/integrations/hi_trust.rb | 27 + .../billing/integrations/hi_trust/helper.rb | 58 + .../integrations/hi_trust/notification.rb | 59 + .../billing/integrations/hi_trust/return.rb | 67 + .../billing/integrations/liqpay.rb | 30 + .../billing/integrations/liqpay/helper.rb | 43 + .../integrations/liqpay/notification.rb | 89 + .../billing/integrations/liqpay/return.rb | 83 + .../billing/integrations/maksuturva.rb | 86 + .../billing/integrations/maksuturva/helper.rb | 119 + .../integrations/maksuturva/notification.rb | 48 + .../billing/integrations/moneybookers.rb | 26 + .../integrations/moneybookers/helper.rb | 75 + .../integrations/moneybookers/notification.rb | 129 + .../billing/integrations/nochex.rb | 88 + .../billing/integrations/nochex/helper.rb | 68 + .../integrations/nochex/notification.rb | 94 + .../billing/integrations/nochex/return.rb | 10 + .../billing/integrations/notification.rb | 71 + .../billing/integrations/paxum.rb | 44 + .../billing/integrations/paxum/common.rb | 24 + .../billing/integrations/paxum/helper.rb | 42 + .../integrations/paxum/notification.rb | 33 + .../billing/integrations/pay_fast.rb | 70 + .../billing/integrations/pay_fast/common.rb | 42 + .../billing/integrations/pay_fast/helper.rb | 50 + .../integrations/pay_fast/notification.rb | 134 + .../billing/integrations/pay_fast/return.rb | 10 + .../billing/integrations/payflow_link.rb | 21 + .../integrations/payflow_link/helper.rb | 116 + .../integrations/payflow_link/notification.rb | 78 + .../billing/integrations/paypal.rb | 39 + .../billing/integrations/paypal/helper.rb | 119 + .../integrations/paypal/notification.rb | 227 + .../billing/integrations/paypal/return.rb | 10 + .../integrations/paypal_payments_advanced.rb | 20 + .../paypal_payments_advanced/helper.rb | 15 + .../billing/integrations/paysbuy.rb | 36 + .../billing/integrations/paysbuy/helper.rb | 15 + .../integrations/paysbuy/notification.rb | 28 + .../billing/integrations/payu_in.rb | 43 + .../billing/integrations/payu_in/helper.rb | 74 + .../integrations/payu_in/notification.rb | 167 + .../billing/integrations/payu_in/return.rb | 53 + .../billing/integrations/pxpay.rb | 31 + .../billing/integrations/pxpay/helper.rb | 111 + .../integrations/pxpay/notification.rb | 157 + .../billing/integrations/pxpay/return.rb | 25 + .../billing/integrations/quickpay.rb | 21 + .../billing/integrations/quickpay/helper.rb | 74 + .../integrations/quickpay/notification.rb | 137 + .../billing/integrations/rbkmoney.rb | 17 + .../billing/integrations/rbkmoney/helper.rb | 23 + .../integrations/rbkmoney/notification.rb | 91 + .../billing/integrations/return.rb | 42 + .../billing/integrations/robokassa.rb | 49 + .../billing/integrations/robokassa/common.rb | 19 + .../billing/integrations/robokassa/helper.rb | 50 + .../integrations/robokassa/notification.rb | 55 + .../billing/integrations/robokassa/return.rb | 17 + .../billing/integrations/sage_pay_form.rb | 37 + .../integrations/sage_pay_form/encryption.rb | 33 + .../integrations/sage_pay_form/helper.rb | 136 + .../sage_pay_form/notification.rb | 210 + .../integrations/sage_pay_form/return.rb | 31 + .../billing/integrations/two_checkout.rb | 44 + .../integrations/two_checkout/helper.rb | 91 + .../integrations/two_checkout/notification.rb | 139 + .../integrations/two_checkout/return.rb | 17 + .../billing/integrations/valitor.rb | 33 + .../billing/integrations/valitor/helper.rb | 86 + .../integrations/valitor/notification.rb | 13 + .../integrations/valitor/response_fields.rb | 97 + .../billing/integrations/valitor/return.rb | 13 + .../billing/integrations/verkkomaksut.rb | 20 + .../integrations/verkkomaksut/helper.rb | 87 + .../integrations/verkkomaksut/notification.rb | 59 + .../billing/integrations/web_pay.rb | 45 + .../billing/integrations/web_pay/common.rb | 50 + .../billing/integrations/web_pay/helper.rb | 68 + .../integrations/web_pay/notification.rb | 51 + .../billing/integrations/webmoney.rb | 43 + .../billing/integrations/webmoney/common.rb | 17 + .../billing/integrations/webmoney/helper.rb | 39 + .../integrations/webmoney/notification.rb | 43 + .../billing/integrations/world_pay.rb | 34 + .../billing/integrations/world_pay/helper.rb | 100 + .../integrations/world_pay/notification.rb | 160 + .../lib/active_merchant/billing/response.rb | 77 + .../lib/active_merchant/version.rb | 3 + .../lib/activemerchant.rb | 1 + .../lib/support/gateway_support.rb | 65 + .../lib/support/outbound_hosts.rb | 25 + .../lib/support/ssl_verify.rb | 93 + 327 files changed, 52355 insertions(+), 18 deletions(-) create mode 100644 vendor/gems/active_utils-1.0.5/.gitignore create mode 100644 vendor/gems/active_utils-1.0.5/Gemfile create mode 100644 vendor/gems/active_utils-1.0.5/MIT-LICENSE create mode 100644 vendor/gems/active_utils-1.0.5/README.md create mode 100644 vendor/gems/active_utils-1.0.5/Rakefile create mode 100644 vendor/gems/active_utils-1.0.5/active_utils.gemspec create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/connection.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/country.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/error.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/network_connection_retries.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/post_data.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/posts_data.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/requires_parameters.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/utils.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/common/validateable.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/active_utils/version.rb create mode 100644 vendor/gems/active_utils-1.0.5/lib/certs/cacert.pem create mode 100644 vendor/gems/active_utils-1.0.5/test/test_helper.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/connection_test.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/country_code_test.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/country_test.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/network_connection_retries_test.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/post_data_test.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/posts_data_test.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/utils_test.rb create mode 100644 vendor/gems/active_utils-1.0.5/test/unit/validateable_test.rb create mode 100644 vendor/gems/activemerchant-1.33.0/CHANGELOG create mode 100644 vendor/gems/activemerchant-1.33.0/CONTRIBUTORS create mode 100644 vendor/gems/activemerchant-1.33.0/MIT-LICENSE create mode 100644 vendor/gems/activemerchant-1.33.0/README.md create mode 100644 vendor/gems/activemerchant-1.33.0/gem-public_cert.pem create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/avs_result.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/base.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/check.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_formatting.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_methods.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/cvv_result.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/expiry_date.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateway.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net_cim.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/balanced.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/banwire.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/barclays_epdq.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream_interac.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/blue_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/bogus.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree/braintree_common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_blue.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_orange.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_save.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream_modern.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cc5.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/certo_direct.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cyber_source.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/data_cash.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/efsnet.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/elavon.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/epay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/evo_ca.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_managed.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_rapid.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/exact.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/fat_zebra.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/federated_canada.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/finansbank.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/first_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/firstdata_e4.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/garanti.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/hdfc.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_base.rb create mode 100755 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_response.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal_rabobank.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/inspire.rb create mode 100755 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/instapay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/iridium.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/itransact.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/jetpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/linkpoint.rb create mode 100755 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/litle.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_e_solutions.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_ware.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_warrior.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/mercury.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/metrics_global.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs/migs_codes.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments_cim.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris_us.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nab_transact.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/net_registry.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netaxept.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netbilling.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nmi.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ogone.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/optimal_payment.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/avs_result.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_gate_xml.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_junction.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_secure.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paybox_direct.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_response.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express_uk.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_uk.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payment_express.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paymill.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_bogus.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_ca.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_digital_goods.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express_common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paystation.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payway.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pin.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/plugnpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psigate.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psl_card.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/qbms.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quantum.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quickpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/realex.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/redsys.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_core.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sallie_mae.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/samurai.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_net.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_au.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_tech.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/skip_jack.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/smart_ps.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/spreedly_core.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/stripe.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trans_first.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transax.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transnational.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trust_commerce.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_advanced.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_transaction.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/verifi.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/viaklix.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/vindicia.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/webpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/wirecard.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/worldpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/status.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/action_view_helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/status.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/notification.rb create mode 100755 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in.rb create mode 100755 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/helper.rb create mode 100755 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/notification.rb create mode 100755 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/response_fields.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/return.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/common.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/helper.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/notification.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/response.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/active_merchant/version.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/activemerchant.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/support/gateway_support.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/support/outbound_hosts.rb create mode 100644 vendor/gems/activemerchant-1.33.0/lib/support/ssl_verify.rb diff --git a/Gemfile b/Gemfile index d8d5911e2..0a2115ddc 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,14 @@ gem 'haml' gem 'cancan' -gem 'activemerchant' +# vendored activemerchant for testing- needed for bogus paypal +# gateway monkeypatch +gem 'activemerchant', '1.33.0', + :path => 'vendor/gems/activemerchant-1.33.0', + :require => 'active_merchant' +gem 'active_utils', '1.0.5', + :path => 'vendor/gems/active_utils-1.0.5' + # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' diff --git a/Gemfile.lock b/Gemfile.lock index 8a2ad9de5..9bc276930 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,15 @@ +PATH + remote: vendor/gems/active_utils-1.0.5 + specs: + active_utils (1.0.5) + activesupport (>= 2.3.11) + i18n + +PATH + remote: vendor/gems/activemerchant-1.33.0 + specs: + activemerchant (1.33.0) + GEM remote: https://rubygems.org/ specs: @@ -14,17 +26,6 @@ GEM rack-cache (~> 1.2) rack-test (~> 0.6.1) sprockets (~> 2.2.1) - active_utils (1.0.5) - activesupport (>= 2.3.11) - i18n - activemerchant (1.32.1) - active_utils (>= 1.0.2) - activesupport (>= 2.3.14) - builder (>= 2.0.0) - i18n - json (>= 1.5.1) - money - nokogiri activemodel (3.2.13) activesupport (= 3.2.13) builder (~> 3.0.0) @@ -127,8 +128,6 @@ GEM mime-types (~> 1.16) treetop (~> 1.4.8) mime-types (1.21) - money (5.1.1) - i18n (~> 0.6.0) multi_json (1.7.1) net-scp (1.1.0) net-ssh (>= 2.6.5) @@ -245,7 +244,8 @@ PLATFORMS ruby DEPENDENCIES - activemerchant + active_utils (= 1.0.5)! + activemerchant (= 1.33.0)! bluecloth bootstrap-datepicker-rails bundler (>= 1.1.5) diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index efc21acaf..f1ef42906 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -51,7 +51,12 @@ class OrdersController < ApplicationController @order.completed_at = Time.zone.now @order.save - @order.record_paypal_details(params[:token]) + if (params[:token]) + @order.record_paypal_details(params[:token]) + else + flash[:alert] = "PayPal didn't return a token for your order. Please notify support." + end + @order.update_account # apply paid account benefits, etc. respond_to do |format| diff --git a/config/environments/test.rb b/config/environments/test.rb index e570d4630..6718e2e84 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -48,8 +48,8 @@ Growstuff::Application.configure do config.after_initialize do ActiveMerchant::Billing::Base.mode = :test - ::STANDARD_GATEWAY = ActiveMerchant::Billing::BogusGateway.new - ::EXPRESS_GATEWAY = ActiveMerchant::Billing::BogusGateway.new + ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalBogusGateway.new + ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalBogusGateway.new end end diff --git a/spec/controllers/orders_controller_spec.rb b/spec/controllers/orders_controller_spec.rb index 3d209f8e4..75e7b4346 100644 --- a/spec/controllers/orders_controller_spec.rb +++ b/spec/controllers/orders_controller_spec.rb @@ -32,6 +32,17 @@ describe OrdersController do end end + describe "GET checkout" do + it "redirects to Paypal" do + member = FactoryGirl.create(:member) + sign_in member + order = Order.create!(:member_id => member.id) + get :checkout, {:id => order.to_param} + response.status.should eq 302 + response.redirect_url.should match /paypal\.com/ + end + end + describe "GET complete" do it "assigns the requested order as @order" do member = FactoryGirl.create(:member) diff --git a/vendor/gems/active_utils-1.0.5/.gitignore b/vendor/gems/active_utils-1.0.5/.gitignore new file mode 100644 index 000000000..2ac8271fc --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/.gitignore @@ -0,0 +1,5 @@ +pkg/* +*.gem +.bundle +.DS_Store +Gemfile.lock diff --git a/vendor/gems/active_utils-1.0.5/Gemfile b/vendor/gems/active_utils-1.0.5/Gemfile new file mode 100644 index 000000000..c80ee3697 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/Gemfile @@ -0,0 +1,3 @@ +source "http://rubygems.org" + +gemspec diff --git a/vendor/gems/active_utils-1.0.5/MIT-LICENSE b/vendor/gems/active_utils-1.0.5/MIT-LICENSE new file mode 100644 index 000000000..29230683b --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011 Shopify + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gems/active_utils-1.0.5/README.md b/vendor/gems/active_utils-1.0.5/README.md new file mode 100644 index 000000000..d942d0aab --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/README.md @@ -0,0 +1,15 @@ +# Active Utils + +Active Utils extracts commonly used modules and classes used by [Active Merchant](http://github.com/Shopify/active_merchant), [Active Shipping](http://github.com/Shopify/active_shipping), and [Active Fulfillment](http://github.com/Shopify/active_fulfillment). + +### Includes + +* Connection - base class for making HTTP requests +* Country - find countries mapped by name, country codes, and numeric values +* Error - common error classes used throughout the Active projects +* PostData - helper class for managing required fields that are to be POST-ed +* PostsData - making SSL HTTP requests +* RequiresParameters - helper method to ensure the required parameters are passed in +* Utils - common utils such as uid generator +* Validateable - module used for making models validateable +* NetworkConnectionRetries - module for retrying network connections when connection errors occur diff --git a/vendor/gems/active_utils-1.0.5/Rakefile b/vendor/gems/active_utils-1.0.5/Rakefile new file mode 100644 index 000000000..0389bb0a8 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/Rakefile @@ -0,0 +1,13 @@ +require 'bundler' +Bundler::GemHelper.install_tasks + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.pattern = 'test/unit/**/*_test.rb' + t.ruby_opts << '-rubygems' + t.libs << 'test' + t.verbose = true +end + +task :default => "test" diff --git a/vendor/gems/active_utils-1.0.5/active_utils.gemspec b/vendor/gems/active_utils-1.0.5/active_utils.gemspec new file mode 100644 index 000000000..6e887da9b --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/active_utils.gemspec @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require "active_utils/version" + +Gem::Specification.new do |s| + s.name = "active_utils" + s.version = ActiveUtils::VERSION + s.platform = Gem::Platform::RUBY + s.authors = ["Shopify"] + s.email = ["developers@jadedpixel.com"] + s.homepage = "http://github.com/shopify/active_utils" + s.summary = %q{Common utils used by active_merchant, active_fulfillment, and active_shipping} + + s.rubyforge_project = "active_utils" + + s.add_dependency('activesupport', '>= 2.3.11') + s.add_dependency('i18n') + + s.add_development_dependency('rake') + s.add_development_dependency('mocha') + + s.files = `git ls-files`.split("\n") + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } + s.require_paths = ["lib"] +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils.rb new file mode 100644 index 000000000..86665aa77 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils.rb @@ -0,0 +1,20 @@ +require 'active_support/core_ext/hash/indifferent_access' +require 'active_support/core_ext/hash/conversions' +require 'active_support/core_ext/class/attribute' + +module ActiveMerchant + autoload :NetworkConnectionRetries, 'active_utils/common/network_connection_retries' + autoload :Connection, 'active_utils/common/connection' + autoload :Country, 'active_utils/common/country' + autoload :CountryCode, 'active_utils/common/country' + autoload :ActiveMerchantError, 'active_utils/common/error' + autoload :ConnectionError, 'active_utils/common/error' + autoload :RetriableConnectionError, 'active_utils/common/error' + autoload :ResponseError, 'active_utils/common/error' + autoload :ClientCertificateError, 'active_utils/common/error' + autoload :PostData, 'active_utils/common/post_data' + autoload :PostsData, 'active_utils/common/posts_data' + autoload :RequiresParameters, 'active_utils/common/requires_parameters' + autoload :Utils, 'active_utils/common/utils' + autoload :Validateable, 'active_utils/common/validateable' +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/connection.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/connection.rb new file mode 100644 index 000000000..8f3300159 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/connection.rb @@ -0,0 +1,147 @@ +require 'uri' +require 'net/http' +require 'net/https' +require 'benchmark' + +module ActiveMerchant + class Connection + include NetworkConnectionRetries + + MAX_RETRIES = 3 + OPEN_TIMEOUT = 60 + READ_TIMEOUT = 60 + VERIFY_PEER = true + RETRY_SAFE = false + RUBY_184_POST_HEADERS = { "Content-Type" => "application/x-www-form-urlencoded" } + + attr_accessor :endpoint + attr_accessor :open_timeout + attr_accessor :read_timeout + attr_accessor :verify_peer + attr_accessor :pem + attr_accessor :pem_password + attr_accessor :wiredump_device + attr_accessor :logger + attr_accessor :tag + attr_accessor :ignore_http_status + + def initialize(endpoint) + @endpoint = endpoint.is_a?(URI) ? endpoint : URI.parse(endpoint) + @open_timeout = OPEN_TIMEOUT + @read_timeout = READ_TIMEOUT + @retry_safe = RETRY_SAFE + @verify_peer = VERIFY_PEER + @ignore_http_status = false + end + + def request(method, body, headers = {}) + retry_exceptions(:max_retries => MAX_RETRIES, :logger => logger, :tag => tag) do + begin + info "#{method.to_s.upcase} #{endpoint}", tag + + result = nil + + realtime = Benchmark.realtime do + result = case method + when :get + raise ArgumentError, "GET requests do not support a request body" if body + http.get(endpoint.request_uri, headers) + when :post + debug body + http.post(endpoint.request_uri, body, RUBY_184_POST_HEADERS.merge(headers)) + when :put + debug body + http.put(endpoint.request_uri, body, headers) + when :delete + # It's kind of ambiguous whether the RFC allows bodies + # for DELETE requests. But Net::HTTP's delete method + # very unambiguously does not. + raise ArgumentError, "DELETE requests do not support a request body" if body + http.delete(endpoint.request_uri, headers) + else + raise ArgumentError, "Unsupported request method #{method.to_s.upcase}" + end + end + + info "--> %d %s (%d %.4fs)" % [result.code, result.message, result.body ? result.body.length : 0, realtime], tag + debug result.body + result + end + end + end + + private + def http + http = Net::HTTP.new(endpoint.host, endpoint.port) + configure_debugging(http) + configure_timeouts(http) + configure_ssl(http) + configure_cert(http) + http + end + + def configure_debugging(http) + http.set_debug_output(wiredump_device) + end + + def configure_timeouts(http) + http.open_timeout = open_timeout + http.read_timeout = read_timeout + end + + def configure_ssl(http) + return unless endpoint.scheme == "https" + + http.use_ssl = true + + if verify_peer + http.verify_mode = OpenSSL::SSL::VERIFY_PEER + http.ca_file = File.dirname(__FILE__) + '/../../certs/cacert.pem' + else + http.verify_mode = OpenSSL::SSL::VERIFY_NONE + end + end + + def configure_cert(http) + return if pem.blank? + + http.cert = OpenSSL::X509::Certificate.new(pem) + + if pem_password + http.key = OpenSSL::PKey::RSA.new(pem, pem_password) + else + http.key = OpenSSL::PKey::RSA.new(pem) + end + end + + def handle_response(response) + if @ignore_http_status then + return response.body + else + case response.code.to_i + when 200...300 + response.body + else + raise ResponseError.new(response) + end + end + end + + def debug(message, tag = nil) + log(:debug, message, tag) + end + + def info(message, tag = nil) + log(:info, message, tag) + end + + def error(message, tag = nil) + log(:error, message, tag) + end + + def log(level, message, tag) + message = "[#{tag}] #{message}" if tag + logger.send(level, message) if logger + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/country.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/country.rb new file mode 100644 index 000000000..a2ed3a310 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/country.rb @@ -0,0 +1,328 @@ +#!ruby19 +# encoding: utf-8 + +module ActiveMerchant #:nodoc: + class InvalidCountryCodeError < StandardError + end + + class CountryCodeFormatError < StandardError + end + + class CountryCode + attr_reader :value, :format + def initialize(value) + @value = value.to_s.upcase + detect_format + end + + def to_s + value + end + + private + + def detect_format + case @value + when /^[[:alpha:]]{2}$/ + @format = :alpha2 + when /^[[:alpha:]]{3}$/ + @format = :alpha3 + when /^[[:digit:]]{3}$/ + @format = :numeric + else + raise CountryCodeFormatError, "The country code is not formatted correctly #{@value}" + end + end + end + + class Country + include RequiresParameters + attr_reader :name + + def initialize(options = {}) + requires!(options, :name, :alpha2, :alpha3, :numeric) + @name = options.delete(:name) + @codes = options.collect{|k,v| CountryCode.new(v)} + end + + def code(format) + @codes.detect{|c| c.format == format} + end + + def ==(other) + (@name == other.name) + end + alias eql? == + + def hash + @name.hash + end + + def to_s + @name + end + + COUNTRIES = [ + { :alpha2 => 'AF', :name => 'Afghanistan', :alpha3 => 'AFG', :numeric => '004' }, + { :alpha2 => 'AL', :name => 'Albania', :alpha3 => 'ALB', :numeric => '008' }, + { :alpha2 => 'DZ', :name => 'Algeria', :alpha3 => 'DZA', :numeric => '012' }, + { :alpha2 => 'AS', :name => 'American Samoa', :alpha3 => 'ASM', :numeric => '016' }, + { :alpha2 => 'AD', :name => 'Andorra', :alpha3 => 'AND', :numeric => '020' }, + { :alpha2 => 'AO', :name => 'Angola', :alpha3 => 'AGO', :numeric => '024' }, + { :alpha2 => 'AI', :name => 'Anguilla', :alpha3 => 'AIA', :numeric => '660' }, + { :alpha2 => 'AG', :name => 'Antigua and Barbuda', :alpha3 => 'ATG', :numeric => '028' }, + { :alpha2 => 'AR', :name => 'Argentina', :alpha3 => 'ARG', :numeric => '032' }, + { :alpha2 => 'AM', :name => 'Armenia', :alpha3 => 'ARM', :numeric => '051' }, + { :alpha2 => 'AW', :name => 'Aruba', :alpha3 => 'ABW', :numeric => '533' }, + { :alpha2 => 'AU', :name => 'Australia', :alpha3 => 'AUS', :numeric => '036' }, + { :alpha2 => 'AT', :name => 'Austria', :alpha3 => 'AUT', :numeric => '040' }, + { :alpha2 => 'AZ', :name => 'Azerbaijan', :alpha3 => 'AZE', :numeric => '031' }, + { :alpha2 => 'BS', :name => 'Bahamas', :alpha3 => 'BHS', :numeric => '044' }, + { :alpha2 => 'BH', :name => 'Bahrain', :alpha3 => 'BHR', :numeric => '048' }, + { :alpha2 => 'BD', :name => 'Bangladesh', :alpha3 => 'BGD', :numeric => '050' }, + { :alpha2 => 'BB', :name => 'Barbados', :alpha3 => 'BRB', :numeric => '052' }, + { :alpha2 => 'BY', :name => 'Belarus', :alpha3 => 'BLR', :numeric => '112' }, + { :alpha2 => 'BE', :name => 'Belgium', :alpha3 => 'BEL', :numeric => '056' }, + { :alpha2 => 'BZ', :name => 'Belize', :alpha3 => 'BLZ', :numeric => '084' }, + { :alpha2 => 'BJ', :name => 'Benin', :alpha3 => 'BEN', :numeric => '204' }, + { :alpha2 => 'BM', :name => 'Bermuda', :alpha3 => 'BMU', :numeric => '060' }, + { :alpha2 => 'BT', :name => 'Bhutan', :alpha3 => 'BTN', :numeric => '064' }, + { :alpha2 => 'BO', :name => 'Bolivia', :alpha3 => 'BOL', :numeric => '068' }, + { :alpha2 => 'BA', :name => 'Bosnia and Herzegovina', :alpha3 => 'BIH', :numeric => '070' }, + { :alpha2 => 'BW', :name => 'Botswana', :alpha3 => 'BWA', :numeric => '072' }, + { :alpha2 => 'BV', :name => 'Bouvet Island', :alpha3 => 'BVD', :numeric => '074' }, + { :alpha2 => 'BR', :name => 'Brazil', :alpha3 => 'BRA', :numeric => '076' }, + { :alpha2 => 'IO', :name => 'British Indian Ocean Territory', :alpha3 => 'IOT', :numeric => '086' }, + { :alpha2 => 'BN', :name => 'Brunei Darussalam', :alpha3 => 'BRN', :numeric => '096' }, + { :alpha2 => 'BG', :name => 'Bulgaria', :alpha3 => 'BGR', :numeric => '100' }, + { :alpha2 => 'BF', :name => 'Burkina Faso', :alpha3 => 'BFA', :numeric => '854' }, + { :alpha2 => 'BI', :name => 'Burundi', :alpha3 => 'BDI', :numeric => '108' }, + { :alpha2 => 'KH', :name => 'Cambodia', :alpha3 => 'KHM', :numeric => '116' }, + { :alpha2 => 'CM', :name => 'Cameroon', :alpha3 => 'CMR', :numeric => '120' }, + { :alpha2 => 'CA', :name => 'Canada', :alpha3 => 'CAN', :numeric => '124' }, + { :alpha2 => 'CV', :name => 'Cape Verde', :alpha3 => 'CPV', :numeric => '132' }, + { :alpha2 => 'KY', :name => 'Cayman Islands', :alpha3 => 'CYM', :numeric => '136' }, + { :alpha2 => 'CF', :name => 'Central African Republic', :alpha3 => 'CAF', :numeric => '140' }, + { :alpha2 => 'TD', :name => 'Chad', :alpha3 => 'TCD', :numeric => '148' }, + { :alpha2 => 'CL', :name => 'Chile', :alpha3 => 'CHL', :numeric => '152' }, + { :alpha2 => 'CN', :name => 'China', :alpha3 => 'CHN', :numeric => '156' }, + { :alpha2 => 'CX', :name => 'Christmas Island', :alpha3 => 'CXR', :numeric => '162' }, + { :alpha2 => 'CC', :name => 'Cocos (Keeling) Islands', :alpha3 => 'CCK', :numeric => '166' }, + { :alpha2 => 'CO', :name => 'Colombia', :alpha3 => 'COL', :numeric => '170' }, + { :alpha2 => 'KM', :name => 'Comoros', :alpha3 => 'COM', :numeric => '174' }, + { :alpha2 => 'CG', :name => 'Congo', :alpha3 => 'COG', :numeric => '178' }, + { :alpha2 => 'CD', :name => 'Congo, the Democratic Republic of the', :alpha3 => 'COD', :numeric => '180' }, + { :alpha2 => 'CK', :name => 'Cook Islands', :alpha3 => 'COK', :numeric => '184' }, + { :alpha2 => 'CR', :name => 'Costa Rica', :alpha3 => 'CRI', :numeric => '188' }, + { :alpha2 => 'CI', :name => 'Cote D\'Ivoire', :alpha3 => 'CIV', :numeric => '384' }, + { :alpha2 => 'HR', :name => 'Croatia', :alpha3 => 'HRV', :numeric => '191' }, + { :alpha2 => 'CU', :name => 'Cuba', :alpha3 => 'CUB', :numeric => '192' }, + { :alpha2 => 'CY', :name => 'Cyprus', :alpha3 => 'CYP', :numeric => '196' }, + { :alpha2 => 'CZ', :name => 'Czech Republic', :alpha3 => 'CZE', :numeric => '203' }, + { :alpha2 => 'DK', :name => 'Denmark', :alpha3 => 'DNK', :numeric => '208' }, + { :alpha2 => 'DJ', :name => 'Djibouti', :alpha3 => 'DJI', :numeric => '262' }, + { :alpha2 => 'DM', :name => 'Dominica', :alpha3 => 'DMA', :numeric => '212' }, + { :alpha2 => 'DO', :name => 'Dominican Republic', :alpha3 => 'DOM', :numeric => '214' }, + { :alpha2 => 'EC', :name => 'Ecuador', :alpha3 => 'ECU', :numeric => '218' }, + { :alpha2 => 'EG', :name => 'Egypt', :alpha3 => 'EGY', :numeric => '818' }, + { :alpha2 => 'SV', :name => 'El Salvador', :alpha3 => 'SLV', :numeric => '222' }, + { :alpha2 => 'GQ', :name => 'Equatorial Guinea', :alpha3 => 'GNQ', :numeric => '226' }, + { :alpha2 => 'ER', :name => 'Eritrea', :alpha3 => 'ERI', :numeric => '232' }, + { :alpha2 => 'EE', :name => 'Estonia', :alpha3 => 'EST', :numeric => '233' }, + { :alpha2 => 'ET', :name => 'Ethiopia', :alpha3 => 'ETH', :numeric => '231' }, + { :alpha2 => 'FK', :name => 'Falkland Islands (Malvinas)', :alpha3 => 'FLK', :numeric => '238' }, + { :alpha2 => 'FO', :name => 'Faroe Islands', :alpha3 => 'FRO', :numeric => '234' }, + { :alpha2 => 'FJ', :name => 'Fiji', :alpha3 => 'FJI', :numeric => '242' }, + { :alpha2 => 'FI', :name => 'Finland', :alpha3 => 'FIN', :numeric => '246' }, + { :alpha2 => 'FR', :name => 'France', :alpha3 => 'FRA', :numeric => '250' }, + { :alpha2 => 'GF', :name => 'French Guiana', :alpha3 => 'GUF', :numeric => '254' }, + { :alpha2 => 'PF', :name => 'French Polynesia', :alpha3 => 'PYF', :numeric => '258' }, + { :alpha2 => 'TF', :name => 'French Southern Territories', :alpha3 => 'ATF', :numeric => '260' }, + { :alpha2 => 'GA', :name => 'Gabon', :alpha3 => 'GAB', :numeric => '266' }, + { :alpha2 => 'GM', :name => 'Gambia', :alpha3 => 'GMB', :numeric => '270' }, + { :alpha2 => 'GE', :name => 'Georgia', :alpha3 => 'GEO', :numeric => '268' }, + { :alpha2 => 'DE', :name => 'Germany', :alpha3 => 'DEU', :numeric => '276' }, + { :alpha2 => 'GH', :name => 'Ghana', :alpha3 => 'GHA', :numeric => '288' }, + { :alpha2 => 'GI', :name => 'Gibraltar', :alpha3 => 'GIB', :numeric => '292' }, + { :alpha2 => 'GR', :name => 'Greece', :alpha3 => 'GRC', :numeric => '300' }, + { :alpha2 => 'GL', :name => 'Greenland', :alpha3 => 'GRL', :numeric => '304' }, + { :alpha2 => 'GD', :name => 'Grenada', :alpha3 => 'GRD', :numeric => '308' }, + { :alpha2 => 'GP', :name => 'Guadeloupe', :alpha3 => 'GLP', :numeric => '312' }, + { :alpha2 => 'GU', :name => 'Guam', :alpha3 => 'GUM', :numeric => '316' }, + { :alpha2 => 'GT', :name => 'Guatemala', :alpha3 => 'GTM', :numeric => '320' }, + { :alpha2 => 'GG', :name => 'Guernsey', :alpha3 => 'GGY', :numeric => '831' }, + { :alpha2 => 'GN', :name => 'Guinea', :alpha3 => 'GIN', :numeric => '324' }, + { :alpha2 => 'GW', :name => 'Guinea-Bissau', :alpha3 => 'GNB', :numeric => '624' }, + { :alpha2 => 'GY', :name => 'Guyana', :alpha3 => 'GUY', :numeric => '328' }, + { :alpha2 => 'HT', :name => 'Haiti', :alpha3 => 'HTI', :numeric => '332' }, + { :alpha2 => 'HM', :name => 'Heard Island And Mcdonald Islands', :alpha3 => 'HMD', :numeric => '334' }, + { :alpha2 => 'VA', :name => 'Holy See (Vatican City State)', :alpha3 => 'VAT', :numeric => '336' }, + { :alpha2 => 'HN', :name => 'Honduras', :alpha3 => 'HND', :numeric => '340' }, + { :alpha2 => 'HK', :name => 'Hong Kong', :alpha3 => 'HKG', :numeric => '344' }, + { :alpha2 => 'HU', :name => 'Hungary', :alpha3 => 'HUN', :numeric => '348' }, + { :alpha2 => 'IS', :name => 'Iceland', :alpha3 => 'ISL', :numeric => '352' }, + { :alpha2 => 'IN', :name => 'India', :alpha3 => 'IND', :numeric => '356' }, + { :alpha2 => 'ID', :name => 'Indonesia', :alpha3 => 'IDN', :numeric => '360' }, + { :alpha2 => 'IR', :name => 'Iran, Islamic Republic of', :alpha3 => 'IRN', :numeric => '364' }, + { :alpha2 => 'IQ', :name => 'Iraq', :alpha3 => 'IRQ', :numeric => '368' }, + { :alpha2 => 'IE', :name => 'Ireland', :alpha3 => 'IRL', :numeric => '372' }, + { :alpha2 => 'IM', :name => 'Isle Of Man', :alpha3 => 'IMN', :numeric => '833' }, + { :alpha2 => 'IL', :name => 'Israel', :alpha3 => 'ISR', :numeric => '376' }, + { :alpha2 => 'IT', :name => 'Italy', :alpha3 => 'ITA', :numeric => '380' }, + { :alpha2 => 'JM', :name => 'Jamaica', :alpha3 => 'JAM', :numeric => '388' }, + { :alpha2 => 'JP', :name => 'Japan', :alpha3 => 'JPN', :numeric => '392' }, + { :alpha2 => 'JE', :name => 'Jersey', :alpha3 => 'JEY', :numeric => '832' }, + { :alpha2 => 'JO', :name => 'Jordan', :alpha3 => 'JOR', :numeric => '400' }, + { :alpha2 => 'KZ', :name => 'Kazakhstan', :alpha3 => 'KAZ', :numeric => '398' }, + { :alpha2 => 'KE', :name => 'Kenya', :alpha3 => 'KEN', :numeric => '404' }, + { :alpha2 => 'KI', :name => 'Kiribati', :alpha3 => 'KIR', :numeric => '296' }, + { :alpha2 => 'KP', :name => 'Korea, Democratic People\'s Republic of', :alpha3 => 'PRK', :numeric => '408' }, + { :alpha2 => 'KR', :name => 'Korea, Republic of', :alpha3 => 'KOR', :numeric => '410' }, + { :alpha2 => 'KW', :name => 'Kuwait', :alpha3 => 'KWT', :numeric => '414' }, + { :alpha2 => 'KG', :name => 'Kyrgyzstan', :alpha3 => 'KGZ', :numeric => '417' }, + { :alpha2 => 'LA', :name => 'Lao People\'s Democratic Republic', :alpha3 => 'LAO', :numeric => '418' }, + { :alpha2 => 'LV', :name => 'Latvia', :alpha3 => 'LVA', :numeric => '428' }, + { :alpha2 => 'LB', :name => 'Lebanon', :alpha3 => 'LBN', :numeric => '422' }, + { :alpha2 => 'LS', :name => 'Lesotho', :alpha3 => 'LSO', :numeric => '426' }, + { :alpha2 => 'LR', :name => 'Liberia', :alpha3 => 'LBR', :numeric => '430' }, + { :alpha2 => 'LY', :name => 'Libyan Arab Jamahiriya', :alpha3 => 'LBY', :numeric => '434' }, + { :alpha2 => 'LI', :name => 'Liechtenstein', :alpha3 => 'LIE', :numeric => '438' }, + { :alpha2 => 'LT', :name => 'Lithuania', :alpha3 => 'LTU', :numeric => '440' }, + { :alpha2 => 'LU', :name => 'Luxembourg', :alpha3 => 'LUX', :numeric => '442' }, + { :alpha2 => 'MO', :name => 'Macao', :alpha3 => 'MAC', :numeric => '446' }, + { :alpha2 => 'MK', :name => 'Macedonia, the Former Yugoslav Republic of', :alpha3 => 'MKD', :numeric => '807' }, + { :alpha2 => 'MG', :name => 'Madagascar', :alpha3 => 'MDG', :numeric => '450' }, + { :alpha2 => 'MW', :name => 'Malawi', :alpha3 => 'MWI', :numeric => '454' }, + { :alpha2 => 'MY', :name => 'Malaysia', :alpha3 => 'MYS', :numeric => '458' }, + { :alpha2 => 'MV', :name => 'Maldives', :alpha3 => 'MDV', :numeric => '462' }, + { :alpha2 => 'ML', :name => 'Mali', :alpha3 => 'MLI', :numeric => '466' }, + { :alpha2 => 'MT', :name => 'Malta', :alpha3 => 'MLT', :numeric => '470' }, + { :alpha2 => 'MH', :name => 'Marshall Islands', :alpha3 => 'MHL', :numeric => '584' }, + { :alpha2 => 'MQ', :name => 'Martinique', :alpha3 => 'MTQ', :numeric => '474' }, + { :alpha2 => 'MR', :name => 'Mauritania', :alpha3 => 'MRT', :numeric => '478' }, + { :alpha2 => 'MU', :name => 'Mauritius', :alpha3 => 'MUS', :numeric => '480' }, + { :alpha2 => 'YT', :name => 'Mayotte', :alpha3 => 'MYT', :numeric => '175' }, + { :alpha2 => 'MX', :name => 'Mexico', :alpha3 => 'MEX', :numeric => '484' }, + { :alpha2 => 'FM', :name => 'Micronesia, Federated States of', :alpha3 => 'FSM', :numeric => '583' }, + { :alpha2 => 'MD', :name => 'Moldova, Republic of', :alpha3 => 'MDA', :numeric => '498' }, + { :alpha2 => 'MC', :name => 'Monaco', :alpha3 => 'MCO', :numeric => '492' }, + { :alpha2 => 'MN', :name => 'Mongolia', :alpha3 => 'MNG', :numeric => '496' }, + { :alpha2 => 'ME', :name => 'Montenegro', :alpha3 => 'MNE', :numeric => '499' }, + { :alpha2 => 'MS', :name => 'Montserrat', :alpha3 => 'MSR', :numeric => '500' }, + { :alpha2 => 'MA', :name => 'Morocco', :alpha3 => 'MAR', :numeric => '504' }, + { :alpha2 => 'MZ', :name => 'Mozambique', :alpha3 => 'MOZ', :numeric => '508' }, + { :alpha2 => 'MM', :name => 'Myanmar', :alpha3 => 'MMR', :numeric => '104' }, + { :alpha2 => 'NA', :name => 'Namibia', :alpha3 => 'NAM', :numeric => '516' }, + { :alpha2 => 'NR', :name => 'Nauru', :alpha3 => 'NRU', :numeric => '520' }, + { :alpha2 => 'NP', :name => 'Nepal', :alpha3 => 'NPL', :numeric => '524' }, + { :alpha2 => 'NL', :name => 'Netherlands', :alpha3 => 'NLD', :numeric => '528' }, + { :alpha2 => 'AN', :name => 'Netherlands Antilles', :alpha3 => 'ANT', :numeric => '530' }, + { :alpha2 => 'NC', :name => 'New Caledonia', :alpha3 => 'NCL', :numeric => '540' }, + { :alpha2 => 'NZ', :name => 'New Zealand', :alpha3 => 'NZL', :numeric => '554' }, + { :alpha2 => 'NI', :name => 'Nicaragua', :alpha3 => 'NIC', :numeric => '558' }, + { :alpha2 => 'NE', :name => 'Niger', :alpha3 => 'NER', :numeric => '562' }, + { :alpha2 => 'NG', :name => 'Nigeria', :alpha3 => 'NGA', :numeric => '566' }, + { :alpha2 => 'NU', :name => 'Niue', :alpha3 => 'NIU', :numeric => '570' }, + { :alpha2 => 'NF', :name => 'Norfolk Island', :alpha3 => 'NFK', :numeric => '574' }, + { :alpha2 => 'MP', :name => 'Northern Mariana Islands', :alpha3 => 'MNP', :numeric => '580' }, + { :alpha2 => 'NO', :name => 'Norway', :alpha3 => 'NOR', :numeric => '578' }, + { :alpha2 => 'OM', :name => 'Oman', :alpha3 => 'OMN', :numeric => '512' }, + { :alpha2 => 'PK', :name => 'Pakistan', :alpha3 => 'PAK', :numeric => '586' }, + { :alpha2 => 'PW', :name => 'Palau', :alpha3 => 'PLW', :numeric => '585' }, + { :alpha2 => 'PS', :name => 'Palestinian Territory, Occupied', :alpha3 => 'PSE', :numeric => '275' }, + { :alpha2 => 'PA', :name => 'Panama', :alpha3 => 'PAN', :numeric => '591' }, + { :alpha2 => 'PG', :name => 'Papua New Guinea', :alpha3 => 'PNG', :numeric => '598' }, + { :alpha2 => 'PY', :name => 'Paraguay', :alpha3 => 'PRY', :numeric => '600' }, + { :alpha2 => 'PE', :name => 'Peru', :alpha3 => 'PER', :numeric => '604' }, + { :alpha2 => 'PH', :name => 'Philippines', :alpha3 => 'PHL', :numeric => '608' }, + { :alpha2 => 'PN', :name => 'Pitcairn', :alpha3 => 'PCN', :numeric => '612' }, + { :alpha2 => 'PL', :name => 'Poland', :alpha3 => 'POL', :numeric => '616' }, + { :alpha2 => 'PT', :name => 'Portugal', :alpha3 => 'PRT', :numeric => '620' }, + { :alpha2 => 'PR', :name => 'Puerto Rico', :alpha3 => 'PRI', :numeric => '630' }, + { :alpha2 => 'QA', :name => 'Qatar', :alpha3 => 'QAT', :numeric => '634' }, + { :alpha2 => 'RE', :name => 'Reunion', :alpha3 => 'REU', :numeric => '638' }, + { :alpha2 => 'RO', :name => 'Romania', :alpha3 => 'ROM', :numeric => '642' }, + { :alpha2 => 'RU', :name => 'Russian Federation', :alpha3 => 'RUS', :numeric => '643' }, + { :alpha2 => 'RW', :name => 'Rwanda', :alpha3 => 'RWA', :numeric => '646' }, + { :alpha2 => 'BL', :name => 'Saint Barthélemy', :alpha3 => 'BLM', :numeric => '652' }, + { :alpha2 => 'SH', :name => 'Saint Helena', :alpha3 => 'SHN', :numeric => '654' }, + { :alpha2 => 'KN', :name => 'Saint Kitts and Nevis', :alpha3 => 'KNA', :numeric => '659' }, + { :alpha2 => 'LC', :name => 'Saint Lucia', :alpha3 => 'LCA', :numeric => '662' }, + { :alpha2 => 'MF', :name => 'Saint Martin (French part)', :alpha3 => 'MAF', :numeric => '663' }, + { :alpha2 => 'PM', :name => 'Saint Pierre and Miquelon', :alpha3 => 'SPM', :numeric => '666' }, + { :alpha2 => 'VC', :name => 'Saint Vincent and the Grenadines', :alpha3 => 'VCT', :numeric => '670' }, + { :alpha2 => 'WS', :name => 'Samoa', :alpha3 => 'WSM', :numeric => '882' }, + { :alpha2 => 'SM', :name => 'San Marino', :alpha3 => 'SMR', :numeric => '674' }, + { :alpha2 => 'ST', :name => 'Sao Tome and Principe', :alpha3 => 'STP', :numeric => '678' }, + { :alpha2 => 'SA', :name => 'Saudi Arabia', :alpha3 => 'SAU', :numeric => '682' }, + { :alpha2 => 'SN', :name => 'Senegal', :alpha3 => 'SEN', :numeric => '686' }, + { :alpha2 => 'RS', :name => 'Serbia', :alpha3 => 'SRB', :numeric => '688' }, + { :alpha2 => 'SC', :name => 'Seychelles', :alpha3 => 'SYC', :numeric => '690' }, + { :alpha2 => 'SL', :name => 'Sierra Leone', :alpha3 => 'SLE', :numeric => '694' }, + { :alpha2 => 'SG', :name => 'Singapore', :alpha3 => 'SGP', :numeric => '702' }, + { :alpha2 => 'SK', :name => 'Slovakia', :alpha3 => 'SVK', :numeric => '703' }, + { :alpha2 => 'SI', :name => 'Slovenia', :alpha3 => 'SVN', :numeric => '705' }, + { :alpha2 => 'SB', :name => 'Solomon Islands', :alpha3 => 'SLB', :numeric => '090' }, + { :alpha2 => 'SO', :name => 'Somalia', :alpha3 => 'SOM', :numeric => '706' }, + { :alpha2 => 'ZA', :name => 'South Africa', :alpha3 => 'ZAF', :numeric => '710' }, + { :alpha2 => 'GS', :name => 'South Georgia and the South Sandwich Islands', :alpha3 => 'SGS', :numeric => '239' }, + { :alpha2 => 'ES', :name => 'Spain', :alpha3 => 'ESP', :numeric => '724' }, + { :alpha2 => 'LK', :name => 'Sri Lanka', :alpha3 => 'LKA', :numeric => '144' }, + { :alpha2 => 'SD', :name => 'Sudan', :alpha3 => 'SDN', :numeric => '736' }, + { :alpha2 => 'SR', :name => 'Suriname', :alpha3 => 'SUR', :numeric => '740' }, + { :alpha2 => 'SJ', :name => 'Svalbard and Jan Mayen', :alpha3 => 'SJM', :numeric => '744' }, + { :alpha2 => 'SZ', :name => 'Swaziland', :alpha3 => 'SWZ', :numeric => '748' }, + { :alpha2 => 'SE', :name => 'Sweden', :alpha3 => 'SWE', :numeric => '752' }, + { :alpha2 => 'CH', :name => 'Switzerland', :alpha3 => 'CHE', :numeric => '756' }, + { :alpha2 => 'SY', :name => 'Syrian Arab Republic', :alpha3 => 'SYR', :numeric => '760' }, + { :alpha2 => 'TW', :name => 'Taiwan, Province of China', :alpha3 => 'TWN', :numeric => '158' }, + { :alpha2 => 'TJ', :name => 'Tajikistan', :alpha3 => 'TJK', :numeric => '762' }, + { :alpha2 => 'TZ', :name => 'Tanzania, United Republic of', :alpha3 => 'TZA', :numeric => '834' }, + { :alpha2 => 'TH', :name => 'Thailand', :alpha3 => 'THA', :numeric => '764' }, + { :alpha2 => 'TL', :name => 'Timor Leste', :alpha3 => 'TLS', :numeric => '626' }, + { :alpha2 => 'TG', :name => 'Togo', :alpha3 => 'TGO', :numeric => '768' }, + { :alpha2 => 'TK', :name => 'Tokelau', :alpha3 => 'TKL', :numeric => '772' }, + { :alpha2 => 'TO', :name => 'Tonga', :alpha3 => 'TON', :numeric => '776' }, + { :alpha2 => 'TT', :name => 'Trinidad and Tobago', :alpha3 => 'TTO', :numeric => '780' }, + { :alpha2 => 'TN', :name => 'Tunisia', :alpha3 => 'TUN', :numeric => '788' }, + { :alpha2 => 'TR', :name => 'Turkey', :alpha3 => 'TUR', :numeric => '792' }, + { :alpha2 => 'TM', :name => 'Turkmenistan', :alpha3 => 'TKM', :numeric => '795' }, + { :alpha2 => 'TC', :name => 'Turks and Caicos Islands', :alpha3 => 'TCA', :numeric => '796' }, + { :alpha2 => 'TV', :name => 'Tuvalu', :alpha3 => 'TUV', :numeric => '798' }, + { :alpha2 => 'UG', :name => 'Uganda', :alpha3 => 'UGA', :numeric => '800' }, + { :alpha2 => 'UA', :name => 'Ukraine', :alpha3 => 'UKR', :numeric => '804' }, + { :alpha2 => 'AE', :name => 'United Arab Emirates', :alpha3 => 'ARE', :numeric => '784' }, + { :alpha2 => 'GB', :name => 'United Kingdom', :alpha3 => 'GBR', :numeric => '826' }, + { :alpha2 => 'US', :name => 'United States', :alpha3 => 'USA', :numeric => '840' }, + { :alpha2 => 'UM', :name => 'United States Minor Outlying Islands', :alpha3 => 'UMI', :numeric => '581' }, + { :alpha2 => 'UY', :name => 'Uruguay', :alpha3 => 'URY', :numeric => '858' }, + { :alpha2 => 'UZ', :name => 'Uzbekistan', :alpha3 => 'UZB', :numeric => '860' }, + { :alpha2 => 'VU', :name => 'Vanuatu', :alpha3 => 'VUT', :numeric => '548' }, + { :alpha2 => 'VE', :name => 'Venezuela', :alpha3 => 'VEN', :numeric => '862' }, + { :alpha2 => 'VN', :name => 'Viet Nam', :alpha3 => 'VNM', :numeric => '704' }, + { :alpha2 => 'VG', :name => 'Virgin Islands, British', :alpha3 => 'VGB', :numeric => '092' }, + { :alpha2 => 'VI', :name => 'Virgin Islands, U.S.', :alpha3 => 'VIR', :numeric => '850' }, + { :alpha2 => 'WF', :name => 'Wallis and Futuna', :alpha3 => 'WLF', :numeric => '876' }, + { :alpha2 => 'EH', :name => 'Western Sahara', :alpha3 => 'ESH', :numeric => '732' }, + { :alpha2 => 'YE', :name => 'Yemen', :alpha3 => 'YEM', :numeric => '887' }, + { :alpha2 => 'ZM', :name => 'Zambia', :alpha3 => 'ZMB', :numeric => '894' }, + { :alpha2 => 'ZW', :name => 'Zimbabwe', :alpha3 => 'ZWE', :numeric => '716' }, + { :alpha2 => 'AX', :name => 'Åland Islands', :alpha3 => 'ALA', :numeric => '248' } + ] + + def self.find(name) + raise InvalidCountryCodeError, "Cannot lookup country for an empty name" if name.blank? + + case name.length + when 2, 3 + upcase_name = name.upcase + country_code = CountryCode.new(name) + country = COUNTRIES.detect{|c| c[country_code.format] == upcase_name } + else + country = COUNTRIES.detect{|c| c[:name] == name } + end + raise InvalidCountryCodeError, "No country could be found for the country #{name}" if country.nil? + Country.new(country.dup) + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/error.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/error.rb new file mode 100644 index 000000000..36c5e38c7 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/error.rb @@ -0,0 +1,26 @@ +module ActiveMerchant #:nodoc: + class ActiveMerchantError < StandardError #:nodoc: + end + + class ConnectionError < ActiveMerchantError # :nodoc: + end + + class RetriableConnectionError < ConnectionError # :nodoc: + end + + class ResponseError < ActiveMerchantError # :nodoc: + attr_reader :response + + def initialize(response, message = nil) + @response = response + @message = message + end + + def to_s + "Failed with #{response.code} #{response.message if response.respond_to?(:message)}" + end + end + + class ClientCertificateError < ActiveMerchantError # :nodoc + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/network_connection_retries.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/network_connection_retries.rb new file mode 100644 index 000000000..df53af3b8 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/network_connection_retries.rb @@ -0,0 +1,58 @@ +module ActiveMerchant + module NetworkConnectionRetries + DEFAULT_RETRIES = 3 + DEFAULT_CONNECTION_ERRORS = { + EOFError => "The remote server dropped the connection", + Errno::ECONNRESET => "The remote server reset the connection", + Timeout::Error => "The connection to the remote server timed out", + Errno::ETIMEDOUT => "The connection to the remote server timed out" + } + + def self.included(base) + base.send(:attr_accessor, :retry_safe) + end + + def retry_exceptions(options={}) + connection_errors = DEFAULT_CONNECTION_ERRORS.merge(options[:connection_exceptions] || {}) + + retry_network_exceptions(options) do + begin + yield + rescue Errno::ECONNREFUSED => e + raise ActiveMerchant::RetriableConnectionError, "The remote server refused the connection" + rescue OpenSSL::X509::CertificateError => e + NetworkConnectionRetries.log(options[:logger], :error, e.message, options[:tag]) + raise ActiveMerchant::ClientCertificateError, "The remote server did not accept the provided SSL certificate" + rescue *connection_errors.keys => e + raise ActiveMerchant::ConnectionError, connection_errors[e.class] + end + end + end + + private + + def retry_network_exceptions(options = {}) + retries = options[:max] || DEFAULT_RETRIES + + begin + yield + rescue ActiveMerchant::RetriableConnectionError => e + retries -= 1 + retry unless retries.zero? + NetworkConnectionRetries.log(options[:logger], :error, e.message, options[:tag]) + raise ActiveMerchant::ConnectionError, e.message + rescue ActiveMerchant::ConnectionError => e + retries -= 1 + retry if (options[:retry_safe] || retry_safe) && !retries.zero? + NetworkConnectionRetries.log(options[:logger], :error, e.message, options[:tag]) + raise + end + end + + def self.log(logger, level, message, tag=nil) + tag ||= self.class.to_s + message = "[#{tag}] #{message}" + logger.send(level, message) if logger + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/post_data.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/post_data.rb new file mode 100644 index 000000000..192d08e85 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/post_data.rb @@ -0,0 +1,24 @@ +require 'cgi' + +module ActiveMerchant + class PostData < Hash + class_attribute :required_fields, :instance_writer => false + self.required_fields = [] + + def []=(key, value) + return if value.blank? && !required?(key) + super + end + + def to_post_data + collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + alias_method :to_s, :to_post_data + + private + def required?(key) + required_fields.include?(key) + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/posts_data.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/posts_data.rb new file mode 100644 index 000000000..584f19435 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/posts_data.rb @@ -0,0 +1,69 @@ +module ActiveMerchant #:nodoc: + module PostsData #:nodoc: + + def self.included(base) + base.superclass_delegating_accessor :ssl_strict + base.ssl_strict = true + + base.class_attribute :retry_safe + base.retry_safe = false + + base.superclass_delegating_accessor :open_timeout + base.open_timeout = 60 + + base.superclass_delegating_accessor :read_timeout + base.read_timeout = 60 + + base.superclass_delegating_accessor :logger + base.superclass_delegating_accessor :wiredump_device + end + + def ssl_get(endpoint, headers={}) + ssl_request(:get, endpoint, nil, headers) + end + + def ssl_post(endpoint, data, headers = {}) + ssl_request(:post, endpoint, data, headers) + end + + def ssl_request(method, endpoint, data, headers) + handle_response(raw_ssl_request(method, endpoint, data, headers)) + end + + def raw_ssl_request(method, endpoint, data, headers = {}) + logger.warn "#{self.class} using ssl_strict=false, which is insecure" if logger unless ssl_strict + + connection = new_connection(endpoint) + connection.open_timeout = open_timeout + connection.read_timeout = read_timeout + connection.retry_safe = retry_safe + connection.verify_peer = ssl_strict + connection.logger = logger + connection.tag = self.class.name + connection.wiredump_device = wiredump_device + + connection.pem = @options[:pem] if @options + connection.pem_password = @options[:pem_password] if @options + + connection.ignore_http_status = @options[:ignore_http_status] if @options + + connection.request(method, data, headers) + end + + private + + def new_connection(endpoint) + Connection.new(endpoint) + end + + def handle_response(response) + case response.code.to_i + when 200...300 + response.body + else + raise ResponseError.new(response) + end + end + + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/requires_parameters.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/requires_parameters.rb new file mode 100644 index 000000000..4e1f2e1aa --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/requires_parameters.rb @@ -0,0 +1,16 @@ +module ActiveMerchant #:nodoc: + module RequiresParameters #:nodoc: + def requires!(hash, *params) + params.each do |param| + if param.is_a?(Array) + raise ArgumentError.new("Missing required parameter: #{param.first}") unless hash.has_key?(param.first) + + valid_options = param[1..-1] + raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(:words_connector => 'or')}") unless valid_options.include?(hash[param.first]) + else + raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param) + end + end + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/utils.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/utils.rb new file mode 100644 index 000000000..fddee5e06 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/utils.rb @@ -0,0 +1,20 @@ +require 'securerandom' + +module ActiveMerchant #:nodoc: + module Utils #:nodoc: + def generate_unique_id + SecureRandom.hex(16) + end + + module_function :generate_unique_id + + def deprecated(message) + warning = Kernel.caller[1] + message + if respond_to?(:logger) && logger.present? + logger.warn(warning) + else + warn(warning) + end + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/common/validateable.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/validateable.rb new file mode 100644 index 000000000..8e1d2c909 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/common/validateable.rb @@ -0,0 +1,81 @@ +module ActiveMerchant #:nodoc: + module Validateable #:nodoc: + def valid? + errors.clear + + before_validate if respond_to?(:before_validate, true) + validate if respond_to?(:validate, true) + + errors.empty? + end + + def initialize(attributes = {}) + self.attributes = attributes + end + + def errors + @errors ||= Errors.new(self) + end + + private + + def attributes=(attributes) + unless attributes.nil? + for key, value in attributes + send("#{key}=", value ) + end + end + end + + # This hash keeps the errors of the object + class Errors < HashWithIndifferentAccess + + def initialize(base) + super() { |h, k| h[k] = [] ; h[k] } + @base = base + end + + def count + size + end + + def empty? + all? { |k, v| v && v.empty? } + end + + # returns a specific fields error message. + # if more than one error is available we will only return the first. If no error is available + # we return an empty string + def on(field) + self[field].to_a.first + end + + def add(field, error) + self[field] << error + end + + def add_to_base(error) + add(:base, error) + end + + def each_full + full_messages.each { |msg| yield msg } + end + + def full_messages + result = [] + + self.each do |key, messages| + next if messages.blank? + if key == 'base' + result << "#{messages.first}" + else + result << "#{key.to_s.humanize} #{messages.first}" + end + end + + result + end + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/lib/active_utils/version.rb b/vendor/gems/active_utils-1.0.5/lib/active_utils/version.rb new file mode 100644 index 000000000..d4504aa02 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/active_utils/version.rb @@ -0,0 +1,3 @@ +module ActiveUtils + VERSION = "1.0.5" +end diff --git a/vendor/gems/active_utils-1.0.5/lib/certs/cacert.pem b/vendor/gems/active_utils-1.0.5/lib/certs/cacert.pem new file mode 100644 index 000000000..16494cbf9 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/lib/certs/cacert.pem @@ -0,0 +1,7815 @@ +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## Converted by the service run by Daniel Stenberg +## URL: http://curl.haxx.se/docs/caextract.html +## Converted at: Wed Feb 28 04:14:50 UTC 2007 +CVS_ID "@(#) $RCSfile: certdata.txt,v $ $Revision: 1.37 $ $Date: 2005/04/18 16:08:07 $" +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## '/mozilla/security/nss/lib/ckfw/builtins/certdata.txt' +## +## This file was automatically converted and downloaded through the services +## provided by http://curl.haxx.se/docs/caextract.html +## +## +## The contents of this file are subject to the Mozilla Public License Version +## 1.1 (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS IS" basis, +## WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +## for the specific language governing rights and limitations under the +## License. +## +## The Original Code is the Netscape security libraries. +## +## The Initial Developer of the Original Code is Netscape Communications +## Corporation. Portions created by Netscape are Copyright (C) 1994-2000 +## Netscape Communications Corporation. All Rights Reserved. +## +## Contributor(s): +## +## Alternatively, the contents of this file may be used under the terms of the +## GNU General Public License Version 2 or later (the "GPL"), in which case +## the provisions of the GPL are applicable instead of those above. If you +## wish to allow use of your version of this file only under the terms of the +## GPL and not to allow others to use your version of this file under the MPL, +## indicate your decision by deleting the provisions above and replace them +## with the notice and other provisions required by the GPL. If you do not +## delete the provisions above, a recipient may use your version of this file +## under either the MPL or the GPL. +## + +Verisign/RSA Secure Server CA +============================= + +MD5 Fingerprint=74:7B:82:03:43:F0:00:9E:6B:B3:EC:47:BF:85:A5:93 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 02:ad:66:7e:4e:45:fe:5e:57:6f:3c:98:19:5e:dd:c0 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + Validity + Not Before: Nov 9 00:00:00 1994 GMT + Not After : Jan 7 23:59:59 2010 GMT + Subject: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1000 bit) + Modulus (1000 bit): + 00:92:ce:7a:c1:ae:83:3e:5a:aa:89:83:57:ac:25: + 01:76:0c:ad:ae:8e:2c:37:ce:eb:35:78:64:54:03: + e5:84:40:51:c9:bf:8f:08:e2:8a:82:08:d2:16:86: + 37:55:e9:b1:21:02:ad:76:68:81:9a:05:a2:4b:c9: + 4b:25:66:22:56:6c:88:07:8f:f7:81:59:6d:84:07: + 65:70:13:71:76:3e:9b:77:4c:e3:50:89:56:98:48: + b9:1d:a7:29:1a:13:2e:4a:11:59:9c:1e:15:d5:49: + 54:2c:73:3a:69:82:b1:97:39:9c:6d:70:67:48:e5: + dd:2d:d6:c8:1e:7b + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 65:dd:7e:e1:b2:ec:b0:e2:3a:e0:ec:71:46:9a:19:11:b8:d3: + c7:a0:b4:03:40:26:02:3e:09:9c:e1:12:b3:d1:5a:f6:37:a5: + b7:61:03:b6:5b:16:69:3b:c6:44:08:0c:88:53:0c:6b:97:49: + c7:3e:35:dc:6c:b9:bb:aa:df:5c:bb:3a:2f:93:60:b6:a9:4b: + 4d:f2:20:f7:cd:5f:7f:64:7b:8e:dc:00:5c:d7:fa:77:ca:39: + 16:59:6f:0e:ea:d3:b5:83:7f:4d:4d:42:56:76:b4:c9:5f:04: + f8:38:f8:eb:d2:5f:75:5f:cd:7b:fc:e5:8e:80:7c:fc:50 +-----BEGIN CERTIFICATE----- +MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD +VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 +MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV +BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy +dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ +ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII +0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI +uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI +hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 +YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc +1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== +-----END CERTIFICATE----- + +ABAecom (sub., Am. Bankers Assn.) Root CA +========================================= + +MD5 Fingerprint=41:B8:07:F7:A8:D1:09:EE:B4:9A:8E:70:4D:FC:1B:78 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + d0:1e:40:90:00:00:46:52:00:00:00:01:00:00:00:04 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=DC, L=Washington, O=ABA.ECOM, INC., CN=ABA.ECOM Root CA/emailAddress=admin@digsigtrust.com + Validity + Not Before: Jul 12 17:33:53 1999 GMT + Not After : Jul 9 17:33:53 2009 GMT + Subject: C=US, ST=DC, L=Washington, O=ABA.ECOM, INC., CN=ABA.ECOM Root CA/emailAddress=admin@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b1:d3:11:e0:79:55:43:07:08:4c:cb:05:42:00: + e2:0d:83:46:3d:e4:93:ba:b6:06:d3:0d:59:bd:3e: + c1:ce:43:67:01:8a:21:a8:ef:bc:cc:d0:a2:cc:b0: + 55:96:53:84:66:05:00:da:44:49:80:d8:54:0a:a5: + 25:86:94:ed:63:56:ff:70:6c:a3:a1:19:d2:78:be: + 68:2a:44:5e:2f:cf:cc:18:5e:47:bc:3a:b1:46:3d: + 1e:f0:b9:2c:34:5f:8c:7c:4c:08:29:9d:40:55:eb: + 3c:7d:83:de:b5:f0:f7:8a:83:0e:a1:4c:b4:3a:a5: + b3:5f:5a:22:97:ec:19:9b:c1:05:68:fd:e6:b7:a9: + 91:94:2c:e4:78:48:24:1a:25:19:3a:eb:95:9c:39: + 0a:8a:cf:42:b2:f0:1c:d5:5f:fb:6b:ed:68:56:7b: + 39:2c:72:38:b0:ee:93:a9:d3:7b:77:3c:eb:71:03: + a9:38:4a:16:6c:89:2a:ca:da:33:13:79:c2:55:8c: + ed:9c:bb:f2:cb:5b:10:f8:2e:61:35:c6:29:4c:2a: + d0:2a:63:d1:65:59:b4:f8:cd:f9:f4:00:84:b6:57: + 42:85:9d:32:a8:f9:2a:54:fb:ff:78:41:bc:bd:71: + 28:f4:bb:90:bc:ff:96:34:04:e3:45:9e:a1:46:28: + 40:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:8 + Signature Algorithm: sha1WithRSAEncryption + 04:6f:25:86:e4:e6:96:27:b4:d9:42:c0:d0:c9:00:b1:7f:54: + 3e:87:b2:6d:24:a9:2f:0a:7e:fd:a4:44:b0:f8:54:07:bd:1b: + 9d:9d:ca:7b:50:24:7b:11:5b:49:a3:a6:bf:12:74:d5:89:b7: + b7:2f:98:64:25:14:b7:61:e9:7f:60:80:6b:d3:64:e8:ab:bd: + 1a:d6:51:fa:c0:b4:5d:77:1a:7f:64:08:5e:79:c6:05:4c:f1: + 7a:dd:4d:7d:ce:e6:48:7b:54:d2:61:92:81:d6:1b:d6:00:f0: + 0e:9e:28:77:a0:4d:88:c7:22:76:19:c3:c7:9e:1b:a6:77:78: + f8:5f:9b:56:d1:f0:f2:17:ac:8e:9d:59:e6:1f:fe:57:b6:d9: + 5e:e1:5d:9f:45:ec:61:68:19:41:e1:b2:20:26:fe:5a:30:76: + 24:ff:40:72:3c:79:9f:7c:22:48:ab:46:cd:db:b3:86:2c:8f: + bf:05:41:d3:c1:e3:14:e3:41:17:26:d0:7c:a7:71:4c:19:e8: + 4a:0f:72:58:31:7d:ec:60:7a:a3:22:28:bd:19:24:60:3f:3b: + 87:73:c0:6b:e4:cb:ae:b7:ab:25:43:b2:55:2d:7b:ab:06:0e: + 75:5d:34:e5:5d:73:6d:9e:b2:75:40:a5:59:c9:4f:31:71:88: + d9:88:7f:54 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIRANAeQJAAAEZSAAAAAQAAAAQwDQYJKoZIhvcNAQEFBQAw +gYkxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJEQzETMBEGA1UEBxMKV2FzaGluZ3Rv +bjEXMBUGA1UEChMOQUJBLkVDT00sIElOQy4xGTAXBgNVBAMTEEFCQS5FQ09NIFJv +b3QgQ0ExJDAiBgkqhkiG9w0BCQEWFWFkbWluQGRpZ3NpZ3RydXN0LmNvbTAeFw05 +OTA3MTIxNzMzNTNaFw0wOTA3MDkxNzMzNTNaMIGJMQswCQYDVQQGEwJVUzELMAkG +A1UECBMCREMxEzARBgNVBAcTCldhc2hpbmd0b24xFzAVBgNVBAoTDkFCQS5FQ09N +LCBJTkMuMRkwFwYDVQQDExBBQkEuRUNPTSBSb290IENBMSQwIgYJKoZIhvcNAQkB +FhVhZG1pbkBkaWdzaWd0cnVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCx0xHgeVVDBwhMywVCAOINg0Y95JO6tgbTDVm9PsHOQ2cBiiGo77zM +0KLMsFWWU4RmBQDaREmA2FQKpSWGlO1jVv9wbKOhGdJ4vmgqRF4vz8wYXke8OrFG +PR7wuSw0X4x8TAgpnUBV6zx9g9618PeKgw6hTLQ6pbNfWiKX7BmbwQVo/ea3qZGU +LOR4SCQaJRk665WcOQqKz0Ky8BzVX/tr7WhWezkscjiw7pOp03t3POtxA6k4ShZs +iSrK2jMTecJVjO2cu/LLWxD4LmE1xilMKtAqY9FlWbT4zfn0AIS2V0KFnTKo+SpU ++/94Qby9cSj0u5C8/5Y0BONFnqFGKECBAgMBAAGjFjAUMBIGA1UdEwEB/wQIMAYB +Af8CAQgwDQYJKoZIhvcNAQEFBQADggEBAARvJYbk5pYntNlCwNDJALF/VD6Hsm0k +qS8Kfv2kRLD4VAe9G52dyntQJHsRW0mjpr8SdNWJt7cvmGQlFLdh6X9ggGvTZOir +vRrWUfrAtF13Gn9kCF55xgVM8XrdTX3O5kh7VNJhkoHWG9YA8A6eKHegTYjHInYZ +w8eeG6Z3ePhfm1bR8PIXrI6dWeYf/le22V7hXZ9F7GFoGUHhsiAm/lowdiT/QHI8 +eZ98IkirRs3bs4Ysj78FQdPB4xTjQRcm0HyncUwZ6EoPclgxfexgeqMiKL0ZJGA/ +O4dzwGvky663qyVDslUte6sGDnVdNOVdc22esnVApVnJTzFxiNmIf1Q= +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 1 +======================================= + +MD5 Fingerprint=25:7A:BA:83:2E:B6:A2:0B:DA:FE:F5:02:0F:08:D7:AD +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 913315222 (0x36701596) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E1 + Validity + Not Before: Dec 10 18:10:23 1998 GMT + Not After : Dec 10 18:40:23 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a0:6c:81:a9:cf:34:1e:24:dd:fe:86:28:cc:de: + 83:2f:f9:5e:d4:42:d2:e8:74:60:66:13:98:06:1c: + a9:51:12:69:6f:31:55:b9:49:72:00:08:7e:d3:a5: + 62:44:37:24:99:8f:d9:83:48:8f:99:6d:95:13:bb: + 43:3b:2e:49:4e:88:37:c1:bb:58:7f:fe:e1:bd:f8: + bb:61:cd:f3:47:c0:99:a6:f1:f3:91:e8:78:7c:00: + cb:61:c9:44:27:71:69:55:4a:7e:49:4d:ed:a2:a3: + be:02:4c:00:ca:02:a8:ee:01:02:31:64:0f:52:2d: + 13:74:76:36:b5:7a:b4:2d:71 + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E1/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 10 18:10:23 1998 GMT, Not After: Dec 10 18:10:23 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8 + + X509v3 Subject Key Identifier: + 6A:79:7E:91:69:46:18:13:0A:02:77:A5:59:5B:60:98:25:0E:A2:F8 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 22:12:d8:7a:1d:dc:81:06:b6:09:65:b2:87:c8:1f:5e:b4:2f: + e9:c4:1e:f2:3c:c1:bb:04:90:11:4a:83:4e:7e:93:b9:4d:42: + c7:92:26:a0:5c:34:9a:38:72:f8:fd:6b:16:3e:20:ee:82:8b: + 31:2a:93:36:85:23:88:8a:3c:03:68:d3:c9:09:0f:4d:fc:6c: + a4:da:28:72:93:0e:89:80:b0:7d:fe:80:6f:65:6d:18:33:97: + 8b:c2:6b:89:ee:60:3d:c8:9b:ef:7f:2b:32:62:73:93:cb:3c: + e3:7b:e2:76:78:45:bc:a1:93:04:bb:86:9f:3a:5b:43:7a:c3: + 8a:65 +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg +bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ +j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV +Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw +MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 +fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i ++DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN +QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ +gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 3 +======================================= + +MD5 Fingerprint=93:C2:8E:11:7B:D4:F3:03:19:BD:28:75:13:4A:45:4A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 913232846 (0x366ed3ce) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Digital Signature Trust Co., OU=DSTCA E2 + Validity + Not Before: Dec 9 19:17:26 1998 GMT + Not After : Dec 9 19:47:26 2018 GMT + Subject: C=US, O=Digital Signature Trust Co., OU=DSTCA E2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:93:8f:17:92:ef:33:13:18:eb:10:7f:4e:16: + bf:ff:06:8f:2a:85:bc:5e:f9:24:a6:24:88:b6:03: + b7:c1:c3:5f:03:5b:d1:6f:ae:7e:42:ea:66:23:b8: + 63:83:56:fb:28:2d:e1:38:8b:b4:ee:a8:01:e1:ce: + 1c:b6:88:2a:22:46:85:fb:9f:a7:70:a9:47:14:3f: + ce:de:65:f0:a8:71:f7:4f:26:6c:8c:bc:c6:b5:ef: + de:49:27:ff:48:2a:7d:e8:4d:03:cc:c7:b2:52:c6: + 17:31:13:3b:b5:4d:db:c8:c4:f6:c3:0f:24:2a:da: + 0c:9d:e7:91:5b:80:cd:94:9d + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Digital Signature Trust Co./OU=DSTCA E2/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Dec 9 19:17:26 1998 GMT, Not After: Dec 9 19:17:26 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B + + X509v3 Subject Key Identifier: + 1E:82:4D:28:65:80:3C:C9:41:6E:AC:35:2E:5A:CB:DE:EE:F8:39:5B + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 47:8d:83:ad:62:f2:db:b0:9e:45:22:05:b9:a2:d6:03:0e:38: + 72:e7:9e:fc:7b:e6:93:b6:9a:a5:a2:94:c8:34:1d:91:d1:c5: + d7:f4:0a:25:0f:3d:78:81:9e:0f:b1:67:c4:90:4c:63:dd:5e: + a7:e2:ba:9f:f5:f7:4d:a5:31:7b:9c:29:2d:4c:fe:64:3e:ec: + b6:53:fe:ea:9b:ed:82:db:74:75:4b:07:79:6e:1e:d8:19:83: + 73:de:f5:3e:d0:b5:de:e7:4b:68:7d:43:2e:2a:20:e1:7e:a0: + 78:44:9e:08:f5:98:f9:c7:7f:1b:1b:d6:06:20:02:58:a1:c3: + a2:03 +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV +UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL +EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ +BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x +ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/ +k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso +LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o +TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG +SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx +JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI +RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3 +MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C +TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5 +WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG +SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR +xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL +B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 2 +======================================= + +MD5 Fingerprint=6C:C9:A7:6E:47:F1:0C:E3:53:3B:78:4C:4D:C2:6A:C5 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:02:7c:00:00:00:02:00:00:00:01 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/emailAddress=ca@digsigtrust.com + Validity + Not Before: Dec 1 18:18:55 1998 GMT + Not After : Nov 28 18:18:55 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X1, CN=DST RootCA X1/emailAddress=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d2:c6:26:b6:e7:a5:3d:c1:c4:68:d5:50:6f:53: + c5:6f:49:13:09:b8:af:2c:48:8d:14:6a:a3:17:5f: + 5a:f9:d3:2e:75:2f:d8:28:62:d1:93:2f:fc:4d:d4: + ab:87:e5:08:c7:99:e7:92:3f:75:bd:eb:25:b4:15: + c1:9b:19:3d:d2:44:8d:d7:74:20:6d:37:02:8f:69: + 93:5b:8a:c4:19:9d:f4:b2:0e:fc:16:6c:b9:b1:05: + 92:83:d1:85:2c:60:94:3e:45:55:a0:d9:ab:08:21: + e6:60:e8:3b:74:f2:99:50:51:68:d0:03:2d:b1:80: + be:a3:d8:52:b0:44:cd:43:4a:70:8e:58:85:95:e1: + 4e:2c:d6:2d:41:6f:d6:84:e7:c8:98:44:ca:47:db: + 2c:24:a5:69:26:cf:6b:b8:27:62:c3:f4:c9:7a:92: + 23:ed:13:67:82:ae:45:2e:45:e5:7e:72:3f:85:9d: + 94:62:10:e6:3c:91:a1:ad:77:00:e0:15:ec:f3:84: + 80:72:7a:8e:6e:60:97:c7:24:59:10:34:83:5b:e1: + a5:a4:69:b6:57:35:1c:78:59:c6:d3:2f:3a:73:67: + ee:94:ca:04:13:05:62:06:70:23:b3:f4:7c:ee:45: + d9:64:0b:5b:49:aa:a4:43:ce:26:c4:44:12:6c:b8: + dd:79 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + a2:37:b2:3f:69:fb:d7:86:79:54:49:31:95:33:2b:f3:d1:09: + 14:49:62:60:86:a5:b0:11:e2:50:c2:1d:06:57:3e:2d:e8:33: + 64:be:9b:aa:ad:5f:1b:4d:d4:99:95:a2:8b:9a:c9:62:72:b5: + 69:ea:d9:58:ab:35:ed:15:a2:43:d6:b6:bc:07:79:65:64:73: + 7d:d7:79:ca:7b:d5:5a:51:c6:e1:53:04:96:8d:38:cf:a3:17: + ac:39:71:6b:01:c3:8b:53:3c:63:e9:ee:79:c0:e4:be:92:32: + 64:7a:b3:1f:97:94:62:bd:ea:b2:20:15:95:fb:97:f2:78:2f: + 63:36:40:38:e3:46:0f:1d:dd:ac:95:ca:e7:4b:90:7b:b1:4b: + a9:d4:c5:eb:9a:da:aa:d5:a3:94:14:46:8d:2d:1f:f3:3a:d6: + 93:3a:f6:3e:79:fc:e8:e6:b0:75:ed:ee:3d:c9:70:c7:5d:aa: + 81:4b:46:25:1c:c7:6c:15:e3:95:4e:0f:aa:32:37:94:0a:17: + 24:92:13:84:58:d2:63:6f:2b:f7:e6:5b:62:0b:13:17:b0:0d: + 52:4c:fe:fe:6f:5c:e2:91:6e:1d:fd:a4:62:d7:68:fa:8e:7a: + 4f:d2:08:da:93:dc:f0:92:11:7a:d0:dc:72:93:0c:73:93:62: + 85:68:d0:f4 +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAACfAAAAAIAAAABMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDExITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODEyMDExODE4NTVaFw0wODExMjgx +ODE4NTVaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDExFjAUBgNVBAMTDURTVCBSb290Q0EgWDEx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANLGJrbnpT3BxGjVUG9TxW9JEwm4ryxIjRRqoxdf +WvnTLnUv2Chi0ZMv/E3Uq4flCMeZ55I/db3rJbQVwZsZPdJEjdd0IG03Ao9pk1uK +xBmd9LIO/BZsubEFkoPRhSxglD5FVaDZqwgh5mDoO3TymVBRaNADLbGAvqPYUrBE +zUNKcI5YhZXhTizWLUFv1oTnyJhEykfbLCSlaSbPa7gnYsP0yXqSI+0TZ4KuRS5F +5X5yP4WdlGIQ5jyRoa13AOAV7POEgHJ6jm5gl8ckWRA0g1vhpaRptlc1HHhZxtMv +OnNn7pTKBBMFYgZwI7P0fO5F2WQLW0mqpEPOJsREEmy43XkCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAojeyP2n714Z5VEkxlTMr89EJFEliYIalsBHiUMIdBlc+Legz +ZL6bqq1fG03UmZWii5rJYnK1aerZWKs17RWiQ9a2vAd5ZWRzfdd5ynvVWlHG4VME +lo04z6MXrDlxawHDi1M8Y+nuecDkvpIyZHqzH5eUYr3qsiAVlfuX8ngvYzZAOONG +Dx3drJXK50uQe7FLqdTF65raqtWjlBRGjS0f8zrWkzr2Pnn86Oawde3uPclwx12q +gUtGJRzHbBXjlU4PqjI3lAoXJJIThFjSY28r9+ZbYgsTF7ANUkz+/m9c4pFuHf2k +Ytdo+o56T9II2pPc8JIRetDccpMMc5NihWjQ9A== +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 4 +======================================= + +MD5 Fingerprint=CD:3B:3D:62:5B:09:B8:09:36:87:9E:12:2F:71:64:BA +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + d0:1e:40:8b:00:00:77:6d:00:00:00:01:00:00:00:04 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/emailAddress=ca@digsigtrust.com + Validity + Not Before: Nov 30 22:46:16 1998 GMT + Not After : Nov 27 22:46:16 2008 GMT + Subject: C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA X2, CN=DST RootCA X2/emailAddress=ca@digsigtrust.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:dc:75:f0:8c:c0:75:96:9a:c0:62:1f:26:f7:c4: + e1:9a:ea:e0:56:73:5b:99:cd:01:44:a8:08:b6:d5: + a7:da:1a:04:18:39:92:4a:78:a3:81:c2:f5:77:7a: + 50:b4:70:ff:9a:ab:c6:c7:ca:6e:83:4f:42:98:fb: + 26:0b:da:dc:6d:d6:a9:99:55:52:67:e9:28:03:92: + dc:e5:b0:05:9a:0f:15:f9:6b:59:72:56:f2:fa:39: + fc:aa:68:ee:0f:1f:10:83:2f:fc:9d:fa:17:96:dd: + 82:e3:e6:45:7d:c0:4b:80:44:1f:ed:2c:e0:84:fd: + 91:5c:92:54:69:25:e5:62:69:dc:e5:ee:00:52:bd: + 33:0b:ad:75:02:85:a7:64:50:2d:c5:19:19:30:c0: + 26:db:c9:d3:fd:2e:99:ad:59:b5:0b:4d:d4:41:ae: + 85:48:43:59:dc:b7:a8:e2:a2:de:c3:8f:d7:b8:a1: + 62:a6:68:50:52:e4:cf:31:a7:94:85:da:9f:46:32: + 17:56:e5:f2:eb:66:3d:12:ff:43:db:98:ef:77:cf: + cb:81:8d:34:b1:c6:50:4a:26:d1:e4:3e:41:50:af: + 6c:ae:22:34:2e:d5:6b:6e:83:ba:79:b8:76:65:48: + da:09:29:64:63:22:b9:fb:47:76:85:8c:86:44:cb: + 09:db + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + b5:36:0e:5d:e1:61:28:5a:11:65:c0:3f:83:03:79:4d:be:28: + a6:0b:07:02:52:85:cd:f8:91:d0:10:6c:b5:6a:20:5b:1c:90: + d9:30:3c:c6:48:9e:8a:5e:64:f9:a1:71:77:ef:04:27:1f:07: + eb:e4:26:f7:73:74:c9:44:18:1a:66:d3:e0:43:af:91:3b:d1: + cb:2c:d8:74:54:3a:1c:4d:ca:d4:68:cd:23:7c:1d:10:9e:45: + e9:f6:00:6e:a6:cd:19:ff:4f:2c:29:8f:57:4d:c4:77:92:be: + e0:4c:09:fb:5d:44:86:66:21:a8:b9:32:a2:56:d5:e9:8c:83: + 7c:59:3f:c4:f1:0b:e7:9d:ec:9e:bd:9c:18:0e:3e:c2:39:79: + 28:b7:03:0d:08:cb:c6:e7:d9:01:37:50:10:ec:cc:61:16:40: + d4:af:31:74:7b:fc:3f:31:a7:d0:47:73:33:39:1b:cc:4e:6a: + d7:49:83:11:06:fe:eb:82:58:33:32:4c:f0:56:ac:1e:9c:2f: + 56:9a:7b:c1:4a:1c:a5:fd:55:36:ce:fc:96:4d:f4:b0:f0:ec: + b7:6c:82:ed:2f:31:99:42:4c:a9:b2:0d:b8:15:5d:f1:df:ba: + c9:b5:4a:d4:64:98:b3:26:a9:30:c8:fd:a6:ec:ab:96:21:ad: + 7f:c2:78:b6 +-----BEGIN CERTIFICATE----- +MIID2DCCAsACEQDQHkCLAAB3bQAAAAEAAAAEMA0GCSqGSIb3DQEBBQUAMIGpMQsw +CQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMOU2FsdCBMYWtlIENp +dHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UE +CxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIxITAfBgkqhkiG9w0B +CQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTAeFw05ODExMzAyMjQ2MTZaFw0wODExMjcy +MjQ2MTZaMIGpMQswCQYDVQQGEwJ1czENMAsGA1UECBMEVXRhaDEXMBUGA1UEBxMO +U2FsdCBMYWtlIENpdHkxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0 +IENvLjERMA8GA1UECxMIRFNUQ0EgWDIxFjAUBgNVBAMTDURTVCBSb290Q0EgWDIx +ITAfBgkqhkiG9w0BCQEWEmNhQGRpZ3NpZ3RydXN0LmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBANx18IzAdZaawGIfJvfE4Zrq4FZzW5nNAUSoCLbV +p9oaBBg5kkp4o4HC9Xd6ULRw/5qrxsfKboNPQpj7Jgva3G3WqZlVUmfpKAOS3OWw +BZoPFflrWXJW8vo5/Kpo7g8fEIMv/J36F5bdguPmRX3AS4BEH+0s4IT9kVySVGkl +5WJp3OXuAFK9MwutdQKFp2RQLcUZGTDAJtvJ0/0uma1ZtQtN1EGuhUhDWdy3qOKi +3sOP17ihYqZoUFLkzzGnlIXan0YyF1bl8utmPRL/Q9uY73fPy4GNNLHGUEom0eQ+ +QVCvbK4iNC7Va26Dunm4dmVI2gkpZGMiuftHdoWMhkTLCdsCAwEAATANBgkqhkiG +9w0BAQUFAAOCAQEAtTYOXeFhKFoRZcA/gwN5Tb4opgsHAlKFzfiR0BBstWogWxyQ +2TA8xkieil5k+aFxd+8EJx8H6+Qm93N0yUQYGmbT4EOvkTvRyyzYdFQ6HE3K1GjN +I3wdEJ5F6fYAbqbNGf9PLCmPV03Ed5K+4EwJ+11EhmYhqLkyolbV6YyDfFk/xPEL +553snr2cGA4+wjl5KLcDDQjLxufZATdQEOzMYRZA1K8xdHv8PzGn0EdzMzkbzE5q +10mDEQb+64JYMzJM8FasHpwvVpp7wUocpf1VNs78lk30sPDst2yC7S8xmUJMqbIN +uBVd8d+6ybVK1GSYsyapMMj9puyrliGtf8J4tg== +-----END CERTIFICATE----- + +Verisign Class 1 Public Primary Certification Authority +======================================================= + +MD5 Fingerprint=97:60:E8:57:5F:D3:50:47:E5:43:0C:94:36:8A:B0:62 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + cd:ba:7f:56:f0:df:e4:bc:54:fe:22:ac:b3:72:aa:55 + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:19:bf:6d:a3:56:61:2d:99:48:71:f6:67:de: + b9:8d:eb:b7:9e:86:80:0a:91:0e:fa:38:25:af:46: + 88:82:e5:73:a8:a0:9b:24:5d:0d:1f:cc:65:6e:0c: + b0:d0:56:84:18:87:9a:06:9b:10:a1:73:df:b4:58: + 39:6b:6e:c1:f6:15:d5:a8:a8:3f:aa:12:06:8d:31: + ac:7f:b0:34:d7:8f:34:67:88:09:cd:14:11:e2:4e: + 45:56:69:1f:78:02:80:da:dc:47:91:29:bb:36:c9: + 63:5c:c5:e0:d7:2d:87:7b:a1:b7:32:b0:7b:30:ba: + 2a:2f:31:aa:ee:a3:67:da:db + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 4c:3f:b8:8b:c6:68:df:ee:43:33:0e:5d:e9:a6:cb:07:84:4d: + 7a:33:ff:92:1b:f4:36:ad:d8:95:22:36:68:11:6c:7c:42:cc: + f3:9c:2e:c4:07:3f:14:b0:0f:4f:ff:90:92:76:f9:e2:bc:4a: + e9:8f:cd:a0:80:0a:f7:c5:29:f1:82:22:5d:b8:b1:dd:81:23: + a3:7b:25:15:46:30:79:16:f8:ea:05:4b:94:7f:1d:c2:1c:c8: + e3:b7:f4:10:40:3c:13:c3:5f:1f:53:e8:48:e4:86:b4:7b:a1: + 35:b0:7b:25:ba:b8:d3:8e:ab:3f:38:9d:00:34:00:98:f3:d1: + 71:94 +-----BEGIN CERTIFICATE----- +MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 +NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD +VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp +bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N +H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR +4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN +BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo +EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 +FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx +lA== +-----END CERTIFICATE----- + +Verisign Class 2 Public Primary Certification Authority +======================================================= + +MD5 Fingerprint=B3:9C:25:B1:C3:2E:32:53:80:15:30:9D:4D:02:77:3E +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 2d:1b:fc:4a:17:8d:a3:91:eb:e7:ff:f5:8b:45:be:0b + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:5a:8b:a3:0d:6a:23:83:80:6b:cf:39:87:f4: + 21:13:33:06:4c:25:a2:ed:55:12:97:c5:a7:80:b9: + fa:83:c1:20:a0:fa:2f:15:0d:7c:a1:60:6b:7e:79: + 2c:fa:06:0f:3a:ae:f6:1b:6f:b1:d2:ff:2f:28:52: + 5f:83:7d:4b:c4:7a:b7:f8:66:1f:80:54:fc:b7:c2: + 8e:59:4a:14:57:46:d1:9a:93:be:41:91:03:bb:15: + 80:93:5c:eb:e7:cc:08:6c:3f:3e:b3:4a:fc:ff:4b: + 6c:23:d5:50:82:26:44:19:8e:23:c3:71:ea:19:24: + 47:04:9e:75:bf:c8:a6:00:1f + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + 8a:1b:2b:fa:39:c1:74:d7:5e:d8:19:64:a2:58:4a:2d:37:e0: + 33:47:0f:ac:ed:f7:aa:db:1e:e4:8b:06:5c:60:27:ca:45:52: + ce:16:ef:3f:06:64:e7:94:68:7c:60:33:15:11:69:af:9d:62: + 8d:a3:03:54:6b:a6:be:e5:ee:05:18:60:04:bf:42:80:fd:d0: + a8:a8:1e:01:3b:f7:a3:5c:af:a3:dc:e6:26:80:23:3c:b8:44: + 74:f7:0a:ae:49:8b:61:78:cc:24:bf:88:8a:a7:0e:ea:73:19: + 41:fd:4d:03:f0:88:d1:e5:78:8d:a5:2a:4f:f6:97:0d:17:77: + ca:d8 +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh +YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 +FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg +J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc +r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= + +MD5 Fingerprint=10:FC:63:5D:F6:26:3E:0D:F3:25:BE:5F:79:CD:67:67 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 70:ba:e4:1d:10:d9:29:34:b6:38:ca:7b:03:cc:ba:bf + Signature Algorithm: md2WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + Validity + Not Before: Jan 29 00:00:00 1996 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:5c:59:9e:f2:1b:8a:01:14:b4:10:df:04:40: + db:e3:57:af:6a:45:40:8f:84:0c:0b:d1:33:d9:d9: + 11:cf:ee:02:58:1f:25:f7:2a:a8:44:05:aa:ec:03: + 1f:78:7f:9e:93:b9:9a:00:aa:23:7d:d6:ac:85:a2: + 63:45:c7:72:27:cc:f4:4c:c6:75:71:d2:39:ef:4f: + 42:f0:75:df:0a:90:c6:8e:20:6f:98:0f:f8:ac:23: + 5f:70:29:36:a4:c9:86:e7:b1:9a:20:cb:53:a5:85: + e7:3d:be:7d:9a:fe:24:45:33:dc:76:15:ed:0f:a2: + 71:64:4c:65:2e:81:68:45:a7 + Exponent: 65537 (0x10001) + Signature Algorithm: md2WithRSAEncryption + bb:4c:12:2b:cf:2c:26:00:4f:14:13:dd:a6:fb:fc:0a:11:84: + 8c:f3:28:1c:67:92:2f:7c:b6:c5:fa:df:f0:e8:95:bc:1d:8f: + 6c:2c:a8:51:cc:73:d8:a4:c0:53:f0:4e:d6:26:c0:76:01:57: + 81:92:5e:21:f1:d1:b1:ff:e7:d0:21:58:cd:69:17:e3:44:1c: + 9c:19:44:39:89:5c:dc:9c:00:0f:56:8d:02:99:ed:a2:90:45: + 4c:e4:bb:10:a4:3d:f0:32:03:0e:f1:ce:f8:e8:c9:51:8c:e6: + 62:9f:e6:9f:c0:7d:b7:72:9c:c9:36:3a:6b:9f:4e:a8:ff:64: + 0d:64 +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do +lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc +AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +-----END CERTIFICATE----- + +Verisign Class 1 Public Primary Certification Authority - G2 +============================================================ + +MD5 Fingerprint=DB:23:3D:F9:69:FA:4B:B9:95:80:44:73:5E:7D:41:83 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 4c:c7:ea:aa:98:3e:71:d3:93:10:f8:3d:3a:89:91:92 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:aa:d0:ba:be:16:2d:b8:83:d4:ca:d2:0f:bc:76: + 31:ca:94:d8:1d:93:8c:56:02:bc:d9:6f:1a:6f:52: + 36:6e:75:56:0a:55:d3:df:43:87:21:11:65:8a:7e: + 8f:bd:21:de:6b:32:3f:1b:84:34:95:05:9d:41:35: + eb:92:eb:96:dd:aa:59:3f:01:53:6d:99:4f:ed:e5: + e2:2a:5a:90:c1:b9:c4:a6:15:cf:c8:45:eb:a6:5d: + 8e:9c:3e:f0:64:24:76:a5:cd:ab:1a:6f:b6:d8:7b: + 51:61:6e:a6:7f:87:c8:e2:b7:e5:34:dc:41:88:ea: + 09:40:be:73:92:3d:6b:e7:75 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + a9:4f:c3:0d:c7:67:be:2c:cb:d9:a8:cd:2d:75:e7:7e:15:9e: + 3b:72:eb:7e:eb:5c:2d:09:87:d6:6b:6d:60:7c:e5:ae:c5:90: + 23:0c:5c:4a:d0:af:b1:5d:f3:c7:b6:0a:db:e0:15:93:0d:dd: + 03:bc:c7:76:8a:b5:dd:4f:c3:9b:13:75:b8:01:c0:e6:c9:5b: + 6b:a5:b8:89:dc:ac:a4:dd:72:ed:4e:a1:f7:4f:bc:06:d3:ea: + c8:64:74:7b:c2:95:41:9c:65:73:58:f1:90:9a:3c:6a:b1:98: + c9:c4:87:bc:cf:45:6d:45:e2:6e:22:3f:fe:bc:0f:31:5c:e8: + f2:d9 +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK +VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm +Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J +h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul +uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 +DzFc6PLZ +-----END CERTIFICATE----- + +Verisign Class 2 Public Primary Certification Authority - G2 +============================================================ + +MD5 Fingerprint=2D:BB:E5:25:D3:D1:65:82:3A:B7:0E:FA:E6:EB:E2:E1 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + b9:2f:60:cc:88:9f:a1:7a:46:09:b8:5b:70:6c:8a:af + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a7:88:01:21:74:2c:e7:1a:03:f0:98:e1:97:3c: + 0f:21:08:f1:9c:db:97:e9:9a:fc:c2:04:06:13:be: + 5f:52:c8:cc:1e:2c:12:56:2c:b8:01:69:2c:cc:99: + 1f:ad:b0:96:ae:79:04:f2:13:39:c1:7b:98:ba:08: + 2c:e8:c2:84:13:2c:aa:69:e9:09:f4:c7:a9:02:a4: + 42:c2:23:4f:4a:d8:f0:0e:a2:fb:31:6c:c9:e6:6f: + 99:27:07:f5:e6:f4:4c:78:9e:6d:eb:46:86:fa:b9: + 86:c9:54:f2:b2:c4:af:d4:46:1c:5a:c9:15:30:ff: + 0d:6c:f5:2d:0e:6d:ce:7f:77 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 72:2e:f9:7f:d1:f1:71:fb:c4:9e:f6:c5:5e:51:8a:40:98:b8: + 68:f8:9b:1c:83:d8:e2:9d:bd:ff:ed:a1:e6:66:ea:2f:09:f4: + ca:d7:ea:a5:2b:95:f6:24:60:86:4d:44:2e:83:a5:c4:2d:a0: + d3:ae:78:69:6f:72:da:6c:ae:08:f0:63:92:37:e6:bb:c4:30: + 17:ad:77:cc:49:35:aa:cf:d8:8f:d1:be:b7:18:96:47:73:6a: + 54:22:34:64:2d:b6:16:9b:59:5b:b4:51:59:3a:b3:0b:14:f4: + 12:df:67:a0:f4:ad:32:64:5e:b1:46:72:27:8c:12:7b:c5:44: + b4:ae +-----BEGIN CERTIFICATE----- +MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns +YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y +aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe +Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj +IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx +KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM +HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw +DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC +AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji +nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX +rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn +jBJ7xUS0rg== +-----END CERTIFICATE----- + +GTE CyberTrust Root CA +====================== + +MD5 Fingerprint=C4:D7:F0:B2:A3:C5:7D:61:67:F0:04:CD:43:D3:BA:58 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 419 (0x1a3) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, CN=GTE CyberTrust Root + Validity + Not Before: Feb 23 23:01:00 1996 GMT + Not After : Feb 23 23:59:00 2006 GMT + Subject: C=US, O=GTE Corporation, CN=GTE CyberTrust Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b8:e6:4f:ba:db:98:7c:71:7c:af:44:b7:d3:0f: + 46:d9:64:e5:93:c1:42:8e:c7:ba:49:8d:35:2d:7a: + e7:8b:bd:e5:05:31:59:c6:b1:2f:0a:0c:fb:9f:a7: + 3f:a2:09:66:84:56:1e:37:29:1b:87:e9:7e:0c:ca: + 9a:9f:a5:7f:f5:15:94:a3:d5:a2:46:82:d8:68:4c: + d1:37:15:06:68:af:bd:f8:b0:b3:f0:29:f5:95:5a: + 09:16:61:77:0a:22:25:d4:4f:45:aa:c7:bd:e5:96: + df:f9:d4:a8:8e:42:cc:24:c0:1e:91:27:4a:b5:6d: + 06:80:63:39:c4:a2:5e:38:03 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 12:b3:75:c6:5f:1d:e1:61:55:80:00:d4:81:4b:7b:31:0f:23: + 63:e7:3d:f3:03:f9:f4:36:a8:bb:d9:e3:a5:97:4d:ea:2b:29: + e0:d6:6a:73:81:e6:c0:89:a3:d3:f1:e0:a5:a5:22:37:9a:63: + c2:48:20:b4:db:72:e3:c8:f6:d9:7c:be:b1:af:53:da:14:b4: + 21:b8:d6:d5:96:e3:fe:4e:0c:59:62:b6:9a:4a:f9:42:dd:8c: + 6f:81:a9:71:ff:f4:0a:72:6d:6d:44:0e:9d:f3:74:74:a8:d5: + 34:49:e9:5e:9e:e9:b4:7a:e1:e5:5a:1f:84:30:9c:d3:9f:a5: + 25:d8 +-----BEGIN CERTIFICATE----- +MIIB+jCCAWMCAgGjMA0GCSqGSIb3DQEBBAUAMEUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xHDAaBgNVBAMTE0dURSBDeWJlclRydXN0IFJv +b3QwHhcNOTYwMjIzMjMwMTAwWhcNMDYwMjIzMjM1OTAwWjBFMQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMRwwGgYDVQQDExNHVEUgQ3liZXJU +cnVzdCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC45k+625h8cXyv +RLfTD0bZZOWTwUKOx7pJjTUteueLveUFMVnGsS8KDPufpz+iCWaEVh43KRuH6X4M +ypqfpX/1FZSj1aJGgthoTNE3FQZor734sLPwKfWVWgkWYXcKIiXUT0Wqx73llt/5 +1KiOQswkwB6RJ0q1bQaAYznEol44AwIDAQABMA0GCSqGSIb3DQEBBAUAA4GBABKz +dcZfHeFhVYAA1IFLezEPI2PnPfMD+fQ2qLvZ46WXTeorKeDWanOB5sCJo9Px4KWl +IjeaY8JIILTbcuPI9tl8vrGvU9oUtCG41tWW4/5ODFlitppK+ULdjG+BqXH/9Apy +bW1EDp3zdHSo1TRJ6V6e6bR64eVaH4QwnNOfpSXY +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G2 +============================================================ + +MD5 Fingerprint=A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 7d:d9:fe:07:cf:a8:1e:b7:10:79:67:fb:a7:89:34:c6 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cc:5e:d1:11:5d:5c:69:d0:ab:d3:b9:6a:4c:99: + 1f:59:98:30:8e:16:85:20:46:6d:47:3f:d4:85:20: + 84:e1:6d:b3:f8:a4:ed:0c:f1:17:0f:3b:f9:a7:f9: + 25:d7:c1:cf:84:63:f2:7c:63:cf:a2:47:f2:c6:5b: + 33:8e:64:40:04:68:c1:80:b9:64:1c:45:77:c7:d8: + 6e:f5:95:29:3c:50:e8:34:d7:78:1f:a8:ba:6d:43: + 91:95:8f:45:57:5e:7e:c5:fb:ca:a4:04:eb:ea:97: + 37:54:30:6f:bb:01:47:32:33:cd:dc:57:9b:64:69: + 61:f8:9b:1d:1c:89:4f:5c:67 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 51:4d:cd:be:5c:cb:98:19:9c:15:b2:01:39:78:2e:4d:0f:67: + 70:70:99:c6:10:5a:94:a4:53:4d:54:6d:2b:af:0d:5d:40:8b: + 64:d3:d7:ee:de:56:61:92:5f:a6:c4:1d:10:61:36:d3:2c:27: + 3c:e8:29:09:b9:11:64:74:cc:b5:73:9f:1c:48:a9:bc:61:01: + ee:e2:17:a6:0c:e3:40:08:3b:0e:e7:eb:44:73:2a:9a:f1:69: + 92:ef:71:14:c3:39:ac:71:a7:91:09:6f:e4:71:06:b3:ba:59: + 57:26:79:00:f6:f8:0d:a2:33:30:28:d4:aa:58:a0:9d:9d:69: + 91:fd +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 +pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 +13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk +U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i +F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY +oJ2daZH9 +-----END CERTIFICATE----- + +Verisign Class 4 Public Primary Certification Authority - G2 +============================================================ + +MD5 Fingerprint=26:6D:2C:19:98:B6:70:68:38:50:54:19:EC:90:34:60 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 32:88:8e:9a:d2:f5:eb:13:47:f8:7f:c4:20:37:25:f8 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: May 18 00:00:00 1998 GMT + Not After : Aug 1 23:59:59 2028 GMT + Subject: C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ba:f0:e4:cf:f9:c4:ae:85:54:b9:07:57:f9:8f: + c5:7f:68:11:f8:c4:17:b0:44:dc:e3:30:73:d5:2a: + 62:2a:b8:d0:cc:1c:ed:28:5b:7e:bd:6a:dc:b3:91: + 24:ca:41:62:3c:fc:02:01:bf:1c:16:31:94:05:97: + 76:6e:a2:ad:bd:61:17:6c:4e:30:86:f0:51:37:2a: + 50:c7:a8:62:81:dc:5b:4a:aa:c1:a0:b4:6e:eb:2f: + e5:57:c5:b1:2b:40:70:db:5a:4d:a1:8e:1f:bd:03: + 1f:d8:03:d4:8f:4c:99:71:bc:e2:82:cc:58:e8:98: + 3a:86:d3:86:38:f3:00:29:1f + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 85:8c:12:c1:a7:b9:50:15:7a:cb:3e:ac:b8:43:8a:dc:aa:dd: + 14:ba:89:81:7e:01:3c:23:71:21:88:2f:82:dc:63:fa:02:45: + ac:45:59:d7:2a:58:44:5b:b7:9f:81:3b:92:68:3d:e2:37:24: + f5:7b:6c:8f:76:35:96:09:a8:59:9d:b9:ce:23:ab:74:d6:83: + fd:32:73:27:d8:69:3e:43:74:f6:ae:c5:89:9a:e7:53:7c:e9: + 7b:f6:4b:f3:c1:65:83:de:8d:8a:9c:3c:88:8d:39:59:fc:aa: + 3f:22:8d:a1:c1:66:50:81:72:4c:ed:22:64:4f:4f:ca:80:91: + b6:29 +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh +c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy +MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp +emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X +DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw +FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg +UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo +YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 +MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB +AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM +HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK +qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj +cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y +cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP +T8qAkbYp +-----END CERTIFICATE----- + +GlobalSign Root CA +================== + +MD5 Fingerprint=AB:BF:EA:E3:6B:29:A6:CC:A6:78:35:99:EF:AD:2B:80 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 02:00:00:00:00:00:d6:78:b7:94:05 + Signature Algorithm: md5WithRSAEncryption + Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Validity + Not Before: Sep 1 12:00:00 1998 GMT + Not After : Jan 28 12:00:00 2014 GMT + Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:da:0e:e6:99:8d:ce:a3:e3:4f:8a:7e:fb:f1:8b: + 83:25:6b:ea:48:1f:f1:2a:b0:b9:95:11:04:bd:f0: + 63:d1:e2:67:66:cf:1c:dd:cf:1b:48:2b:ee:8d:89: + 8e:9a:af:29:80:65:ab:e9:c7:2d:12:cb:ab:1c:4c: + 70:07:a1:3d:0a:30:cd:15:8d:4f:f8:dd:d4:8c:50: + 15:1c:ef:50:ee:c4:2e:f7:fc:e9:52:f2:91:7d:e0: + 6d:d5:35:30:8e:5e:43:73:f2:41:e9:d5:6a:e3:b2: + 89:3a:56:39:38:6f:06:3c:88:69:5b:2a:4d:c5:a7: + 54:b8:6c:89:cc:9b:f9:3c:ca:e5:fd:89:f5:12:3c: + 92:78:96:d6:dc:74:6e:93:44:61:d1:8d:c7:46:b2: + 75:0e:86:e8:19:8a:d5:6d:6c:d5:78:16:95:a2:e9: + c8:0a:38:eb:f2:24:13:4f:73:54:93:13:85:3a:1b: + bc:1e:34:b5:8b:05:8c:b9:77:8b:b1:db:1f:20:91: + ab:09:53:6e:90:ce:7b:37:74:b9:70:47:91:22:51: + 63:16:79:ae:b1:ae:41:26:08:c8:19:2b:d1:46:aa: + 48:d6:64:2a:d7:83:34:ff:2c:2a:c1:6c:19:43:4a: + 07:85:e7:d3:7c:f6:21:68:ef:ea:f2:52:9f:7f:93: + 90:cf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + ae:aa:9f:fc:b7:d2:cb:1f:5f:39:29:28:18:9e:34:c9:6c:4f: + 6f:1a:f0:64:a2:70:4a:4f:13:86:9b:60:28:9e:e8:81:49:98: + 7d:0a:bb:e5:b0:9d:3d:36:db:8f:05:51:ff:09:31:2a:1f:dd: + 89:77:9e:0f:2e:6c:95:04:ed:86:cb:b4:00:3f:84:02:4d:80: + 6a:2a:2d:78:0b:ae:6f:2b:a2:83:44:83:1f:cd:50:82:4c:24: + af:bd:f7:a5:b4:c8:5a:0f:f4:e7:47:5e:49:8e:37:96:fe:9a: + 88:05:3a:d9:c0:db:29:87:e6:19:96:47:a7:3a:a6:8c:8b:3c: + 77:fe:46:63:a7:53:da:21:d1:ac:7e:49:a2:4b:e6:c3:67:59: + 2f:b3:8a:0e:bb:2c:bd:a9:aa:42:7c:35:c1:d8:7f:d5:a7:31: + 3a:4e:63:43:39:af:08:b0:61:34:8c:d3:98:a9:43:34:f6:0f: + 87:29:3b:9d:c2:56:58:98:77:c3:f7:1b:ac:f6:9d:f8:3e:aa: + a7:54:45:f0:f5:f9:d5:31:65:fe:6b:58:9c:71:b3:1e:d7:52: + ea:32:17:fc:40:60:1d:c9:79:24:b2:f6:6c:fd:a8:66:0e:82: + dd:98:cb:da:c2:44:4f:2e:a0:7b:f2:f7:6b:2c:76:11:84:46: + 8a:78:a3:e3 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQU +YHtmGkUNl8qJUC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B +AQQFAAOCAQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq7 +5bCdPTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q +gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT2iHR +rH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlDNPYPhyk7 +ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o +Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w== +-----END CERTIFICATE----- + +ValiCert Class 1 VA +=================== + +MD5 Fingerprint=65:58:AB:15:AD:57:6C:1E:A8:A7:B5:69:AC:BF:FF:EB +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com + Validity + Not Before: Jun 25 22:23:48 1999 GMT + Not After : Jun 25 22:23:48 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d8:59:82:7a:89:b8:96:ba:a6:2f:68:6f:58:2e: + a7:54:1c:06:6e:f4:ea:8d:48:bc:31:94:17:f0:f3: + 4e:bc:b2:b8:35:92:76:b0:d0:a5:a5:01:d7:00:03: + 12:22:19:08:f8:ff:11:23:9b:ce:07:f5:bf:69:1a: + 26:fe:4e:e9:d1:7f:9d:2c:40:1d:59:68:6e:a6:f8: + 58:b0:9d:1a:8f:d3:3f:f1:dc:19:06:81:a8:0e:e0: + 3a:dd:c8:53:45:09:06:e6:0f:70:c3:fa:40:a6:0e: + e2:56:05:0f:18:4d:fc:20:82:d1:73:55:74:8d:76: + 72:a0:1d:9d:1d:c0:dd:3f:71 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 50:68:3d:49:f4:2c:1c:06:94:df:95:60:7f:96:7b:17:fe:4f: + 71:ad:64:c8:dd:77:d2:ef:59:55:e8:3f:e8:8e:05:2a:21:f2: + 07:d2:b5:a7:52:fe:9c:b1:b6:e2:5b:77:17:40:ea:72:d6:23: + cb:28:81:32:c3:00:79:18:ec:59:17:89:c9:c6:6a:1e:71:c9: + fd:b7:74:a5:25:45:69:c5:48:ab:19:e1:45:8a:25:6b:19:ee: + e5:bb:12:f5:7f:f7:a6:8d:51:c3:f0:9d:74:b7:a9:3e:a0:a5: + ff:b6:49:03:13:da:22:cc:ed:71:82:2b:99:cf:3a:b7:f5:2d: + 72:c8 +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy +NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y +LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ +TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y +TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 +LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW +I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw +nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI +-----END CERTIFICATE----- + +ValiCert Class 2 VA +=================== + +MD5 Fingerprint=A9:23:75:9B:BA:49:36:6E:31:C2:DB:F2:E7:66:BA:87 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com + Validity + Not Before: Jun 26 00:19:54 1999 GMT + Not After : Jun 26 00:19:54 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:3a:71:ca:e5:ab:c8:59:92:55:d7:ab:d8:74: + 0e:f9:ee:d9:f6:55:47:59:65:47:0e:05:55:dc:eb: + 98:36:3c:5c:53:5d:d3:30:cf:38:ec:bd:41:89:ed: + 25:42:09:24:6b:0a:5e:b3:7c:dd:52:2d:4c:e6:d4: + d6:7d:5a:59:a9:65:d4:49:13:2d:24:4d:1c:50:6f: + b5:c1:85:54:3b:fe:71:e4:d3:5c:42:f9:80:e0:91: + 1a:0a:5b:39:36:67:f3:3f:55:7c:1b:3f:b4:5f:64: + 73:34:e3:b4:12:bf:87:64:f8:da:12:ff:37:27:c1: + b3:43:bb:ef:7b:6e:2e:69:f7 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 3b:7f:50:6f:6f:50:94:99:49:62:38:38:1f:4b:f8:a5:c8:3e: + a7:82:81:f6:2b:c7:e8:c5:ce:e8:3a:10:82:cb:18:00:8e:4d: + bd:a8:58:7f:a1:79:00:b5:bb:e9:8d:af:41:d9:0f:34:ee:21: + 81:19:a0:32:49:28:f4:c4:8e:56:d5:52:33:fd:50:d5:7e:99: + 6c:03:e4:c9:4c:fc:cb:6c:ab:66:b3:4a:21:8c:e5:b5:0c:32: + 3e:10:b2:cc:6c:a1:dc:9a:98:4c:02:5b:f3:ce:b9:9e:a5:72: + 0e:4a:b7:3f:3c:e6:16:68:f8:be:ed:74:4c:bc:5b:d5:62:1f: + 43:dd +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy +NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY +dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 +WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS +v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v +UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu +IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC +W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd +-----END CERTIFICATE----- + +RSA Root Certificate 1 +====================== + +MD5 Fingerprint=A2:6F:53:B7:EE:40:DB:4A:68:E7:FA:18:D9:10:4B:72 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com + Validity + Not Before: Jun 26 00:22:33 1999 GMT + Not After : Jun 26 00:22:33 2019 GMT + Subject: L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 Policy Validation Authority, CN=http://www.valicert.com//emailAddress=info@valicert.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e3:98:51:96:1c:e8:d5:b1:06:81:6a:57:c3:72: + 75:93:ab:cf:9e:a6:fc:f3:16:52:d6:2d:4d:9f:35: + 44:a8:2e:04:4d:07:49:8a:38:29:f5:77:37:e7:b7: + ab:5d:df:36:71:14:99:8f:dc:c2:92:f1:e7:60:92: + 97:ec:d8:48:dc:bf:c1:02:20:c6:24:a4:28:4c:30: + 5a:76:6d:b1:5c:f3:dd:de:9e:10:71:a1:88:c7:5b: + 9b:41:6d:ca:b0:b8:8e:15:ee:ad:33:2b:cf:47:04: + 5c:75:71:0a:98:24:98:29:a7:49:59:a5:dd:f8:b7: + 43:62:61:f3:d3:e2:d0:55:3f + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 56:bb:02:58:84:67:08:2c:df:1f:db:7b:49:33:f5:d3:67:9d: + f4:b4:0a:10:b3:c9:c5:2c:e2:92:6a:71:78:27:f2:70:83:42: + d3:3e:cf:a9:54:f4:f1:d8:92:16:8c:d1:04:cb:4b:ab:c9:9f: + 45:ae:3c:8a:a9:b0:71:33:5d:c8:c5:57:df:af:a8:35:b3:7f: + 89:87:e9:e8:25:92:b8:7f:85:7a:ae:d6:bc:1e:37:58:2a:67: + c9:91:cf:2a:81:3e:ed:c6:39:df:c0:3e:19:9c:19:cc:13:4d: + 82:41:b5:8c:de:e0:3d:60:08:20:0f:45:7e:6b:a2:7f:a3:8c: + 15:ee +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 +IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz +BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y +aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG +9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy +NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y +azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw +Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl +cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD +cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs +2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY +JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE +Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ +n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A +PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu +-----END CERTIFICATE----- + +Verisign Class 1 Public Primary Certification Authority - G3 +============================================================ + +MD5 Fingerprint=B1:47:BC:18:57:D1:18:A0:78:2D:EC:71:E8:2A:95:73 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 8b:5b:75:56:84:54:85:0b:00:cf:af:38:48:ce:b1:a4 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 1 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:dd:84:d4:b9:b4:f9:a7:d8:f3:04:78:9c:de:3d: + dc:6c:13:16:d9:7a:dd:24:51:66:c0:c7:26:59:0d: + ac:06:08:c2:94:d1:33:1f:f0:83:35:1f:6e:1b:c8: + de:aa:6e:15:4e:54:27:ef:c4:6d:1a:ec:0b:e3:0e: + f0:44:a5:57:c7:40:58:1e:a3:47:1f:71:ec:60:f6: + 6d:94:c8:18:39:ed:fe:42:18:56:df:e4:4c:49:10: + 78:4e:01:76:35:63:12:36:dd:66:bc:01:04:36:a3: + 55:68:d5:a2:36:09:ac:ab:21:26:54:06:ad:3f:ca: + 14:e0:ac:ca:ad:06:1d:95:e2:f8:9d:f1:e0:60:ff: + c2:7f:75:2b:4c:cc:da:fe:87:99:21:ea:ba:fe:3e: + 54:d7:d2:59:78:db:3c:6e:cf:a0:13:00:1a:b8:27: + a1:e4:be:67:96:ca:a0:c5:b3:9c:dd:c9:75:9e:eb: + 30:9a:5f:a3:cd:d9:ae:78:19:3f:23:e9:5c:db:29: + bd:ad:55:c8:1b:54:8c:63:f6:e8:a6:ea:c7:37:12: + 5c:a3:29:1e:02:d9:db:1f:3b:b4:d7:0f:56:47:81: + 15:04:4a:af:83:27:d1:c5:58:88:c1:dd:f6:aa:a7: + a3:18:da:68:aa:6d:11:51:e1:bf:65:6b:9f:96:76: + d1:3d + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + ab:66:8d:d7:b3:ba:c7:9a:b6:e6:55:d0:05:f1:9f:31:8d:5a: + aa:d9:aa:46:26:0f:71:ed:a5:ad:53:56:62:01:47:2a:44:e9: + fe:3f:74:0b:13:9b:b9:f4:4d:1b:b2:d1:5f:b2:b6:d2:88:5c: + b3:9f:cd:cb:d4:a7:d9:60:95:84:3a:f8:c1:37:1d:61:ca:e7: + b0:c5:e5:91:da:54:a6:ac:31:81:ae:97:de:cd:08:ac:b8:c0: + 97:80:7f:6e:72:a4:e7:69:13:95:65:1f:c4:93:3c:fd:79:8f: + 04:d4:3e:4f:ea:f7:9e:ce:cd:67:7c:4f:65:02:ff:91:85:54: + 73:c7:ff:36:f7:86:2d:ec:d0:5e:4f:ff:11:9f:72:06:d6:b8: + 1a:f1:4c:0d:26:65:e2:44:80:1e:c7:9f:e3:dd:e8:0a:da:ec: + a5:20:80:69:68:a1:4f:7e:e1:6b:cf:07:41:fa:83:8e:bc:38: + dd:b0:2e:11:b1:6b:b2:42:cc:9a:bc:f9:48:22:79:4a:19:0f: + b2:1c:3e:20:74:d9:6a:c3:be:f2:28:78:13:56:79:4f:6d:50: + ea:1b:b0:b5:57:b1:37:66:58:23:f3:dc:0f:df:0a:87:c4:ef: + 86:05:d5:38:14:60:99:a3:4b:de:06:96:71:2c:f2:db:b6:1f: + a4:ef:3f:ee +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 +nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO +8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV +ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb +PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 +6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr +n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a +qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 +wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 +ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs +pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 +E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== +-----END CERTIFICATE----- + +Verisign Class 2 Public Primary Certification Authority - G3 +============================================================ + +MD5 Fingerprint=F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 61:70:cb:49:8c:5f:98:45:29:e7:b0:a6:d9:50:5b:7a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 2 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:af:0a:0d:c2:d5:2c:db:67:b9:2d:e5:94:27:dd: + a5:be:e0:b0:4d:8f:b3:61:56:3c:d6:7c:c3:f4:cd: + 3e:86:cb:a2:88:e2:e1:d8:a4:69:c5:b5:e2:bf:c1: + a6:47:50:5e:46:39:8b:d5:96:ba:b5:6f:14:bf:10: + ce:27:13:9e:05:47:9b:31:7a:13:d8:1f:d9:d3:02: + 37:8b:ad:2c:47:f0:8e:81:06:a7:0d:30:0c:eb:f7: + 3c:0f:20:1d:dc:72:46:ee:a5:02:c8:5b:c3:c9:56: + 69:4c:c5:18:c1:91:7b:0b:d5:13:00:9b:bc:ef:c3: + 48:3e:46:60:20:85:2a:d5:90:b6:cd:8b:a0:cc:32: + dd:b7:fd:40:55:b2:50:1c:56:ae:cc:8d:77:4d:c7: + 20:4d:a7:31:76:ef:68:92:8a:90:1e:08:81:56:b2: + ad:69:a3:52:d0:cb:1c:c4:23:3d:1f:99:fe:4c:e8: + 16:63:8e:c6:08:8e:f6:31:f6:d2:fa:e5:76:dd:b5: + 1c:92:a3:49:cd:cd:01:cd:68:cd:a9:69:ba:a3:eb: + 1d:0d:9c:a4:20:a6:c1:a0:c5:d1:46:4c:17:6d:d2: + ac:66:3f:96:8c:e0:84:d4:36:ff:22:59:c5:f9:11: + 60:a8:5f:04:7d:f2:1a:f6:25:42:61:0f:c4:4a:b8: + 3e:89 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 34:26:15:3c:c0:8d:4d:43:49:1d:bd:e9:21:92:d7:66:9c:b7: + de:c5:b8:d0:e4:5d:5f:76:22:c0:26:f9:84:3a:3a:f9:8c:b5: + fb:ec:60:f1:e8:ce:04:b0:c8:dd:a7:03:8f:30:f3:98:df:a4: + e6:a4:31:df:d3:1c:0b:46:dc:72:20:3f:ae:ee:05:3c:a4:33: + 3f:0b:39:ac:70:78:73:4b:99:2b:df:30:c2:54:b0:a8:3b:55: + a1:fe:16:28:cd:42:bd:74:6e:80:db:27:44:a7:ce:44:5d:d4: + 1b:90:98:0d:1e:42:94:b1:00:2c:04:d0:74:a3:02:05:22:63: + 63:cd:83:b5:fb:c1:6d:62:6b:69:75:fd:5d:70:41:b9:f5:bf: + 7c:df:be:c1:32:73:22:21:8b:58:81:7b:15:91:7a:ba:e3:64: + 48:b0:7f:fb:36:25:da:95:d0:f1:24:14:17:dd:18:80:6b:46: + 23:39:54:f5:8e:62:09:04:1d:94:90:a6:9b:e6:25:e2:42:45: + aa:b8:90:ad:be:08:8f:a9:0b:42:18:94:cf:72:39:e1:b1:43: + e0:28:cf:b7:e7:5a:6c:13:6b:49:b3:ff:e3:18:7c:89:8b:33: + 5d:ac:33:d7:a7:f9:da:3a:55:c9:58:10:f9:aa:ef:5a:b6:cf: + 4b:4b:df:2a +-----BEGIN CERTIFICATE----- +MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ +BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy +aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp +Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV +BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp +Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g +Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU +J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO +JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY +wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o +koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN +qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E +Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe +xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u +7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU +sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI +sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP +cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ + +MD5 Fingerprint=CD:68:B6:A7:C7:C4:CE:75:E0:1D:4F:57:44:61:92:09 +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 9b:7e:06:49:a3:3e:62:b9:d5:ee:90:48:71:29:ef:57 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:cb:ba:9c:52:fc:78:1f:1a:1e:6f:1b:37:73:bd: + f8:c9:6b:94:12:30:4f:f0:36:47:f5:d0:91:0a:f5: + 17:c8:a5:61:c1:16:40:4d:fb:8a:61:90:e5:76:20: + c1:11:06:7d:ab:2c:6e:a6:f5:11:41:8e:fa:2d:ad: + 2a:61:59:a4:67:26:4c:d0:e8:bc:52:5b:70:20:04: + 58:d1:7a:c9:a4:69:bc:83:17:64:ad:05:8b:bc:d0: + 58:ce:8d:8c:f5:eb:f0:42:49:0b:9d:97:27:67:32: + 6e:e1:ae:93:15:1c:70:bc:20:4d:2f:18:de:92:88: + e8:6c:85:57:11:1a:e9:7e:e3:26:11:54:a2:45:96: + 55:83:ca:30:89:e8:dc:d8:a3:ed:2a:80:3f:7f:79: + 65:57:3e:15:20:66:08:2f:95:93:bf:aa:47:2f:a8: + 46:97:f0:12:e2:fe:c2:0a:2b:51:e6:76:e6:b7:46: + b7:e2:0d:a6:cc:a8:c3:4c:59:55:89:e6:e8:53:5c: + 1c:ea:9d:f0:62:16:0b:a7:c9:5f:0c:f0:de:c2:76: + ce:af:f7:6a:f2:fa:41:a6:a2:33:14:c9:e5:7a:63: + d3:9e:62:37:d5:85:65:9e:0e:e6:53:24:74:1b:5e: + 1d:12:53:5b:c7:2c:e7:83:49:3b:15:ae:8a:68:b9: + 57:97 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 11:14:96:c1:ab:92:08:f7:3f:2f:c9:b2:fe:e4:5a:9f:64:de: + db:21:4f:86:99:34:76:36:57:dd:d0:15:2f:c5:ad:7f:15:1f: + 37:62:73:3e:d4:e7:5f:ce:17:03:db:35:fa:2b:db:ae:60:09: + 5f:1e:5f:8f:6e:bb:0b:3d:ea:5a:13:1e:0c:60:6f:b5:c0:b5: + 23:22:2e:07:0b:cb:a9:74:cb:47:bb:1d:c1:d7:a5:6b:cc:2f: + d2:42:fd:49:dd:a7:89:cf:53:ba:da:00:5a:28:bf:82:df:f8: + ba:13:1d:50:86:82:fd:8e:30:8f:29:46:b0:1e:3d:35:da:38: + 62:16:18:4a:ad:e6:b6:51:6c:de:af:62:eb:01:d0:1e:24:fe: + 7a:8f:12:1a:12:68:b8:fb:66:99:14:14:45:5c:ae:e7:ae:69: + 17:81:2b:5a:37:c9:5e:2a:f4:c6:e2:a1:5c:54:9b:a6:54:00: + cf:f0:f1:c1:c7:98:30:1a:3b:36:16:db:a3:6e:ea:fd:ad:b2: + c2:da:ef:02:47:13:8a:c0:f1:b3:31:ad:4f:1c:e1:4f:9c:af: + 0f:0c:9d:f7:78:0d:d8:f4:35:56:80:da:b7:6d:17:8f:9d:1e: + 81:64:e1:fe:c5:45:ba:ad:6b:b9:0a:7a:4e:4f:4b:84:ee:4b: + f1:7d:dd:11 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +Verisign Class 4 Public Primary Certification Authority - G3 +============================================================ + +MD5 Fingerprint=DB:C8:F2:27:2E:B1:EA:6A:29:23:5D:FE:56:3E:33:DF +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + ec:a0:a7:8b:6e:75:6a:01:cf:c4:7c:cc:2f:94:5e:d7 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3 + Validity + Not Before: Oct 1 00:00:00 1999 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary Certification Authority - G3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:cb:a5:11:69:c6:59:ab:f1:8f:b5:19:0f:56: + ce:cc:b5:1f:20:e4:9e:26:25:4b:e0:73:65:89:59: + de:d0:83:e4:f5:0f:b5:bb:ad:f1:7c:e8:21:fc:e4: + e8:0c:ee:7c:45:22:19:76:92:b4:13:b7:20:5b:09: + fa:61:ae:a8:f2:a5:8d:85:c2:2a:d6:de:66:36:d2: + 9b:02:f4:a8:92:60:7c:9c:69:b4:8f:24:1e:d0:86: + 52:f6:32:9c:41:58:1e:22:bd:cd:45:62:95:08:6e: + d0:66:dd:53:a2:cc:f0:10:dc:54:73:8b:04:a1:46: + 33:33:5c:17:40:b9:9e:4d:d3:f3:be:55:83:e8:b1: + 89:8e:5a:7c:9a:96:22:90:3b:88:25:f2:d2:53:88: + 02:0c:0b:78:f2:e6:37:17:4b:30:46:07:e4:80:6d: + a6:d8:96:2e:e8:2c:f8:11:b3:38:0d:66:a6:9b:ea: + c9:23:5b:db:8e:e2:f3:13:8e:1a:59:2d:aa:02:f0: + ec:a4:87:66:dc:c1:3f:f5:d8:b9:f4:ec:82:c6:d2: + 3d:95:1d:e5:c0:4f:84:c9:d9:a3:44:28:06:6a:d7: + 45:ac:f0:6b:6a:ef:4e:5f:f8:11:82:1e:38:63:34: + 66:50:d4:3e:93:73:fa:30:c3:66:ad:ff:93:2d:97: + ef:03 + Exponent: 65537 (0x10001) + Signature Algorithm: sha1WithRSAEncryption + 8f:fa:25:6b:4f:5b:e4:a4:4e:27:55:ab:22:15:59:3c:ca:b5: + 0a:d4:4a:db:ab:dd:a1:5f:53:c5:a0:57:39:c2:ce:47:2b:be: + 3a:c8:56:bf:c2:d9:27:10:3a:b1:05:3c:c0:77:31:bb:3a:d3: + 05:7b:6d:9a:1c:30:8c:80:cb:93:93:2a:83:ab:05:51:82:02: + 00:11:67:6b:f3:88:61:47:5f:03:93:d5:5b:0d:e0:f1:d4:a1: + 32:35:85:b2:3a:db:b0:82:ab:d1:cb:0a:bc:4f:8c:5b:c5:4b: + 00:3b:1f:2a:82:a6:7e:36:85:dc:7e:3c:67:00:b5:e4:3b:52: + e0:a8:eb:5d:15:f9:c6:6d:f0:ad:1d:0e:85:b7:a9:9a:73:14: + 5a:5b:8f:41:28:c0:d5:e8:2d:4d:a4:5e:cd:aa:d9:ed:ce:dc: + d8:d5:3c:42:1d:17:c1:12:5d:45:38:c3:38:f3:fc:85:2e:83: + 46:48:b2:d7:20:5f:92:36:8f:e7:79:0f:98:5e:99:e8:f0:d0: + a4:bb:f5:53:bd:2a:ce:59:b0:af:6e:7f:6c:bb:d2:1e:00:b0: + 21:ed:f8:41:62:82:b9:d8:b2:c4:bb:46:50:f3:31:c5:8f:01: + a8:74:eb:f5:78:27:da:e7:f7:66:43:f3:9e:83:3e:20:aa:c3: + 35:60:91:ce +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 +GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ ++mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd +U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm +NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY +ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ +ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 +CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq +g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c +2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ +bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- + +GTE CyberTrust Global Root +========================== + +MD5 Fingerprint=CA:3D:D3:68:F1:03:5C:D0:32:FA:B8:2B:59:E8:5A:DB +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 421 (0x1a5) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root + Validity + Not Before: Aug 13 00:29:00 1998 GMT + Not After : Aug 13 23:59:00 2018 GMT + Subject: C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE CyberTrust Global Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:95:0f:a0:b6:f0:50:9c:e8:7a:c7:88:cd:dd:17: + 0e:2e:b0:94:d0:1b:3d:0e:f6:94:c0:8a:94:c7:06: + c8:90:97:c8:b8:64:1a:7a:7e:6c:3c:53:e1:37:28: + 73:60:7f:b2:97:53:07:9f:53:f9:6d:58:94:d2:af: + 8d:6d:88:67:80:e6:ed:b2:95:cf:72:31:ca:a5:1c: + 72:ba:5c:02:e7:64:42:e7:f9:a9:2c:d6:3a:0d:ac: + 8d:42:aa:24:01:39:e6:9c:3f:01:85:57:0d:58:87: + 45:f8:d3:85:aa:93:69:26:85:70:48:80:3f:12:15: + c7:79:b4:1f:05:2f:3b:62:99 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 6d:eb:1b:09:e9:5e:d9:51:db:67:22:61:a4:2a:3c:48:77:e3: + a0:7c:a6:de:73:a2:14:03:85:3d:fb:ab:0e:30:c5:83:16:33: + 81:13:08:9e:7b:34:4e:df:40:c8:74:d7:b9:7d:dc:f4:76:55: + 7d:9b:63:54:18:e9:f0:ea:f3:5c:b1:d9:8b:42:1e:b9:c0:95: + 4e:ba:fa:d5:e2:7c:f5:68:61:bf:8e:ec:05:97:5f:5b:b0:d7: + a3:85:34:c4:24:a7:0d:0f:95:93:ef:cb:94:d8:9e:1f:9d:5c: + 85:6d:c7:aa:ae:4f:1f:22:b5:cd:95:ad:ba:a7:cc:f9:ab:0b: + 7a:7f +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH +iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS +r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 +04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r +GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 +3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P +lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- + +Entrust.net Secure Server CA +============================ + +MD5 Fingerprint=DF:F2:80:73:CC:F1:E6:61:73:FC:F5:42:E9:C5:7C:EE +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 927650371 (0x374ad243) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Validity + Not Before: May 25 16:09:40 1999 GMT + Not After : May 25 16:39:40 2019 GMT + Subject: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cd:28:83:34:54:1b:89:f3:0f:af:37:91:31:ff: + af:31:60:c9:a8:e8:b2:10:68:ed:9f:e7:93:36:f1: + 0a:64:bb:47:f5:04:17:3f:23:47:4d:c5:27:19:81: + 26:0c:54:72:0d:88:2d:d9:1f:9a:12:9f:bc:b3:71: + d3:80:19:3f:47:66:7b:8c:35:28:d2:b9:0a:df:24: + da:9c:d6:50:79:81:7a:5a:d3:37:f7:c2:4a:d8:29: + 92:26:64:d1:e4:98:6c:3a:00:8a:f5:34:9b:65:f8: + ed:e3:10:ff:fd:b8:49:58:dc:a0:de:82:39:6b:81: + b1:16:19:61:b9:54:b6:e6:43 + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority/CN=CRL1 + URI:http://www.entrust.net/CRL/net1.crl + + X509v3 Private Key Usage Period: + Not Before: May 25 16:09:40 1999 GMT, Not After: May 25 16:09:40 2019 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A + + X509v3 Subject Key Identifier: + F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: sha1WithRSAEncryption + 90:dc:30:02:fa:64:74:c2:a7:0a:a5:7c:21:8d:34:17:a8:fb: + 47:0e:ff:25:7c:8d:13:0a:fb:e4:98:b5:ef:8c:f8:c5:10:0d: + f7:92:be:f1:c3:d5:d5:95:6a:04:bb:2c:ce:26:36:65:c8:31: + c6:e7:ee:3f:e3:57:75:84:7a:11:ef:46:4f:18:f4:d3:98:bb: + a8:87:32:ba:72:f6:3c:e2:3d:9f:d7:1d:d9:c3:60:43:8c:58: + 0e:22:96:2f:62:a3:2c:1f:ba:ad:05:ef:ab:32:78:87:a0:54: + 73:19:b5:5c:05:f9:52:3e:6d:2d:45:0b:f7:0a:93:ea:ed:06: + f9:b2 +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 +MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE +ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j +b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg +U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ +I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 +wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC +AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb +oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 +BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 +MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi +E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa +MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI +hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN +95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd +2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- + +Entrust.net Secure Personal CA +============================== + +MD5 Fingerprint=0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 939758062 (0x380391ee) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Validity + Not Before: Oct 12 19:24:30 1999 GMT + Not After : Oct 12 19:54:30 2019 GMT + Subject: C=US, O=Entrust.net, OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab., OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c8:3a:99:5e:31:17:df:ac:27:6f:90:7b:e4:19: + ff:45:a3:34:c2:db:c1:a8:4f:f0:68:ea:84:fd:9f: + 75:79:cf:c1:8a:51:94:af:c7:57:03:47:64:9e:ad: + 82:1b:5a:da:7f:37:78:47:bb:37:98:12:96:ce:c6: + 13:7d:ef:d2:0c:30:51:a9:39:9e:55:f8:fb:b1:e7: + 30:de:83:b2:ba:3e:f1:d5:89:3b:3b:85:ba:aa:74: + 2c:fe:3f:31:6e:af:91:95:6e:06:d4:07:4d:4b:2c: + 56:47:18:04:52:da:0e:10:93:bf:63:90:9b:e1:df: + 8c:e6:02:a4:e6:4f:5e:f7:8b + Exponent: 3 (0x3) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=US/O=Entrust.net/OU=www.entrust.net/Client_CA_Info/CPS incorp. by ref. limits liab./OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Client Certification Authority/CN=CRL1 + URI:http://www.entrust.net/CRL/Client1.crl + + X509v3 Private Key Usage Period: + Not Before: Oct 12 19:24:30 1999 GMT, Not After: Oct 12 19:24:30 2019 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C + + X509v3 Subject Key Identifier: + C4:FB:9C:29:7B:97:CD:4C:96:FC:EE:5B:B3:CA:99:74:8B:95:EA:4C + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0 +..V4.0.... + Signature Algorithm: md5WithRSAEncryption + 3f:ae:8a:f1:d7:66:03:05:9e:3e:fa:ea:1c:46:bb:a4:5b:8f: + 78:9a:12:48:99:f9:f4:35:de:0c:36:07:02:6b:10:3a:89:14: + 81:9c:31:a6:7c:b2:41:b2:6a:e7:07:01:a1:4b:f9:9f:25:3b: + 96:ca:99:c3:3e:a1:51:1c:f3:c3:2e:44:f7:b0:67:46:aa:92: + e5:3b:da:1c:19:14:38:30:d5:e2:a2:31:25:2e:f1:ec:45:38: + ed:f8:06:58:03:73:62:b0:10:31:8f:40:bf:64:e0:5c:3e:c5: + 4f:1f:da:12:43:ff:4c:e6:06:26:a8:9b:19:aa:44:3c:76:b2: + 5c:ec +-----BEGIN CERTIFICATE----- +MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50cnVzdC5u +ZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBsaW1pdHMgbGlh +Yi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBaMIHJMQswCQYDVQQGEwJVUzEU +MBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9D +bGllbnRfQ0FfSW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMq +RW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0G +CSqGSIb3DQEBAQUAA4GLADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo +6oT9n3V5z8GKUZSvx1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux +5zDeg7K6PvHViTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zm +AqTmT173iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSC +ARkwggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50 +cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5m +by9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMp +IDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQg +Q2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCyg +KqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9DbGllbnQxLmNybDArBgNV +HRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkxMDEyMTkyNDMwWjALBgNVHQ8E +BAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW/O5bs8qZdIuV6kwwHQYDVR0OBBYE +FMT7nCl7l81MlvzuW7PKmXSLlepMMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7 +pFuPeJoSSJn59DXeDDYHAmsQOokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzz +wy5E97BnRqqS5TvaHBkUODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/a +EkP/TOYGJqibGapEPHayXOw= +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= + +MD5 Fingerprint=BA:21:EA:20:D6:DD:DB:8F:C1:57:8B:40:AD:A1:FC:FC +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 946059622 (0x3863b966) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Validity + Not Before: Dec 24 17:50:51 1999 GMT + Not After : Dec 24 18:20:51 2019 GMT + Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ad:4d:4b:a9:12:86:b2:ea:a3:20:07:15:16:64: + 2a:2b:4b:d1:bf:0b:4a:4d:8e:ed:80:76:a5:67:b7: + 78:40:c0:73:42:c8:68:c0:db:53:2b:dd:5e:b8:76: + 98:35:93:8b:1a:9d:7c:13:3a:0e:1f:5b:b7:1e:cf: + e5:24:14:1e:b1:81:a9:8d:7d:b8:cc:6b:4b:03:f1: + 02:0c:dc:ab:a5:40:24:00:7f:74:94:a1:9d:08:29: + b3:88:0b:f5:87:77:9d:55:cd:e4:c3:7e:d7:6a:64: + ab:85:14:86:95:5b:97:32:50:6f:3d:c8:ba:66:0c: + e3:fc:bd:b8:49:c1:76:89:49:19:fd:c0:a8:bd:89: + a3:67:2f:c6:9f:bc:71:19:60:b8:2d:e9:2c:c9:90: + 76:66:7b:94:e2:af:78:d6:65:53:5d:3c:d6:9c:b2: + cf:29:03:f9:2f:a4:50:b2:d4:48:ce:05:32:55:8a: + fd:b2:64:4c:0e:e4:98:07:75:db:7f:df:b9:08:55: + 60:85:30:29:f9:7b:48:a4:69:86:e3:35:3f:1e:86: + 5d:7a:7a:15:bd:ef:00:8e:15:22:54:17:00:90:26: + 93:bc:0e:49:68:91:bf:f8:47:d3:9d:95:42:c1:0e: + 4d:df:6f:26:cf:c3:18:21:62:66:43:70:d6:d5:c0: + 07:e1 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Authority Key Identifier: + keyid:55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 + + X509v3 Subject Key Identifier: + 55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70 + 1.2.840.113533.7.65.0: + 0...V5.0:4.0.... + Signature Algorithm: sha1WithRSAEncryption + 59:47:ac:21:84:8a:17:c9:9c:89:53:1e:ba:80:85:1a:c6:3c: + 4e:3e:b1:9c:b6:7c:c6:92:5d:18:64:02:e3:d3:06:08:11:61: + 7c:63:e3:2b:9d:31:03:70:76:d2:a3:28:a0:f4:bb:9a:63:73: + ed:6d:e5:2a:db:ed:14:a9:2b:c6:36:11:d0:2b:eb:07:8b:a5: + da:9e:5c:19:9d:56:12:f5:54:29:c8:05:ed:b2:12:2a:8d:f4: + 03:1b:ff:e7:92:10:87:b0:3a:b5:c3:9d:05:37:12:a3:c7:f4: + 15:b9:d5:a4:39:16:9b:53:3a:23:91:f1:a8:82:a2:6a:88:68: + c1:79:02:22:bc:aa:a6:d6:ae:df:b0:14:5f:b8:87:d0:dd:7c: + 7f:7b:ff:af:1c:cf:e6:db:07:ad:5e:db:85:9d:d0:2b:0d:33: + db:04:d1:e6:49:40:13:2b:76:fb:3e:e9:9c:89:0f:15:ce:18: + b0:85:78:21:4f:6b:4f:0e:fa:36:67:cd:07:f2:ff:08:d0:e2: + de:d9:bf:2a:af:b8:87:86:21:3c:04:ca:b7:94:68:7f:cf:3c: + e9:98:d7:38:ff:ec:c0:d9:50:f0:2e:4b:58:ae:46:6f:d0:2e: + c3:60:da:72:55:72:bd:4c:45:9e:61:ba:bf:84:81:92:03:d1: + d2:69:7c:c5 +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy +MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA +vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G +CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA +WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ +h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 +f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN +B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy +vUxFnmG6v4SBkgPR0ml8xQ== +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= + +MD5 Fingerprint=AC:B6:94:A5:9C:17:E0:D7:91:52:9B:B1:97:06:A6:E4 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 33554617 (0x20000b9) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root + Validity + Not Before: May 12 18:46:00 2000 GMT + Not After : May 12 23:59:00 2025 GMT + Subject: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:a3:04:bb:22:ab:98:3d:57:e8:26:72:9a:b5:79: + d4:29:e2:e1:e8:95:80:b1:b0:e3:5b:8e:2b:29:9a: + 64:df:a1:5d:ed:b0:09:05:6d:db:28:2e:ce:62:a2: + 62:fe:b4:88:da:12:eb:38:eb:21:9d:c0:41:2b:01: + 52:7b:88:77:d3:1c:8f:c7:ba:b9:88:b5:6a:09:e7: + 73:e8:11:40:a7:d1:cc:ca:62:8d:2d:e5:8f:0b:a6: + 50:d2:a8:50:c3:28:ea:f5:ab:25:87:8a:9a:96:1c: + a9:67:b8:3f:0c:d5:f7:f9:52:13:2f:c2:1b:d5:70: + 70:f0:8f:c0:12:ca:06:cb:9a:e1:d9:ca:33:7a:77: + d6:f8:ec:b9:f1:68:44:42:48:13:d2:c0:c2:a4:ae: + 5e:60:fe:b6:a6:05:fc:b4:dd:07:59:02:d4:59:18: + 98:63:f5:a5:63:e0:90:0c:7d:5d:b2:06:7a:f3:85: + ea:eb:d4:03:ae:5e:84:3e:5f:ff:15:ed:69:bc:f9: + 39:36:72:75:cf:77:52:4d:f3:c9:90:2c:b9:3d:e5: + c9:23:53:3f:1f:24:98:21:5c:07:99:29:bd:c6:3a: + ec:e7:6e:86:3a:6b:97:74:63:33:bd:68:18:31:f0: + 78:8d:76:bf:fc:9e:8e:5d:2a:86:a7:4d:90:dc:27: + 1a:39 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + E5:9D:59:30:82:47:58:CC:AC:FA:08:54:36:86:7B:3A:B5:04:4D:F0 + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:3 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 85:0c:5d:8e:e4:6f:51:68:42:05:a0:dd:bb:4f:27:25:84:03: + bd:f7:64:fd:2d:d7:30:e3:a4:10:17:eb:da:29:29:b6:79:3f: + 76:f6:19:13:23:b8:10:0a:f9:58:a4:d4:61:70:bd:04:61:6a: + 12:8a:17:d5:0a:bd:c5:bc:30:7c:d6:e9:0c:25:8d:86:40:4f: + ec:cc:a3:7e:38:c6:37:11:4f:ed:dd:68:31:8e:4c:d2:b3:01: + 74:ee:be:75:5e:07:48:1a:7f:70:ff:16:5c:84:c0:79:85:b8: + 05:fd:7f:be:65:11:a3:0f:c0:02:b4:f8:52:37:39:04:d5:a9: + 31:7a:18:bf:a0:2a:f4:12:99:f7:a3:45:82:e3:3c:5e:f5:9d: + 9e:b5:c8:9e:7c:2e:c8:a4:9e:4e:08:14:4b:6d:fd:70:6d:6b: + 1a:63:bd:64:e6:1f:b7:ce:f0:f2:9f:2e:bb:1b:b7:f2:50:88: + 73:92:c2:e2:e3:16:8d:9a:32:02:ab:8e:18:dd:e9:10:11:ee: + 7e:35:ab:90:af:3e:30:94:7a:d0:33:3d:a7:65:0f:f5:fc:8e: + 9e:62:cf:47:44:2c:01:5d:bb:1d:b5:32:d2:47:d2:38:2e:d0: + fe:81:dc:32:6a:1e:b5:ee:3c:d5:fc:e7:81:1d:19:c3:24:42: + ea:63:39:a9 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Equifax Secure Global eBusiness CA +================================== + +MD5 Fingerprint=8F:5D:77:06:27:C4:98:3C:5B:93:78:E7:D7:7D:9B:CC +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1 + Validity + Not Before: Jun 21 04:00:00 1999 GMT + Not After : Jun 21 04:00:00 2020 GMT + Subject: C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ba:e7:17:90:02:65:b1:34:55:3c:49:c2:51:d5: + df:a7:d1:37:8f:d1:e7:81:73:41:52:60:9b:9d:a1: + 17:26:78:ad:c7:b1:e8:26:94:32:b5:de:33:8d:3a: + 2f:db:f2:9a:7a:5a:73:98:a3:5c:e9:fb:8a:73:1b: + 5c:e7:c3:bf:80:6c:cd:a9:f4:d6:2b:c0:f7:f9:99: + aa:63:a2:b1:47:02:0f:d4:e4:51:3a:12:3c:6c:8a: + 5a:54:84:70:db:c1:c5:90:cf:72:45:cb:a8:59:c0: + cd:33:9d:3f:a3:96:eb:85:33:21:1c:3e:1e:3e:60: + 6e:76:9c:67:85:c5:c8:c3:61 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:BE:A8:A0:74:72:50:6B:44:B7:C9:23:D8:FB:A8:FF:B3:57:6B:68:6C + + X509v3 Subject Key Identifier: + BE:A8:A0:74:72:50:6B:44:B7:C9:23:D8:FB:A8:FF:B3:57:6B:68:6C + Signature Algorithm: md5WithRSAEncryption + 30:e2:01:51:aa:c7:ea:5f:da:b9:d0:65:0f:30:d6:3e:da:0d: + 14:49:6e:91:93:27:14:31:ef:c4:f7:2d:45:f8:ec:c7:bf:a2: + 41:0d:23:b4:92:f9:19:00:67:bd:01:af:cd:e0:71:fc:5a:cf: + 64:c4:e0:96:98:d0:a3:40:e2:01:8a:ef:27:07:f1:65:01:8a: + 44:2d:06:65:75:52:c0:86:10:20:21:5f:6c:6b:0f:6c:ae:09: + 1c:af:f2:a2:18:34:c4:75:a4:73:1c:f1:8d:dc:ef:ad:f9:b3: + 76:b4:92:bf:dc:95:10:1e:be:cb:c8:3b:5a:84:60:19:56:94: + a9:55 +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT +ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw +MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj +dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l +c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC +UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc +58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ +o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr +aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA +A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA +Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv +8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 1 +============================= + +MD5 Fingerprint=64:9C:EF:2E:44:FC:C6:8F:52:07:D0:51:73:8F:CB:3D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1 + Validity + Not Before: Jun 21 04:00:00 1999 GMT + Not After : Jun 21 04:00:00 2020 GMT + Subject: C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:2f:19:bc:17:b7:77:de:93:a9:5f:5a:0d:17: + 4f:34:1a:0c:98:f4:22:d9:59:d4:c4:68:46:f0:b4: + 35:c5:85:03:20:c6:af:45:a5:21:51:45:41:eb:16: + 58:36:32:6f:e2:50:62:64:f9:fd:51:9c:aa:24:d9: + f4:9d:83:2a:87:0a:21:d3:12:38:34:6c:8d:00:6e: + 5a:a0:d9:42:ee:1a:21:95:f9:52:4c:55:5a:c5:0f: + 38:4f:46:fa:6d:f8:2e:35:d6:1d:7c:eb:e2:f0:b0: + 75:80:c8:a9:13:ac:be:88:ef:3a:6e:ab:5f:2a:38: + 62:02:b0:12:7b:fe:8f:a6:03 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:4A:78:32:52:11:DB:59:16:36:5E:DF:C1:14:36:40:6A:47:7C:4C:A1 + + X509v3 Subject Key Identifier: + 4A:78:32:52:11:DB:59:16:36:5E:DF:C1:14:36:40:6A:47:7C:4C:A1 + Signature Algorithm: md5WithRSAEncryption + 75:5b:a8:9b:03:11:e6:e9:56:4c:cd:f9:a9:4c:c0:0d:9a:f3: + cc:65:69:e6:25:76:cc:59:b7:d6:54:c3:1d:cd:99:ac:19:dd: + b4:85:d5:e0:3d:fc:62:20:a7:84:4b:58:65:f1:e2:f9:95:21: + 3f:f5:d4:7e:58:1e:47:87:54:3e:58:a1:b5:b5:f8:2a:ef:71: + e7:bc:c3:f6:b1:49:46:e2:d7:a0:6b:e5:56:7a:9a:27:98:7c: + 46:62:14:e7:c9:fc:6e:03:12:79:80:38:1d:48:82:8d:fc:17: + fe:2a:96:2b:b5:62:a6:a6:3d:bd:7f:92:59:cd:5a:2a:82:b2: + 37:79 +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT +ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw +MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j +LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ +KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo +RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu +WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw +Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK +eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM +zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ +WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN +/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 2 +============================= + +MD5 Fingerprint=AA:BF:BF:64:97:DA:98:1D:6F:C6:08:3A:95:70:33:CA +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 930140085 (0x3770cfb5) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2 + Validity + Not Before: Jun 23 12:14:45 1999 GMT + Not After : Jun 23 12:14:45 2019 GMT + Subject: C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e4:39:39:93:1e:52:06:1b:28:36:f8:b2:a3:29: + c5:ed:8e:b2:11:bd:fe:eb:e7:b4:74:c2:8f:ff:05: + e7:d9:9d:06:bf:12:c8:3f:0e:f2:d6:d1:24:b2:11: + de:d1:73:09:8a:d4:b1:2c:98:09:0d:1e:50:46:b2: + 83:a6:45:8d:62:68:bb:85:1b:20:70:32:aa:40:cd: + a6:96:5f:c4:71:37:3f:04:f3:b7:41:24:39:07:1a: + 1e:2e:61:58:a0:12:0b:e5:a5:df:c5:ab:ea:37:71: + cc:1c:c8:37:3a:b9:97:52:a7:ac:c5:6a:24:94:4e: + 9c:7b:cf:c0:6a:d6:df:21:bd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + DirName:/C=US/O=Equifax Secure/OU=Equifax Secure eBusiness CA-2/CN=CRL1 + + X509v3 Private Key Usage Period: + Not After: Jun 23 12:14:45 2019 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:50:9E:0B:EA:AF:5E:B9:20:48:A6:50:6A:CB:FD:D8:20:7A:A7:82:76 + + X509v3 Subject Key Identifier: + 50:9E:0B:EA:AF:5E:B9:20:48:A6:50:6A:CB:FD:D8:20:7A:A7:82:76 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V3.0c.... + Signature Algorithm: sha1WithRSAEncryption + 0c:86:82:ad:e8:4e:1a:f5:8e:89:27:e2:35:58:3d:29:b4:07: + 8f:36:50:95:bf:6e:c1:9e:eb:c4:90:b2:85:a8:bb:b7:42:e0: + 0f:07:39:df:fb:9e:90:b2:d1:c1:3e:53:9f:03:44:b0:7e:4b: + f4:6f:e4:7c:1f:e7:e2:b1:e4:b8:9a:ef:c3:bd:ce:de:0b:32: + 34:d9:de:28:ed:33:6b:c4:d4:d7:3d:12:58:ab:7d:09:2d:cb: + 70:f5:13:8a:94:a1:27:a4:d6:70:c5:6d:94:b5:c9:7d:9d:a0: + d2:c6:08:49:d9:66:9b:a6:d3:f4:0b:dc:c5:26:57:e1:91:30: + ea:cd +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj +dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 +NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD +VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G +vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ +BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX +MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl +IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw +NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq +y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy +0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 +E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN +-----END CERTIFICATE----- + +Visa International Global Root 2 +================================ + +MD5 Fingerprint=35:48:95:36:4A:54:5A:72:96:8E:E0:64:CC:EF:2C:8C +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 798 (0x31e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VISA, OU=Visa International Service Association, CN=GP Root 2 + Validity + Not Before: Aug 16 22:51:00 2000 GMT + Not After : Aug 15 23:59:00 2020 GMT + Subject: C=US, O=VISA, OU=Visa International Service Association, CN=GP Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:a9:01:70:b5:aa:c4:40:f0:ab:6a:26:61:79:19: + 00:fc:bf:9b:37:59:0c:af:6f:64:1b:f8:da:95:94: + 24:69:33:11:70:ca:e3:56:74:a2:17:57:64:5c:20: + 06:e1:d6:ef:71:b7:3b:f7:ab:c1:69:d0:49:a4:b1: + 04:d7:f4:57:62:89:5c:b0:75:2d:17:24:69:e3:42: + 60:e4:ee:74:d6:ab:80:56:d8:88:28:e1:fb:6d:22: + fd:23:7c:46:73:4f:7e:54:73:1e:a8:2c:55:58:75: + b7:4c:f3:5a:45:a5:02:1a:fa:da:9d:c3:45:c3:22: + 5e:f3:8b:f1:60:29:d2:c7:5f:b4:0c:3a:51:83:ef: + 30:f8:d4:e7:c7:f2:fa:99:a3:22:50:be:f9:05:37: + a3:ad:ed:9a:c3:e6:ec:88:1b:b6:19:27:1b:38:8b: + 80:4d:ec:b9:c7:c5:89:cb:fc:1a:32:ed:23:f0:b5: + 01:58:f9:f6:8f:e0:85:a9:4c:09:72:39:12:db:b3: + f5:cf:4e:62:64:da:c6:19:15:3a:63:1d:e9:17:55: + a1:4c:22:3c:34:32:46:f8:65:57:ba:2b:ef:36:8c: + 6a:fa:d9:d9:44:f4:aa:dd:84:d7:0d:1c:b2:54:ac: + 32:85:b4:64:0d:de:41:bb:b1:34:c6:01:86:32:64: + d5:9f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 9E:7D:4B:34:BF:71:AD:C2:05:F6:03:75:80:CE:A9:4F:1A:C4:24:4C + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 21:a5:76:14:55:f9:ad:27:70:8f:3c:f4:d5:6c:c8:cc:0a:ab: + a3:98:0b:8a:06:23:c5:c9:61:db:99:07:69:35:26:31:fe:c7: + 2e:84:c2:99:61:d4:0d:e9:7d:2e:13:2b:7c:8e:85:b6:85:c7: + 4b:cf:35:b6:2c:47:3d:ce:29:2f:d8:6f:9f:89:1c:64:93:bf: + 08:bd:76:d0:90:8a:94:b3:7f:28:5b:6e:ac:4d:33:2c:ed:65: + dc:16:cc:e2:cd:ae:a4:3d:62:92:06:95:26:bf:df:b9:e4:20: + a6:73:6a:c1:be:f7:94:44:d6:4d:6f:2a:0b:6b:18:4d:74:10: + 36:68:6a:5a:c1:6a:a7:dd:36:29:8c:b8:30:8b:4f:21:3f:00: + 2e:54:30:07:3a:ba:8a:e4:c3:9e:ca:d8:b5:d8:7b:ce:75:45: + 66:07:f4:6d:2d:d8:7a:ca:e9:89:8a:f2:23:d8:2f:cb:6e:00: + 36:4f:fb:f0:2f:01:cc:0f:c0:22:65:f4:ab:e2:4e:61:2d:03: + 82:7d:91:16:b5:30:d5:14:de:5e:c7:90:fc:a1:fc:ab:10:af: + 5c:6b:70:a7:07:ef:29:86:e8:b2:25:c7:20:ff:26:dd:77:ef: + 79:44:14:c4:bd:dd:3b:c5:03:9b:77:23:ec:a0:ec:bb:5a:39: + b5:cc:ad:06 +-----BEGIN CERTIFICATE----- +MIIDgDCCAmigAwIBAgICAx4wDQYJKoZIhvcNAQEFBQAwYTELMAkGA1UEBhMCVVMx +DTALBgNVBAoTBFZJU0ExLzAtBgNVBAsTJlZpc2EgSW50ZXJuYXRpb25hbCBTZXJ2 +aWNlIEFzc29jaWF0aW9uMRIwEAYDVQQDEwlHUCBSb290IDIwHhcNMDAwODE2MjI1 +MTAwWhcNMjAwODE1MjM1OTAwWjBhMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklT +QTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRp +b24xEjAQBgNVBAMTCUdQIFJvb3QgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKkBcLWqxEDwq2omYXkZAPy/mzdZDK9vZBv42pWUJGkzEXDK41Z0ohdX +ZFwgBuHW73G3O/erwWnQSaSxBNf0V2KJXLB1LRckaeNCYOTudNargFbYiCjh+20i +/SN8RnNPflRzHqgsVVh1t0zzWkWlAhr62p3DRcMiXvOL8WAp0sdftAw6UYPvMPjU +58fy+pmjIlC++QU3o63tmsPm7IgbthknGziLgE3sucfFicv8GjLtI/C1AVj59o/g +halMCXI5Etuz9c9OYmTaxhkVOmMd6RdVoUwiPDQyRvhlV7or7zaMavrZ2UT0qt2E +1w0cslSsMoW0ZA3eQbuxNMYBhjJk1Z8CAwEAAaNCMEAwHQYDVR0OBBYEFJ59SzS/ +ca3CBfYDdYDOqU8axCRMMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQAhpXYUVfmtJ3CPPPTVbMjMCqujmAuKBiPFyWHb +mQdpNSYx/scuhMKZYdQN6X0uEyt8joW2hcdLzzW2LEc9zikv2G+fiRxkk78IvXbQ +kIqUs38oW26sTTMs7WXcFsziza6kPWKSBpUmv9+55CCmc2rBvveURNZNbyoLaxhN +dBA2aGpawWqn3TYpjLgwi08hPwAuVDAHOrqK5MOeyti12HvOdUVmB/RtLdh6yumJ +ivIj2C/LbgA2T/vwLwHMD8AiZfSr4k5hLQOCfZEWtTDVFN5ex5D8ofyrEK9ca3Cn +B+8phuiyJccg/ybdd+95RBTEvd07xQObdyPsoOy7Wjm1zK0G +-----END CERTIFICATE----- + +beTRUSTed Root CA +================= + +MD5 Fingerprint=85:CA:76:5A:1B:D1:68:22:DC:A2:23:12:CA:C6:80:34 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 961510791 (0x394f7d87) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=WW, O=beTRUSTed, CN=beTRUSTed Root CAs, CN=beTRUSTed Root CA + Validity + Not Before: Jun 20 14:21:04 2000 GMT + Not After : Jun 20 13:21:04 2010 GMT + Subject: C=WW, O=beTRUSTed, CN=beTRUSTed Root CAs, CN=beTRUSTed Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d4:b4:73:7a:13:0a:38:55:01:be:89:56:e1:94: + 9e:d4:be:5a:eb:4a:34:75:1b:61:29:c4:e1:ad:08: + 60:21:78:48:ff:b4:d0:fa:5e:41:8d:61:44:87:e8: + ed:c9:58:fa:fc:93:9a:df:4f:ea:3e:35:7d:f8:33: + 7a:e6:f1:d7:cd:6f:49:4b:3d:4f:2d:6e:0e:83:3a: + 18:78:77:a3:cf:e7:f4:4d:73:d8:9a:3b:1a:1d:be: + 95:53:cf:20:97:c2:cf:3e:24:52:6c:0c:8e:65:59: + c5:71:ff:62:09:8f:aa:c5:8f:cc:60:a0:73:4a:d7: + 38:3f:15:72:bf:a2:97:b7:70:e8:af:e2:7e:16:06: + 4c:f5:aa:64:26:72:07:25:ad:35:fc:18:b1:26:d7: + d8:ff:19:0e:83:1b:8c:dc:78:45:67:34:3d:f4:af: + 1c:8d:e4:6d:6b:ed:20:b3:67:9a:b4:61:cb:17:6f: + 89:35:ff:e7:4e:c0:32:12:e7:ee:ec:df:ff:97:30: + 74:ed:8d:47:8e:eb:b4:c3:44:e6:a7:4c:7f:56:43: + e8:b8:bc:b6:be:fa:83:97:e6:bb:fb:c4:b6:93:be: + 19:18:3e:8c:81:b9:73:88:16:f4:96:43:9c:67:73: + 17:90:d8:09:6e:63:ac:4a:b6:23:c4:01:a1:ad:a4: + e4:c5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.6334.1.0.0 + User Notice: + Explicit Text: Reliance on this certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, and certification practice statement, which can be found at beTRUSTed's web site, https://www.beTRUSTed.com/vault/terms + CPS: https://www.beTRUSTed.com/vault/terms + + X509v3 CRL Distribution Points: + DirName:/O=beTRUSTed/C=WW + + X509v3 Subject Key Identifier: + 2A:B9:9B:69:2E:3B:9B:D8:CD:DE:2A:31:04:34:6B:CA:07:18:AB:67 + X509v3 Authority Key Identifier: + keyid:2A:B9:9B:69:2E:3B:9B:D8:CD:DE:2A:31:04:34:6B:CA:07:18:AB:67 + + X509v3 Key Usage: critical + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 79:61:db:a3:5e:6e:16:b1:ea:76:51:f9:cb:15:9b:cb:69:be: + e6:81:6b:9f:28:1f:65:3e:dd:11:85:92:d4:e8:41:bf:7e:33: + bd:23:e7:f1:20:bf:a4:b4:a6:19:01:c6:8c:8d:35:7c:65:a4: + 4f:09:a4:d6:d8:23:15:05:13:a7:43:79:af:db:a3:0e:9b:7b: + 78:1a:f3:04:86:5a:c6:f6:8c:20:47:38:49:50:06:9d:72:67: + 3a:f0:98:03:ad:96:67:44:fc:3f:10:0d:86:4d:e4:00:3b:29: + 7b:ce:3b:3b:99:86:61:25:40:84:dc:13:62:b7:fa:ca:59:d6: + 03:1e:d6:53:01:cd:6d:4c:68:55:40:e1:ee:6b:c7:2a:00:00: + 48:82:b3:0a:01:c3:60:2a:0c:f7:82:35:ee:48:86:96:e4:74: + d4:3d:ea:01:71:ba:04:75:40:a7:a9:7f:39:39:9a:55:97:29: + 65:ae:19:55:25:05:72:47:d3:e8:18:dc:b8:e9:af:43:73:01: + 12:74:a3:e1:5c:5f:15:5d:24:f3:f9:e4:f4:b6:67:67:12:e7: + 64:22:8a:f6:a5:41:a6:1c:b6:60:63:45:8a:10:b4:ba:46:10: + ae:41:57:65:6c:3f:23:10:3f:21:10:59:b7:e4:40:dd:26:0c: + 23:f6:aa:ae +-----BEGIN CERTIFICATE----- +MIIFLDCCBBSgAwIBAgIEOU99hzANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJX +VzESMBAGA1UEChMJYmVUUlVTVGVkMRswGQYDVQQDExJiZVRSVVNUZWQgUm9vdCBD +QXMxGjAYBgNVBAMTEWJlVFJVU1RlZCBSb290IENBMB4XDTAwMDYyMDE0MjEwNFoX +DTEwMDYyMDEzMjEwNFowWjELMAkGA1UEBhMCV1cxEjAQBgNVBAoTCWJlVFJVU1Rl +ZDEbMBkGA1UEAxMSYmVUUlVTVGVkIFJvb3QgQ0FzMRowGAYDVQQDExFiZVRSVVNU +ZWQgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANS0c3oT +CjhVAb6JVuGUntS+WutKNHUbYSnE4a0IYCF4SP+00PpeQY1hRIfo7clY+vyTmt9P +6j41ffgzeubx181vSUs9Ty1uDoM6GHh3o8/n9E1z2Jo7Gh2+lVPPIJfCzz4kUmwM +jmVZxXH/YgmPqsWPzGCgc0rXOD8Vcr+il7dw6K/ifhYGTPWqZCZyByWtNfwYsSbX +2P8ZDoMbjNx4RWc0PfSvHI3kbWvtILNnmrRhyxdviTX/507AMhLn7uzf/5cwdO2N +R47rtMNE5qdMf1ZD6Li8tr76g5fmu/vEtpO+GRg+jIG5c4gW9JZDnGdzF5DYCW5j +rEq2I8QBoa2k5MUCAwEAAaOCAfgwggH0MA8GA1UdEwEB/wQFMAMBAf8wggFZBgNV +HSAEggFQMIIBTDCCAUgGCisGAQQBsT4BAAAwggE4MIIBAQYIKwYBBQUHAgIwgfQa +gfFSZWxpYW5jZSBvbiB0aGlzIGNlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBhc3N1 +bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0 +ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGFuZCBjZXJ0aWZpY2F0aW9uIHBy +YWN0aWNlIHN0YXRlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IGJlVFJVU1Rl +ZCdzIHdlYiBzaXRlLCBodHRwczovL3d3dy5iZVRSVVNUZWQuY29tL3ZhdWx0L3Rl +cm1zMDEGCCsGAQUFBwIBFiVodHRwczovL3d3dy5iZVRSVVNUZWQuY29tL3ZhdWx0 +L3Rlcm1zMDQGA1UdHwQtMCswKaAnoCWkIzAhMRIwEAYDVQQKEwliZVRSVVNUZWQx +CzAJBgNVBAYTAldXMB0GA1UdDgQWBBQquZtpLjub2M3eKjEENGvKBxirZzAfBgNV +HSMEGDAWgBQquZtpLjub2M3eKjEENGvKBxirZzAOBgNVHQ8BAf8EBAMCAf4wDQYJ +KoZIhvcNAQEFBQADggEBAHlh26Nebhax6nZR+csVm8tpvuaBa58oH2U+3RGFktTo +Qb9+M70j5/Egv6S0phkBxoyNNXxlpE8JpNbYIxUFE6dDea/bow6be3ga8wSGWsb2 +jCBHOElQBp1yZzrwmAOtlmdE/D8QDYZN5AA7KXvOOzuZhmElQITcE2K3+spZ1gMe +1lMBzW1MaFVA4e5rxyoAAEiCswoBw2AqDPeCNe5IhpbkdNQ96gFxugR1QKepfzk5 +mlWXKWWuGVUlBXJH0+gY3Ljpr0NzARJ0o+FcXxVdJPP55PS2Z2cS52QiivalQaYc +tmBjRYoQtLpGEK5BV2VsPyMQPyEQWbfkQN0mDCP2qq4= +-----END CERTIFICATE----- + +AddTrust Low-Value Services Root +================================ + +MD5 Fingerprint=1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Class 1 CA Root + Validity + Not Before: May 30 10:38:31 2000 GMT + Not After : May 30 10:38:31 2020 GMT + Subject: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Class 1 CA Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:96:96:d4:21:49:60:e2:6b:e8:41:07:0c:de:c4: + e0:dc:13:23:cd:c1:35:c7:fb:d6:4e:11:0a:67:5e: + f5:06:5b:6b:a5:08:3b:5b:29:16:3a:e7:87:b2:34: + 06:c5:bc:05:a5:03:7c:82:cb:29:10:ae:e1:88:81: + bd:d6:9e:d3:fe:2d:56:c1:15:ce:e3:26:9d:15:2e: + 10:fb:06:8f:30:04:de:a7:b4:63:b4:ff:b1:9c:ae: + 3c:af:77:b6:56:c5:b5:ab:a2:e9:69:3a:3d:0e:33: + 79:32:3f:70:82:92:99:61:6d:8d:30:08:8f:71:3f: + a6:48:57:19:f8:25:dc:4b:66:5c:a5:74:8f:98:ae: + c8:f9:c0:06:22:e7:ac:73:df:a5:2e:fb:52:dc:b1: + 15:65:20:fa:35:66:69:de:df:2c:f1:6e:bc:30:db: + 2c:24:12:db:eb:35:35:68:90:cb:00:b0:97:21:3d: + 74:21:23:65:34:2b:bb:78:59:a3:d6:e1:76:39:9a: + a4:49:8e:8c:74:af:6e:a4:9a:a3:d9:9b:d2:38:5c: + 9b:a2:18:cc:75:23:84:be:eb:e2:4d:33:71:8e:1a: + f0:c2:f8:c7:1d:a2:ad:03:97:2c:f8:cf:25:c6:f6: + b8:24:31:b1:63:5d:92:7f:63:f0:25:c9:53:2e:1f: + bf:4d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 95:B1:B4:F0:94:B6:BD:C7:DA:D1:11:09:21:BE:C1:AF:49:FD:10:7B + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:95:B1:B4:F0:94:B6:BD:C7:DA:D1:11:09:21:BE:C1:AF:49:FD:10:7B + DirName:/C=SE/O=AddTrust AB/OU=AddTrust TTP Network/CN=AddTrust Class 1 CA Root + serial:01 + + Signature Algorithm: sha1WithRSAEncryption + 2c:6d:64:1b:1f:cd:0d:dd:b9:01:fa:96:63:34:32:48:47:99: + ae:97:ed:fd:72:16:a6:73:47:5a:f4:eb:dd:e9:f5:d6:fb:45: + cc:29:89:44:5d:bf:46:39:3d:e8:ee:bc:4d:54:86:1e:1d:6c: + e3:17:27:43:e1:89:56:2b:a9:6f:72:4e:49:33:e3:72:7c:2a: + 23:9a:bc:3e:ff:28:2a:ed:a3:ff:1c:23:ba:43:57:09:67:4d: + 4b:62:06:2d:f8:ff:6c:9d:60:1e:d8:1c:4b:7d:b5:31:2f:d9: + d0:7c:5d:f8:de:6b:83:18:78:37:57:2f:e8:33:07:67:df:1e: + c7:6b:2a:95:76:ae:8f:57:a3:f0:f4:52:b4:a9:53:08:cf:e0: + 4f:d3:7a:53:8b:fd:bb:1c:56:36:f2:fe:b2:b6:e5:76:bb:d5: + 22:65:a7:3f:fe:d1:66:ad:0b:bc:6b:99:86:ef:3f:7d:f3:18: + 32:ca:7b:c6:e3:ab:64:46:95:f8:26:69:d9:55:83:7b:2c:96: + 07:ff:59:2c:44:a3:c6:e5:e9:a9:dc:a1:63:80:5a:21:5e:21: + cf:53:54:f0:ba:6f:89:db:a8:aa:95:cf:8b:e3:71:cc:1e:1b: + 20:44:08:c0:7a:b6:40:fd:c4:e4:35:e1:1d:16:1c:d0:bc:2b: + 8e:d6:71:d9 +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw +MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD +VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul +CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n +tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl +dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch +PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC ++Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O +BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk +ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X +7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz +43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl +pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA +WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- + +Thawte Personal Basic CA +======================== + +MD5 Fingerprint=E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/emailAddress=personal-basic@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Basic CA/emailAddress=personal-basic@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bc:bc:93:53:6d:c0:50:4f:82:15:e6:48:94:35: + a6:5a:be:6f:42:fa:0f:47:ee:77:75:72:dd:8d:49: + 9b:96:57:a0:78:d4:ca:3f:51:b3:69:0b:91:76:17: + 22:07:97:6a:c4:51:93:4b:e0:8d:ef:37:95:a1:0c: + 4d:da:34:90:1d:17:89:97:e0:35:38:57:4a:c0:f4: + 08:70:e9:3c:44:7b:50:7e:61:9a:90:e3:23:d3:88: + 11:46:27:f5:0b:07:0e:bb:dd:d1:7f:20:0a:88:b9: + 56:0b:2e:1c:80:da:f1:e3:9e:29:ef:14:bd:0a:44: + fb:1b:5b:18:d1:bf:23:93:21 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 2d:e2:99:6b:b0:3d:7a:89:d7:59:a2:94:01:1f:2b:dd:12:4b: + 53:c2:ad:7f:aa:a7:00:5c:91:40:57:25:4a:38:aa:84:70:b9: + d9:80:0f:a5:7b:5c:fb:73:c6:bd:d7:8a:61:5c:03:e3:2d:27: + a8:17:e0:84:85:42:dc:5e:9b:c6:b7:b2:6d:bb:74:af:e4:3f: + cb:a7:b7:b0:e0:5d:be:78:83:25:94:d2:db:81:0f:79:07:6d: + 4f:f4:39:15:5a:52:01:7b:de:32:d6:4d:38:f6:12:5c:06:50: + df:05:5b:bd:14:4b:a1:df:29:ba:3b:41:8d:f7:63:56:a1:df: + 22:b1 +-----BEGIN CERTIFICATE----- +MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj +IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X +DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw +EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE +ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy +dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD +QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 +dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK +wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 +G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF +AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 +c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P +9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== +-----END CERTIFICATE----- + +AddTrust External Root +====================== + +MD5 Fingerprint=1D:35:54:04:85:78:B0:3F:42:42:4D:BF:20:73:0A:3F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root + Validity + Not Before: May 30 10:48:38 2000 GMT + Not After : May 30 10:48:38 2020 GMT + Subject: C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust External CA Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b7:f7:1a:33:e6:f2:00:04:2d:39:e0:4e:5b:ed: + 1f:bc:6c:0f:cd:b5:fa:23:b6:ce:de:9b:11:33:97: + a4:29:4c:7d:93:9f:bd:4a:bc:93:ed:03:1a:e3:8f: + cf:e5:6d:50:5a:d6:97:29:94:5a:80:b0:49:7a:db: + 2e:95:fd:b8:ca:bf:37:38:2d:1e:3e:91:41:ad:70: + 56:c7:f0:4f:3f:e8:32:9e:74:ca:c8:90:54:e9:c6: + 5f:0f:78:9d:9a:40:3c:0e:ac:61:aa:5e:14:8f:9e: + 87:a1:6a:50:dc:d7:9a:4e:af:05:b3:a6:71:94:9c: + 71:b3:50:60:0a:c7:13:9d:38:07:86:02:a8:e9:a8: + 69:26:18:90:ab:4c:b0:4f:23:ab:3a:4f:84:d8:df: + ce:9f:e1:69:6f:bb:d7:42:d7:6b:44:e4:c7:ad:ee: + 6d:41:5f:72:5a:71:08:37:b3:79:65:a4:59:a0:94: + 37:f7:00:2f:0d:c2:92:72:da:d0:38:72:db:14:a8: + 45:c4:5d:2a:7d:b7:b4:d6:c4:ee:ac:cd:13:44:b7: + c9:2b:dd:43:00:25:fa:61:b9:69:6a:58:23:11:b7: + a7:33:8f:56:75:59:f5:cd:29:d7:46:b7:0a:2b:65: + b6:d3:42:6f:15:b2:b8:7b:fb:ef:e9:5d:53:d5:34: + 5a:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A + DirName:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root + serial:01 + + Signature Algorithm: sha1WithRSAEncryption + b0:9b:e0:85:25:c2:d6:23:e2:0f:96:06:92:9d:41:98:9c:d9: + 84:79:81:d9:1e:5b:14:07:23:36:65:8f:b0:d8:77:bb:ac:41: + 6c:47:60:83:51:b0:f9:32:3d:e7:fc:f6:26:13:c7:80:16:a5: + bf:5a:fc:87:cf:78:79:89:21:9a:e2:4c:07:0a:86:35:bc:f2: + de:51:c4:d2:96:b7:dc:7e:4e:ee:70:fd:1c:39:eb:0c:02:51: + 14:2d:8e:bd:16:e0:c1:df:46:75:e7:24:ad:ec:f4:42:b4:85: + 93:70:10:67:ba:9d:06:35:4a:18:d3:2b:7a:cc:51:42:a1:7a: + 63:d1:e6:bb:a1:c5:2b:c2:36:be:13:0d:e6:bd:63:7e:79:7b: + a7:09:0d:40:ab:6a:dd:8f:8a:c3:f6:f6:8c:1a:42:05:51:d4: + 45:f5:9f:a7:62:21:68:15:20:43:3c:99:e7:7c:bd:24:d8:a9: + 91:17:73:88:3f:56:1b:31:38:18:b4:71:0f:9a:cd:c8:0e:9e: + 8e:2e:1b:e1:8c:98:83:cb:1f:31:f1:44:4c:c6:04:73:49:76: + 60:0f:c7:f8:bd:17:80:6b:2e:e9:cc:4c:0e:5a:9a:79:0f:20: + 0a:2e:d5:9e:63:26:1e:55:92:94:d8:82:17:5a:7b:d0:bc:c7: + 8f:4e:86:04 +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +AddTrust Public Services Root +============================= + +MD5 Fingerprint=C1:62:3E:23:C5:82:73:9C:03:59:4B:2B:E9:77:49:7F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Public CA Root + Validity + Not Before: May 30 10:41:50 2000 GMT + Not After : May 30 10:41:50 2020 GMT + Subject: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Public CA Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:e9:1a:30:8f:83:88:14:c1:20:d8:3c:9b:8f:1b: + 7e:03:74:bb:da:69:d3:46:a5:f8:8e:c2:0c:11:90: + 51:a5:2f:66:54:40:55:ea:db:1f:4a:56:ee:9f:23: + 6e:f4:39:cb:a1:b9:6f:f2:7e:f9:5d:87:26:61:9e: + 1c:f8:e2:ec:a6:81:f8:21:c5:24:cc:11:0c:3f:db: + 26:72:7a:c7:01:97:07:17:f9:d7:18:2c:30:7d:0e: + 7a:1e:62:1e:c6:4b:c0:fd:7d:62:77:d3:44:1e:27: + f6:3f:4b:44:b3:b7:38:d9:39:1f:60:d5:51:92:73: + 03:b4:00:69:e3:f3:14:4e:ee:d1:dc:09:cf:77:34: + 46:50:b0:f8:11:f2:fe:38:79:f7:07:39:fe:51:92: + 97:0b:5b:08:5f:34:86:01:ad:88:97:eb:66:cd:5e: + d1:ff:dc:7d:f2:84:da:ba:77:ad:dc:80:08:c7:a7: + 87:d6:55:9f:97:6a:e8:c8:11:64:ba:e7:19:29:3f: + 11:b3:78:90:84:20:52:5b:11:ef:78:d0:83:f6:d5: + 48:90:d0:30:1c:cf:80:f9:60:fe:79:e4:88:f2:dd: + 00:eb:94:45:eb:65:94:69:40:ba:c0:d5:b4:b8:ba: + 7d:04:11:a8:eb:31:05:96:94:4e:58:21:8e:9f:d0: + 60:fd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 81:3E:37:D8:92:B0:1F:77:9F:5C:B4:AB:73:AA:E7:F6:34:60:2F:FA + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:81:3E:37:D8:92:B0:1F:77:9F:5C:B4:AB:73:AA:E7:F6:34:60:2F:FA + DirName:/C=SE/O=AddTrust AB/OU=AddTrust TTP Network/CN=AddTrust Public CA Root + serial:01 + + Signature Algorithm: sha1WithRSAEncryption + 03:f7:15:4a:f8:24:da:23:56:16:93:76:dd:36:28:b9:ae:1b: + b8:c3:f1:64:ba:20:18:78:95:29:27:57:05:bc:7c:2a:f4:b9: + 51:55:da:87:02:de:0f:16:17:31:f8:aa:79:2e:09:13:bb:af: + b2:20:19:12:e5:93:f9:4b:f9:83:e8:44:d5:b2:41:25:bf:88: + 75:6f:ff:10:fc:4a:54:d0:5f:f0:fa:ef:36:73:7d:1b:36:45: + c6:21:6d:b4:15:b8:4e:cf:9c:5c:a5:3d:5a:00:8e:06:e3:3c: + 6b:32:7b:f2:9f:f0:b6:fd:df:f0:28:18:48:f0:c6:bc:d0:bf: + 34:80:96:c2:4a:b1:6d:8e:c7:90:45:de:2f:67:ac:45:04:a3: + 7a:dc:55:92:c9:47:66:d8:1a:8c:c7:ed:9c:4e:9a:e0:12:bb: + b5:6a:4c:84:e1:e1:22:0d:87:00:64:fe:8c:7d:62:39:65:a6: + ef:42:b6:80:25:12:61:01:a8:24:13:70:00:11:26:5f:fa:35: + 50:c5:48:cc:06:47:e8:27:d8:70:8d:5f:64:e6:a1:44:26:5e: + 22:ec:92:cd:ff:42:9a:44:21:6d:5c:c5:e3:22:1d:5f:47:12: + e7:ce:5f:5d:fa:d8:aa:b1:33:2d:d9:76:f2:4e:3a:33:0c:2b: + b3:2d:90:06 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx +MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB +ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV +BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV +6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX +GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP +dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH +1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF +62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW +BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL +MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU +cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv +b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 +IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ +iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh +4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm +XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +AddTrust Qualified Certificates Root +==================================== + +MD5 Fingerprint=27:EC:39:47:CD:DA:5A:AF:E2:9A:01:65:21:A9:4C:BB +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Qualified CA Root + Validity + Not Before: May 30 10:44:50 2000 GMT + Not After : May 30 10:44:50 2020 GMT + Subject: C=SE, O=AddTrust AB, OU=AddTrust TTP Network, CN=AddTrust Qualified CA Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:e4:1e:9a:fe:dc:09:5a:87:a4:9f:47:be:11:5f: + af:84:34:db:62:3c:79:78:b7:e9:30:b5:ec:0c:1c: + 2a:c4:16:ff:e0:ec:71:eb:8a:f5:11:6e:ed:4f:0d: + 91:d2:12:18:2d:49:15:01:c2:a4:22:13:c7:11:64: + ff:22:12:9a:b9:8e:5c:2f:08:cf:71:6a:b3:67:01: + 59:f1:5d:46:f3:b0:78:a5:f6:0e:42:7a:e3:7f:1b: + cc:d0:f0:b7:28:fd:2a:ea:9e:b3:b0:b9:04:aa:fd: + f6:c7:b4:b1:b8:2a:a0:fb:58:f1:19:a0:6f:70:25: + 7e:3e:69:4a:7f:0f:22:d8:ef:ad:08:11:9a:29:99: + e1:aa:44:45:9a:12:5e:3e:9d:6d:52:fc:e7:a0:3d: + 68:2f:f0:4b:70:7c:13:38:ad:bc:15:25:f1:d6:ce: + ab:a2:c0:31:d6:2f:9f:e0:ff:14:59:fc:84:93:d9: + 87:7c:4c:54:13:eb:9f:d1:2d:11:f8:18:3a:3a:de: + 25:d9:f7:d3:40:ed:a4:06:12:c4:3b:e1:91:c1:56: + 35:f0:14:dc:65:36:09:6e:ab:a4:07:c7:35:d1:c2: + 03:33:36:5b:75:26:6d:42:f1:12:6b:43:6f:4b:71: + 94:fa:34:1d:ed:13:6e:ca:80:7f:98:2f:6c:b9:65: + d8:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 39:95:8B:62:8B:5C:C9:D4:80:BA:58:0F:97:3F:15:08:43:CC:98:A7 + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Authority Key Identifier: + keyid:39:95:8B:62:8B:5C:C9:D4:80:BA:58:0F:97:3F:15:08:43:CC:98:A7 + DirName:/C=SE/O=AddTrust AB/OU=AddTrust TTP Network/CN=AddTrust Qualified CA Root + serial:01 + + Signature Algorithm: sha1WithRSAEncryption + 19:ab:75:ea:f8:8b:65:61:95:13:ba:69:04:ef:86:ca:13:a0: + c7:aa:4f:64:1b:3f:18:f6:a8:2d:2c:55:8f:05:b7:30:ea:42: + 6a:1d:c0:25:51:2d:a7:bf:0c:b3:ed:ef:08:7f:6c:3c:46:1a: + ea:18:43:df:76:cc:f9:66:86:9c:2c:68:f5:e9:17:f8:31:b3: + 18:c4:d6:48:7d:23:4c:68:c1:7e:bb:01:14:6f:c5:d9:6e:de: + bb:04:42:6a:f8:f6:5c:7d:e5:da:fa:87:eb:0d:35:52:67:d0: + 9e:97:76:05:93:3f:95:c7:01:e6:69:55:38:7f:10:61:99:c9: + e3:5f:a6:ca:3e:82:63:48:aa:e2:08:48:3e:aa:f2:b2:85:62: + a6:b4:a7:d9:bd:37:9c:68:b5:2d:56:7d:b0:b7:3f:a0:b1:07: + d6:e9:4f:dc:de:45:71:30:32:7f:1b:2e:09:f9:bf:52:a1:ee: + c2:80:3e:06:5c:2e:55:40:c1:1b:f5:70:45:b0:dc:5d:fa:f6: + 72:5a:77:d2:63:cd:cf:58:89:00:42:63:3f:79:39:d0:44:b0: + 82:6e:41:19:e8:dd:e0:c1:88:5a:d1:1e:71:93:1f:24:30:74: + e5:1e:a8:de:3c:27:37:7f:83:ae:9e:77:cf:f0:30:b1:ff:4b: + 99:e8:c6:a1 +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 +b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 +MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK +EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh +BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq +xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G +87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i +2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U +WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 +0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G +A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr +pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL +ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm +aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv +hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm +hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 +P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y +iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no +xqE= +-----END CERTIFICATE----- + +Verisign Class 1 Public Primary OCSP Responder +============================================== + +MD5 Fingerprint=7E:6F:3A:53:1B:7C:BE:B0:30:DB:43:1E:1E:94:89:B2 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2b:68:d4:a3:46:9e:c5:3b:28:09:ab:38:5d:7f:27:20 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 1 Public Primary Certification Authority + Validity + Not Before: Aug 4 00:00:00 2000 GMT + Not After : Aug 3 23:59:59 2004 GMT + Subject: O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/RPA (c)00, CN=Class 1 Public Primary OCSP Responder + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b9:ed:5e:7a:3a:77:5f:ce:5f:3a:52:fc:cd:64: + f7:71:b5:6f:6a:96:c6:59:92:55:94:5d:2f:5b:2e: + c1:11:ea:26:8a:cb:a7:81:3c:f6:5a:44:de:7a:13: + 2f:fd:5a:51:d9:7b:37:26:4a:c0:27:3f:04:03:6a: + 56:c1:83:2c:e1:6f:5b:a9:54:50:24:4a:c6:2e:7a: + 4c:a1:5b:37:54:24:21:31:1f:a1:78:18:76:a7:b1: + 70:da:22:d0:6a:fe:07:62:40:c6:f7:f6:9b:7d:0c: + 06:b8:4b:c7:28:e4:66:23:84:51:ef:46:b7:93:d8: + 81:33:cb:e5:36:ac:c6:e8:05 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DirName:/CN=OCSP 1-1 + X509v3 CRL Distribution Points: + URI:http://crl.verisign.com/pca1.crl + + X509v3 Extended Key Usage: + OCSP Signing + Authority Information Access: + OCSP - URI:http://ocsp.verisign.com/ocsp/status + + X509v3 Certificate Policies: + Policy: 2.16.840.1.113733.1.7.1.1 + CPS: https://www.verisign.com/RPA + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature + Signature Algorithm: sha1WithRSAEncryption + 70:90:dd:b8:e4:be:53:17:7c:7f:02:e9:d5:f7:8b:99:93:31: + 60:8d:7e:e6:60:6b:24:ef:60:ac:d2:ce:91:de:80:6d:09:a4: + d3:b8:38:e5:44:ca:72:5e:0d:2d:c1:77:9c:bd:2c:03:78:29: + 8d:a4:a5:77:87:f5:f1:2b:26:ad:cc:07:6c:3a:54:5a:28:e0: + 09:f3:4d:0a:04:ca:d4:58:69:0b:a7:b3:f5:dd:01:a5:e7:dc: + f0:1f:ba:c1:5d:90:8d:b3:ea:4f:c1:11:59:97:6a:b2:2b:13: + b1:da:ad:97:a1:b3:b1:a0:20:5b:ca:32:ab:8d:cf:13:f0:1f: + 29:c3 +-----BEGIN CERTIFICATE----- +MIIDnjCCAwegAwIBAgIQK2jUo0aexTsoCas4XX8nIDANBgkqhkiG9w0BAQUFADBf +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT +LkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw +HhcNMDAwODA0MDAwMDAwWhcNMDQwODAzMjM1OTU5WjCBpzEXMBUGA1UEChMOVmVy +aVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5 +BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20v +UlBBIChjKTAwMS4wLAYDVQQDEyVDbGFzcyAxIFB1YmxpYyBQcmltYXJ5IE9DU1Ag +UmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC57V56Ondfzl86 +UvzNZPdxtW9qlsZZklWUXS9bLsER6iaKy6eBPPZaRN56Ey/9WlHZezcmSsAnPwQD +albBgyzhb1upVFAkSsYuekyhWzdUJCExH6F4GHansXDaItBq/gdiQMb39pt9DAa4 +S8co5GYjhFHvRreT2IEzy+U2rMboBQIDAQABo4IBEDCCAQwwIAYDVR0RBBkwF6QV +MBMxETAPBgNVBAMTCE9DU1AgMS0xMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9j +cmwudmVyaXNpZ24uY29tL3BjYTEuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEIG +CCsGAQUFBwEBBDYwNDAyBggrBgEFBQcwAaYmFiRodHRwOi8vb2NzcC52ZXJpc2ln +bi5jb20vb2NzcC9zdGF0dXMwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcBATAqMCgG +CCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vUlBBMAkGA1UdEwQC +MAAwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBBQUAA4GBAHCQ3bjkvlMXfH8C6dX3 +i5mTMWCNfuZgayTvYKzSzpHegG0JpNO4OOVEynJeDS3Bd5y9LAN4KY2kpXeH9fEr +Jq3MB2w6VFoo4AnzTQoEytRYaQuns/XdAaXn3PAfusFdkI2z6k/BEVmXarIrE7Ha +rZehs7GgIFvKMquNzxPwHynD +-----END CERTIFICATE----- + +Verisign Class 2 Public Primary OCSP Responder +============================================== + +MD5 Fingerprint=F3:45:BD:10:96:0D:85:4B:EF:9F:11:62:34:A7:5E:B5 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 09:46:17:e6:1d:d8:d4:1c:a0:0c:a0:62:e8:79:8a:a7 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 2 Public Primary Certification Authority + Validity + Not Before: Aug 1 00:00:00 2000 GMT + Not After : Jul 31 23:59:59 2004 GMT + Subject: O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/RPA (c)00, CN=Class 2 Public Primary OCSP Responder + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d0:ca:63:31:61:7f:44:34:7c:05:7d:0b:3d:6a: + 90:cb:79:4b:77:0a:3f:4b:c7:23:e5:c0:62:2d:7e: + 9c:7e:3e:88:87:91:d0:ac:e8:4d:49:87:a2:96:90: + 8a:dd:04:a5:02:3f:8c:9b:e9:89:fe:62:a0:e2:5a: + bd:c8:dd:b4:78:e6:a5:42:93:08:67:01:c0:20:4d: + d7:5c:f4:5d:da:b3:e3:37:a6:52:1a:2c:4c:65:4d: + 8a:87:d9:a8:a3:f1:49:54:bb:3c:5c:80:51:68:c6: + fb:49:ff:0b:55:ab:15:dd:fb:9a:c1:b9:1d:74:0d: + b2:8c:44:5d:89:fc:9f:f9:83 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DirName:/CN=OCSP 1-2 + X509v3 CRL Distribution Points: + URI:http://crl.verisign.com/pca2.crl + + X509v3 Extended Key Usage: + OCSP Signing + Authority Information Access: + OCSP - URI:http://ocsp.verisign.com/ocsp/status + + X509v3 Certificate Policies: + Policy: 2.16.840.1.113733.1.7.1.1 + CPS: https://www.verisign.com/RPA + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature + Signature Algorithm: sha1WithRSAEncryption + 1f:7d:09:6e:24:46:75:04:9c:f3:26:9b:e3:39:6e:17:ef:bc: + bd:a2:1b:d2:02:84:86:ab:d0:40:97:2c:c4:43:88:37:19:6b: + 22:a8:03:71:50:9d:20:dc:36:60:20:9a:73:2d:73:55:6c:58: + 9b:2c:c2:b4:34:2c:7a:33:42:ca:91:d9:e9:43:af:cf:1e:e0: + f5:c4:7a:ab:3f:72:63:1e:a9:37:e1:5b:3b:88:b3:13:86:82: + 90:57:cb:57:ff:f4:56:be:22:dd:e3:97:a8:e1:bc:22:43:c2: + dd:4d:db:f6:81:9e:92:14:9e:39:0f:13:54:de:82:d8:c0:5e: + 34:8d +-----BEGIN CERTIFICATE----- +MIIDnjCCAwegAwIBAgIQCUYX5h3Y1BygDKBi6HmKpzANBgkqhkiG9w0BAQUFADBf +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT +LkNsYXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw +HhcNMDAwODAxMDAwMDAwWhcNMDQwNzMxMjM1OTU5WjCBpzEXMBUGA1UEChMOVmVy +aVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5 +BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20v +UlBBIChjKTAwMS4wLAYDVQQDEyVDbGFzcyAyIFB1YmxpYyBQcmltYXJ5IE9DU1Ag +UmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQymMxYX9ENHwF +fQs9apDLeUt3Cj9LxyPlwGItfpx+PoiHkdCs6E1Jh6KWkIrdBKUCP4yb6Yn+YqDi +Wr3I3bR45qVCkwhnAcAgTddc9F3as+M3plIaLExlTYqH2aij8UlUuzxcgFFoxvtJ +/wtVqxXd+5rBuR10DbKMRF2J/J/5gwIDAQABo4IBEDCCAQwwIAYDVR0RBBkwF6QV +MBMxETAPBgNVBAMTCE9DU1AgMS0yMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9j +cmwudmVyaXNpZ24uY29tL3BjYTIuY3JsMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEIG +CCsGAQUFBwEBBDYwNDAyBggrBgEFBQcwAaYmFiRodHRwOi8vb2NzcC52ZXJpc2ln +bi5jb20vb2NzcC9zdGF0dXMwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcBATAqMCgG +CCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vUlBBMAkGA1UdEwQC +MAAwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBBQUAA4GBAB99CW4kRnUEnPMmm+M5 +bhfvvL2iG9IChIar0ECXLMRDiDcZayKoA3FQnSDcNmAgmnMtc1VsWJsswrQ0LHoz +QsqR2elDr88e4PXEeqs/cmMeqTfhWzuIsxOGgpBXy1f/9Fa+It3jl6jhvCJDwt1N +2/aBnpIUnjkPE1TegtjAXjSN +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary OCSP Responder +============================================== + +MD5 Fingerprint=7D:51:92:C9:76:83:98:16:DE:8C:B3:86:C4:7D:66:FB +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 2e:96:9e:bf:b6:62:6c:ec:7b:e9:73:cc:e3:6c:c1:84 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + Validity + Not Before: Aug 4 00:00:00 2000 GMT + Not After : Aug 3 23:59:59 2004 GMT + Subject: O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/RPA (c)00, CN=Class 3 Public Primary OCSP Responder + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f1:e4:08:0e:83:bb:75:e3:48:e5:b8:db:a6:f0: + b9:ab:e9:3c:62:c7:5e:35:5b:d0:02:54:11:d8:c9: + d1:56:b9:76:4b:b9:ab:7a:e6:cd:ba:f6:0c:04:d6: + 7e:d6:b0:0a:65:ac:4e:39:e3:f1:f7:2d:a3:25:39: + ef:b0:8b:cf:be:db:0c:5d:6e:70:f4:07:cd:70:f7: + 3a:c0:3e:35:16:ed:78:8c:43:cf:c2:26:2e:47:d6: + 86:7d:9c:f1:be:d6:67:0c:22:25:a4:ca:65:e6:1f: + 7a:78:28:2f:3f:05:db:04:21:bf:e1:45:66:fe:3c: + b7:82:ed:5a:b8:16:15:b9:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DirName:/CN=OCSP 1-3 + X509v3 CRL Distribution Points: + URI:http://crl.verisign.com/pca3.1.1.crl + + X509v3 Extended Key Usage: + OCSP Signing + Authority Information Access: + OCSP - URI:http://ocsp.verisign.com/ocsp/status + + X509v3 Certificate Policies: + Policy: 2.16.840.1.113733.1.7.1.1 + CPS: https://www.verisign.com/RPA + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature + Signature Algorithm: sha1WithRSAEncryption + 02:f6:53:63:c0:a9:1e:f2:d0:8b:33:30:8f:48:9b:4c:b0:56: + b4:83:71:4a:be:dc:50:d8:f5:b6:e0:0b:db:bd:78:4f:e9:cf: + 09:34:da:29:49:9d:01:73:5a:91:91:82:54:2c:13:0a:d3:77: + 23:cf:37:fc:63:de:a7:e3:f6:b7:b5:69:45:28:49:c3:91:dc: + aa:47:1c:a9:88:99:2c:05:2a:8d:8d:8a:fa:62:e2:5a:b7:00: + 20:5d:39:c4:28:c2:cb:fc:9e:a8:89:ae:5b:3d:8e:12:ea:32: + b2:fc:eb:14:d7:09:15:1a:c0:cd:1b:d5:b5:15:4e:41:d5:96: + e3:4e +-----BEGIN CERTIFICATE----- +MIIDojCCAwugAwIBAgIQLpaev7ZibOx76XPM42zBhDANBgkqhkiG9w0BAQUFADBf +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT +LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw +HhcNMDAwODA0MDAwMDAwWhcNMDQwODAzMjM1OTU5WjCBpzEXMBUGA1UEChMOVmVy +aVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5 +BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20v +UlBBIChjKTAwMS4wLAYDVQQDEyVDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IE9DU1Ag +UmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDx5AgOg7t140jl +uNum8Lmr6Txix141W9ACVBHYydFWuXZLuat65s269gwE1n7WsAplrE454/H3LaMl +Oe+wi8++2wxdbnD0B81w9zrAPjUW7XiMQ8/CJi5H1oZ9nPG+1mcMIiWkymXmH3p4 +KC8/BdsEIb/hRWb+PLeC7Vq4FhW5VQIDAQABo4IBFDCCARAwIAYDVR0RBBkwF6QV +MBMxETAPBgNVBAMTCE9DU1AgMS0zMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9j +cmwudmVyaXNpZ24uY29tL3BjYTMuMS4xLmNybDATBgNVHSUEDDAKBggrBgEFBQcD +CTBCBggrBgEFBQcBAQQ2MDQwMgYIKwYBBQUHMAGmJhYkaHR0cDovL29jc3AudmVy +aXNpZ24uY29tL29jc3Avc3RhdHVzMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQEw +KjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL1JQQTAJBgNV +HRMEAjAAMAsGA1UdDwQEAwIHgDANBgkqhkiG9w0BAQUFAAOBgQAC9lNjwKke8tCL +MzCPSJtMsFa0g3FKvtxQ2PW24AvbvXhP6c8JNNopSZ0Bc1qRkYJULBMK03cjzzf8 +Y96n4/a3tWlFKEnDkdyqRxypiJksBSqNjYr6YuJatwAgXTnEKMLL/J6oia5bPY4S +6jKy/OsU1wkVGsDNG9W1FU5B1ZbjTg== +-----END CERTIFICATE----- + +Verisign Secure Server OCSP Responder +===================================== + +MD5 Fingerprint=2C:62:C3:D8:80:01:16:09:EA:59:EA:78:AB:10:43:F6 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + ff:45:d5:27:5d:24:fb:b3:c2:39:24:53:57:e1:4f:de + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + Validity + Not Before: Aug 4 00:00:00 2000 GMT + Not After : Aug 3 23:59:59 2004 GMT + Subject: O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/RPA (c)00, CN=Secure Server OCSP Responder + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b8:51:99:64:85:0e:ee:b3:0a:68:f0:bf:63:76: + 1d:53:f5:fc:a1:78:8c:33:ee:9f:f4:be:39:da:9b: + 0f:4d:47:a9:8f:20:e8:4b:44:bd:ce:cd:7b:90:d1: + 30:e8:90:c4:25:7b:89:28:de:bd:f6:93:1d:ff:b9: + ff:92:b5:a9:8d:e4:ae:cc:e2:c3:07:83:6a:a3:72: + 10:01:27:62:22:a6:35:26:39:2d:9e:cf:60:0c:fc: + 47:a4:d7:d0:42:78:a7:1d:6c:d0:cb:4f:15:a7:29: + 0a:b4:95:45:c4:b1:e7:5a:09:d7:39:95:d8:1d:35: + 9e:c2:bd:b3:5d:c1:0c:4b:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DirName:/CN=OCSP 1-4 + X509v3 CRL Distribution Points: + URI:http://crl.verisign.com/RSASecureServer-p.crl + + X509v3 Extended Key Usage: + OCSP Signing + Authority Information Access: + OCSP - URI:http://ocsp.verisign.com/ocsp/status + + X509v3 Certificate Policies: + Policy: 2.16.840.1.113733.1.7.1.1 + CPS: https://www.verisign.com/RPA + + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature + Signature Algorithm: sha1WithRSAEncryption + 00:b3:10:53:66:9c:49:93:2e:31:a0:02:42:d2:58:57:7e:66: + a1:fe:1b:8a:61:18:50:40:2c:1e:2b:41:a5:d6:db:ff:ac:08: + 1c:5a:05:6d:02:5c:2a:b6:96:4f:47:db:be:4e:db:ce:cc:ba: + 86:b8:18:ce:b1:12:91:5f:63:f7:f3:48:3e:cc:f1:4d:13:e4: + 6d:09:94:78:00:92:cb:a3:20:9d:06:0b:6a:a0:43:07:ce:d1: + 19:6c:8f:18:75:9a:9f:17:33:fd:a9:26:b8:e3:e2:de:c2:a8: + c4:5a:8a:7f:98:d6:07:06:6b:cc:56:9e:86:70:ce:d4:ef +-----BEGIN CERTIFICATE----- +MIIDnzCCAwygAwIBAgIRAP9F1SddJPuzwjkkU1fhT94wDQYJKoZIhvcNAQEFBQAw +XzELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMu +MS4wLAYDVQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MB4XDTAwMDgwNDAwMDAwMFoXDTA0MDgwMzIzNTk1OVowgZ4xFzAVBgNVBAoTDlZl +cmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTsw +OQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29t +L1JQQSAoYykwMDElMCMGA1UEAxMcU2VjdXJlIFNlcnZlciBPQ1NQIFJlc3BvbmRl +cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuFGZZIUO7rMKaPC/Y3YdU/X8 +oXiMM+6f9L452psPTUepjyDoS0S9zs17kNEw6JDEJXuJKN699pMd/7n/krWpjeSu +zOLDB4Nqo3IQASdiIqY1Jjktns9gDPxHpNfQQninHWzQy08VpykKtJVFxLHnWgnX +OZXYHTWewr2zXcEMSx8CAwEAAaOCAR0wggEZMCAGA1UdEQQZMBekFTATMREwDwYD +VQQDEwhPQ1NQIDEtNDA+BgNVHR8ENzA1MDOgMaAvhi1odHRwOi8vY3JsLnZlcmlz +aWduLmNvbS9SU0FTZWN1cmVTZXJ2ZXItcC5jcmwwEwYDVR0lBAwwCgYIKwYBBQUH +AwkwQgYIKwYBBQUHAQEENjA0MDIGCCsGAQUFBzABpiYWJGh0dHA6Ly9vY3NwLnZl +cmlzaWduLmNvbS9vY3NwL3N0YXR1czBEBgNVHSAEPTA7MDkGC2CGSAGG+EUBBwEB +MCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9SUEEwCQYD +VR0TBAIwADALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEFBQADfgAAsxBTZpxJky4x +oAJC0lhXfmah/huKYRhQQCweK0Gl1tv/rAgcWgVtAlwqtpZPR9u+TtvOzLqGuBjO +sRKRX2P380g+zPFNE+RtCZR4AJLLoyCdBgtqoEMHztEZbI8YdZqfFzP9qSa44+Le +wqjEWop/mNYHBmvMVp6GcM7U7w== +-----END CERTIFICATE----- + +Verisign Time Stamping Authority CA +=================================== + +MD5 Fingerprint=89:49:54:8C:C8:68:9A:83:29:EC:DC:06:73:21:AB:97 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 53:61:b2:60:ae:db:71:8e:a7:94:b3:13:33:f4:07:09 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign Trust Network + Validity + Not Before: Sep 26 00:00:00 2000 GMT + Not After : Sep 25 23:59:59 2010 GMT + Subject: O=VeriSign, Inc., OU=VeriSign Trust Network, OU=Terms of use at https://www.verisign.com/rpa (c)00, CN=VeriSign Time Stamping Authority CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d2:19:9d:67:c2:00:21:59:62:ce:b4:09:22:44: + 69:8a:f8:25:5a:db:ed:0d:b7:36:7e:4e:e0:bb:94: + 3e:90:25:87:c2:61:47:29:d9:bd:54:b8:63:cc:2c: + 7d:69:b4:33:36:f4:37:07:9a:c1:dd:40:54:fc:e0: + 78:9d:a0:93:b9:09:3d:23:51:7f:44:c2:14:74:db: + 0a:be:cb:c9:30:34:40:98:3e:d0:d7:25:10:81:94: + bd:07:4f:9c:d6:54:27:df:2e:a8:bf:cb:90:8c:8d: + 75:4b:bc:e2:e8:44:87:cd:e6:41:0a:25:6e:e8:f4: + 24:02:c5:52:0f:6e:ec:98:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE, pathlen:0 + X509v3 Certificate Policies: + Policy: 2.16.840.1.113733.1.7.23.1.3 + CPS: https://www.verisign.com/rpa + + X509v3 CRL Distribution Points: + URI:http://crl.verisign.com/pca3.crl + + X509v3 Key Usage: + Certificate Sign, CRL Sign + Authority Information Access: + OCSP - URI:http://ocsp.verisign.com/ocsp/status + + Signature Algorithm: sha1WithRSAEncryption + 82:70:68:95:df:b6:0d:c2:01:70:19:4a:d2:54:56:1e:ac:f2: + 45:4c:87:b8:f5:35:eb:78:4b:05:a9:c8:9d:3b:19:21:2e:70: + 34:4a:a2:f5:89:e0:15:75:45:e7:28:37:00:34:27:29:e8:37: + 4b:f2:ef:44:97:6b:17:51:1a:c3:56:9d:3c:1a:8a:f6:4a:46: + 46:37:8c:fa:cb:f5:64:5a:38:68:2e:1c:c3:ef:70:ce:b8:46: + 06:16:bf:f7:7e:e7:b5:a8:3e:45:ac:a9:25:75:22:7b:6f:3f: + b0:9c:94:e7:c7:73:ab:ac:1f:ee:25:9b:c0:16:ed:b7:ca:5b: + f0:14 +-----BEGIN CERTIFICATE----- +MIIDzTCCAzagAwIBAgIQU2GyYK7bcY6nlLMTM/QHCTANBgkqhkiG9w0BAQUFADCB +wTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTwwOgYDVQQL +EzNDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzIxOjA4BgNVBAsTMShjKSAxOTk4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmswHhcNMDAwOTI2MDAwMDAwWhcNMTAwOTI1MjM1OTU5WjCBpTEXMBUGA1UEChMO +VmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsx +OzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5j +b20vcnBhIChjKTAwMSwwKgYDVQQDEyNWZXJpU2lnbiBUaW1lIFN0YW1waW5nIEF1 +dGhvcml0eSBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0hmdZ8IAIVli +zrQJIkRpivglWtvtDbc2fk7gu5Q+kCWHwmFHKdm9VLhjzCx9abQzNvQ3B5rB3UBU +/OB4naCTuQk9I1F/RMIUdNsKvsvJMDRAmD7Q1yUQgZS9B0+c1lQn3y6ov8uQjI11 +S7zi6ESHzeZBCiVu6PQkAsVSD27smHUCAwEAAaOB3zCB3DAPBgNVHRMECDAGAQH/ +AgEAMEUGA1UdIAQ+MDwwOgYMYIZIAYb4RQEHFwEDMCowKAYIKwYBBQUHAgEWHGh0 +dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwMQYDVR0fBCowKDAmoCSgIoYgaHR0 +cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwCwYDVR0PBAQDAgEGMEIGCCsG +AQUFBwEBBDYwNDAyBggrBgEFBQcwAaYmFiRodHRwOi8vb2NzcC52ZXJpc2lnbi5j +b20vb2NzcC9zdGF0dXMwDQYJKoZIhvcNAQEFBQADgYEAgnBold+2DcIBcBlK0lRW +HqzyRUyHuPU163hLBanInTsZIS5wNEqi9YngFXVF5yg3ADQnKeg3S/LvRJdrF1Ea +w1adPBqK9kpGRjeM+sv1ZFo4aC4cw+9wzrhGBha/937ntag+RaypJXUie28/sJyU +58dzq6wf7iWbwBbtt8pb8BQ= +-----END CERTIFICATE----- + +Thawte Time Stamping CA +======================= + +MD5 Fingerprint=7F:66:7A:71:D3:EB:69:78:20:9A:51:14:9D:83:DA:20 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Durbanville, O=Thawte, OU=Thawte Certification, CN=Thawte Timestamping CA + Validity + Not Before: Jan 1 00:00:00 1997 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Durbanville, O=Thawte, OU=Thawte Certification, CN=Thawte Timestamping CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d6:2b:58:78:61:45:86:53:ea:34:7b:51:9c:ed: + b0:e6:2e:18:0e:fe:e0:5f:a8:27:d3:b4:c9:e0:7c: + 59:4e:16:0e:73:54:60:c1:7f:f6:9f:2e:e9:3a:85: + 24:15:3c:db:47:04:63:c3:9e:c4:94:1a:5a:df:4c: + 7a:f3:d9:43:1d:3c:10:7a:79:25:db:90:fe:f0:51: + e7:30:d6:41:00:fd:9f:28:df:79:be:94:bb:9d:b6: + 14:e3:23:85:d7:a9:41:e0:4c:a4:79:b0:2b:1a:8b: + f2:f8:3b:8a:3e:45:ac:71:92:00:b4:90:41:98:fb: + 5f:ed:fa:b7:2e:8a:f8:88:37 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 67:db:e2:c2:e6:87:3d:40:83:86:37:35:7d:1f:ce:9a:c3:0c: + 66:20:a8:ba:aa:04:89:86:c2:f5:10:08:0d:bf:cb:a2:05:8a: + d0:4d:36:3e:f4:d7:ef:69:c6:5e:e4:b0:94:6f:4a:b9:e7:de: + 5b:88:b6:7b:db:e3:27:e5:76:c3:f0:35:c1:cb:b5:27:9b:33: + 79:dc:90:a6:00:9e:77:fa:fc:cd:27:94:42:16:9c:d3:1c:68: + ec:bf:5c:dd:e5:a9:7b:10:0a:32:74:54:13:31:8b:85:03:84: + 91:b7:58:01:30:14:38:af:28:ca:fc:b1:50:19:19:09:ac:89: + 49:d3 +-----BEGIN CERTIFICATE----- +MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN +BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd +BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN +MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g +Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG +A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l +c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT +6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa +Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL +8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC +9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ +pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ +CayJSdM= +-----END CERTIFICATE----- + +Entrust.net Global Secure Server CA +=================================== + +MD5 Fingerprint=9D:66:6A:CC:FF:D5:F5:43:B4:BF:8C:16:D1:2B:A8:99 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 949686588 (0x389b113c) + Signature Algorithm: md5WithRSAEncryption + Issuer: O=Entrust.net, OU=www.entrust.net/SSL_CPS incorp. by ref. (limits liab.), OU=(c) 2000 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Validity + Not Before: Feb 4 17:20:00 2000 GMT + Not After : Feb 4 17:50:00 2020 GMT + Subject: O=Entrust.net, OU=www.entrust.net/SSL_CPS incorp. by ref. (limits liab.), OU=(c) 2000 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c7:c1:5f:4e:71:f1:ce:f0:60:86:0f:d2:58:7f: + d3:33:97:2d:17:a2:75:30:b5:96:64:26:2f:68:c3: + 44:ab:a8:75:e6:00:67:34:57:9e:65:c7:22:9b:73: + e6:d3:dd:08:0e:37:55:aa:25:46:81:6c:bd:fe:a8: + f6:75:57:57:8c:90:6c:4a:c3:3e:8b:4b:43:0a:c9: + 11:56:9a:9a:27:22:99:cf:55:9e:61:d9:02:e2:7c: + b6:7c:38:07:dc:e3:7f:4f:9a:b9:03:41:80:b6:75: + 67:13:0b:9f:e8:57:36:c8:5d:00:36:de:66:14:da: + 6e:76:1f:4f:37:8c:82:13:89 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/O=Entrust.net/OU=www.entrust.net/SSL_CPS incorp. by ref. (limits liab.)/OU=(c) 2000 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Feb 4 17:20:00 2000 GMT, Not After: Feb 4 17:50:00 2020 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:CB:6C:C0:6B:E3:BB:3E:CB:FC:22:9C:FE:FB:8B:92:9C:B0:F2:6E:22 + + X509v3 Subject Key Identifier: + CB:6C:C0:6B:E3:BB:3E:CB:FC:22:9C:FE:FB:8B:92:9C:B0:F2:6E:22 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V5.0:4.0.... + Signature Algorithm: md5WithRSAEncryption + 62:db:81:91:ce:c8:9a:77:42:2f:ec:bd:27:a3:53:0f:50:1b: + ea:4e:92:f0:a9:af:a9:a0:ba:48:61:cb:ef:c9:06:ef:1f:d5: + f4:ee:df:56:2d:e6:ca:6a:19:73:aa:53:be:92:b3:50:02:b6: + 85:26:72:63:d8:75:50:62:75:14:b7:b3:50:1a:3f:ca:11:00: + 0b:85:45:69:6d:b6:a5:ae:51:e1:4a:dc:82:3f:6c:8c:34:b2: + 77:6b:d9:02:f6:7f:0e:ea:65:04:f1:cd:54:ca:ba:c9:cc:e0: + 84:f7:c8:3e:11:97:d3:60:09:18:bc:05:ff:6c:89:33:f0:ec: + 15:0f +-----BEGIN CERTIFICATE----- +MIIElTCCA/6gAwIBAgIEOJsRPDANBgkqhkiG9w0BAQQFADCBujEUMBIGA1UEChML +RW50cnVzdC5uZXQxPzA9BgNVBAsUNnd3dy5lbnRydXN0Lm5ldC9TU0xfQ1BTIGlu +Y29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDIwMDAg +RW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJl +IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDQxNzIwMDBa +Fw0yMDAyMDQxNzUwMDBaMIG6MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDE/MD0GA1UE +CxQ2d3d3LmVudHJ1c3QubmV0L1NTTF9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p +dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5ldCBMaW1pdGVk +MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp +b24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHwV9OcfHO +8GCGD9JYf9Mzly0XonUwtZZkJi9ow0SrqHXmAGc0V55lxyKbc+bT3QgON1WqJUaB +bL3+qPZ1V1eMkGxKwz6LS0MKyRFWmponIpnPVZ5h2QLifLZ8OAfc439PmrkDQYC2 +dWcTC5/oVzbIXQA23mYU2m52H083jIITiQIDAQABo4IBpDCCAaAwEQYJYIZIAYb4 +QgEBBAQDAgAHMIHjBgNVHR8EgdswgdgwgdWggdKggc+kgcwwgckxFDASBgNVBAoT +C0VudHJ1c3QubmV0MT8wPQYDVQQLFDZ3d3cuZW50cnVzdC5uZXQvU1NMX0NQUyBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw +IEVudHJ1c3QubmV0IExpbWl0ZWQxOjA4BgNVBAMTMUVudHJ1c3QubmV0IFNlY3Vy +ZSBTZXJ2ZXIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEw +KwYDVR0QBCQwIoAPMjAwMDAyMDQxNzIwMDBagQ8yMDIwMDIwNDE3NTAwMFowCwYD +VR0PBAQDAgEGMB8GA1UdIwQYMBaAFMtswGvjuz7L/CKc/vuLkpyw8m4iMB0GA1Ud +DgQWBBTLbMBr47s+y/winP77i5KcsPJuIjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2 +fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQQFAAOBgQBi24GRzsia +d0Iv7L0no1MPUBvqTpLwqa+poLpIYcvvyQbvH9X07t9WLebKahlzqlO+krNQAraF +JnJj2HVQYnUUt7NQGj/KEQALhUVpbbalrlHhStyCP2yMNLJ3a9kC9n8O6mUE8c1U +yrrJzOCE98g+EZfTYAkYvAX/bIkz8OwVDw== +-----END CERTIFICATE----- + +Thawte Personal Premium CA +========================== + +MD5 Fingerprint=3A:B2:DE:22:9A:20:93:49:F9:ED:C8:D2:8A:E7:68:0D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/emailAddress=personal-premium@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Premium CA/emailAddress=personal-premium@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:66:d9:f8:07:44:cf:b9:8c:2e:f0:a1:ef:13: + 45:6c:05:df:de:27:16:51:36:41:11:6c:6c:3b:ed: + fe:10:7d:12:9e:e5:9b:42:9a:fe:60:31:c3:66:b7: + 73:3a:48:ae:4e:d0:32:37:94:88:b5:0d:b6:d9:f3: + f2:44:d9:d5:88:12:dd:76:4d:f2:1a:fc:6f:23:1e: + 7a:f1:d8:98:45:4e:07:10:ef:16:42:d0:43:75:6d: + 4a:de:e2:aa:c9:31:ff:1f:00:70:7c:66:cf:10:25: + 08:ba:fa:ee:00:e9:46:03:66:27:11:15:3b:aa:5b: + f2:98:dd:36:42:b2:da:88:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 69:36:89:f7:34:2a:33:72:2f:6d:3b:d4:22:b2:b8:6f:9a:c5: + 36:66:0e:1b:3c:a1:b1:75:5a:e6:fd:35:d3:f8:a8:f2:07:6f: + 85:67:8e:de:2b:b9:e2:17:b0:3a:a0:f0:0e:a2:00:9a:df:f3: + 14:15:6e:bb:c8:85:5a:98:80:f9:ff:be:74:1d:3d:f3:fe:30: + 25:d1:37:34:67:fa:a5:71:79:30:61:29:72:c0:e0:2c:4c:fb: + 56:e4:3a:a8:6f:e5:32:59:52:db:75:28:50:59:0c:f8:0b:19: + e4:ac:d9:af:96:8d:2f:50:db:07:c3:ea:1f:ab:33:e0:f5:2b: + 31:89 +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p +dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv +bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa +QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY +BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u +IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl +bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu +Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs +Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI +Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD +ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH +b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh +KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ +-----END CERTIFICATE----- + +Entrust.net Global Secure Personal CA +===================================== + +MD5 Fingerprint=9A:77:19:18:ED:96:CF:DF:1B:B7:0E:F5:8D:B9:88:2E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 949941988 (0x389ef6e4) + Signature Algorithm: md5WithRSAEncryption + Issuer: O=Entrust.net, OU=www.entrust.net/GCCA_CPS incorp. by ref. (limits liab.), OU=(c) 2000 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Validity + Not Before: Feb 7 16:16:40 2000 GMT + Not After : Feb 7 16:46:40 2020 GMT + Subject: O=Entrust.net, OU=www.entrust.net/GCCA_CPS incorp. by ref. (limits liab.), OU=(c) 2000 Entrust.net Limited, CN=Entrust.net Client Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:93:74:b4:b6:e4:c5:4b:d6:a1:68:7f:62:d5:ec: + f7:51:57:b3:72:4a:98:f5:d0:89:c9:ad:63:cd:4d: + 35:51:6a:84:d4:ad:c9:68:79:6f:b8:eb:11:db:87: + ae:5c:24:51:13:f1:54:25:84:af:29:2b:9f:e3:80: + e2:d9:cb:dd:c6:45:49:34:88:90:5e:01:97:ef:ea: + 53:a6:dd:fc:c1:de:4b:2a:25:e4:e9:35:fa:55:05: + 06:e5:89:7a:ea:a4:11:57:3b:fc:7c:3d:36:cd:67: + 35:6d:a4:a9:25:59:bd:66:f5:f9:27:e4:95:67:d6: + 3f:92:80:5e:f2:34:7d:2b:85 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/O=Entrust.net/OU=www.entrust.net/GCCA_CPS incorp. by ref. (limits liab.)/OU=(c) 2000 Entrust.net Limited/CN=Entrust.net Client Certification Authority/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Feb 7 16:16:40 2000 GMT, Not After: Feb 7 16:46:40 2020 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:84:8B:74:FD:C5:8D:C0:FF:27:6D:20:37:45:7C:FE:2D:CE:BA:D3:7D + + X509v3 Subject Key Identifier: + 84:8B:74:FD:C5:8D:C0:FF:27:6D:20:37:45:7C:FE:2D:CE:BA:D3:7D + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V5.0:4.0.... + Signature Algorithm: md5WithRSAEncryption + 4e:6f:35:80:3b:d1:8a:f5:0e:a7:20:cb:2d:65:55:d0:92:f4: + e7:84:b5:06:26:83:12:84:0b:ac:3b:b2:44:ee:bd:cf:40:db: + 20:0e:ba:6e:14:ea:30:e0:3b:62:7c:7f:8b:6b:7c:4a:a7:d5: + 35:3c:be:a8:5c:ea:4b:bb:93:8e:80:66:ab:0f:29:fd:4d:2d: + bf:1a:9b:0a:90:c5:ab:da:d1:b3:86:d4:2f:24:52:5c:7a:6d: + c6:f2:fe:e5:4d:1a:30:8c:90:f2:ba:d7:4a:3e:43:7e:d4:c8: + 50:1a:87:f8:4f:81:c7:76:0b:84:3a:72:9d:ce:65:66:97:ae: + 26:5e +-----BEGIN CERTIFICATE----- +MIIEgzCCA+ygAwIBAgIEOJ725DANBgkqhkiG9w0BAQQFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9HQ0NBX0NQUyBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAyMDAw +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVu +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMDAyMDcxNjE2NDBaFw0yMDAy +MDcxNjQ2NDBaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0dDQ0FfQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDIwMDAgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTdLS25MVL1qFof2LV7PdRV7Ny +Spj10InJrWPNTTVRaoTUrcloeW+46xHbh65cJFET8VQlhK8pK5/jgOLZy93GRUk0 +iJBeAZfv6lOm3fzB3ksqJeTpNfpVBQbliXrqpBFXO/x8PTbNZzVtpKklWb1m9fkn +5JVn1j+SgF7yNH0rhQIDAQABo4IBnjCCAZowEQYJYIZIAYb4QgEBBAQDAgAHMIHd +BgNVHR8EgdUwgdIwgc+ggcyggcmkgcYwgcMxFDASBgNVBAoTC0VudHJ1c3QubmV0 +MUAwPgYDVQQLFDd3d3cuZW50cnVzdC5uZXQvR0NDQV9DUFMgaW5jb3JwLiBieSBy +ZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMjAwMCBFbnRydXN0Lm5l +dCBMaW1pdGVkMTMwMQYDVQQDEypFbnRydXN0Lm5ldCBDbGllbnQgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMDAy +MDcxNjE2NDBagQ8yMDIwMDIwNzE2NDY0MFowCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFISLdP3FjcD/J20gN0V8/i3OutN9MB0GA1UdDgQWBBSEi3T9xY3A/ydtIDdF +fP4tzrrTfTAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4w +AwIEkDANBgkqhkiG9w0BAQQFAAOBgQBObzWAO9GK9Q6nIMstZVXQkvTnhLUGJoMS +hAusO7JE7r3PQNsgDrpuFOow4DtifH+La3xKp9U1PL6oXOpLu5OOgGarDyn9TS2/ +GpsKkMWr2tGzhtQvJFJcem3G8v7lTRowjJDyutdKPkN+1MhQGof4T4HHdguEOnKd +zmVml64mXg== +-----END CERTIFICATE----- + +AOL Time Warner Root Certification Authority 1 +============================================== + +MD5 Fingerprint=E7:7A:DC:B1:1F:6E:06:1F:74:6C:59:16:27:C3:4B:C0 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=AOL Time Warner Inc., OU=America Online Inc., CN=AOL Time Warner Root Certification Authority 1 + Validity + Not Before: May 29 06:00:00 2002 GMT + Not After : Nov 20 15:03:00 2037 GMT + Subject: C=US, O=AOL Time Warner Inc., OU=America Online Inc., CN=AOL Time Warner Root Certification Authority 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:99:de:8f:c3:25:a3:69:34:e8:05:f7:74:b9:bf: + 5a:97:19:b9:2f:94:d2:93:e5:2d:89:ca:84:7c:3f: + 10:43:1b:8c:8b:7c:84:58:f8:24:7c:48:cf:2a:fd: + c0:15:d9:18:7e:84:1a:17:d3:db:9e:d7:ca:e4:d9: + d7:aa:58:51:87:f0:f0:8b:48:4e:e2:c2:c4:59:69: + 30:62:b6:30:a2:8c:0b:11:99:61:35:6d:7e:ef:c5: + b1:19:06:20:12:8e:42:e1:df:0f:96:10:52:a8:cf: + 9c:5f:95:14:d8:af:3b:75:0b:31:20:1f:44:2f:a2: + 62:41:b3:bb:18:21:db:ca:71:3c:8c:ec:b6:b9:0d: + 9f:ef:51:ef:4d:7b:12:f2:0b:0c:e1:ac:40:8f:77: + 7f:b0:ca:78:71:0c:5d:16:71:70:a2:d7:c2:3a:85: + cd:0e:9a:c4:e0:00:b0:d5:25:ea:dc:2b:e4:94:2d: + 38:9c:89:41:57:64:28:65:19:1c:b6:44:b4:c8:31: + 6b:8e:01:7b:76:59:25:7f:15:1c:84:08:7c:73:65: + 20:0a:a1:04:2e:1a:32:a8:9a:20:b1:9c:2c:21:59: + e7:fb:cf:ee:70:2d:08:ca:63:3e:2c:9b:93:19:6a: + a4:c2:97:ff:b7:86:57:88:85:6c:9e:15:16:2b:4d: + 2c:b3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + A1:36:30:16:CB:86:90:00:45:80:53:B1:8F:C8:D8:3D:7C:BE:5F:12 + X509v3 Authority Key Identifier: + keyid:A1:36:30:16:CB:86:90:00:45:80:53:B1:8F:C8:D8:3D:7C:BE:5F:12 + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 8a:20:18:a5:be:b3:2f:b4:a6:84:00:40:30:29:fa:b4:14:73: + 4c:79:45:a7:f6:70:e0:e8:7e:64:1e:0a:95:7c:6a:61:c2:ef: + 4e:1f:be:ff:c9:99:1f:07:61:4a:e1:5d:4c:cd:ad:ee:d0:52: + 32:d9:59:32:bc:da:79:72:d6:7b:09:e8:02:81:35:d3:0a:df: + 11:1d:c9:79:a0:80:4d:fe:5a:d7:56:d6:ed:0f:2a:af:a7:18: + 75:33:0c:ea:c1:61:05:4f:6a:9a:89:f2:8d:b9:9f:2e:ef:b0: + 5f:5a:00:eb:be:ad:a0:f8:44:05:67:bc:cb:04:ef:9e:64:c5: + e9:c8:3f:05:bf:c6:2f:07:1c:c3:36:71:86:ca:38:66:4a:cd: + d6:b8:4b:c6:6c:a7:97:3b:fa:13:2d:6e:23:61:87:a1:63:42: + ac:c2:cb:97:9f:61:68:cf:2d:4c:04:9d:d7:25:4f:0a:0e:4d: + 90:8b:18:56:a8:93:48:57:dc:6f:ae:bd:9e:67:57:77:89:50: + b3:be:11:9b:45:67:83:86:19:87:d3:98:bd:08:1a:16:1f:58: + 82:0b:e1:96:69:05:4b:8e:ec:83:51:31:07:d5:d4:9f:ff:59: + 7b:a8:6e:85:cf:d3:4b:a9:49:b0:5f:b0:39:28:68:0e:73:dd: + 25:9a:de:12 +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh +IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAwMFoXDTM3MTEyMDE1 +MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg +SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M +IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U +0pPlLYnKhHw/EEMbjIt8hFj4JHxIzyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItI +TuLCxFlpMGK2MKKMCxGZYTVtfu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAf +RC+iYkGzuxgh28pxPIzstrkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqF +zQ6axOAAsNUl6twr5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqh +BC4aMqiaILGcLCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEA +AaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jY +PXy+XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/ +BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNMeUWn +9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7CegCgTXT +Ct8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77BfWgDrvq2g+EQF +Z7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oTLW4jYYehY0KswsuX +n2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCzvhGbRWeDhhmH05i9CBoW +H1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmwX7A5KGgOc90lmt4S +-----END CERTIFICATE----- + +AOL Time Warner Root Certification Authority 2 +============================================== + +MD5 Fingerprint=01:5A:99:C3:D6:4F:A9:4B:3C:3B:B1:A3:AB:27:4C:BF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=AOL Time Warner Inc., OU=America Online Inc., CN=AOL Time Warner Root Certification Authority 2 + Validity + Not Before: May 29 06:00:00 2002 GMT + Not After : Sep 28 23:43:00 2037 GMT + Subject: C=US, O=AOL Time Warner Inc., OU=America Online Inc., CN=AOL Time Warner Root Certification Authority 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (4096 bit) + Modulus (4096 bit): + 00:b4:37:5a:08:16:99:14:e8:55:b1:1b:24:6b:fc: + c7:8b:e6:87:a9:89:ee:8b:99:cd:4f:40:86:a4:b6: + 4d:c9:d9:b1:dc:3c:4d:0d:85:4c:15:6c:46:8b:52: + 78:9f:f8:23:fd:67:f5:24:3a:68:5d:d0:f7:64:61: + 41:54:a3:8b:a5:08:d2:29:5b:9b:60:4f:26:83:d1: + 63:12:56:49:76:a4:16:c2:a5:9d:45:ac:8b:84:95: + a8:16:b1:ec:9f:ea:24:1a:ef:b9:57:5c:9a:24:21: + 2c:4d:0e:71:1f:a6:ac:5d:45:74:03:98:c4:54:8c: + 16:4a:41:77:86:95:75:0c:47:01:66:60:fc:15:f1: + 0f:ea:f5:14:78:c7:0e:d7:6e:81:1c:5e:bf:5e:e7: + 3a:2a:d8:97:17:30:7c:00:ad:08:9d:33:af:b8:99: + 61:80:8b:a8:95:7e:14:dc:12:6c:a4:d0:d8:ef:40: + 49:02:36:f9:6e:a9:d6:1d:96:56:04:b2:b3:2d:16: + 56:86:8f:d9:20:57:80:cd:67:10:6d:b0:4c:f0:da: + 46:b6:ea:25:2e:46:af:8d:b0:85:38:34:8b:14:26: + 82:2b:ac:ae:99:0b:8e:14:d7:52:bd:9e:69:c3:86: + 02:0b:ea:76:75:31:09:ce:33:19:21:85:43:e6:89: + 2d:9f:25:37:67:f1:23:6a:d2:00:6d:97:f9:9f:e7: + 29:ca:dd:1f:d7:06:ea:b8:c9:b9:09:21:9f:c8:3f: + 06:c5:d2:e9:12:46:00:4e:7b:08:eb:42:3d:2b:48: + 6e:9d:67:dd:4b:02:e4:44:f3:93:19:a5:27:ce:69: + 7a:be:67:d3:fc:50:a4:2c:ab:c3:6b:b9:e3:80:4c: + cf:05:61:4b:2b:dc:1b:b9:a6:d2:d0:aa:f5:2b:73: + fb:ce:90:35:9f:0c:52:1c:bf:5c:21:61:11:5b:15: + 4b:a9:24:51:fc:a4:5c:f7:17:9d:b0:d2:fa:07:e9: + 8f:56:e4:1a:8c:68:8a:04:d3:7c:5a:e3:9e:a2:a1: + ca:71:5b:a2:d4:a0:e7:29:85:5d:03:68:2a:4f:d2: + 06:d7:3d:f9:c3:03:2f:3f:65:f9:67:1e:47:40:d3: + 63:0f:e3:d5:8e:f9:85:ab:97:4c:b3:d7:26:eb:96: + 0a:94:de:85:36:9c:c8:7f:81:09:02:49:2a:0e:f5: + 64:32:0c:82:d1:ba:6a:82:1b:b3:4b:74:11:f3:8c: + 77:d6:9f:bf:dc:37:a4:a7:55:04:2f:d4:31:e8:d3: + 46:b9:03:7c:da:12:4e:59:64:b7:51:31:31:50:a0: + ca:1c:27:d9:10:2e:ad:d6:bd:10:66:2b:c3:b0:22: + 4a:12:5b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 4F:69:6D:03:7E:9D:9F:07:18:43:BC:B7:10:4E:D5:BF:A9:C4:20:28 + X509v3 Authority Key Identifier: + keyid:4F:69:6D:03:7E:9D:9F:07:18:43:BC:B7:10:4E:D5:BF:A9:C4:20:28 + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 3b:f3:ae:ca:e8:2e:87:85:fb:65:59:e7:ad:11:14:a5:57:bc: + 58:9f:24:12:57:bb:fb:3f:34:da:ee:ad:7a:2a:34:72:70:31: + 6b:c7:19:98:80:c9:82:de:37:77:5e:54:8b:8e:f2:ea:67:4f: + c9:74:84:91:56:09:d5:e5:7a:9a:81:b6:81:c2:ad:36:e4:f1: + 54:11:53:f3:34:45:01:26:c8:e5:1a:bc:34:44:21:de:ad:25: + fc:76:16:77:21:90:80:98:57:9d:4e:ea:ec:2f:aa:3c:14:7b: + 57:c1:7e:18:14:67:ee:24:c6:bd:ba:15:b0:d2:18:bd:b7:55: + 81:ac:53:c0:e8:dd:69:12:13:42:b7:02:b5:05:41:ca:79:50: + 6e:82:0e:71:72:93:46:e8:9d:0d:5d:bd:ae:ce:29:ad:63:d5: + 55:16:80:30:27:ff:76:ba:f7:b8:d6:4a:e3:d9:b5:f9:52:d0: + 4e:40:a9:c7:e5:c2:32:c7:aa:76:24:e1:6b:05:50:eb:c5:bf: + 0a:54:e5:b9:42:3c:24:fb:b7:07:9c:30:9f:79:5a:e6:e0:40: + 52:15:f4:fc:aa:f4:56:f9:44:97:87:ed:0e:65:72:5e:be:26: + fb:4d:a4:2d:08:07:de:d8:5c:a0:dc:81:33:99:18:25:11:77: + a7:eb:fd:58:09:2c:99:6b:1b:8a:f3:52:3f:1a:4d:48:60:f1: + a0:f6:33:02:53:8b:ed:25:09:b8:0d:2d:ed:97:73:ec:d7:96: + 1f:8e:60:0e:da:10:9b:2f:18:24:f6:a6:4d:0a:f9:3b:cb:75: + c2:cc:2f:ce:24:69:c9:0a:22:8e:59:a7:f7:82:0c:d7:d7:6b: + 35:9c:43:00:6a:c4:95:67:ba:9c:45:cb:b8:0e:37:f7:dc:4e: + 01:4f:be:0a:b6:03:d3:ad:8a:45:f7:da:27:4d:29:b1:48:df: + e4:11:e4:96:46:bd:6c:02:3e:d6:51:c8:95:17:01:15:a9:f2: + aa:aa:f2:bf:2f:65:1b:6f:d0:b9:1a:93:f5:8e:35:c4:80:87: + 3e:94:2f:66:e4:e9:a8:ff:41:9c:70:2a:4f:2a:39:18:95:1e: + 7e:fb:61:01:3c:51:08:2e:28:18:a4:16:0f:31:fd:3a:6c:23: + 93:20:76:e1:fd:07:85:d1:5b:3f:d2:1c:73:32:dd:fa:b9:f8: + 8c:cf:02:87:7a:9a:96:e4:ed:4f:89:8d:53:43:ab:0e:13:c0: + 01:15:b4:79:38:db:fc:6e:3d:9e:51:b6:b8:13:8b:67:cf:f9: + 7c:d9:22:1d:f6:5d:c5:1c:01:2f:98:e8:7a:24:18:bc:84:d7: + fa:dc:72:5b:f7:c1:3a:68 +-----BEGIN CERTIFICATE----- +MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx +HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh +IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAwMFoXDTM3MDkyODIz +NDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg +SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M +IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ +7ouZzU9AhqS2TcnZsdw8TQ2FTBVsRotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilb +m2BPJoPRYxJWSXakFsKlnUWsi4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOY +xFSMFkpBd4aVdQxHAWZg/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZ +YYCLqJV+FNwSbKTQ2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbq +JS5Gr42whTg0ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fx +I2rSAG2X+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETz +kxmlJ85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh +EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNoKk/S +Btc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJKg71ZDIM +gtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1ExMVCgyhwn2RAu +rda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaAFE9pbQN+nZ8HGEO8txBO +1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAO/Ouyugu +h4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0cnAxa8cZmIDJgt43d15Ui47y6mdP +yXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRFASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q +7C+qPBR7V8F+GBRn7iTGvboVsNIYvbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKT +RuidDV29rs4prWPVVRaAMCf/drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ +ClTluUI8JPu3B5wwn3la5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyB +M5kYJRF3p+v9WAksmWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQ +my8YJPamTQr5O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xO +AU++CrYD062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT +9Y41xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H +hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOLZ8/5 +fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg= +-----END CERTIFICATE----- + +beTRUSTed Root CA-Baltimore Implementation +========================================== + +MD5 Fingerprint=81:35:B9:FB:FB:12:CA:18:69:36:EB:AE:69:78:A1:F1 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1018510662 (0x3cb53d46) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=beTRUSTed, OU=beTRUSTed Root CAs, CN=beTRUSTed Root CA-Baltimore Implementation + Validity + Not Before: Apr 11 07:38:51 2002 GMT + Not After : Apr 11 07:38:51 2022 GMT + Subject: O=beTRUSTed, OU=beTRUSTed Root CAs, CN=beTRUSTed Root CA-Baltimore Implementation + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bc:7e:c4:39:9c:8c:e3:d6:1c:86:ff:ca:62:ad: + e0:7f:30:45:7a:8e:1a:b3:b8:c7:f9:d1:36:ff:22: + f3:4e:6a:5f:84:10:fb:66:81:c3:94:79:31:d2:91: + e1:77:8e:18:2a:c3:14:de:51:f5:4f:a3:2b:bc:18: + 16:e2:b5:dd:79:de:22:f8:82:7e:cb:81:1f:fd:27: + 2c:8f:fa:97:64:22:8e:f8:ff:61:a3:9c:1b:1e:92: + 8f:c0:a8:09:df:09:11:ec:b7:7d:31:9a:1a:ea:83: + 21:06:3c:9f:ba:5c:ff:94:ea:6a:b8:c3:6b:55:34: + 4f:3d:32:1f:dd:81:14:e0:c4:3c:cd:9d:30:f8:30: + a9:97:d3:ee:cc:a3:d0:1f:5f:1c:13:81:d4:18:ab: + 94:d1:63:c3:9e:7f:35:92:9e:5f:44:ea:ec:f4:22: + 5c:b7:e8:3d:7d:a4:f9:89:a9:91:b2:2a:d9:eb:33: + 87:ee:a5:fd:e3:da:cc:88:e6:89:26:6e:c7:2b:82: + d0:5e:9d:59:db:14:ec:91:83:05:c3:5e:0e:c6:2a: + d0:04:dd:71:3d:20:4e:58:27:fc:53:fb:78:78:19: + 14:b2:fc:90:52:89:38:62:60:07:b4:a0:ec:ac:6b: + 50:d6:fd:b9:28:6b:ef:52:2d:3a:b2:ff:f1:01:40: + ac:37 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.6334.0.0.1.9.40.51377 + User Notice: + Explicit Text: Reliance on or use of this Certificate creates an acknowledgment and acceptance of the then applicable standard terms and conditions of use, the Certification Practice Statement and the Relying Party Agreement, which can be found at the beTRUSTed web site, http://www.betrusted.com/products_services/index.html + CPS: http://www.betrusted.com/products_services/index.html + + X509v3 Subject Key Identifier: + 45:3D:C3:A9:D1:DC:3F:24:56:98:1C:73:18:88:6A:FF:83:47:ED:B6 + X509v3 Authority Key Identifier: + keyid:45:3D:C3:A9:D1:DC:3F:24:56:98:1C:73:18:88:6A:FF:83:47:ED:B6 + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 49:92:bc:a3:ee:ac:bd:fa:0d:c9:8b:79:86:1c:23:76:b0:80: + 59:77:fc:da:7f:b4:4b:df:c3:64:4b:6a:4e:0e:ad:f2:7d:59: + 77:05:ad:0a:89:73:b0:fa:bc:cb:dc:8d:00:88:8f:a6:a0:b2: + ea:ac:52:27:bf:a1:48:7c:97:10:7b:ba:ed:13:1d:9a:07:6e: + cb:31:62:12:e8:63:03:aa:7d:6d:e3:f8:1b:76:21:78:1b:9f: + 4b:43:8c:d3:49:86:f6:1b:5c:f6:2e:60:15:d3:e9:e3:7b:75: + 3f:d0:02:83:d0:18:82:41:cd:65:37:ea:8e:32:7e:bd:6b:99: + 5d:30:11:c8:db:48:54:1c:3b:e1:a7:13:d3:6a:48:93:f7:3d: + 8c:7f:05:e8:ce:f3:88:2a:63:04:b8:ea:7e:58:7c:01:7b:5b: + e1:c5:7d:ef:21:e0:8d:0e:5d:51:7d:b1:67:fd:a3:bd:38:36: + c6:f2:38:86:87:1a:96:68:60:46:fb:28:14:47:55:e1:a7:80: + 0c:6b:e2:ea:df:4d:7c:90:48:a0:36:bd:09:17:89:7f:c3:f2: + d3:9c:9c:e3:dd:c4:1b:dd:f5:b7:71:b3:53:05:89:06:d0:cb: + 4a:80:c1:c8:53:90:b5:3c:31:88:17:50:9f:c9:c4:0e:8b:d8: + a8:02:63:0d +-----BEGIN CERTIFICATE----- +MIIFajCCBFKgAwIBAgIEPLU9RjANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq +YmVUUlVTVGVkIFJvb3QgQ0EtQmFsdGltb3JlIEltcGxlbWVudGF0aW9uMB4XDTAy +MDQxMTA3Mzg1MVoXDTIyMDQxMTA3Mzg1MVowZjESMBAGA1UEChMJYmVUUlVTVGVk +MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl +ZCBSb290IENBLUJhbHRpbW9yZSBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALx+xDmcjOPWHIb/ymKt4H8wRXqOGrO4x/nRNv8i +805qX4QQ+2aBw5R5MdKR4XeOGCrDFN5R9U+jK7wYFuK13XneIviCfsuBH/0nLI/6 +l2Qijvj/YaOcGx6Sj8CoCd8JEey3fTGaGuqDIQY8n7pc/5TqarjDa1U0Tz0yH92B +FODEPM2dMPgwqZfT7syj0B9fHBOB1BirlNFjw55/NZKeX0Tq7PQiXLfoPX2k+Ymp +kbIq2eszh+6l/ePazIjmiSZuxyuC0F6dWdsU7JGDBcNeDsYq0ATdcT0gTlgn/FP7 +eHgZFLL8kFKJOGJgB7Sg7KxrUNb9uShr71ItOrL/8QFArDcCAwEAAaOCAh4wggIa +MA8GA1UdEwEB/wQFMAMBAf8wggG1BgNVHSAEggGsMIIBqDCCAaQGDysGAQQBsT4A +AAEJKIORMTCCAY8wggFIBggrBgEFBQcCAjCCAToaggE2UmVsaWFuY2Ugb24gb3Ig +dXNlIG9mIHRoaXMgQ2VydGlmaWNhdGUgY3JlYXRlcyBhbiBhY2tub3dsZWRnbWVu +dCBhbmQgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJk +IHRlcm1zIGFuZCBjb25kaXRpb25zIG9mIHVzZSwgdGhlIENlcnRpZmljYXRpb24g +UHJhY3RpY2UgU3RhdGVtZW50IGFuZCB0aGUgUmVseWluZyBQYXJ0eSBBZ3JlZW1l +bnQsIHdoaWNoIGNhbiBiZSBmb3VuZCBhdCB0aGUgYmVUUlVTVGVkIHdlYiBzaXRl +LCBodHRwOi8vd3d3LmJldHJ1c3RlZC5jb20vcHJvZHVjdHNfc2VydmljZXMvaW5k +ZXguaHRtbDBBBggrBgEFBQcCARY1aHR0cDovL3d3dy5iZXRydXN0ZWQuY29tL3By +b2R1Y3RzX3NlcnZpY2VzL2luZGV4Lmh0bWwwHQYDVR0OBBYEFEU9w6nR3D8kVpgc +cxiIav+DR+22MB8GA1UdIwQYMBaAFEU9w6nR3D8kVpgccxiIav+DR+22MA4GA1Ud +DwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEASZK8o+6svfoNyYt5hhwjdrCA +WXf82n+0S9/DZEtqTg6t8n1ZdwWtColzsPq8y9yNAIiPpqCy6qxSJ7+hSHyXEHu6 +7RMdmgduyzFiEuhjA6p9beP4G3YheBufS0OM00mG9htc9i5gFdPp43t1P9ACg9AY +gkHNZTfqjjJ+vWuZXTARyNtIVBw74acT02pIk/c9jH8F6M7ziCpjBLjqflh8AXtb +4cV97yHgjQ5dUX2xZ/2jvTg2xvI4hocalmhgRvsoFEdV4aeADGvi6t9NfJBIoDa9 +CReJf8Py05yc493EG931t3GzUwWJBtDLSoDByFOQtTwxiBdQn8nEDovYqAJjDQ== +-----END CERTIFICATE----- + +beTRUSTed Root CA - Entrust Implementation +========================================== + +MD5 Fingerprint=7D:86:90:8F:5B:F1:F2:40:C0:F7:3D:62:B5:A4:A9:3B +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1018515264 (0x3cb54f40) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=beTRUSTed, OU=beTRUSTed Root CAs, CN=beTRUSTed Root CA - Entrust Implementation + Validity + Not Before: Apr 11 08:24:27 2002 GMT + Not After : Apr 11 08:54:27 2022 GMT + Subject: O=beTRUSTed, OU=beTRUSTed Root CAs, CN=beTRUSTed Root CA - Entrust Implementation + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ba:f4:44:03:aa:12:6a:b5:43:ec:55:92:b6:30: + 7d:35:57:0c:db:f3:0d:27:6e:4c:f7:50:a8:9b:4e: + 2b:6f:db:f5:ad:1c:4b:5d:b3:a9:c1:fe:7b:44:eb: + 5b:a3:05:0d:1f:c5:34:2b:30:00:29:f1:78:40:b2: + a4:ff:3a:f4:01:88:17:7e:e6:d4:26:d3:ba:4c:ea: + 32:fb:43:77:97:87:23:c5:db:43:a3:f5:2a:a3:51: + 5e:e1:3b:d2:65:69:7e:55:15:9b:7a:e7:69:f7:44: + e0:57:b5:15:e8:66:60:0f:0d:03:fb:82:8e:a3:e8: + 11:7b:6c:be:c7:63:0e:17:93:df:cf:4b:ae:6e:73: + 75:e0:f3:aa:b9:a4:c0:09:1b:85:ea:71:29:88:41: + 32:f9:f0:2a:0e:6c:09:f2:74:6b:66:6c:52:13:1f: + 18:bc:d4:3e:f7:d8:6e:20:9e:ca:fe:fc:21:94:ee: + 13:28:4b:d7:5c:5e:0c:66:ee:e9:bb:0f:c1:34:b1: + 7f:08:76:f3:3d:26:70:c9:8b:25:1d:62:24:0c:ea: + 1c:75:4e:c0:12:e4:ba:13:1d:30:29:2d:56:33:05: + bb:97:59:7e:c6:49:4f:89:d7:2f:24:a8:b6:88:40: + b5:64:92:53:56:24:e4:a2:a0:85:b3:5e:90:b4:12: + 33:cd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.6334.0.0.2.9.40.51377 + User Notice: + Explicit Text: Reliance on or use of this Certificate creates an acknowledgment and acceptance of the then applicable standard terms and conditions of use, the Certification Practice Statement and the Relying Party Agreement, which can be found at the beTRUSTed web site, https://www.betrusted.com/products_services/index.html + CPS: https://www.betrusted.com/products_services/index.html + + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/O=beTRUSTed/OU=beTRUSTed Root CAs/CN=beTRUSTed Root CA - Entrust Implementation/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Apr 11 08:24:27 2002 GMT, Not After: Apr 11 08:54:27 2022 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:7D:70:E5:AE:38:8B:06:3F:AA:1C:1A:8F:F9:CF:24:30:AA:84:84:16 + + X509v3 Subject Key Identifier: + 7D:70:E5:AE:38:8B:06:3F:AA:1C:1A:8F:F9:CF:24:30:AA:84:84:16 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V6.0:4.0.... + Signature Algorithm: sha1WithRSAEncryption + 2a:b8:17:ce:1f:10:94:eb:b8:9a:b7:b9:5f:ec:da:f7:92:24: + ac:dc:92:3b:c7:20:8d:f2:99:e5:5d:38:a1:c2:34:ed:c5:13: + 59:5c:05:b5:2b:4f:61:9b:91:fb:41:fc:fc:d5:3c:4d:98:76: + 06:f5:81:7d:eb:dd:90:e6:d1:56:54:da:e3:2d:0c:9f:11:32: + 94:22:01:7a:f6:6c:2c:74:67:04:cc:a5:8f:8e:2c:b3:43:b5: + 94:a2:d0:7d:e9:62:7f:06:be:27:01:83:9e:3a:fd:8a:ee:98: + 43:4a:6b:d7:b5:97:3b:3a:bf:4f:6d:b4:63:fa:33:00:34:2e: + 2d:6d:96:c9:7b:ca:99:63:ba:be:f4:f6:30:a0:2d:98:96:e9: + 56:44:05:a9:44:a3:61:10:eb:82:a1:67:5d:bc:5d:27:75:aa: + 8a:28:36:2a:38:92:d9:dd:a4:5e:00:a5:cc:cc:7c:29:2a:de: + 28:90:ab:b7:e1:b6:ff:7d:25:0b:40:d8:aa:34:a3:2d:de:07: + eb:5f:ce:0a:dd:ca:7e:3a:7d:26:c1:62:68:3a:e6:2f:37:f3: + 81:86:21:c4:a9:64:aa:ef:45:36:d1:1a:66:7c:f8:e9:37:d6: + d6:61:be:a2:ad:48:e7:df:e6:74:fe:d3:6d:7d:d2:25:dc:ac: + 62:57:a9:f7 +-----BEGIN CERTIFICATE----- +MIIGUTCCBTmgAwIBAgIEPLVPQDANBgkqhkiG9w0BAQUFADBmMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEzMDEGA1UEAxMq +YmVUUlVTVGVkIFJvb3QgQ0EgLSBFbnRydXN0IEltcGxlbWVudGF0aW9uMB4XDTAy +MDQxMTA4MjQyN1oXDTIyMDQxMTA4NTQyN1owZjESMBAGA1UEChMJYmVUUlVTVGVk +MRswGQYDVQQLExJiZVRSVVNUZWQgUm9vdCBDQXMxMzAxBgNVBAMTKmJlVFJVU1Rl +ZCBSb290IENBIC0gRW50cnVzdCBJbXBsZW1lbnRhdGlvbjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALr0RAOqEmq1Q+xVkrYwfTVXDNvzDSduTPdQqJtO +K2/b9a0cS12zqcH+e0TrW6MFDR/FNCswACnxeECypP869AGIF37m1CbTukzqMvtD +d5eHI8XbQ6P1KqNRXuE70mVpflUVm3rnafdE4Fe1FehmYA8NA/uCjqPoEXtsvsdj +DheT389Lrm5zdeDzqrmkwAkbhepxKYhBMvnwKg5sCfJ0a2ZsUhMfGLzUPvfYbiCe +yv78IZTuEyhL11xeDGbu6bsPwTSxfwh28z0mcMmLJR1iJAzqHHVOwBLkuhMdMCkt +VjMFu5dZfsZJT4nXLySotohAtWSSU1Yk5KKghbNekLQSM80CAwEAAaOCAwUwggMB +MIIBtwYDVR0gBIIBrjCCAaowggGmBg8rBgEEAbE+AAACCSiDkTEwggGRMIIBSQYI +KwYBBQUHAgIwggE7GoIBN1JlbGlhbmNlIG9uIG9yIHVzZSBvZiB0aGlzIENlcnRp +ZmljYXRlIGNyZWF0ZXMgYW4gYWNrbm93bGVkZ21lbnQgYW5kIGFjY2VwdGFuY2Ug +b2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0 +aW9ucyBvZiB1c2UsIHRoZSBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dCBhbmQgdGhlIFJlbHlpbmcgUGFydHkgQWdyZWVtZW50LCB3aGljaCBjYW4gYmUg +Zm91bmQgYXQgdGhlIGJlVFJVU1RlZCB3ZWIgc2l0ZSwgaHR0cHM6Ly93d3cuYmV0 +cnVzdGVkLmNvbS9wcm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMEIGCCsGAQUF +BwIBFjZodHRwczovL3d3dy5iZXRydXN0ZWQuY29tL3Byb2R1Y3RzX3NlcnZpY2Vz +L2luZGV4Lmh0bWwwEQYJYIZIAYb4QgEBBAQDAgAHMIGJBgNVHR8EgYEwfzB9oHug +eaR3MHUxEjAQBgNVBAoTCWJlVFJVU1RlZDEbMBkGA1UECxMSYmVUUlVTVGVkIFJv +b3QgQ0FzMTMwMQYDVQQDEypiZVRSVVNUZWQgUm9vdCBDQSAtIEVudHJ1c3QgSW1w +bGVtZW50YXRpb24xDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMjAwMjA0MTEw +ODI0MjdagQ8yMDIyMDQxMTA4NTQyN1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaA +FH1w5a44iwY/qhwaj/nPJDCqhIQWMB0GA1UdDgQWBBR9cOWuOIsGP6ocGo/5zyQw +qoSEFjAMBgNVHRMEBTADAQH/MB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIE +kDANBgkqhkiG9w0BAQUFAAOCAQEAKrgXzh8QlOu4mre5X+za95IkrNySO8cgjfKZ +5V04ocI07cUTWVwFtStPYZuR+0H8/NU8TZh2BvWBfevdkObRVlTa4y0MnxEylCIB +evZsLHRnBMylj44ss0O1lKLQfelifwa+JwGDnjr9iu6YQ0pr17WXOzq/T220Y/oz +ADQuLW2WyXvKmWO6vvT2MKAtmJbpVkQFqUSjYRDrgqFnXbxdJ3Wqiig2KjiS2d2k +XgClzMx8KSreKJCrt+G2/30lC0DYqjSjLd4H61/OCt3Kfjp9JsFiaDrmLzfzgYYh +xKlkqu9FNtEaZnz46TfW1mG+oq1I59/mdP7TbX3SJdysYlep9w== +-----END CERTIFICATE----- + +beTRUSTed Root CA - RSA Implementation +====================================== + +MD5 Fingerprint=86:42:05:09:BC:A7:9D:EC:1D:F3:2E:0E:BA:D8:1D:D0 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 3b:59:c7:7b:cd:5b:57:9e:bd:37:52:ac:76:b4:aa:1a + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=beTRUSTed, OU=beTRUSTed Root CAs, CN=beTRUSTed Root CA - RSA Implementation + Validity + Not Before: Apr 11 11:18:13 2002 GMT + Not After : Apr 12 11:07:25 2022 GMT + Subject: O=beTRUSTed, OU=beTRUSTed Root CAs, CN=beTRUSTed Root CA - RSA Implementation + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:e4:ba:34:30:09:8e:57:d0:b9:06:2c:6f:6e:24: + 80:22:bf:5d:43:a6:fa:4f:ac:82:e7:1c:68:70:85: + 1b:a3:6e:b5:aa:78:d9:6e:07:4b:3f:e9:df:f5:ea: + e8:54:a1:61:8a:0e:2f:69:75:18:b7:0c:e5:14:8d: + 71:6e:98:b8:55:fc:0c:95:d0:9b:6e:e1:2d:88:d4: + 3a:40:6b:92:f1:99:96:64:de:db:ff:78:f4:ee:96: + 1d:47:89:7c:d4:be:b9:88:77:23:3a:09:e6:04:9e: + 6d:aa:5e:d2:c8:bd:9a:4e:19:df:89:ea:5b:0e:7e: + c3:e4:b4:f0:e0:69:3b:88:0f:41:90:f8:d4:71:43: + 24:c1:8f:26:4b:3b:56:e9:ff:8c:6c:37:e9:45:ad: + 85:8c:53:c3:60:86:90:4a:96:c9:b3:54:b0:bb:17: + f0:1c:45:d9:d4:1b:19:64:56:0a:19:f7:cc:e1:ff: + 86:af:7e:58:5e:ac:7a:90:1f:c9:28:39:45:7b:a2: + b6:c7:9c:1f:da:85:d4:21:86:59:30:93:be:53:33: + 37:f6:ef:41:cf:33:c7:ab:72:6b:25:f5:f3:53:1b: + 0c:4c:2e:f1:75:4b:ef:a0:87:f7:fe:8a:15:d0:6c: + d5:cb:f9:68:53:b9:70:15:13:c2:f5:2e:fb:43:35: + 75:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.6334.0.0.3.9.40.51377 + CPS: http://www.betrusted.com/products_services/index.html + User Notice: + Explicit Text: Reliance on or use of this Certificate creates an acknowledgment and acceptance of the then applicable standard terms and conditions of use, the Certification Practice Statement and the Relying Party Agreement, which can be found at the beTRUSTed web site, http://www.betrusted.com/products_services/index.html + + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:A9:EC:14:7E:F9:D9:43:CC:53:2B:14:AD:CF:F7:F0:59:89:41:CD:19 + + X509v3 Subject Key Identifier: + A9:EC:14:7E:F9:D9:43:CC:53:2B:14:AD:CF:F7:F0:59:89:41:CD:19 + Signature Algorithm: sha1WithRSAEncryption + db:97:b0:75:ea:0c:c4:c1:98:ca:56:05:c0:a8:ad:26:48:af: + 2d:20:e8:81:c7:b6:df:43:c1:2c:1d:75:4b:d4:42:8d:e7:7a: + a8:74:dc:66:42:59:87:b3:f5:69:6d:d9:a9:9e:b3:7d:1c:31: + c1:f5:54:e2:59:24:49:e5:ee:bd:39:a6:6b:8a:98:44:fb:9b: + d7:2a:83:97:34:2d:c7:7d:35:4c:2d:34:b8:3e:0d:c4:ec:88: + 27:af:9e:92:fd:50:61:82:a8:60:07:14:53:cc:65:13:c1:f6: + 47:44:69:d2:31:c8:a6:dd:2e:b3:0b:de:4a:8d:5b:3d:ab:0d: + c2:35:52:a2:56:37:cc:32:8b:28:85:42:9c:91:40:7a:70:2b: + 38:36:d5:e1:73:1a:1f:e5:fa:7e:5f:dc:d6:9c:3b:30:ea:db: + c0:5b:27:5c:d3:73:07:c1:c2:f3:4c:9b:6f:9f:1b:ca:1e:aa: + a8:38:33:09:58:b2:ae:fc:07:e8:36:dc:55:ba:2f:4f:40:fe: + 7a:bd:06:a6:81:c1:93:22:7c:86:11:0a:06:77:48:ae:35:b7: + 2f:32:9a:61:5e:8b:be:29:9f:29:24:88:56:39:2c:a8:d2:ab: + 96:03:5a:d4:48:9f:b9:40:84:0b:98:68:fb:01:43:d6:1b:e2: + 09:b1:97:1c +-----BEGIN CERTIFICATE----- +MIIFaDCCBFCgAwIBAgIQO1nHe81bV569N1KsdrSqGjANBgkqhkiG9w0BAQUFADBi +MRIwEAYDVQQKEwliZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENB +czEvMC0GA1UEAxMmYmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRp +b24wHhcNMDIwNDExMTExODEzWhcNMjIwNDEyMTEwNzI1WjBiMRIwEAYDVQQKEwli +ZVRSVVNUZWQxGzAZBgNVBAsTEmJlVFJVU1RlZCBSb290IENBczEvMC0GA1UEAxMm +YmVUUlVTVGVkIFJvb3QgQ0EgLSBSU0EgSW1wbGVtZW50YXRpb24wggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkujQwCY5X0LkGLG9uJIAiv11DpvpPrILn +HGhwhRujbrWqeNluB0s/6d/16uhUoWGKDi9pdRi3DOUUjXFumLhV/AyV0Jtu4S2I +1DpAa5LxmZZk3tv/ePTulh1HiXzUvrmIdyM6CeYEnm2qXtLIvZpOGd+J6lsOfsPk +tPDgaTuID0GQ+NRxQyTBjyZLO1bp/4xsN+lFrYWMU8NghpBKlsmzVLC7F/AcRdnU +GxlkVgoZ98zh/4avflherHqQH8koOUV7orbHnB/ahdQhhlkwk75TMzf270HPM8er +cmsl9fNTGwxMLvF1S++gh/f+ihXQbNXL+WhTuXAVE8L1LvtDNXUtAgMBAAGjggIY +MIICFDAMBgNVHRMEBTADAQH/MIIBtQYDVR0gBIIBrDCCAagwggGkBg8rBgEEAbE+ +AAADCSiDkTEwggGPMEEGCCsGAQUFBwIBFjVodHRwOi8vd3d3LmJldHJ1c3RlZC5j +b20vcHJvZHVjdHNfc2VydmljZXMvaW5kZXguaHRtbDCCAUgGCCsGAQUFBwICMIIB +OhqCATZSZWxpYW5jZSBvbiBvciB1c2Ugb2YgdGhpcyBDZXJ0aWZpY2F0ZSBjcmVh +dGVzIGFuIGFja25vd2xlZGdtZW50IGFuZCBhY2NlcHRhbmNlIG9mIHRoZSB0aGVu +IGFwcGxpY2FibGUgc3RhbmRhcmQgdGVybXMgYW5kIGNvbmRpdGlvbnMgb2YgdXNl +LCB0aGUgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQgYW5kIHRoZSBS +ZWx5aW5nIFBhcnR5IEFncmVlbWVudCwgd2hpY2ggY2FuIGJlIGZvdW5kIGF0IHRo +ZSBiZVRSVVNUZWQgd2ViIHNpdGUsIGh0dHA6Ly93d3cuYmV0cnVzdGVkLmNvbS9w +cm9kdWN0c19zZXJ2aWNlcy9pbmRleC5odG1sMAsGA1UdDwQEAwIBBjAfBgNVHSME +GDAWgBSp7BR++dlDzFMrFK3P9/BZiUHNGTAdBgNVHQ4EFgQUqewUfvnZQ8xTKxSt +z/fwWYlBzRkwDQYJKoZIhvcNAQEFBQADggEBANuXsHXqDMTBmMpWBcCorSZIry0g +6IHHtt9DwSwddUvUQo3neqh03GZCWYez9Wlt2ames30cMcH1VOJZJEnl7r05pmuK +mET7m9cqg5c0Lcd9NUwtNLg+DcTsiCevnpL9UGGCqGAHFFPMZRPB9kdEadIxyKbd +LrML3kqNWz2rDcI1UqJWN8wyiyiFQpyRQHpwKzg21eFzGh/l+n5f3NacOzDq28Bb +J1zTcwfBwvNMm2+fG8oeqqg4MwlYsq78B+g23FW6L09A/nq9BqaBwZMifIYRCgZ3 +SK41ty8ymmFei74pnykkiFY5LKjSq5YDWtRIn7lAhAuYaPsBQ9Yb4gmxlxw= +-----END CERTIFICATE----- + +RSA Security 2048 v3 +==================== + +MD5 Fingerprint=77:0D:19:B1:21:FD:00:42:9C:3E:0C:A5:DD:0B:02:8E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0a:01:01:01:00:00:02:7c:00:00:00:0a:00:00:00:02 + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=RSA Security Inc, OU=RSA Security 2048 V3 + Validity + Not Before: Feb 22 20:39:23 2001 GMT + Not After : Feb 22 20:39:23 2026 GMT + Subject: O=RSA Security Inc, OU=RSA Security 2048 V3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b7:8f:55:71:d2:80:dd:7b:69:79:a7:f0:18:50: + 32:3c:62:67:f6:0a:95:07:dd:e6:1b:f3:9e:d9:d2: + 41:54:6b:ad:9f:7c:be:19:cd:fb:46:ab:41:68:1e: + 18:ea:55:c8:2f:91:78:89:28:fb:27:29:60:ff:df: + 8f:8c:3b:c9:49:9b:b5:a4:94:ce:01:ea:3e:b5:63: + 7b:7f:26:fd:19:dd:c0:21:bd:84:d1:2d:4f:46:c3: + 4e:dc:d8:37:39:3b:28:af:cb:9d:1a:ea:2b:af:21: + a5:c1:23:22:b8:b8:1b:5a:13:87:57:83:d1:f0:20: + e7:e8:4f:23:42:b0:00:a5:7d:89:e9:e9:61:73:94: + 98:71:26:bc:2d:6a:e0:f7:4d:f0:f1:b6:2a:38:31: + 81:0d:29:e1:00:c1:51:0f:4c:52:f8:04:5a:aa:7d: + 72:d3:b8:87:2a:bb:63:10:03:2a:b3:a1:4f:0d:5a: + 5e:46:b7:3d:0e:f5:74:ec:99:9f:f9:3d:24:81:88: + a6:dd:60:54:e8:95:36:3d:c6:09:93:9a:a3:12:80: + 00:55:99:19:47:bd:d0:a5:7c:c3:ba:fb:1f:f7:f5: + 0f:f8:ac:b9:b5:f4:37:98:13:18:de:85:5b:b7:0c: + 82:3b:87:6f:95:39:58:30:da:6e:01:68:17:22:cc: + c0:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:07:C3:51:30:A4:AA:E9:45:AE:35:24:FA:FF:24:2C:33:D0:B1:9D:8C + + X509v3 Subject Key Identifier: + 07:C3:51:30:A4:AA:E9:45:AE:35:24:FA:FF:24:2C:33:D0:B1:9D:8C + Signature Algorithm: sha1WithRSAEncryption + 5f:3e:86:76:6e:b8:35:3c:4e:36:1c:1e:79:98:bf:fd:d5:12: + 11:79:52:0e:ee:31:89:bc:dd:7f:f9:d1:c6:15:21:e8:8a:01: + 54:0d:3a:fb:54:b9:d6:63:d4:b1:aa:96:4d:a2:42:4d:d4:53: + 1f:8b:10:de:7f:65:be:60:13:27:71:88:a4:73:e3:84:63:d1: + a4:55:e1:50:93:e6:1b:0e:79:d0:67:bc:46:c8:bf:3f:17:0d: + 95:e6:c6:90:69:de:e7:b4:2f:de:95:7d:d0:12:3f:3d:3e:7f: + 4d:3f:14:68:f5:11:50:d5:c1:f4:90:a5:08:1d:31:60:ff:60: + 8c:23:54:0a:af:fe:a1:6e:c5:d1:7a:2a:68:78:cf:1e:82:0a: + 20:b4:1f:ad:e5:85:b2:6a:68:75:4e:ad:25:37:94:85:be:bd: + a1:d4:ea:b7:0c:4b:3c:9d:e8:12:00:f0:5f:ac:0d:e1:ac:70: + 63:73:f7:7f:79:9f:32:25:42:74:05:80:28:bf:bd:c1:24:96: + 58:15:b1:17:21:e9:89:4b:db:07:88:67:f4:15:ad:70:3e:2f: + 4d:85:3b:c2:b7:db:fe:98:68:23:89:e1:74:0f:de:f4:c5:84: + 63:29:1b:cc:cb:07:c9:00:a4:a9:d7:c2:22:4f:67:d7:77:ec: + 20:05:61:de +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy +MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp +eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg +/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl +wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh +AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 +PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu +AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR +MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc +HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ +Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ +f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO +rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch +6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 +7CAFYd4= +-----END CERTIFICATE----- + +RSA Security 1024 v3 +==================== + +MD5 Fingerprint=3A:E5:50:B0:39:BE:C7:46:36:33:A1:FE:82:3E:8D:94 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 0a:01:01:01:00:00:02:7c:00:00:00:0b:00:00:00:02 + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=RSA Security Inc, OU=RSA Security 1024 V3 + Validity + Not Before: Feb 22 21:01:49 2001 GMT + Not After : Feb 22 20:01:49 2026 GMT + Subject: O=RSA Security Inc, OU=RSA Security 1024 V3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d5:dd:fe:66:09:cf:24:3c:3e:ae:81:4e:4e:8a: + c4:69:80:5b:59:3b:df:b9:4d:4c:ca:b5:2d:c3:27: + 2d:3c:af:00:42:6d:bc:28:a6:96:cf:7f:d7:58:ac: + 83:0a:a3:55:b5:7b:17:90:15:84:4c:8a:ee:26:99: + dc:58:ef:c7:38:a6:aa:af:d0:8e:42:c8:62:d7:ab: + ac:a9:fb:4a:7d:bf:ea:fe:12:4d:dd:ff:26:2d:6f: + 36:54:68:c8:d2:84:56:ee:92:53:61:09:b3:3f:39: + 9b:a8:c9:9b:bd:ce:9f:7e:d4:19:6a:16:29:18:be: + d7:3a:69:dc:25:5b:33:1a:51 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:C4:C0:1C:A4:07:94:FD:CD:4D:01:D4:54:DA:A5:0C:5F:DE:AE:05:5A + + X509v3 Subject Key Identifier: + C4:C0:1C:A4:07:94:FD:CD:4D:01:D4:54:DA:A5:0C:5F:DE:AE:05:5A + Signature Algorithm: sha1WithRSAEncryption + 3f:2d:6a:e3:26:43:95:7d:89:97:65:fb:75:e4:72:1d:46:57: + c4:61:6b:69:9f:12:9b:2c:d5:5a:e8:c0:a2:f0:43:95:e3:1f: + e9:76:cd:dc:eb:bc:93:a0:65:0a:c7:4d:4f:5f:a7:af:a2:46: + 14:b9:0c:f3:cc:bd:6a:6e:b7:9d:de:25:42:d0:54:ff:9e:68: + 73:63:dc:24:eb:22:bf:a8:72:f2:5e:00:e1:0d:4e:3a:43:6e: + 99:4e:3f:89:78:03:98:ca:f3:55:cc:9d:ae:8e:c1:aa:45:98: + fa:8f:1a:a0:8d:88:23:f1:15:41:0d:a5:46:3e:91:3f:8b:eb: + f7:71 +-----BEGIN CERTIFICATE----- +MIICXDCCAcWgAwIBAgIQCgEBAQAAAnwAAAALAAAAAjANBgkqhkiG9w0BAQUFADA6 +MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp +dHkgMTAyNCBWMzAeFw0wMTAyMjIyMTAxNDlaFw0yNjAyMjIyMDAxNDlaMDoxGTAX +BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAx +MDI0IFYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDV3f5mCc8kPD6ugU5O +isRpgFtZO9+5TUzKtS3DJy08rwBCbbwoppbPf9dYrIMKo1W1exeQFYRMiu4mmdxY +78c4pqqv0I5CyGLXq6yp+0p9v+r+Ek3d/yYtbzZUaMjShFbuklNhCbM/OZuoyZu9 +zp9+1BlqFikYvtc6adwlWzMaUQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBTEwBykB5T9zU0B1FTapQxf3q4FWjAd +BgNVHQ4EFgQUxMAcpAeU/c1NAdRU2qUMX96uBVowDQYJKoZIhvcNAQEFBQADgYEA +Py1q4yZDlX2Jl2X7deRyHUZXxGFraZ8SmyzVWujAovBDleMf6XbN3Ou8k6BlCsdN +T1+nr6JGFLkM88y9am63nd4lQtBU/55oc2PcJOsiv6hy8l4A4Q1OOkNumU4/iXgD +mMrzVcydro7BqkWY+o8aoI2II/EVQQ2lRj6RP4vr93E= +-----END CERTIFICATE----- + +GeoTrust Global CA +================== + +MD5 Fingerprint=F7:75:AB:29:FB:51:4E:B7:77:5E:FF:05:3C:99:8E:F5 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 144470 (0x23456) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA + Validity + Not Before: May 21 04:00:00 2002 GMT + Not After : May 21 04:00:00 2022 GMT + Subject: C=US, O=GeoTrust Inc., CN=GeoTrust Global CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:da:cc:18:63:30:fd:f4:17:23:1a:56:7e:5b:df: + 3c:6c:38:e4:71:b7:78:91:d4:bc:a1:d8:4c:f8:a8: + 43:b6:03:e9:4d:21:07:08:88:da:58:2f:66:39:29: + bd:05:78:8b:9d:38:e8:05:b7:6a:7e:71:a4:e6:c4: + 60:a6:b0:ef:80:e4:89:28:0f:9e:25:d6:ed:83:f3: + ad:a6:91:c7:98:c9:42:18:35:14:9d:ad:98:46:92: + 2e:4f:ca:f1:87:43:c1:16:95:57:2d:50:ef:89:2d: + 80:7a:57:ad:f2:ee:5f:6b:d2:00:8d:b9:14:f8:14: + 15:35:d9:c0:46:a3:7b:72:c8:91:bf:c9:55:2b:cd: + d0:97:3e:9c:26:64:cc:df:ce:83:19:71:ca:4e:e6: + d4:d5:7b:a9:19:cd:55:de:c8:ec:d2:5e:38:53:e5: + 5c:4f:8c:2d:fe:50:23:36:fc:66:e6:cb:8e:a4:39: + 19:00:b7:95:02:39:91:0b:0e:fe:38:2e:d1:1d:05: + 9a:f6:4d:3e:6f:0f:07:1d:af:2c:1e:8f:60:39:e2: + fa:36:53:13:39:d4:5e:26:2b:db:3d:a8:14:bd:32: + eb:18:03:28:52:04:71:e5:ab:33:3d:e1:38:bb:07: + 36:84:62:9c:79:ea:16:30:f4:5f:c0:2b:e8:71:6b: + e4:f9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E + X509v3 Authority Key Identifier: + keyid:C0:7A:98:68:8D:89:FB:AB:05:64:0C:11:7D:AA:7D:65:B8:CA:CC:4E + + Signature Algorithm: sha1WithRSAEncryption + 35:e3:29:6a:e5:2f:5d:54:8e:29:50:94:9f:99:1a:14:e4:8f: + 78:2a:62:94:a2:27:67:9e:d0:cf:1a:5e:47:e9:c1:b2:a4:cf: + dd:41:1a:05:4e:9b:4b:ee:4a:6f:55:52:b3:24:a1:37:0a:eb: + 64:76:2a:2e:2c:f3:fd:3b:75:90:bf:fa:71:d8:c7:3d:37:d2: + b5:05:95:62:b9:a6:de:89:3d:36:7b:38:77:48:97:ac:a6:20: + 8f:2e:a6:c9:0c:c2:b2:99:45:00:c7:ce:11:51:22:22:e0:a5: + ea:b6:15:48:09:64:ea:5e:4f:74:f7:05:3e:c7:8a:52:0c:db: + 15:b4:bd:6d:9b:e5:c6:b1:54:68:a9:e3:69:90:b6:9a:a5:0f: + b8:b9:3f:20:7d:ae:4a:b5:b8:9c:e4:1d:b6:ab:e6:94:a5:c1: + c7:83:ad:db:f5:27:87:0e:04:6c:d5:ff:dd:a0:5d:ed:87:52: + b7:2b:15:02:ae:39:a6:6a:74:e9:da:c4:e7:bc:4d:34:1e:a9: + 5c:4d:33:5f:92:09:2f:88:66:5d:77:97:c7:1d:76:13:a9:d5: + e5:f1:16:09:11:35:d5:ac:db:24:71:70:2c:98:56:0b:d9:17: + b4:d1:e3:51:2b:5e:75:e8:d5:d0:dc:4f:34:ed:c2:05:66:80: + a1:cb:e6:33 +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- + +UTN-USER First-Network Applications +=================================== + +MD5 Fingerprint=BF:60:59:A3:5B:BA:F6:A7:76:42:DA:6F:1A:7B:50:CF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 44:be:0c:8b:50:00:24:b4:11:d3:36:30:4b:c0:33:77 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications + Validity + Not Before: Jul 9 18:48:39 1999 GMT + Not After : Jul 9 18:57:49 2019 GMT + Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b3:fb:91:a1:e4:36:55:85:ac:06:34:5b:a0:9a: + 58:b2:f8:b5:0f:05:77:83:ae:32:b1:76:92:68:ec: + 23:4a:c9:76:3f:e3:9c:b6:37:79:03:b9:ab:69:8d: + 07:25:b6:19:67:e4:b0:1b:18:73:61:4a:e8:7e:cd: + d3:2f:64:e3:a6:7c:0c:fa:17:80:a3:0d:47:89:4f: + 51:71:2f:ee:fc:3f:f9:b8:16:80:87:89:93:25:20: + 9a:43:82:69:24:76:28:59:35:a1:1d:c0:7f:83:06: + 64:16:20:2c:d3:49:a4:85:b4:c0:61:7f:51:08:f8: + 68:15:91:80:cb:a5:d5:ee:3b:3a:f4:84:04:5e:60: + 59:a7:8c:34:72:ee:b8:78:c5:d1:3b:12:4a:6f:7e: + 65:27:b9:a4:55:c5:b9:6f:43:a4:c5:1d:2c:99:c0: + 52:a4:78:4c:15:b3:40:98:08:6b:43:c6:01:b0:7a: + 7b:f5:6b:1c:22:3f:cb:ef:ff:a8:d0:3a:4b:76:15: + 9e:d2:d1:c6:2e:e3:db:57:1b:32:a2:b8:6f:e8:86: + a6:3f:70:ab:e5:70:92:ab:44:1e:40:50:fb:9c:a3: + 62:e4:6c:6e:a0:c8:de:e2:80:42:fa:e9:2f:e8:ce: + 32:04:8f:7c:8d:b7:1c:a3:35:3c:15:dd:9e:c3:ae: + 97:a5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + FA:86:C9:DB:E0:BA:E9:78:F5:4B:A8:D6:15:DF:F0:D3:E1:6A:14:3C + X509v3 CRL Distribution Points: + URI:http://crl.usertrust.com/UTN-USERFirst-NetworkApplications.crl + + Signature Algorithm: sha1WithRSAEncryption + a4:f3:25:cc:d1:d4:91:83:22:d0:cc:32:ab:9b:96:4e:34:91: + 54:20:25:34:61:5f:2a:02:15:e1:8b:aa:ff:7d:64:51:cf:0a: + ff:bc:7d:d8:21:6a:78:cb:2f:51:6f:f8:42:1d:33:bd:eb:b5: + 7b:94:c3:c3:a9:a0:2d:df:d1:29:1f:1d:fe:8f:3f:bb:a8:45: + 2a:7f:d1:6e:55:24:e2:bb:02:fb:31:3f:be:e8:bc:ec:40:2b: + f8:01:d4:56:38:e4:ca:44:82:b5:61:20:21:67:65:f6:f0:0b: + e7:34:f8:a5:c2:9c:a3:5c:40:1f:85:93:95:06:de:4f:d4:27: + a9:b6:a5:fc:16:cd:73:31:3f:b8:65:27:cf:d4:53:1a:f0:ac: + 6e:9f:4f:05:0c:03:81:a7:84:29:c4:5a:bd:64:57:72:ad:3b: + cf:37:18:a6:98:c6:ad:06:b4:dc:08:a3:04:d5:29:a4:96:9a: + 12:67:4a:8c:60:45:9d:f1:23:9a:b0:00:9c:68:b5:98:50:d3: + ef:8e:2e:92:65:b1:48:3e:21:be:15:30:2a:0d:b5:0c:a3:6b: + 3f:ae:7f:57:f5:1f:96:7c:df:6f:dd:82:30:2c:65:1b:40:4a: + cd:68:b9:72:ec:71:76:ec:54:8e:1f:85:0c:01:6a:fa:a6:38: + ac:1f:c4:84 +-----BEGIN CERTIFICATE----- +MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCB +ozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3Qt +TmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5WhcNMTkwNzA5MTg1 +NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0 +IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYD +VQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VS +Rmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCz+5Gh5DZVhawGNFugmliy+LUPBXeDrjKxdpJo7CNKyXY/45y2 +N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4CjDUeJT1FxL+78P/m4FoCH +iZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXuOzr0hARe +YFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1 +axwiP8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6g +yN7igEL66S/ozjIEj3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQD +AgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPh +ahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9V +VE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0GCSqGSIb3DQEB +BQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y +IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6Lzs +QCv4AdRWOOTKRIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4 +ZSfP1FMa8Kxun08FDAOBp4QpxFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qM +YEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAqDbUMo2s/rn9X9R+WfN9v3YIwLGUb +QErNaLly7HF27FSOH4UMAWr6pjisH8SE +-----END CERTIFICATE----- + +Thawte Personal Freemail CA +=========================== + +MD5 Fingerprint=1E:74:C3:86:3C:0C:35:C5:3E:C2:7F:EF:3C:AA:3C:D9 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/emailAddress=personal-freemail@thawte.com + Validity + Not Before: Jan 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division, CN=Thawte Personal Freemail CA/emailAddress=personal-freemail@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d4:69:d7:d4:b0:94:64:5b:71:e9:47:d8:0c:51: + b6:ea:72:91:b0:84:5e:7d:2d:0d:8f:7b:12:df:85: + 25:75:28:74:3a:42:2c:63:27:9f:95:7b:4b:ef:7e: + 19:87:1d:86:ea:a3:dd:b9:ce:96:64:1a:c2:14:6e: + 44:ac:7c:e6:8f:e8:4d:0f:71:1f:40:38:a6:00:a3: + 87:78:f6:f9:94:86:5e:ad:ea:c0:5e:76:eb:d9:14: + a3:5d:6e:7a:7c:0c:a5:4b:55:7f:06:19:29:7f:9e: + 9a:26:d5:6a:bb:38:24:08:6a:98:c7:b1:da:a3:98: + 91:fd:79:db:e5:5a:c4:1c:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + c7:ec:92:7e:4e:f8:f5:96:a5:67:62:2a:a4:f0:4d:11:60:d0: + 6f:8d:60:58:61:ac:26:bb:52:35:5c:08:cf:30:fb:a8:4a:96: + 8a:1f:62:42:23:8c:17:0f:f4:ba:64:9c:17:ac:47:29:df:9d: + 98:5e:d2:6c:60:71:5c:a2:ac:dc:79:e3:e7:6e:00:47:1f:b5: + 0d:28:e8:02:9d:e4:9a:fd:13:f4:a6:d9:7c:b1:f8:dc:5f:23: + 26:09:91:80:73:d0:14:1b:de:43:a9:83:25:f2:e6:9c:2f:15: + ca:fe:a6:ab:8a:07:75:8b:0c:dd:51:84:6b:e4:f8:d1:ce:77: + a2:81 +-----BEGIN CERTIFICATE----- +MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD +VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT +ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt +YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu +Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa +MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG +cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh +d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY +DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E +rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq +uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN +BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP +MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa +/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei +gQ== +-----END CERTIFICATE----- + +America Online Root Certification Authority 1 +============================================= + +MD5 Fingerprint=14:F1:08:AD:9D:FA:64:E2:89:E7:1C:CF:A8:AD:7D:5E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=America Online Inc., CN=America Online Root Certification Authority 1 + Validity + Not Before: May 28 06:00:00 2002 GMT + Not After : Nov 19 20:43:00 2037 GMT + Subject: C=US, O=America Online Inc., CN=America Online Root Certification Authority 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:a8:2f:e8:a4:69:06:03:47:c3:e9:2a:98:ff:19: + a2:70:9a:c6:50:b2:7e:a5:df:68:4d:1b:7c:0f:b6: + 97:68:7d:2d:a6:8b:97:e9:64:86:c9:a3:ef:a0:86: + bf:60:65:9c:4b:54:88:c2:48:c5:4a:39:bf:14:e3: + 59:55:e5:19:b4:74:c8:b4:05:39:5c:16:a5:e2:95: + 05:e0:12:ae:59:8b:a2:33:68:58:1c:a6:d4:15:b7: + d8:9f:d7:dc:71:ab:7e:9a:bf:9b:8e:33:0f:22:fd: + 1f:2e:e7:07:36:ef:62:39:c5:dd:cb:ba:25:14:23: + de:0c:c6:3d:3c:ce:82:08:e6:66:3e:da:51:3b:16: + 3a:a3:05:7f:a0:dc:87:d5:9c:fc:72:a9:a0:7d:78: + e4:b7:31:55:1e:65:bb:d4:61:b0:21:60:ed:10:32: + 72:c5:92:25:1e:f8:90:4a:18:78:47:df:7e:30:37: + 3e:50:1b:db:1c:d3:6b:9a:86:53:07:b0:ef:ac:06: + 78:f8:84:99:fe:21:8d:4c:80:b6:0c:82:f6:66:70: + 79:1a:d3:4f:a3:cf:f1:cf:46:b0:4b:0f:3e:dd:88: + 62:b8:8c:a9:09:28:3b:7a:c7:97:e1:1e:e5:f4:9f: + c0:c0:ae:24:a0:c8:a1:d9:0f:d6:7b:26:82:69:32: + 3d:a7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 00:AD:D9:A3:F6:79:F6:6E:74:A9:7F:33:3D:81:17:D7:4C:CF:33:DE + X509v3 Authority Key Identifier: + keyid:00:AD:D9:A3:F6:79:F6:6E:74:A9:7F:33:3D:81:17:D7:4C:CF:33:DE + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 7c:8a:d1:1f:18:37:82:e0:b8:b0:a3:ed:56:95:c8:62:61:9c: + 05:a2:cd:c2:62:26:61:cd:10:16:d7:cc:b4:65:34:d0:11:8a: + ad:a8:a9:05:66:ef:74:f3:6d:5f:9d:99:af:f6:8b:fb:eb:52: + b2:05:98:a2:6f:2a:c5:54:bd:25:bd:5f:ae:c8:86:ea:46:2c: + c1:b3:bd:c1:e9:49:70:18:16:97:08:13:8c:20:e0:1b:2e:3a: + 47:cb:1e:e4:00:30:95:5b:f4:45:a3:c0:1a:b0:01:4e:ab:bd: + c0:23:6e:63:3f:80:4a:c5:07:ed:dc:e2:6f:c7:c1:62:f1:e3: + 72:d6:04:c8:74:67:0b:fa:88:ab:a1:01:c8:6f:f0:14:af:d2: + 99:cd:51:93:7e:ed:2e:38:c7:bd:ce:46:50:3d:72:e3:79:25: + 9d:9b:88:2b:10:20:dd:a5:b8:32:9f:8d:e0:29:df:21:74:86: + 82:db:2f:82:30:c6:c7:35:86:b3:f9:96:5f:46:db:0c:45:fd: + f3:50:c3:6f:c6:c3:48:ad:46:a6:e1:27:47:0a:1d:0e:9b:b6: + c2:77:7f:63:f2:e0:7d:1a:be:fc:e0:df:d7:c7:a7:6c:b0:f9: + ae:ba:3c:fd:74:b4:11:e8:58:0d:80:bc:d3:a8:80:3a:99:ed: + 75:cc:46:7b +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk +hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym +1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW +OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb +2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko +O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU +AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF +Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb +LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir +oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C +MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- + +America Online Root Certification Authority 2 +============================================= + +MD5 Fingerprint=D6:ED:3C:CA:E2:66:0F:AF:10:43:0D:77:9B:04:09:BF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=America Online Inc., CN=America Online Root Certification Authority 2 + Validity + Not Before: May 28 06:00:00 2002 GMT + Not After : Sep 29 14:08:00 2037 GMT + Subject: C=US, O=America Online Inc., CN=America Online Root Certification Authority 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (4096 bit) + Modulus (4096 bit): + 00:cc:41:45:1d:e9:3d:4d:10:f6:8c:b1:41:c9:e0: + 5e:cb:0d:b7:bf:47:73:d3:f0:55:4d:dd:c6:0c:fa: + b1:66:05:6a:cd:78:b4:dc:02:db:4e:81:f3:d7:a7: + 7c:71:bc:75:63:a0:5d:e3:07:0c:48:ec:25:c4:03: + 20:f4:ff:0e:3b:12:ff:9b:8d:e1:c6:d5:1b:b4:6d: + 22:e3:b1:db:7f:21:64:af:86:bc:57:22:2a:d6:47: + 81:57:44:82:56:53:bd:86:14:01:0b:fc:7f:74:a4: + 5a:ae:f1:ba:11:b5:9b:58:5a:80:b4:37:78:09:33: + 7c:32:47:03:5c:c4:a5:83:48:f4:57:56:6e:81:36: + 27:18:4f:ec:9b:28:c2:d4:b4:d7:7c:0c:3e:0c:2b: + df:ca:04:d7:c6:8e:ea:58:4e:a8:a4:a5:18:1c:6c: + 45:98:a3:41:d1:2d:d2:c7:6d:8d:19:f1:ad:79:b7: + 81:3f:bd:06:82:27:2d:10:58:05:b5:78:05:b9:2f: + db:0c:6b:90:90:7e:14:59:38:bb:94:24:13:e5:d1: + 9d:14:df:d3:82:4d:46:f0:80:39:52:32:0f:e3:84: + b2:7a:43:f2:5e:de:5f:3f:1d:dd:e3:b2:1b:a0:a1: + 2a:23:03:6e:2e:01:15:87:5c:a6:75:75:c7:97:61: + be:de:86:dc:d4:48:db:bd:2a:bf:4a:55:da:e8:7d: + 50:fb:b4:80:17:b8:94:bf:01:3d:ea:da:ba:7c:e0: + 58:67:17:b9:58:e0:88:86:46:67:6c:9d:10:47:58: + 32:d0:35:7c:79:2a:90:a2:5a:10:11:23:35:ad:2f: + cc:e4:4a:5b:a7:c8:27:f2:83:de:5e:bb:5e:77:e7: + e8:a5:6e:63:c2:0d:5d:61:d0:8c:d2:6c:5a:21:0e: + ca:28:a3:ce:2a:e9:95:c7:48:cf:96:6f:1d:92:25: + c8:c6:c6:c1:c1:0c:05:ac:26:c4:d2:75:d2:e1:2a: + 67:c0:3d:5b:a5:9a:eb:cf:7b:1a:a8:9d:14:45:e5: + 0f:a0:9a:65:de:2f:28:bd:ce:6f:94:66:83:48:29: + d8:ea:65:8c:af:93:d9:64:9f:55:57:26:bf:6f:cb: + 37:31:99:a3:60:bb:1c:ad:89:34:32:62:b8:43:21: + 06:72:0c:a1:5c:6d:46:c5:fa:29:cf:30:de:89:dc: + 71:5b:dd:b6:37:3e:df:50:f5:b8:07:25:26:e5:bc: + b5:fe:3c:02:b3:b7:f8:be:43:c1:87:11:94:9e:23: + 6c:17:8a:b8:8a:27:0c:54:47:f0:a9:b3:c0:80:8c: + a0:27:eb:1d:19:e3:07:8e:77:70:ca:2b:f4:7d:76: + e0:78:67 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 4D:45:C1:68:38:BB:73:A9:69:A1:20:E7:ED:F5:22:A1:23:14:D7:9E + X509v3 Authority Key Identifier: + keyid:4D:45:C1:68:38:BB:73:A9:69:A1:20:E7:ED:F5:22:A1:23:14:D7:9E + + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 67:6b:06:b9:5f:45:3b:2a:4b:33:b3:e6:1b:6b:59:4e:22:cc: + b9:b7:a4:25:c9:a7:c4:f0:54:96:0b:64:f3:b1:58:4f:5e:51: + fc:b2:97:7b:27:65:c2:e5:ca:e7:0d:0c:25:7b:62:e3:fa:9f: + b4:87:b7:45:46:af:83:a5:97:48:8c:a5:bd:f1:16:2b:9b:76: + 2c:7a:35:60:6c:11:80:97:cc:a9:92:52:e6:2b:e6:69:ed:a9: + f8:36:2d:2c:77:bf:61:48:d1:63:0b:b9:5b:52:ed:18:b0:43: + 42:22:a6:b1:77:ae:de:69:c5:cd:c7:1c:a1:b1:a5:1c:10:fb: + 18:be:1a:70:dd:c1:92:4b:be:29:5a:9d:3f:35:be:e5:7d:51: + f8:55:e0:25:75:23:87:1e:5c:dc:ba:9d:b0:ac:b3:69:db:17: + 83:c9:f7:de:0c:bc:08:dc:91:9e:a8:d0:d7:15:37:73:a5:35: + b8:fc:7e:c5:44:40:06:c3:eb:f8:22:80:5c:47:ce:02:e3:11: + 9f:44:ff:fd:9a:32:cc:7d:64:51:0e:eb:57:26:76:3a:e3:1e: + 22:3c:c2:a6:36:dd:19:ef:a7:fc:12:f3:26:c0:59:31:85:4c: + 9c:d8:cf:df:a4:cc:cc:29:93:ff:94:6d:76:5c:13:08:97:f2: + ed:a5:0b:4d:dd:e8:c9:68:0e:66:d3:00:0e:33:12:5b:bc:95: + e5:32:90:a8:b3:c6:6c:83:ad:77:ee:8b:7e:7e:b1:a9:ab:d3: + e1:f1:b6:c0:b1:ea:88:c0:e7:d3:90:e9:28:92:94:7b:68:7b: + 97:2a:0a:67:2d:85:02:38:10:e4:03:61:d4:da:25:36:c7:08: + 58:2d:a1:a7:51:af:30:0a:49:f5:a6:69:87:07:2d:44:46:76: + 8e:2a:e5:9a:3b:d7:18:a2:fc:9c:38:10:cc:c6:3b:d2:b5:17: + 3a:6f:fd:ae:25:bd:f5:72:59:64:b1:74:2a:38:5f:18:4c:df: + cf:71:04:5a:36:d4:bf:2f:99:9c:e8:d9:ba:b1:95:e6:02:4b: + 21:a1:5b:d5:c1:4f:8f:ae:69:6d:53:db:01:93:b5:5c:1e:18: + dd:64:5a:ca:18:28:3e:63:04:11:fd:1c:8d:00:0f:b8:37:df: + 67:8a:9d:66:a9:02:6a:91:ff:13:ca:2f:5d:83:bc:87:93:6c: + dc:24:51:16:04:25:66:fa:b3:d9:c2:ba:29:be:9a:48:38:82: + 99:f4:bf:3b:4a:31:19:f9:bf:8e:21:33:14:ca:4f:54:5f:fb: + ce:fb:8f:71:7f:fd:5e:19:a0:0f:4b:91:b8:c4:54:bc:06:b0: + 45:8f:26:91:a2:8e:fe:a9 +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc +MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP +bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2 +MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft +ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC +206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci +KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2 +JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9 +BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e +Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B +PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67 +Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq +Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ +o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3 ++L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj +YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj +FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn +xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2 +LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc +obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8 +CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe +IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA +DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F +AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX +Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb +AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl +Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw +RY8mkaKO/qk= +-----END CERTIFICATE----- + +Visa eCommerce Root +=================== + +MD5 Fingerprint=FC:11:B8:D8:08:93:30:00:6D:23:F9:7E:EB:52:1E:02 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 13:86:35:4d:1d:3f:06:f2:c1:f9:65:05:d5:90:1c:62 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=VISA, OU=Visa International Service Association, CN=Visa eCommerce Root + Validity + Not Before: Jun 26 02:18:36 2002 GMT + Not After : Jun 24 00:16:12 2022 GMT + Subject: C=US, O=VISA, OU=Visa International Service Association, CN=Visa eCommerce Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:af:57:de:56:1e:6e:a1:da:60:b1:94:27:cb:17: + db:07:3f:80:85:4f:c8:9c:b6:d0:f4:6f:4f:cf:99: + d8:e1:db:c2:48:5c:3a:ac:39:33:c7:1f:6a:8b:26: + 3d:2b:35:f5:48:b1:91:c1:02:4e:04:96:91:7b:b0: + 33:f0:b1:14:4e:11:6f:b5:40:af:1b:45:a5:4a:ef: + 7e:b6:ac:f2:a0:1f:58:3f:12:46:60:3c:8d:a1:e0: + 7d:cf:57:3e:33:1e:fb:47:f1:aa:15:97:07:55:66: + a5:b5:2d:2e:d8:80:59:b2:a7:0d:b7:46:ec:21:63: + ff:35:ab:a5:02:cf:2a:f4:4c:fe:7b:f5:94:5d:84: + 4d:a8:f2:60:8f:db:0e:25:3c:9f:73:71:cf:94:df: + 4a:ea:db:df:72:38:8c:f3:96:bd:f1:17:bc:d2:ba: + 3b:45:5a:c6:a7:f6:c6:17:8b:01:9d:fc:19:a8:2a: + 83:16:b8:3a:48:fe:4e:3e:a0:ab:06:19:e9:53:f3: + 80:13:07:ed:2d:bf:3f:0a:3c:55:20:39:2c:2c:00: + 69:74:95:4a:bc:20:b2:a9:79:e5:18:89:91:a8:dc: + 1c:4d:ef:bb:7e:37:0b:5d:fe:39:a5:88:52:8c:00: + 6c:ec:18:7c:41:bd:f6:8b:75:77:ba:60:9d:84:e7: + fe:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + 15:38:83:0F:3F:2C:3F:70:33:1E:CD:46:FE:07:8C:20:E0:D7:C3:B7 + Signature Algorithm: sha1WithRSAEncryption + 5f:f1:41:7d:7c:5c:08:b9:2b:e0:d5:92:47:fa:67:5c:a5:13: + c3:03:21:9b:2b:4c:89:46:cf:59:4d:c9:fe:a5:40:b6:63:cd: + dd:71:28:95:67:11:cc:24:ac:d3:44:6c:71:ae:01:20:6b:03: + a2:8f:18:b7:29:3a:7d:e5:16:60:53:78:3c:c0:af:15:83:f7: + 8f:52:33:24:bd:64:93:97:ee:8b:f7:db:18:a8:6d:71:b3:f7: + 2c:17:d0:74:25:69:f7:fe:6b:3c:94:be:4d:4b:41:8c:4e:e2: + 73:d0:e3:90:22:73:43:cd:f3:ef:ea:73:ce:45:8a:b0:a6:49: + ff:4c:7d:9d:71:88:c4:76:1d:90:5b:1d:ee:fd:cc:f7:ee:fd: + 60:a5:b1:7a:16:71:d1:16:d0:7c:12:3c:6c:69:97:db:ae:5f: + 39:9a:70:2f:05:3c:19:46:04:99:20:36:d0:60:6e:61:06:bb: + 16:42:8c:70:f7:30:fb:e0:db:66:a3:00:01:bd:e6:2c:da:91: + 5f:a0:46:8b:4d:6a:9c:3d:3d:dd:05:46:fe:76:bf:a0:0a:3c: + e4:00:e6:27:b7:ff:84:2d:de:ba:22:27:96:10:71:eb:22:ed: + df:df:33:9c:cf:e3:ad:ae:8e:d4:8e:e6:4f:51:af:16:92:e0: + 5c:f6:07:0f +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +TC TrustCenter, Germany, Class 2 CA +=================================== + +MD5 Fingerprint=B8:16:33:4C:4C:4C:F2:D8:D3:4D:06:B4:A6:5B:40:03 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1002 (0x3ea) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/emailAddress=certificate@trustcenter.de + Validity + Not Before: Mar 9 11:59:59 1998 GMT + Not After : Jan 1 11:59:59 2011 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 2 CA/emailAddress=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:38:e8:ed:32:00:29:71:83:01:0d:bf:8c:01: + dc:da:c6:ad:39:a4:a9:8a:2f:d5:8b:5c:68:5f:50: + c6:62:f5:66:bd:ca:91:22:ec:aa:1d:51:d7:3d:b3: + 51:b2:83:4e:5d:cb:49:b0:f0:4c:55:e5:6b:2d:c7: + 85:0b:30:1c:92:4e:82:d4:ca:02:ed:f7:6f:be:dc: + e0:e3:14:b8:05:53:f2:9a:f4:56:8b:5a:9e:85:93: + d1:b4:82:56:ae:4d:bb:a8:4b:57:16:bc:fe:f8:58: + 9e:f8:29:8d:b0:7b:cd:78:c9:4f:ac:8b:67:0c:f1: + 9c:fb:fc:57:9b:57:5c:4f:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 84:52:fb:28:df:ff:1f:75:01:bc:01:be:04:56:97:6a:74:42: + 24:31:83:f9:46:b1:06:8a:89:cf:96:2c:33:bf:8c:b5:5f:7a: + 72:a1:85:06:ce:86:f8:05:8e:e8:f9:25:ca:da:83:8c:06:ac: + eb:36:6d:85:91:34:04:36:f4:42:f0:f8:79:2e:0a:48:5c:ab: + cc:51:4f:78:76:a0:d9:ac:19:bd:2a:d1:69:04:28:91:ca:36: + 10:27:80:57:5b:d2:5c:f5:c2:5b:ab:64:81:63:74:51:f4:97: + bf:cd:12:28:f7:4d:66:7f:a7:f0:1c:01:26:78:b2:66:47:70: + 51:64 +-----BEGIN CERTIFICATE----- +MIIDXDCCAsWgAwIBAgICA+owDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF +MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU +QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI +MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcN +AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla +Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy +ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y +IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 +c3RDZW50ZXIgQ2xhc3MgMiBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA +dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANo46O0y +AClxgwENv4wB3NrGrTmkqYov1YtcaF9QxmL1Zr3KkSLsqh1R1z2zUbKDTl3LSbDw +TFXlay3HhQswHJJOgtTKAu33b77c4OMUuAVT8pr0VotanoWT0bSCVq5Nu6hLVxa8 +/vhYnvgpjbB7zXjJT6yLZwzxnPv8V5tXXE8NAgMBAAGjazBpMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 +LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G +CSqGSIb3DQEBBAUAA4GBAIRS+yjf/x91AbwBvgRWl2p0QiQxg/lGsQaKic+WLDO/ +jLVfenKhhQbOhvgFjuj5Jcrag4wGrOs2bYWRNAQ29ELw+HkuCkhcq8xRT3h2oNms +Gb0q0WkEKJHKNhAngFdb0lz1wlurZIFjdFH0l7/NEij3TWZ/p/AcASZ4smZHcFFk +-----END CERTIFICATE----- + +TC TrustCenter, Germany, Class 3 CA +=================================== + +MD5 Fingerprint=5F:94:4A:73:22:B8:F7:D1:31:EC:59:39:F7:8E:FE:6E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1003 (0x3eb) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/emailAddress=certificate@trustcenter.de + Validity + Not Before: Mar 9 11:59:59 1998 GMT + Not After : Jan 1 11:59:59 2011 GMT + Subject: C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data Networks GmbH, OU=TC TrustCenter Class 3 CA/emailAddress=certificate@trustcenter.de + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:b4:c1:35:05:2e:0d:8d:ec:a0:40:6a:1c:0e: + 27:a6:50:92:6b:50:1b:07:de:2e:e7:76:cc:e0:da: + fc:84:a8:5e:8c:63:6a:2b:4d:d9:4e:02:76:11:c1: + 0b:f2:8d:79:ca:00:b6:f1:b0:0e:d7:fb:a4:17:3d: + af:ab:69:7a:96:27:bf:af:33:a1:9a:2a:59:aa:c4: + b5:37:08:f2:12:a5:31:b6:43:f5:32:96:71:28:28: + ab:8d:28:86:df:bb:ee:e3:0c:7d:30:d6:c3:52:ab: + 8f:5d:27:9c:6b:c0:a3:e7:05:6b:57:49:44:b3:6e: + ea:64:cf:d2:8e:7a:50:77:77 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + Netscape CA Policy Url: + http://www.trustcenter.de/guidelines + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Signature Algorithm: md5WithRSAEncryption + 16:3d:c6:cd:c1:bb:85:71:85:46:9f:3e:20:8f:51:28:99:ec: + 2d:45:21:63:23:5b:04:bb:4c:90:b8:88:92:04:4d:bd:7d:01: + a3:3f:f6:ec:ce:f1:de:fe:7d:e5:e1:3e:bb:c6:ab:5e:0b:dd: + 3d:96:c4:cb:a9:d4:f9:26:e6:06:4e:9e:0c:a5:7a:ba:6e:c3: + 7c:82:19:d1:c7:b1:b1:c3:db:0d:8e:9b:40:7c:37:0b:f1:5d: + e8:fd:1f:90:88:a5:0e:4e:37:64:21:a8:4e:8d:b4:9f:f1:de: + 48:ad:d5:56:18:52:29:8b:47:34:12:09:d4:bb:92:35:ef:0f: + db:34 +-----BEGIN CERTIFICATE----- +MIIDXDCCAsWgAwIBAgICA+swDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF +MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU +QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI +MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcN +AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla +Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy +ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y +IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1 +c3RDZW50ZXIgQ2xhc3MgMyBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA +dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALa0wTUF +Lg2N7KBAahwOJ6ZQkmtQGwfeLud2zODa/ISoXoxjaitN2U4CdhHBC/KNecoAtvGw +Dtf7pBc9r6tpepYnv68zoZoqWarEtTcI8hKlMbZD9TKWcSgoq40oht+77uMMfTDW +w1Krj10nnGvAo+cFa1dJRLNu6mTP0o56UHd3AgMBAAGjazBpMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3 +LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G +CSqGSIb3DQEBBAUAA4GBABY9xs3Bu4VxhUafPiCPUSiZ7C1FIWMjWwS7TJC4iJIE +Tb19AaM/9uzO8d7+feXhPrvGq14L3T2WxMup1Pkm5gZOngylerpuw3yCGdHHsbHD +2w2Om0B8NwvxXej9H5CIpQ5ON2QhqE6NtJ/x3kit1VYYUimLRzQSCdS7kjXvD9s0 +-----END CERTIFICATE----- + +Certum Root CA +============== + +MD5 Fingerprint=2C:8F:9F:66:1D:18:90:B1:47:26:9D:8E:86:82:8C:A9 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 65568 (0x10020) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=PL, O=Unizeto Sp. z o.o., CN=Certum CA + Validity + Not Before: Jun 11 10:46:39 2002 GMT + Not After : Jun 11 10:46:39 2027 GMT + Subject: C=PL, O=Unizeto Sp. z o.o., CN=Certum CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ce:b1:c1:2e:d3:4f:7c:cd:25:ce:18:3e:4f:c4: + 8c:6f:80:6a:73:c8:5b:51:f8:9b:d2:dc:bb:00:5c: + b1:a0:fc:75:03:ee:81:f0:88:ee:23:52:e9:e6:15: + 33:8d:ac:2d:09:c5:76:f9:2b:39:80:89:e4:97:4b: + 90:a5:a8:78:f8:73:43:7b:a4:61:b0:d8:58:cc:e1: + 6c:66:7e:9c:f3:09:5e:55:63:84:d5:a8:ef:f3:b1: + 2e:30:68:b3:c4:3c:d8:ac:6e:8d:99:5a:90:4e:34: + dc:36:9a:8f:81:88:50:b7:6d:96:42:09:f3:d7:95: + 83:0d:41:4b:b0:6a:6b:f8:fc:0f:7e:62:9f:67:c4: + ed:26:5f:10:26:0f:08:4f:f0:a4:57:28:ce:8f:b8: + ed:45:f6:6e:ee:25:5d:aa:6e:39:be:e4:93:2f:d9: + 47:a0:72:eb:fa:a6:5b:af:ca:53:3f:e2:0e:c6:96: + 56:11:6e:f7:e9:66:a9:26:d8:7f:95:53:ed:0a:85: + 88:ba:4f:29:a5:42:8c:5e:b6:fc:85:20:00:aa:68: + 0b:a1:1a:85:01:9c:c4:46:63:82:88:b6:22:b1:ee: + fe:aa:46:59:7e:cf:35:2c:d5:b6:da:5d:f7:48:33: + 14:54:b6:eb:d9:6f:ce:cd:88:d6:ab:1b:da:96:3b: + 1d:59 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + b8:8d:ce:ef:e7:14:ba:cf:ee:b0:44:92:6c:b4:39:3e:a2:84: + 6e:ad:b8:21:77:d2:d4:77:82:87:e6:20:41:81:ee:e2:f8:11: + b7:63:d1:17:37:be:19:76:24:1c:04:1a:4c:eb:3d:aa:67:6f: + 2d:d4:cd:fe:65:31:70:c5:1b:a6:02:0a:ba:60:7b:6d:58:c2: + 9a:49:fe:63:32:0b:6b:e3:3a:c0:ac:ab:3b:b0:e8:d3:09:51: + 8c:10:83:c6:34:e0:c5:2b:e0:1a:b6:60:14:27:6c:32:77:8c: + bc:b2:72:98:cf:cd:cc:3f:b9:c8:24:42:14:d6:57:fc:e6:26: + 43:a9:1d:e5:80:90:ce:03:54:28:3e:f7:3f:d3:f8:4d:ed:6a: + 0a:3a:93:13:9b:3b:14:23:13:63:9c:3f:d1:87:27:79:e5:4c: + 51:e3:01:ad:85:5d:1a:3b:b1:d5:73:10:a4:d3:f2:bc:6e:64: + f5:5a:56:90:a8:c7:0e:4c:74:0f:2e:71:3b:f7:c8:47:f4:69: + 6f:15:f2:11:5e:83:1e:9c:7c:52:ae:fd:02:da:12:a8:59:67: + 18:db:bc:70:dd:9b:b1:69:ed:80:ce:89:40:48:6a:0e:35:ca: + 29:66:15:21:94:2c:e8:60:2a:9b:85:4a:40:f3:6b:8a:24:ec: + 06:16:2c:73 +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM +MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD +QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E +jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo +ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI +ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu +Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg +AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 +HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA +uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa +TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg +xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q +CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x +O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs +6GAqm4VKQPNriiTsBhYscw== +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== + +MD5 Fingerprint=49:79:04:B0:EB:87:19:AC:47:B0:BC:11:51:9B:74:D0 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services + Validity + Not Before: Jan 1 00:00:00 2004 GMT + Not After : Dec 31 23:59:59 2028 GMT + Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:be:40:9d:f4:6e:e1:ea:76:87:1c:4d:45:44:8e: + be:46:c8:83:06:9d:c1:2a:fe:18:1f:8e:e4:02:fa: + f3:ab:5d:50:8a:16:31:0b:9a:06:d0:c5:70:22:cd: + 49:2d:54:63:cc:b6:6e:68:46:0b:53:ea:cb:4c:24: + c0:bc:72:4e:ea:f1:15:ae:f4:54:9a:12:0a:c3:7a: + b2:33:60:e2:da:89:55:f3:22:58:f3:de:dc:cf:ef: + 83:86:a2:8c:94:4f:9f:68:f2:98:90:46:84:27:c7: + 76:bf:e3:cc:35:2c:8b:5e:07:64:65:82:c0:48:b0: + a8:91:f9:61:9f:76:20:50:a8:91:c7:66:b5:eb:78: + 62:03:56:f0:8a:1a:13:ea:31:a3:1e:a0:99:fd:38: + f6:f6:27:32:58:6f:07:f5:6b:b8:fb:14:2b:af:b7: + aa:cc:d6:63:5f:73:8c:da:05:99:a8:38:a8:cb:17: + 78:36:51:ac:e9:9e:f4:78:3a:8d:cf:0f:d9:42:e2: + 98:0c:ab:2f:9f:0e:01:de:ef:9f:99:49:f1:2d:df: + ac:74:4d:1b:98:b5:47:c5:e5:29:d1:f9:90:18:c7: + 62:9c:be:83:c7:26:7b:3e:8a:25:c7:c0:dd:9d:e6: + 35:68:10:20:9d:8f:d8:de:d2:c3:84:9c:0d:5e:e8: + 2f:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A0:11:0A:23:3E:96:F1:07:EC:E2:AF:29:EF:82:A5:7F:D0:30:A4:B4 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 CRL Distribution Points: + URI:http://crl.comodoca.com/AAACertificateServices.crl + URI:http://crl.comodo.net/AAACertificateServices.crl + + Signature Algorithm: sha1WithRSAEncryption + 08:56:fc:02:f0:9b:e8:ff:a4:fa:d6:7b:c6:44:80:ce:4f:c4: + c5:f6:00:58:cc:a6:b6:bc:14:49:68:04:76:e8:e6:ee:5d:ec: + 02:0f:60:d6:8d:50:18:4f:26:4e:01:e3:e6:b0:a5:ee:bf:bc: + 74:54:41:bf:fd:fc:12:b8:c7:4f:5a:f4:89:60:05:7f:60:b7: + 05:4a:f3:f6:f1:c2:bf:c4:b9:74:86:b6:2d:7d:6b:cc:d2:f3: + 46:dd:2f:c6:e0:6a:c3:c3:34:03:2c:7d:96:dd:5a:c2:0e:a7: + 0a:99:c1:05:8b:ab:0c:2f:f3:5c:3a:cf:6c:37:55:09:87:de: + 53:40:6c:58:ef:fc:b6:ab:65:6e:04:f6:1b:dc:3c:e0:5a:15: + c6:9e:d9:f1:59:48:30:21:65:03:6c:ec:e9:21:73:ec:9b:03: + a1:e0:37:ad:a0:15:18:8f:fa:ba:02:ce:a7:2c:a9:10:13:2c: + d4:e5:08:26:ab:22:97:60:f8:90:5e:74:d4:a2:9a:53:bd:f2: + a9:68:e0:a2:6e:c2:d7:6c:b1:a3:0f:9e:bf:eb:68:e7:56:f2: + ae:f2:e3:2b:38:3a:09:81:b5:6b:85:d7:be:2d:ed:3f:1a:b7: + b2:63:e2:f5:62:2c:82:d4:6a:00:41:50:f1:39:83:9f:95:e9: + 36:96:98:6e +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +Comodo Secure Services root +=========================== + +MD5 Fingerprint=D3:D9:BD:AE:9F:AC:67:24:B3:C8:1B:52:E1:B9:A9:BD +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Secure Certificate Services + Validity + Not Before: Jan 1 00:00:00 2004 GMT + Not After : Dec 31 23:59:59 2028 GMT + Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Secure Certificate Services + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:c0:71:33:82:8a:d0:70:eb:73:87:82:40:d5:1d: + e4:cb:c9:0e:42:90:f9:de:34:b9:a1:ba:11:f4:25: + 85:f3:cc:72:6d:f2:7b:97:6b:b3:07:f1:77:24:91: + 5f:25:8f:f6:74:3d:e4:80:c2:f8:3c:0d:f3:bf:40: + ea:f7:c8:52:d1:72:6f:ef:c8:ab:41:b8:6e:2e:17: + 2a:95:69:0c:cd:d2:1e:94:7b:2d:94:1d:aa:75:d7: + b3:98:cb:ac:bc:64:53:40:bc:8f:ac:ac:36:cb:5c: + ad:bb:dd:e0:94:17:ec:d1:5c:d0:bf:ef:a5:95:c9: + 90:c5:b0:ac:fb:1b:43:df:7a:08:5d:b7:b8:f2:40: + 1b:2b:27:9e:50:ce:5e:65:82:88:8c:5e:d3:4e:0c: + 7a:ea:08:91:b6:36:aa:2b:42:fb:ea:c2:a3:39:e5: + db:26:38:ad:8b:0a:ee:19:63:c7:1c:24:df:03:78: + da:e6:ea:c1:47:1a:0b:0b:46:09:dd:02:fc:de:cb: + 87:5f:d7:30:63:68:a1:ae:dc:32:a1:ba:be:fe:44: + ab:68:b6:a5:17:15:fd:bd:d5:a7:a7:9a:e4:44:33: + e9:88:8e:fc:ed:51:eb:93:71:4e:ad:01:e7:44:8e: + ab:2d:cb:a8:fe:01:49:48:f0:c0:dd:c7:68:d8:92: + fe:3d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3C:D8:93:88:C2:C0:82:09:CC:01:99:06:93:20:E9:9E:70:09:63:4F + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 CRL Distribution Points: + URI:http://crl.comodoca.com/SecureCertificateServices.crl + URI:http://crl.comodo.net/SecureCertificateServices.crl + + Signature Algorithm: sha1WithRSAEncryption + 87:01:6d:23:1d:7e:5b:17:7d:c1:61:32:cf:8f:e7:f3:8a:94: + 59:66:e0:9e:28:a8:5e:d3:b7:f4:34:e6:aa:39:b2:97:16:c5: + 82:6f:32:a4:e9:8c:e7:af:fd:ef:c2:e8:b9:4b:aa:a3:f4:e6: + da:8d:65:21:fb:ba:80:eb:26:28:85:1a:fe:39:8c:de:5b:04: + 04:b4:54:f9:a3:67:9e:41:fa:09:52:cc:05:48:a8:c9:3f:21: + 04:1e:ce:48:6b:fc:85:e8:c2:7b:af:7f:b7:cc:f8:5f:3a:fd: + 35:c6:0d:ef:97:dc:4c:ab:11:e1:6b:cb:31:d1:6c:fb:48:80: + ab:dc:9c:37:b8:21:14:4b:0d:71:3d:ec:83:33:6e:d1:6e:32: + 16:ec:98:c7:16:8b:59:a6:34:ab:05:57:2d:93:f7:aa:13:cb: + d2:13:e2:b7:2e:3b:cd:6b:50:17:09:68:3e:b5:26:57:ee:b6: + e0:b6:dd:b9:29:80:79:7d:8f:a3:f0:a4:28:a4:15:c4:85:f4: + 27:d4:6b:bf:e5:5c:e4:65:02:76:54:b4:e3:37:66:24:d3:19: + 61:c8:52:10:e5:8b:37:9a:b9:a9:f9:1d:bf:ea:99:92:61:96: + ff:01:cd:a1:5f:0d:bc:71:bc:0e:ac:0b:1d:47:45:1d:c1:ec: + 7c:ec:fd:29 +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp +ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow +fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV +BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM +cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S +HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 +CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk +3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz +6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV +HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud +EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv +Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw +Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww +DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 +5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI +gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ +aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl +izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= +-----END CERTIFICATE----- + +Comodo Trusted Services root +============================ + +MD5 Fingerprint=91:1B:3F:6E:CD:9E:AB:EE:07:FE:1F:71:D2:B3:61:27 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Trusted Certificate Services + Validity + Not Before: Jan 1 00:00:00 2004 GMT + Not After : Dec 31 23:59:59 2028 GMT + Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Trusted Certificate Services + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:df:71:6f:36:58:53:5a:f2:36:54:57:80:c4:74: + 08:20:ed:18:7f:2a:1d:e6:35:9a:1e:25:ac:9c:e5: + 96:7e:72:52:a0:15:42:db:59:dd:64:7a:1a:d0:b8: + 7b:dd:39:15:bc:55:48:c4:ed:3a:00:ea:31:11:ba: + f2:71:74:1a:67:b8:cf:33:cc:a8:31:af:a3:e3:d7: + 7f:bf:33:2d:4c:6a:3c:ec:8b:c3:92:d2:53:77:24: + 74:9c:07:6e:70:fc:bd:0b:5b:76:ba:5f:f2:ff:d7: + 37:4b:4a:60:78:f7:f0:fa:ca:70:b4:ea:59:aa:a3: + ce:48:2f:a9:c3:b2:0b:7e:17:72:16:0c:a6:07:0c: + 1b:38:cf:c9:62:b7:3f:a0:93:a5:87:41:f2:b7:70: + 40:77:d8:be:14:7c:e3:a8:c0:7a:8e:e9:63:6a:d1: + 0f:9a:c6:d2:f4:8b:3a:14:04:56:d4:ed:b8:cc:6e: + f5:fb:e2:2c:58:bd:7f:4f:6b:2b:f7:60:24:58:24: + ce:26:ef:34:91:3a:d5:e3:81:d0:b2:f0:04:02:d7: + 5b:b7:3e:92:ac:6b:12:8a:f9:e4:05:b0:3b:91:49: + 5c:b2:eb:53:ea:f8:9f:47:86:ee:bf:95:c0:c0:06: + 9f:d2:5b:5e:11:1b:f4:c7:04:35:29:d2:55:5c:e4: + ed:eb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + C5:7B:58:BD:ED:DA:25:69:D2:F7:59:16:A8:B3:32:C0:7B:27:5B:F4 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 CRL Distribution Points: + URI:http://crl.comodoca.com/TrustedCertificateServices.crl + URI:http://crl.comodo.net/TrustedCertificateServices.crl + + Signature Algorithm: sha1WithRSAEncryption + c8:93:81:3b:89:b4:af:b8:84:12:4c:8d:d2:f0:db:70:ba:57: + 86:15:34:10:b9:2f:7f:1e:b0:a8:89:60:a1:8a:c2:77:0c:50: + 4a:9b:00:8b:d8:8b:f4:41:e2:d0:83:8a:4a:1c:14:06:b0:a3: + 68:05:70:31:30:a7:53:9b:0e:e9:4a:a0:58:69:67:0e:ae:9d: + f6:a5:2c:41:bf:3c:06:6b:e4:59:cc:6d:10:f1:96:6f:1f:df: + f4:04:02:a4:9f:45:3e:c8:d8:fa:36:46:44:50:3f:82:97:91: + 1f:28:db:18:11:8c:2a:e4:65:83:57:12:12:8c:17:3f:94:36: + fe:5d:b0:c0:04:77:13:b8:f4:15:d5:3f:38:cc:94:3a:55:d0: + ac:98:f5:ba:00:5f:e0:86:19:81:78:2f:28:c0:7e:d3:cc:42: + 0a:f5:ae:50:a0:d1:3e:c6:a1:71:ec:3f:a0:20:8c:66:3a:89: + b4:8e:d4:d8:b1:4d:25:47:ee:2f:88:c8:b5:e1:05:45:c0:be: + 14:71:de:7a:fd:8e:7b:7d:4d:08:96:a5:12:73:f0:2d:ca:37: + 27:74:12:27:4c:cb:b6:97:e9:d9:ae:08:6d:5a:39:40:dd:05: + 47:75:6a:5a:21:b3:a3:18:cf:4e:f7:2e:57:b7:98:70:5e:c8: + c4:78:b0:62 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 +aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla +MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD +VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW +fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt +TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL +fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW +1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 +kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G +A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v +ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo +dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu +Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ +HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS +jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ +xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn +dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- + +IPS Chained CAs root +==================== + +MD5 Fingerprint=8D:72:51:DB:A0:3A:CF:20:77:DF:F2:65:06:5E:DF:EF +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA Chained CAs Certification Authority, CN=IPS CA Chained CAs Certification Authority/emailAddress=ips@mail.ips.es + Validity + Not Before: Dec 29 00:53:58 2001 GMT + Not After : Dec 27 00:53:58 2025 GMT + Subject: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA Chained CAs Certification Authority, CN=IPS CA Chained CAs Certification Authority/emailAddress=ips@mail.ips.es + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:dc:56:92:49:b2:94:20:bc:98:4f:50:eb:68:a4: + a7:49:0b:bf:d2:31:e8:c7:4f:c2:86:0b:fa:68:fd: + 43:5a:8a:f3:60:92:35:99:38:bb:4d:03:52:21:5b: + f0:37:99:35:e1:41:20:81:85:81:05:71:81:9d:b4: + 95:19:a9:5f:76:34:2e:63:37:35:57:8e:b4:1f:42: + 3f:15:5c:e1:7a:c1:5f:13:18:32:31:c9:ad:be:a3: + c7:83:66:1e:b9:9c:04:13:cb:69:c1:06:de:30:06: + bb:33:a3:b5:1f:f0:8f:6f:ce:ff:96:e8:54:be:66: + 80:ae:6b:db:41:84:36:a2:3d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A1:AD:31:B1:F9:3E:E1:17:A6:C8:AB:34:FC:52:87:09:1E:62:52:41 + X509v3 Authority Key Identifier: + keyid:A1:AD:31:B1:F9:3E:E1:17:A6:C8:AB:34:FC:52:87:09:1E:62:52:41 + DirName:/C=ES/ST=Barcelona/L=Barcelona/O=IPS Internet publishing Services s.l./O=ips@mail.ips.es C.I.F. B-60929452/OU=IPS CA Chained CAs Certification Authority/CN=IPS CA Chained CAs Certification Authority/emailAddress=ips@mail.ips.es + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign, Encipher Only, Decipher Only + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping, Microsoft Individual Code Signing, Microsoft Commercial Code Signing, Microsoft Trust List Signing, Microsoft Encrypted File System + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:ips@mail.ips.es + X509v3 Issuer Alternative Name: + email:ips@mail.ips.es + Netscape Comment: + Chained CA Certificate issued by http://www.ips.es/ + Netscape Base Url: + http://www.ips.es/ips2002/ + Netscape CA Revocation Url: + http://www.ips.es/ips2002/ips2002CAC.crl + Netscape Revocation Url: + http://www.ips.es/ips2002/revocationCAC.html? + Netscape Renewal Url: + http://www.ips.es/ips2002/renewalCAC.html? + Netscape CA Policy Url: + http://www.ips.es/ips2002/policyCAC.html + X509v3 CRL Distribution Points: + URI:http://www.ips.es/ips2002/ips2002CAC.crl + URI:http://wwwback.ips.es/ips2002/ips2002CAC.crl + + Authority Information Access: + OCSP - URI:http://ocsp.ips.es/ + + Signature Algorithm: sha1WithRSAEncryption + 44:72:30:9d:56:58:a2:41:1b:28:b7:95:e1:a6:1a:95:5f:a7: + 78:40:2b:ef:db:96:4a:fc:4c:71:63:d9:73:95:bd:02:e2:a2: + 06:c7:be:97:2a:93:80:34:86:03:fa:dc:d8:3d:1e:07:cd:1e: + 73:43:24:60:f5:1d:61:dc:dc:96:a0:bc:fb:1d:e3:e7:12:00: + 27:33:02:c0:c0:2b:53:3d:d8:6b:03:81:a3:db:d6:93:95:20: + ef:d3:96:7e:26:90:89:9c:26:9b:cd:6f:66:ab:ed:03:22:44: + 38:cc:59:bd:9f:db:f6:07:a2:01:7f:26:c4:63:f5:25:42:5e: + 62:bd +-----BEGIN CERTIFICATE----- +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARwxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEzMDEGA1UECxMq +SVBTIENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTMwMQYD +VQQDEypJUFMgQ0EgQ2hhaW5lZCBDQXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +HjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczAeFw0wMTEyMjkwMDUzNTha +Fw0yNTEyMjcwMDUzNThaMIIBHDELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNl +bG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQg +cHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMu +ZXMgQy5JLkYuICBCLTYwOTI5NDUyMTMwMQYDVQQLEypJUFMgQ0EgQ2hhaW5lZCBD +QXMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMzAxBgNVBAMTKklQUyBDQSBDaGFp +bmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYP +aXBzQG1haWwuaXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcVpJJ +spQgvJhPUOtopKdJC7/SMejHT8KGC/po/UNaivNgkjWZOLtNA1IhW/A3mTXhQSCB +hYEFcYGdtJUZqV92NC5jNzVXjrQfQj8VXOF6wV8TGDIxya2+o8eDZh65nAQTy2nB +Bt4wBrszo7Uf8I9vzv+W6FS+ZoCua9tBhDaiPQIDAQABo4IEQzCCBD8wHQYDVR0O +BBYEFKGtMbH5PuEXpsirNPxShwkeYlJBMIIBTgYDVR0jBIIBRTCCAUGAFKGtMbH5 +PuEXpsirNPxShwkeYlJBoYIBJKSCASAwggEcMQswCQYDVQQGEwJFUzESMBAGA1UE +CBMJQmFyY2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJ +bnRlcm5ldCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0Bt +YWlsLmlwcy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxMzAxBgNVBAsTKklQUyBDQSBD +aGFpbmVkIENBcyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEzMDEGA1UEAxMqSVBT +IENBIENoYWluZWQgQ0FzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8E +BQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMG +CCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYB +BAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMw +EYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlwcy5lczBC +BglghkgBhvhCAQ0ENRYzQ2hhaW5lZCBDQSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkg +aHR0cDovL3d3dy5pcHMuZXMvMCkGCWCGSAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlw +cy5lcy9pcHMyMDAyLzA3BglghkgBhvhCAQQEKhYoaHR0cDovL3d3dy5pcHMuZXMv +aXBzMjAwMi9pcHMyMDAyQ0FDLmNybDA8BglghkgBhvhCAQMELxYtaHR0cDovL3d3 +dy5pcHMuZXMvaXBzMjAwMi9yZXZvY2F0aW9uQ0FDLmh0bWw/MDkGCWCGSAGG+EIB +BwQsFipodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3JlbmV3YWxDQUMuaHRtbD8w +NwYJYIZIAYb4QgEIBCoWKGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5 +Q0FDLmh0bWwwbQYDVR0fBGYwZDAuoCygKoYoaHR0cDovL3d3dy5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0FDLmNybDAyoDCgLoYsaHR0cDovL3d3d2JhY2suaXBzLmVz +L2lwczIwMDIvaXBzMjAwMkNBQy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAERyMJ1W +WKJBGyi3leGmGpVfp3hAK+/blkr8THFj2XOVvQLiogbHvpcqk4A0hgP63Ng9HgfN +HnNDJGD1HWHc3JagvPsd4+cSACczAsDAK1M92GsDgaPb1pOVIO/Tln4mkImcJpvN +b2ar7QMiRDjMWb2f2/YHogF/JsRj9SVCXmK9 +-----END CERTIFICATE----- + +Thawte Server CA +================ + +MD5 Fingerprint=C5:70:C4:A2:ED:53:78:0C:C8:10:53:81:64:CB:D0:1D +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com + Validity + Not Before: Aug 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Server CA/emailAddress=server-certs@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:a4:50:6e:c8:ff:56:6b:e6:cf:5d:b6:ea:0c: + 68:75:47:a2:aa:c2:da:84:25:fc:a8:f4:47:51:da: + 85:b5:20:74:94:86:1e:0f:75:c9:e9:08:61:f5:06: + 6d:30:6e:15:19:02:e9:52:c0:62:db:4d:99:9e:e2: + 6a:0c:44:38:cd:fe:be:e3:64:09:70:c5:fe:b1:6b: + 29:b6:2f:49:c8:3b:d4:27:04:25:10:97:2f:e7:90: + 6d:c0:28:42:99:d7:4c:43:de:c3:f5:21:6d:54:9f: + 5d:c3:58:e1:c0:e4:d9:5b:b0:b8:dc:b4:7b:df:36: + 3a:c2:b5:66:22:12:d6:87:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 07:fa:4c:69:5c:fb:95:cc:46:ee:85:83:4d:21:30:8e:ca:d9: + a8:6f:49:1a:e6:da:51:e3:60:70:6c:84:61:11:a1:1a:c8:48: + 3e:59:43:7d:4f:95:3d:a1:8b:b7:0b:62:98:7a:75:8a:dd:88: + 4e:4e:9e:40:db:a8:cc:32:74:b9:6f:0d:c6:e3:b3:44:0b:d9: + 8a:6f:9a:29:9b:99:18:28:3b:d1:e3:40:28:9a:5a:3c:d5:b5: + e7:20:1b:8b:ca:a4:ab:8d:e9:51:d9:e2:4c:2c:59:a9:da:b9: + b2:75:1b:f6:42:f2:ef:c7:f2:18:f9:89:bc:a3:ff:8a:23:2e: + 70:47 +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm +MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx +MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 +dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl +cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 +DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 +yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX +L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj +EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG +7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e +QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ +qdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- + +IPS CLASE1 root +=============== + +MD5 Fingerprint=84:90:1D:95:30:49:56:FC:41:81:F0:45:D7:76:C4:6B +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASE1 Certification Authority, CN=IPS CA CLASE1 Certification Authority/emailAddress=ips@mail.ips.es + Validity + Not Before: Dec 29 00:59:38 2001 GMT + Not After : Dec 27 00:59:38 2025 GMT + Subject: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASE1 Certification Authority, CN=IPS CA CLASE1 Certification Authority/emailAddress=ips@mail.ips.es + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e0:51:27:a7:0b:dd:af:d1:b9:43:5b:82:37:45: + 56:72:ef:9a:b6:c2:12:ef:2c:12:cc:76:f9:06:59: + af:5d:21:d4:d2:5a:b8:a0:d4:f3:6a:fd:ca:69:8d: + 66:48:f7:74:e6:ee:36:bd:e8:96:91:75:a6:71:28: + ca:e7:22:12:32:69:b0:3e:1e:6b:f4:50:52:62:62: + fd:63:3b:7d:7e:ec:ee:38:ea:62:f4:6c:a8:71:8d: + e1:e9:8b:c9:3f:c6:b5:cd:94:42:6f:dd:82:45:3c: + e8:df:09:e8:ef:0a:55:a9:56:47:61:4c:49:64:73: + 10:28:3f:ca:bf:09:ff:c6:2f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EB:B3:19:79:F3:C1:A5:1C:AC:DC:BA:1F:66:A2:B2:9B:69:D0:78:08 + X509v3 Authority Key Identifier: + keyid:EB:B3:19:79:F3:C1:A5:1C:AC:DC:BA:1F:66:A2:B2:9B:69:D0:78:08 + DirName:/C=ES/ST=Barcelona/L=Barcelona/O=IPS Internet publishing Services s.l./O=ips@mail.ips.es C.I.F. B-60929452/OU=IPS CA CLASE1 Certification Authority/CN=IPS CA CLASE1 Certification Authority/emailAddress=ips@mail.ips.es + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign, Encipher Only, Decipher Only + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping, Microsoft Individual Code Signing, Microsoft Commercial Code Signing, Microsoft Trust List Signing, Microsoft Encrypted File System + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:ips@mail.ips.es + X509v3 Issuer Alternative Name: + email:ips@mail.ips.es + Netscape Comment: + CLASE1 CA Certificate issued by http://www.ips.es/ + Netscape Base Url: + http://www.ips.es/ips2002/ + Netscape CA Revocation Url: + http://www.ips.es/ips2002/ips2002CLASE1.crl + Netscape Revocation Url: + http://www.ips.es/ips2002/revocationCLASE1.html? + Netscape Renewal Url: + http://www.ips.es/ips2002/renewalCLASE1.html? + Netscape CA Policy Url: + http://www.ips.es/ips2002/policyCLASE1.html + X509v3 CRL Distribution Points: + URI:http://www.ips.es/ips2002/ips2002CLASE1.crl + URI:http://wwwback.ips.es/ips2002/ips2002CLASE1.crl + + Authority Information Access: + OCSP - URI:http://ocsp.ips.es/ + + Signature Algorithm: sha1WithRSAEncryption + 2b:d0:eb:fd:da:c8:ca:59:6a:da:d3:cc:32:2e:c9:54:1b:8a: + 62:7e:15:2d:e9:d9:31:d3:2e:f4:27:23:ff:5b:ab:c5:4a:b6: + 72:40:ae:53:74:f4:bc:05:b4:c6:d9:c8:c9:77:fb:b7:f9:34: + 7f:78:00:f8:d6:a4:e4:52:3f:2c:4a:63:57:81:75:5a:8e:e8: + 8c:fb:02:c0:94:c6:29:ba:b3:dc:1c:e8:b2:af:d2:2e:62:5b: + 1a:a9:8e:0e:cc:c5:57:45:51:14:e9:4e:1c:88:a5:91:f4:a3: + f7:8e:51:c8:a9:be:86:33:3e:e6:2f:48:6e:af:54:90:4e:ad: + b1:25 +-----BEGIN CERTIFICATE----- +MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAwNTkzOFoXDTI1MTIyNzAw +NTkzOFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTEgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4FEnpwvdr9G5Q1uCN0VWcu+atsIS7ywS +zHb5BlmvXSHU0lq4oNTzav3KaY1mSPd05u42veiWkXWmcSjK5yISMmmwPh5r9FBS +YmL9Yzt9fuzuOOpi9GyocY3h6YvJP8a1zZRCb92CRTzo3wno7wpVqVZHYUxJZHMQ +KD/Kvwn/xi8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBTrsxl588GlHKzcuh9morKb +adB4CDCCAUQGA1UdIwSCATswggE3gBTrsxl588GlHKzcuh9morKbadB4CKGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UxIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UxIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC +BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito +dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEuY3JsMD8GCWCG +SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D +TEFTRTEuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw +czIwMDIvcmVuZXdhbENMQVNFMS5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov +L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTEuaHRtbDBzBgNVHR8EbDBq +MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTEu +Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UxLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v +Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAK9Dr/drIyllq2tPMMi7JVBuK +Yn4VLenZMdMu9Ccj/1urxUq2ckCuU3T0vAW0xtnIyXf7t/k0f3gA+Nak5FI/LEpj +V4F1Wo7ojPsCwJTGKbqz3Bzosq/SLmJbGqmODszFV0VRFOlOHIilkfSj945RyKm+ +hjM+5i9Ibq9UkE6tsSU= +-----END CERTIFICATE----- + +IPS CLASE3 root +=============== + +MD5 Fingerprint=42:76:97:68:CF:A6:B4:38:24:AA:A1:1B:F2:67:DE:CA +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASE3 Certification Authority, CN=IPS CA CLASE3 Certification Authority/emailAddress=ips@mail.ips.es + Validity + Not Before: Dec 29 01:01:44 2001 GMT + Not After : Dec 27 01:01:44 2025 GMT + Subject: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASE3 Certification Authority, CN=IPS CA CLASE3 Certification Authority/emailAddress=ips@mail.ips.es + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ab:17:fe:0e:b0:c6:68:1b:53:f0:52:be:9f:fa: + da:fa:8b:13:04:bb:01:8f:32:d9:1f:8f:4d:ce:36: + 98:da:e4:00:44:8c:28:d8:13:44:2a:a4:6b:4e:17: + 24:42:9c:d3:88:a4:41:82:d6:23:fb:8b:c9:86:e5: + b9:a9:82:05:dc:f1:de:1f:e0:0c:99:55:98:f2:38: + ec:6c:9d:20:03:c0:ef:aa:a3:c6:64:04:51:2d:78: + 0d:a3:d2:a8:3a:d6:24:4c:e9:96:7a:18:ac:13:23: + 22:1b:7c:e8:31:11:b3:5f:09:aa:30:70:71:46:25: + 6b:49:71:80:2b:95:01:b2:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B8:93:FF:2E:CB:DC:2C:8E:A2:E7:7A:FE:36:51:21:A3:98:5B:0C:34 + X509v3 Authority Key Identifier: + keyid:B8:93:FF:2E:CB:DC:2C:8E:A2:E7:7A:FE:36:51:21:A3:98:5B:0C:34 + DirName:/C=ES/ST=Barcelona/L=Barcelona/O=IPS Internet publishing Services s.l./O=ips@mail.ips.es C.I.F. B-60929452/OU=IPS CA CLASE3 Certification Authority/CN=IPS CA CLASE3 Certification Authority/emailAddress=ips@mail.ips.es + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign, Encipher Only, Decipher Only + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping, Microsoft Individual Code Signing, Microsoft Commercial Code Signing, Microsoft Trust List Signing, Microsoft Encrypted File System + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:ips@mail.ips.es + X509v3 Issuer Alternative Name: + email:ips@mail.ips.es + Netscape Comment: + CLASE3 CA Certificate issued by http://www.ips.es/ + Netscape Base Url: + http://www.ips.es/ips2002/ + Netscape CA Revocation Url: + http://www.ips.es/ips2002/ips2002CLASE3.crl + Netscape Revocation Url: + http://www.ips.es/ips2002/revocationCLASE3.html? + Netscape Renewal Url: + http://www.ips.es/ips2002/renewalCLASE3.html? + Netscape CA Policy Url: + http://www.ips.es/ips2002/policyCLASE3.html + X509v3 CRL Distribution Points: + URI:http://www.ips.es/ips2002/ips2002CLASE3.crl + URI:http://wwwback.ips.es/ips2002/ips2002CLASE3.crl + + Authority Information Access: + OCSP - URI:http://ocsp.ips.es/ + + Signature Algorithm: sha1WithRSAEncryption + 17:65:5c:99:95:43:03:27:af:26:e5:eb:d0:b3:17:23:f7:43: + aa:c7:f0:7d:ec:0f:c6:a9:ae:ae:96:0f:76:29:1c:e2:06:2d: + 7e:26:c5:3c:fa:a1:c1:81:ce:53:b0:42:d1:97:57:1a:17:7e: + a4:51:61:c6:ee:e9:5e:ef:05:ba:eb:bd:0f:a7:92:6f:d8:a3: + 06:68:29:8e:79:f5:ff:bf:f9:a7:af:e4:b1:ce:c2:d1:80:42: + 27:05:04:34:f8:c3:7f:16:78:23:0c:07:24:f2:46:47:ad:3b: + 54:d0:af:d5:31:b2:af:7d:c8:ea:e9:d4:56:d9:0e:13:b2:c5: + 45:50 +-----BEGIN CERTIFICATE----- +MIIH6jCCB1OgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARIxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEuMCwGA1UECxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl +SVBTIENBIENMQVNFMyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEeMBwGCSqGSIb3 +DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMDE0NFoXDTI1MTIyNzAx +MDE0NFowggESMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFyY2Vsb25hMRIwEAYD +VQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5ldCBwdWJsaXNoaW5n +IFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlwcy5lcyBDLkkuRi4g +IEItNjA5Mjk0NTIxLjAsBgNVBAsTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxLjAsBgNVBAMTJUlQUyBDQSBDTEFTRTMgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxHjAcBgkqhkiG9w0BCQEWD2lwc0BtYWlsLmlwcy5lczCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxf+DrDGaBtT8FK+n/ra+osTBLsBjzLZ +H49NzjaY2uQARIwo2BNEKqRrThckQpzTiKRBgtYj+4vJhuW5qYIF3PHeH+AMmVWY +8jjsbJ0gA8DvqqPGZARRLXgNo9KoOtYkTOmWehisEyMiG3zoMRGzXwmqMHBxRiVr +SXGAK5UBsh8CAwEAAaOCBEowggRGMB0GA1UdDgQWBBS4k/8uy9wsjqLnev42USGj +mFsMNDCCAUQGA1UdIwSCATswggE3gBS4k/8uy9wsjqLnev42USGjmFsMNKGCARqk +ggEWMIIBEjELMAkGA1UEBhMCRVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UE +BxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJUFMgSW50ZXJuZXQgcHVibGlzaGluZyBT +ZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJpcHNAbWFpbC5pcHMuZXMgQy5JLkYuICBC +LTYwOTI5NDUyMS4wLAYDVQQLEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MS4wLAYDVQQDEyVJUFMgQ0EgQ0xBU0UzIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYD +VR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggr +BgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIB +FQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhC +AQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGB +D2lwc0BtYWlsLmlwcy5lczBBBglghkgBhvhCAQ0ENBYyQ0xBU0UzIENBIENlcnRp +ZmljYXRlIGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgEC +BBwWGmh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMDoGCWCGSAGG+EIBBAQtFito +dHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMuY3JsMD8GCWCG +SAGG+EIBAwQyFjBodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25D +TEFTRTMuaHRtbD8wPAYJYIZIAYb4QgEHBC8WLWh0dHA6Ly93d3cuaXBzLmVzL2lw +czIwMDIvcmVuZXdhbENMQVNFMy5odG1sPzA6BglghkgBhvhCAQgELRYraHR0cDov +L3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lDTEFTRTMuaHRtbDBzBgNVHR8EbDBq +MDGgL6AthitodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJDTEFTRTMu +Y3JsMDWgM6Axhi9odHRwOi8vd3d3YmFjay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAy +Q0xBU0UzLmNybDAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9v +Y3NwLmlwcy5lcy8wDQYJKoZIhvcNAQEFBQADgYEAF2VcmZVDAyevJuXr0LMXI/dD +qsfwfewPxqmurpYPdikc4gYtfibFPPqhwYHOU7BC0ZdXGhd+pFFhxu7pXu8Fuuu9 +D6eSb9ijBmgpjnn1/7/5p6/ksc7C0YBCJwUENPjDfxZ4IwwHJPJGR607VNCv1TGy +r33I6unUVtkOE7LFRVA= +-----END CERTIFICATE----- + +IPS CLASEA1 root +================ + +MD5 Fingerprint=0C:F8:9E:17:FC:D4:03:BD:E6:8D:9B:3C:05:87:FE:84 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASEA1 Certification Authority, CN=IPS CA CLASEA1 Certification Authority/emailAddress=ips@mail.ips.es + Validity + Not Before: Dec 29 01:05:32 2001 GMT + Not After : Dec 27 01:05:32 2025 GMT + Subject: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASEA1 Certification Authority, CN=IPS CA CLASEA1 Certification Authority/emailAddress=ips@mail.ips.es + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:30:d7:dc:d0:54:bd:35:4e:9f:c5:4c:82:ea: + d1:50:3c:47:98:fc:9b:69:9d:77:cd:6e:e0:3f:ee: + eb:32:5f:5f:9f:d2:d0:79:e5:95:73:44:21:32:e0: + 0a:db:9d:d7:ce:8d:ab:52:8b:2b:78:e0:9b:5b:7d: + f4:fd:6d:09:e5:ae:e1:6c:1d:07:23:a0:17:d1:f9: + 7d:a8:46:46:91:22:a8:b2:69:c6:ad:f7:f5:f5:94: + a1:30:94:bd:00:cc:44:7f:ee:c4:9e:c9:c1:e6:8f: + 0a:36:c1:fd:24:3d:01:a0:f5:7b:e2:7c:78:66:43: + 8b:4f:59:f2:9b:d9:fa:49:b3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 67:26:96:E7:A1:BF:D8:B5:03:9D:FE:3B:DC:FE:F2:8A:E6:15:DD:30 + X509v3 Authority Key Identifier: + keyid:67:26:96:E7:A1:BF:D8:B5:03:9D:FE:3B:DC:FE:F2:8A:E6:15:DD:30 + DirName:/C=ES/ST=Barcelona/L=Barcelona/O=IPS Internet publishing Services s.l./O=ips@mail.ips.es C.I.F. B-60929452/OU=IPS CA CLASEA1 Certification Authority/CN=IPS CA CLASEA1 Certification Authority/emailAddress=ips@mail.ips.es + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign, Encipher Only, Decipher Only + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping, Microsoft Individual Code Signing, Microsoft Commercial Code Signing, Microsoft Trust List Signing, Microsoft Encrypted File System + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:ips@mail.ips.es + X509v3 Issuer Alternative Name: + email:ips@mail.ips.es + Netscape Comment: + CLASEA1 CA Certificate issued by http://www.ips.es/ + Netscape Base Url: + http://www.ips.es/ips2002/ + Netscape CA Revocation Url: + http://www.ips.es/ips2002/ips2002CLASEA1.crl + Netscape Revocation Url: + http://www.ips.es/ips2002/revocationCLASEA1.html? + Netscape Renewal Url: + http://www.ips.es/ips2002/renewalCLASEA1.html? + Netscape CA Policy Url: + http://www.ips.es/ips2002/policyCLASEA1.html + X509v3 CRL Distribution Points: + URI:http://www.ips.es/ips2002/ips2002CLASEA1.crl + URI:http://wwwback.ips.es/ips2002/ips2002CLASEA1.crl + + Authority Information Access: + OCSP - URI:http://ocsp.ips.es/ + + Signature Algorithm: sha1WithRSAEncryption + 7e:ba:8a:ac:80:00:84:15:0a:d5:98:51:0c:64:c5:9c:02:58: + 83:66:ca:ad:1e:07:cd:7e:6a:da:80:07:df:03:34:4a:1c:93: + c4:4b:58:20:35:36:71:ed:a2:0a:35:12:a5:a6:65:a7:85:69: + 0a:0e:e3:61:ee:ea:be:28:93:33:d5:ec:e8:be:c4:db:5f:7f: + a8:f9:63:31:c8:6b:96:e2:29:c2:5b:a0:e7:97:36:9d:77:5e: + 31:6b:fe:d3:a7:db:2a:db:db:96:8b:1f:66:de:b6:03:c0:2b: + b3:78:d6:55:07:e5:8f:39:50:de:07:23:72:e6:bd:20:14:4b: + b4:86 +-----BEGIN CERTIFICATE----- +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTEgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUExIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNTMyWhcNMjUxMjI3 +MDEwNTMyWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsw19zQVL01Tp/FTILq0VA8R5j8 +m2mdd81u4D/u6zJfX5/S0HnllXNEITLgCtud186Nq1KLK3jgm1t99P1tCeWu4Wwd +ByOgF9H5fahGRpEiqLJpxq339fWUoTCUvQDMRH/uxJ7JweaPCjbB/SQ9AaD1e+J8 +eGZDi09Z8pvZ+kmzAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUZyaW56G/2LUDnf47 +3P7yiuYV3TAwggFGBgNVHSMEggE9MIIBOYAUZyaW56G/2LUDnf473P7yiuYV3TCh +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTEgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUExIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMSBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG +SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC +AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMS5j +cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 +b2NhdGlvbkNMQVNFQTEuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu +aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTEuaHRtbD8wOwYJYIZIAYb4QgEI +BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMS5odG1s +MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz +MjAwMkNMQVNFQTEuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0xBU0VBMS5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAH66iqyA +AIQVCtWYUQxkxZwCWINmyq0eB81+atqAB98DNEock8RLWCA1NnHtogo1EqWmZaeF +aQoO42Hu6r4okzPV7Oi+xNtff6j5YzHIa5biKcJboOeXNp13XjFr/tOn2yrb25aL +H2betgPAK7N41lUH5Y85UN4HI3LmvSAUS7SG +-----END CERTIFICATE----- + +IPS CLASEA3 root +================ + +MD5 Fingerprint=06:F9:EB:EC:CC:56:9D:88:BA:90:F5:BA:B0:1A:E0:02 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASEA3 Certification Authority, CN=IPS CA CLASEA3 Certification Authority/emailAddress=ips@mail.ips.es + Validity + Not Before: Dec 29 01:07:50 2001 GMT + Not After : Dec 27 01:07:50 2025 GMT + Subject: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA CLASEA3 Certification Authority, CN=IPS CA CLASEA3 Certification Authority/emailAddress=ips@mail.ips.es + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ee:80:00:f6:1a:64:2e:ad:6a:c8:83:b1:8b:a7: + ee:8f:d9:b6:db:cd:1b:bb:86:06:22:76:33:0c:12: + 6d:48:56:61:d2:dc:82:25:62:2f:9f:d2:69:30:65: + 03:42:23:58:bc:47:dc:6b:d6:75:5d:17:3c:e1:ff: + f2:58:67:79:a0:c1:81:b1:d4:56:a2:f2:8d:11:99: + fd:f6:7d:f1:c7:c4:5e:02:2a:9a:e2:4a:b5:13:8a: + 00:fd:8c:77:86:e6:d7:94:f5:20:75:2e:0e:4c:bf: + 74:c4:3f:81:3e:83:b4:a3:38:36:29:e7:e8:2a:f5: + 8c:88:41:aa:80:a6:e3:6c:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1E:9F:57:50:47:B6:61:93:39:D3:2C:FC:DA:5D:3D:05:75:B7:99:02 + X509v3 Authority Key Identifier: + keyid:1E:9F:57:50:47:B6:61:93:39:D3:2C:FC:DA:5D:3D:05:75:B7:99:02 + DirName:/C=ES/ST=Barcelona/L=Barcelona/O=IPS Internet publishing Services s.l./O=ips@mail.ips.es C.I.F. B-60929452/OU=IPS CA CLASEA3 Certification Authority/CN=IPS CA CLASEA3 Certification Authority/emailAddress=ips@mail.ips.es + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign, Encipher Only, Decipher Only + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping, Microsoft Individual Code Signing, Microsoft Commercial Code Signing, Microsoft Trust List Signing, Microsoft Encrypted File System + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:ips@mail.ips.es + X509v3 Issuer Alternative Name: + email:ips@mail.ips.es + Netscape Comment: + CLASEA3 CA Certificate issued by http://www.ips.es/ + Netscape Base Url: + http://www.ips.es/ips2002/ + Netscape CA Revocation Url: + http://www.ips.es/ips2002/ips2002CLASEA3.crl + Netscape Revocation Url: + http://www.ips.es/ips2002/revocationCLASEA3.html? + Netscape Renewal Url: + http://www.ips.es/ips2002/renewalCLASEA3.html? + Netscape CA Policy Url: + http://www.ips.es/ips2002/policyCLASEA3.html + X509v3 CRL Distribution Points: + URI:http://www.ips.es/ips2002/ips2002CLASEA3.crl + URI:http://wwwback.ips.es/ips2002/ips2002CLASEA3.crl + + Authority Information Access: + OCSP - URI:http://ocsp.ips.es/ + + Signature Algorithm: sha1WithRSAEncryption + 4a:3d:20:47:1a:da:89:f4:7a:2b:31:79:ec:01:c0:cc:01:f5: + d6:c1:fc:c8:c3:f3:50:02:51:90:58:2a:9f:e7:35:09:5b:30: + 0a:81:00:25:47:af:d4:0f:0e:9e:60:26:a8:95:a7:83:08:df: + 2d:ac:e9:0e:f7:9c:c8:9f:cb:93:45:f1:ba:6a:c6:67:51:4a: + 69:4f:6b:fe:7d:0b:2f:52:29:c2:50:ad:24:44:ed:23:b3:48: + cb:44:40:c1:03:95:0c:0a:78:06:12:01:f5:91:31:2d:49:8d: + bb:3f:45:4e:2c:e0:e8:cd:b5:c9:14:15:0c:e3:07:83:9b:26: + 75:ef +-----BEGIN CERTIFICATE----- +MIIH9zCCB2CgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCARQxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjEvMC0GA1UECxMm +SVBTIENBIENMQVNFQTMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxLzAtBgNVBAMT +JklQUyBDQSBDTEFTRUEzIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4wHAYJKoZI +hvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMwHhcNMDExMjI5MDEwNzUwWhcNMjUxMjI3 +MDEwNzUwWjCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXMw +gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO6AAPYaZC6tasiDsYun7o/ZttvN +G7uGBiJ2MwwSbUhWYdLcgiViL5/SaTBlA0IjWLxH3GvWdV0XPOH/8lhneaDBgbHU +VqLyjRGZ/fZ98cfEXgIqmuJKtROKAP2Md4bm15T1IHUuDky/dMQ/gT6DtKM4Ninn +6Cr1jIhBqoCm42zvAgMBAAGjggRTMIIETzAdBgNVHQ4EFgQUHp9XUEe2YZM50yz8 +2l09BXW3mQIwggFGBgNVHSMEggE9MIIBOYAUHp9XUEe2YZM50yz82l09BXW3mQKh +ggEcpIIBGDCCARQxCzAJBgNVBAYTAkVTMRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQ +BgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UEChMlSVBTIEludGVybmV0IHB1Ymxpc2hp +bmcgU2VydmljZXMgcy5sLjErMCkGA1UEChQiaXBzQG1haWwuaXBzLmVzIEMuSS5G +LiAgQi02MDkyOTQ1MjEvMC0GA1UECxMmSVBTIENBIENMQVNFQTMgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxLzAtBgNVBAMTJklQUyBDQSBDTEFTRUEzIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOC +AQAwDAYDVR0TBAUwAwEB/zAMBgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUF +BwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYB +BAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglg +hkgBhvhCAQEEBAMCAAcwGgYDVR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1Ud +EgQTMBGBD2lwc0BtYWlsLmlwcy5lczBCBglghkgBhvhCAQ0ENRYzQ0xBU0VBMyBD +QSBDZXJ0aWZpY2F0ZSBpc3N1ZWQgYnkgaHR0cDovL3d3dy5pcHMuZXMvMCkGCWCG +SAGG+EIBAgQcFhpodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyLzA7BglghkgBhvhC +AQQELhYsaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyQ0xBU0VBMy5j +cmwwQAYJYIZIAYb4QgEDBDMWMWh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcmV2 +b2NhdGlvbkNMQVNFQTMuaHRtbD8wPQYJYIZIAYb4QgEHBDAWLmh0dHA6Ly93d3cu +aXBzLmVzL2lwczIwMDIvcmVuZXdhbENMQVNFQTMuaHRtbD8wOwYJYIZIAYb4QgEI +BC4WLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvcG9saWN5Q0xBU0VBMy5odG1s +MHUGA1UdHwRuMGwwMqAwoC6GLGh0dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvaXBz +MjAwMkNMQVNFQTMuY3JsMDagNKAyhjBodHRwOi8vd3d3YmFjay5pcHMuZXMvaXBz +MjAwMi9pcHMyMDAyQ0xBU0VBMy5jcmwwLwYIKwYBBQUHAQEEIzAhMB8GCCsGAQUF +BzABhhNodHRwOi8vb2NzcC5pcHMuZXMvMA0GCSqGSIb3DQEBBQUAA4GBAEo9IEca +2on0eisxeewBwMwB9dbB/MjD81ACUZBYKp/nNQlbMAqBACVHr9QPDp5gJqiVp4MI +3y2s6Q73nMify5NF8bpqxmdRSmlPa/59Cy9SKcJQrSRE7SOzSMtEQMEDlQwKeAYS +AfWRMS1Jjbs/RU4s4OjNtckUFQzjB4ObJnXv +-----END CERTIFICATE----- + +IPS Servidores root +=================== + +MD5 Fingerprint=7B:B5:08:99:9A:8C:18:BF:85:27:7D:0E:AE:DA:B2:AB +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 0 (0x0) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ES, ST=BARCELONA, L=BARCELONA, O=IPS Seguridad CA, OU=Certificaciones, CN=IPS SERVIDORES/emailAddress=ips@mail.ips.es + Validity + Not Before: Jan 1 23:21:07 1998 GMT + Not After : Dec 29 23:21:07 2009 GMT + Subject: C=ES, ST=BARCELONA, L=BARCELONA, O=IPS Seguridad CA, OU=Certificaciones, CN=IPS SERVIDORES/emailAddress=ips@mail.ips.es + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ac:4f:52:74:9f:39:ea:8e:dc:25:c4:bc:98:5d: + 98:64:24:09:3c:21:b3:cc:19:b5:8e:94:8e:87:d1: + f8:37:3e:a1:c8:2d:58:a4:80:35:5b:a1:75:6c:1d: + 45:0c:1f:61:63:6a:5e:6f:9b:0a:4c:c1:c8:b8:61: + 23:35:81:ff:fe:ac:78:70:2d:68:e1:3a:07:98:95: + 02:54:dd:cd:23:b7:80:53:d7:c8:37:45:72:06:24: + 12:ba:13:61:21:8a:6e:75:28:e0:c5:0f:34:fd:36: + d8:45:7f:e1:b8:36:ef:b3:e1:c6:20:8e:e8:b4:38: + bc:e1:3e:f6:11:de:8c:9d:01 + Exponent: 65537 (0x10001) + Signature Algorithm: md5WithRSAEncryption + 2c:f3:c3:79:58:24:de:c6:3b:d1:e0:42:69:b8:ee:64:b3:3d: + 62:01:b9:b3:84:df:23:7d:dd:98:cf:10:a9:fe:00:d8:22:96: + 05:13:07:54:57:c5:a7:de:cb:d9:b8:88:42:f6:99:db:14:77: + 1f:b6:fe:25:3d:e1:a2:3e:03:a9:81:d2:2d:6c:47:f5:96:46: + 8c:22:ab:c8:cc:0d:0e:97:5e:8b:41:b4:3b:c4:0a:06:40:1d: + dd:46:f4:01:dd:ba:82:2e:3c:3d:78:70:9e:7c:18:d0:ab:f8: + b8:77:07:46:71:f1:ca:0b:63:5c:6a:f9:72:94:d5:01:4f:a0: + db:42 +-----BEGIN CERTIFICATE----- +MIICtzCCAiACAQAwDQYJKoZIhvcNAQEEBQAwgaMxCzAJBgNVBAYTAkVTMRIwEAYD +VQQIEwlCQVJDRUxPTkExEjAQBgNVBAcTCUJBUkNFTE9OQTEZMBcGA1UEChMQSVBT +IFNlZ3VyaWRhZCBDQTEYMBYGA1UECxMPQ2VydGlmaWNhY2lvbmVzMRcwFQYDVQQD +Ew5JUFMgU0VSVklET1JFUzEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVz +MB4XDTk4MDEwMTIzMjEwN1oXDTA5MTIyOTIzMjEwN1owgaMxCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCQVJDRUxPTkExEjAQBgNVBAcTCUJBUkNFTE9OQTEZMBcGA1UE +ChMQSVBTIFNlZ3VyaWRhZCBDQTEYMBYGA1UECxMPQ2VydGlmaWNhY2lvbmVzMRcw +FQYDVQQDEw5JUFMgU0VSVklET1JFUzEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwu +aXBzLmVzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsT1J0nznqjtwlxLyY +XZhkJAk8IbPMGbWOlI6H0fg3PqHILVikgDVboXVsHUUMH2Fjal5vmwpMwci4YSM1 +gf/+rHhwLWjhOgeYlQJU3c0jt4BT18g3RXIGJBK6E2Ehim51KODFDzT9NthFf+G4 +Nu+z4cYgjui0OLzhPvYR3oydAQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBACzzw3lY +JN7GO9HgQmm47mSzPWIBubOE3yN93ZjPEKn+ANgilgUTB1RXxafey9m4iEL2mdsU +dx+2/iU94aI+A6mB0i1sR/WWRowiq8jMDQ6XXotBtDvECgZAHd1G9AHduoIuPD14 +cJ58GNCr+Lh3B0Zx8coLY1xq+XKU1QFPoNtC +-----END CERTIFICATE----- + +IPS Timestamping root +===================== + +MD5 Fingerprint=2E:03:FD:C5:F5:D7:2B:94:64:C1:BE:89:31:F1:16:9B +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA Timestamping Certification Authority, CN=IPS CA Timestamping Certification Authority/emailAddress=ips@mail.ips.es + Validity + Not Before: Dec 29 01:10:18 2001 GMT + Not After : Dec 27 01:10:18 2025 GMT + Subject: C=ES, ST=Barcelona, L=Barcelona, O=IPS Internet publishing Services s.l., O=ips@mail.ips.es C.I.F. B-60929452, OU=IPS CA Timestamping Certification Authority, CN=IPS CA Timestamping Certification Authority/emailAddress=ips@mail.ips.es + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bc:b8:ee:56:a5:9a:8c:e6:36:c9:c2:62:a0:66: + 81:8d:1a:d5:7a:d2:73:9f:0e:84:64:ba:95:b4:90: + a7:78:af:ca:fe:54:61:5b:ce:b2:20:57:01:ae:44: + 92:43:10:38:11:f7:68:fc:17:40:a5:68:27:32:3b: + c4:a7:e6:42:71:c5:99:ef:76:ff:2b:95:24:f5:49: + 92:18:68:ca:00:b5:a4:5a:2f:6e:cb:d6:1b:2c:0d: + 54:67:6b:7a:29:a1:58:ab:a2:5a:00:d6:5b:bb:18: + c2:df:f6:1e:13:56:76:9b:a5:68:e2:98:ce:c6:03: + 8a:34:db:4c:83:41:a6:a9:a3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8B:D0:10:50:09:81:F2:9D:09:D5:0E:60:78:03:22:A2:3F:C8:CA:66 + X509v3 Authority Key Identifier: + keyid:8B:D0:10:50:09:81:F2:9D:09:D5:0E:60:78:03:22:A2:3F:C8:CA:66 + DirName:/C=ES/ST=Barcelona/L=Barcelona/O=IPS Internet publishing Services s.l./O=ips@mail.ips.es C.I.F. B-60929452/OU=IPS CA Timestamping Certification Authority/CN=IPS CA Timestamping Certification Authority/emailAddress=ips@mail.ips.es + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Key Agreement, Certificate Sign, CRL Sign, Encipher Only, Decipher Only + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, E-mail Protection, Time Stamping, Microsoft Individual Code Signing, Microsoft Commercial Code Signing, Microsoft Trust List Signing, Microsoft Encrypted File System + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:ips@mail.ips.es + X509v3 Issuer Alternative Name: + email:ips@mail.ips.es + Netscape Comment: + Timestamping CA Certificate issued by http://www.ips.es/ + Netscape Base Url: + http://www.ips.es/ips2002/ + Netscape CA Revocation Url: + http://www.ips.es/ips2002/ips2002Timestamping.crl + Netscape Revocation Url: + http://www.ips.es/ips2002/revocationTimestamping.html? + Netscape Renewal Url: + http://www.ips.es/ips2002/renewalTimestamping.html? + Netscape CA Policy Url: + http://www.ips.es/ips2002/policyTimestamping.html + X509v3 CRL Distribution Points: + URI:http://www.ips.es/ips2002/ips2002Timestamping.crl + URI:http://wwwback.ips.es/ips2002/ips2002Timestamping.crl + + Authority Information Access: + OCSP - URI:http://ocsp.ips.es/ + + Signature Algorithm: sha1WithRSAEncryption + 65:ba:c1:cc:00:1a:95:91:ca:e9:6c:3a:bf:3a:1e:14:08:7c: + fb:83:ee:6b:62:51:d3:33:91:b5:60:79:7e:04:d8:5d:79:37: + e8:c3:5b:b0:c4:67:2d:68:5a:b2:5f:0e:0a:fa:cd:3f:3a:45: + a1:ea:36:cf:26:1e:a7:11:28:c5:94:8f:84:4c:53:08:c5:93: + b3:fc:e2:7f:f5:8d:f3:b1:a9:85:5f:88:de:91:96:ee:17:5b: + ae:a5:ea:70:65:78:2c:21:64:01:95:ce:ce:4c:3e:50:f4:b6: + 59:cb:63:8d:b6:bd:18:d4:87:4a:5f:dc:ef:e9:56:f0:0a:0c: + e8:75 +-----BEGIN CERTIFICATE----- +MIIIODCCB6GgAwIBAgIBADANBgkqhkiG9w0BAQUFADCCAR4xCzAJBgNVBAYTAkVT +MRIwEAYDVQQIEwlCYXJjZWxvbmExEjAQBgNVBAcTCUJhcmNlbG9uYTEuMCwGA1UE +ChMlSVBTIEludGVybmV0IHB1Ymxpc2hpbmcgU2VydmljZXMgcy5sLjErMCkGA1UE +ChQiaXBzQG1haWwuaXBzLmVzIEMuSS5GLiAgQi02MDkyOTQ1MjE0MDIGA1UECxMr +SVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE0MDIG +A1UEAxMrSVBTIENBIFRpbWVzdGFtcGluZyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEeMBwGCSqGSIb3DQEJARYPaXBzQG1haWwuaXBzLmVzMB4XDTAxMTIyOTAxMTAx +OFoXDTI1MTIyNzAxMTAxOFowggEeMQswCQYDVQQGEwJFUzESMBAGA1UECBMJQmFy +Y2Vsb25hMRIwEAYDVQQHEwlCYXJjZWxvbmExLjAsBgNVBAoTJUlQUyBJbnRlcm5l +dCBwdWJsaXNoaW5nIFNlcnZpY2VzIHMubC4xKzApBgNVBAoUImlwc0BtYWlsLmlw +cy5lcyBDLkkuRi4gIEItNjA5Mjk0NTIxNDAyBgNVBAsTK0lQUyBDQSBUaW1lc3Rh +bXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxNDAyBgNVBAMTK0lQUyBDQSBU +aW1lc3RhbXBpbmcgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHjAcBgkqhkiG9w0B +CQEWD2lwc0BtYWlsLmlwcy5lczCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA +vLjuVqWajOY2ycJioGaBjRrVetJznw6EZLqVtJCneK/K/lRhW86yIFcBrkSSQxA4 +Efdo/BdApWgnMjvEp+ZCccWZ73b/K5Uk9UmSGGjKALWkWi9uy9YbLA1UZ2t6KaFY +q6JaANZbuxjC3/YeE1Z2m6Vo4pjOxgOKNNtMg0GmqaMCAwEAAaOCBIAwggR8MB0G +A1UdDgQWBBSL0BBQCYHynQnVDmB4AyKiP8jKZjCCAVAGA1UdIwSCAUcwggFDgBSL +0BBQCYHynQnVDmB4AyKiP8jKZqGCASakggEiMIIBHjELMAkGA1UEBhMCRVMxEjAQ +BgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMS4wLAYDVQQKEyVJ +UFMgSW50ZXJuZXQgcHVibGlzaGluZyBTZXJ2aWNlcyBzLmwuMSswKQYDVQQKFCJp +cHNAbWFpbC5pcHMuZXMgQy5JLkYuICBCLTYwOTI5NDUyMTQwMgYDVQQLEytJUFMg +Q0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MTQwMgYDVQQD +EytJUFMgQ0EgVGltZXN0YW1waW5nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MR4w +HAYJKoZIhvcNAQkBFg9pcHNAbWFpbC5pcHMuZXOCAQAwDAYDVR0TBAUwAwEB/zAM +BgNVHQ8EBQMDB/+AMGsGA1UdJQRkMGIGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIB +FgYKKwYBBAGCNwoDAQYKKwYBBAGCNwoDBDARBglghkgBhvhCAQEEBAMCAAcwGgYD +VR0RBBMwEYEPaXBzQG1haWwuaXBzLmVzMBoGA1UdEgQTMBGBD2lwc0BtYWlsLmlw +cy5lczBHBglghkgBhvhCAQ0EOhY4VGltZXN0YW1waW5nIENBIENlcnRpZmljYXRl +IGlzc3VlZCBieSBodHRwOi8vd3d3Lmlwcy5lcy8wKQYJYIZIAYb4QgECBBwWGmh0 +dHA6Ly93d3cuaXBzLmVzL2lwczIwMDIvMEAGCWCGSAGG+EIBBAQzFjFodHRwOi8v +d3d3Lmlwcy5lcy9pcHMyMDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMEUGCWCG +SAGG+EIBAwQ4FjZodHRwOi8vd3d3Lmlwcy5lcy9pcHMyMDAyL3Jldm9jYXRpb25U +aW1lc3RhbXBpbmcuaHRtbD8wQgYJYIZIAYb4QgEHBDUWM2h0dHA6Ly93d3cuaXBz +LmVzL2lwczIwMDIvcmVuZXdhbFRpbWVzdGFtcGluZy5odG1sPzBABglghkgBhvhC +AQgEMxYxaHR0cDovL3d3dy5pcHMuZXMvaXBzMjAwMi9wb2xpY3lUaW1lc3RhbXBp +bmcuaHRtbDB/BgNVHR8EeDB2MDegNaAzhjFodHRwOi8vd3d3Lmlwcy5lcy9pcHMy +MDAyL2lwczIwMDJUaW1lc3RhbXBpbmcuY3JsMDugOaA3hjVodHRwOi8vd3d3YmFj +ay5pcHMuZXMvaXBzMjAwMi9pcHMyMDAyVGltZXN0YW1waW5nLmNybDAvBggrBgEF +BQcBAQQjMCEwHwYIKwYBBQUHMAGGE2h0dHA6Ly9vY3NwLmlwcy5lcy8wDQYJKoZI +hvcNAQEFBQADgYEAZbrBzAAalZHK6Ww6vzoeFAh8+4Pua2JR0zORtWB5fgTYXXk3 +6MNbsMRnLWhasl8OCvrNPzpFoeo2zyYepxEoxZSPhExTCMWTs/zif/WN87GphV+I +3pGW7hdbrqXqcGV4LCFkAZXOzkw+UPS2Wctjjba9GNSHSl/c7+lW8AoM6HU= +-----END CERTIFICATE----- + +QuoVadis Root CA +================ + +MD5 Fingerprint=27:DE:36:FE:72:B7:00:03:00:9D:F4:F0:1E:6C:04:24 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 985026699 (0x3ab6508b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=BM, O=QuoVadis Limited, OU=Root Certification Authority, CN=QuoVadis Root Certification Authority + Validity + Not Before: Mar 19 18:33:33 2001 GMT + Not After : Mar 17 18:33:33 2021 GMT + Subject: C=BM, O=QuoVadis Limited, OU=Root Certification Authority, CN=QuoVadis Root Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bf:61:b5:95:53:ba:57:fc:fa:f2:67:0b:3a:1a: + df:11:80:64:95:b4:d1:bc:cd:7a:cf:f6:29:96:2e: + 24:54:40:24:38:f7:1a:85:dc:58:4c:cb:a4:27:42: + 97:d0:9f:83:8a:c3:e4:06:03:5b:00:a5:51:1e:70: + 04:74:e2:c1:d4:3a:ab:d7:ad:3b:07:18:05:8e:fd: + 83:ac:ea:66:d9:18:1b:68:8a:f5:57:1a:98:ba:f5: + ed:76:3d:7c:d9:de:94:6a:3b:4b:17:c1:d5:8f:bd: + 65:38:3a:95:d0:3d:55:36:4e:df:79:57:31:2a:1e: + d8:59:65:49:58:20:98:7e:ab:5f:7e:9f:e9:d6:4d: + ec:83:74:a9:c7:6c:d8:ee:29:4a:85:2a:06:14:f9: + 54:e6:d3:da:65:07:8b:63:37:12:d7:d0:ec:c3:7b: + 20:41:44:a3:ed:cb:a0:17:e1:71:65:ce:1d:66:31: + f7:76:01:19:c8:7d:03:58:b6:95:49:1d:a6:12:26: + e8:c6:0c:76:e0:e3:66:cb:ea:5d:a6:26:ee:e5:cc: + 5f:bd:67:a7:01:27:0e:a2:ca:54:c5:b1:7a:95:1d: + 71:1e:4a:29:8a:03:dc:6a:45:c1:a4:19:5e:6f:36: + cd:c3:a2:b0:b7:fe:5c:38:e2:52:bc:f8:44:43:e6: + 90:bb + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:https://ocsp.quovadisoffshore.com + + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.8024.0.1 + User Notice: + Explicit Text: Reliance on the QuoVadis Root Certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certification practices, and the QuoVadis Certificate Policy. + CPS: http://www.quovadis.bm + + X509v3 Subject Key Identifier: + 8B:4B:6D:ED:D3:29:B9:06:19:EC:39:39:A9:F0:97:84:6A:CB:EF:DF + X509v3 Authority Key Identifier: + keyid:8B:4B:6D:ED:D3:29:B9:06:19:EC:39:39:A9:F0:97:84:6A:CB:EF:DF + DirName:/C=BM/O=QuoVadis Limited/OU=Root Certification Authority/CN=QuoVadis Root Certification Authority + serial:3A:B6:50:8B + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 8a:d4:14:b5:fe:f4:9a:92:a7:19:d4:a4:7e:72:18:8f:d9:68: + 7c:52:24:dd:67:6f:39:7a:c4:aa:5e:3d:e2:58:b0:4d:70:98: + 84:61:e8:1b:e3:69:18:0e:ce:fb:47:50:a0:4e:ff:f0:24:1f: + bd:b2:ce:f5:27:fc:ec:2f:53:aa:73:7b:03:3d:74:6e:e6:16: + 9e:eb:a5:2e:c4:bf:56:27:50:2b:62:ba:be:4b:1c:3c:55:5c: + 41:1d:24:be:82:20:47:5d:d5:44:7e:7a:16:68:df:7d:4d:51: + 70:78:57:1d:33:1e:fd:02:99:9c:0c:cd:0a:05:4f:c7:bb:8e: + a4:75:fa:4a:6d:b1:80:8e:09:56:b9:9c:1a:60:fe:5d:c1:d7: + 7a:dc:11:78:d0:d6:5d:c1:b7:d5:ad:32:99:03:3a:8a:cc:54: + 25:39:31:81:7b:13:22:51:ba:46:6c:a1:bb:9e:fa:04:6c:49: + 26:74:8f:d2:73:eb:cc:30:a2:e6:ea:59:22:87:f8:97:f5:0e: + fd:ea:cc:92:a4:16:c4:52:18:ea:21:ce:b1:f1:e6:84:81:e5: + ba:a9:86:28:f2:43:5a:5d:12:9d:ac:1e:d9:a8:e5:0a:6a:a7: + 7f:a0:87:29:cf:f2:89:4d:d4:ec:c5:e2:e6:7a:d0:36:23:8a: + 4a:74:36:f9 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- + +Security Communication Root CA +============================== + +MD5 Fingerprint=F1:BC:63:6A:54:E0:B5:27:F5:CD:E7:1A:E3:4D:6E:4A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=JP, O=SECOM Trust.net, OU=Security Communication RootCA1 + Validity + Not Before: Sep 30 04:20:49 2003 GMT + Not After : Sep 30 04:20:49 2023 GMT + Subject: C=JP, O=SECOM Trust.net, OU=Security Communication RootCA1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b3:b3:fe:7f:d3:6d:b1:ef:16:7c:57:a5:0c:6d: + 76:8a:2f:4b:bf:64:fb:4c:ee:8a:f0:f3:29:7c:f5: + ff:ee:2a:e0:e9:e9:ba:5b:64:22:9a:9a:6f:2c:3a: + 26:69:51:05:99:26:dc:d5:1c:6a:71:c6:9a:7d:1e: + 9d:dd:7c:6c:c6:8c:67:67:4a:3e:f8:71:b0:19:27: + a9:09:0c:a6:95:bf:4b:8c:0c:fa:55:98:3b:d8:e8: + 22:a1:4b:71:38:79:ac:97:92:69:b3:89:7e:ea:21: + 68:06:98:14:96:87:d2:61:36:bc:6d:27:56:9e:57: + ee:c0:c0:56:fd:32:cf:a4:d9:8e:c2:23:d7:8d:a8: + f3:d8:25:ac:97:e4:70:38:f4:b6:3a:b4:9d:3b:97: + 26:43:a3:a1:bc:49:59:72:4c:23:30:87:01:58:f6: + 4e:be:1c:68:56:66:af:cd:41:5d:c8:b3:4d:2a:55: + 46:ab:1f:da:1e:e2:40:3d:db:cd:7d:b9:92:80:9c: + 37:dd:0c:96:64:9d:dc:22:f7:64:8b:df:61:de:15: + 94:52:15:a0:7d:52:c9:4b:a8:21:c9:c6:b1:ed:cb: + c3:95:60:d1:0f:f0:ab:70:f8:df:cb:4d:7e:ec:d6: + fa:ab:d9:bd:7f:54:f2:a5:e9:79:fa:d9:d6:76:24: + 28:73 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + A0:73:49:99:68:DC:85:5B:65:E3:9B:28:2F:57:9F:BD:33:BC:07:48 + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 68:40:a9:a8:bb:e4:4f:5d:79:b3:05:b5:17:b3:60:13:eb:c6: + 92:5d:e0:d1:d3:6a:fe:fb:be:9b:6d:bf:c7:05:6d:59:20:c4: + 1c:f0:b7:da:84:58:02:63:fa:48:16:ef:4f:a5:0b:f7:4a:98: + f2:3f:9e:1b:ad:47:6b:63:ce:08:47:eb:52:3f:78:9c:af:4d: + ae:f8:d5:4f:cf:9a:98:2a:10:41:39:52:c4:dd:d9:9b:0e:ef: + 93:01:ae:b2:2e:ca:68:42:24:42:6c:b0:b3:3a:3e:cd:e9:da: + 48:c4:15:cb:e9:f9:07:0f:92:50:49:8a:dd:31:97:5f:c9:e9: + 37:aa:3b:59:65:97:94:32:c9:b3:9f:3e:3a:62:58:c5:49:ad: + 62:0e:71:a5:32:aa:2f:c6:89:76:43:40:13:13:67:3d:a2:54: + 25:10:cb:f1:3a:f2:d9:fa:db:49:56:bb:a6:fe:a7:41:35:c3: + e0:88:61:c9:88:c7:df:36:10:22:98:59:ea:b0:4a:fb:56:16: + 73:6e:ac:4d:f7:22:a1:4f:ad:1d:7a:2d:45:27:e5:30:c1:5e: + f2:da:13:cb:25:42:51:95:47:03:8c:6c:21:cc:74:42:ed:53: + ff:33:8b:8f:0f:57:01:16:2f:cf:a6:ee:c9:70:22:14:bd:fd: + be:6c:0b:03 +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 1 Root CA +====================== + +MD5 Fingerprint=33:B7:84:F5:5F:27:D7:68:27:DE:14:DE:12:2A:ED:6F +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 36 (0x24) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=FI, O=Sonera, CN=Sonera Class1 CA + Validity + Not Before: Apr 6 10:49:13 2001 GMT + Not After : Apr 6 10:49:13 2021 GMT + Subject: C=FI, O=Sonera, CN=Sonera Class1 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b5:89:1f:2b:4f:67:0a:79:ff:c5:1e:f8:7f:3c: + ed:d1:7e:da:b0:cd:6d:2f:36:ac:34:c6:db:d9:64: + 17:08:63:30:33:22:8a:4c:ee:8e:bb:0f:0d:42:55: + c9:9d:2e:a5:ef:f7:a7:8c:c3:ab:b9:97:cb:8e:ef: + 3f:15:67:a8:82:72:63:53:0f:41:8c:7d:10:95:24: + a1:5a:a5:06:fa:92:57:9d:fa:a5:01:f2:75:e9:1f: + bc:56:26:52:4e:78:19:65:58:55:03:58:c0:14:ae: + 8c:7c:55:5f:70:5b:77:23:06:36:97:f3:24:b5:9a: + 46:95:e4:df:0d:0b:05:45:e5:d1:f2:1d:82:bb:c6: + 13:e0:fe:aa:7a:fd:69:30:94:f3:d2:45:85:fc:f2: + 32:5b:32:de:e8:6c:5d:1f:cb:a4:22:74:b0:80:8e: + 5d:94:f7:06:00:4b:a9:d4:5e:2e:35:50:09:f3:80: + 97:f4:0c:17:ae:39:d8:5f:cd:33:c1:1c:ca:89:c2: + 22:f7:45:12:ed:5e:12:93:9d:63:ab:82:2e:b9:eb: + 42:41:44:cb:4a:1a:00:82:0d:9e:f9:8b:57:3e:4c: + c7:17:ed:2c:8b:72:33:5f:72:7a:38:56:d5:e6:d9: + ae:05:1a:1d:75:45:b1:cb:a5:25:1c:12:57:36:fd: + 22:37 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 47:E2:0C:8B:F6:53:88:52 + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 8b:1a:b2:c9:5d:61:b4:e1:b9:2b:b9:53:d1:b2:85:9d:77:8e: + 16:ee:11:3d:db:c2:63:d9:5b:97:65:fb:12:67:d8:2a:5c:b6: + ab:e5:5e:c3:b7:16:2f:c8:e8:ab:1d:8a:fd:ab:1a:7c:d5:5f: + 63:cf:dc:b0:dd:77:b9:a8:e6:d2:22:38:87:07:14:d9:ff:be: + 56:b5:fd:07:0e:3c:55:ca:16:cc:a7:a6:77:37:fb:db:5c:1f: + 4e:59:06:87:a3:03:43:f5:16:ab:b7:84:bd:4e:ef:9f:31:37: + f0:46:f1:40:b6:d1:0c:a5:64:f8:63:5e:21:db:55:4e:4f:31: + 76:9c:10:61:8e:b6:53:3a:a3:11:be:af:6d:7c:1e:bd:ae:2d: + e2:0c:69:c7:85:53:68:a2:61:ba:c5:3e:b4:79:54:78:9e:0a: + c7:02:be:62:d1:11:82:4b:65:2f:91:5a:c2:a8:87:b1:56:68: + 94:79:f9:25:f7:c1:d5:ae:1a:b8:bb:3d:8f:a9:8a:38:15:f7: + 73:d0:5a:60:d1:80:b0:f0:dc:d5:50:cd:4e:ee:92:48:69:ed: + b2:23:1e:30:cc:c8:94:c8:b6:f5:3b:86:7f:3f:a6:2e:9f:f6: + 3e:2c:b5:92:96:3e:df:2c:93:8a:ff:81:8c:0f:0f:59:21:19: + 57:bd:55:9a +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx +MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG +29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk +oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk +3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL +qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN +nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX +ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H +DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO +TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv +kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w +zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== + +MD5 Fingerprint=A3:EC:75:0F:2E:88:DF:FA:48:01:4E:0B:5C:48:6F:FB +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 29 (0x1d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=FI, O=Sonera, CN=Sonera Class2 CA + Validity + Not Before: Apr 6 07:29:40 2001 GMT + Not After : Apr 6 07:29:40 2021 GMT + Subject: C=FI, O=Sonera, CN=Sonera Class2 CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:90:17:4a:35:9d:ca:f0:0d:96:c7:44:fa:16:37: + fc:48:bd:bd:7f:80:2d:35:3b:e1:6f:a8:67:a9:bf: + 03:1c:4d:8c:6f:32:47:d5:41:68:a4:13:04:c1:35: + 0c:9a:84:43:fc:5c:1d:ff:89:b3:e8:17:18:cd:91: + 5f:fb:89:e3:ea:bf:4e:5d:7c:1b:26:d3:75:79:ed: + e6:84:e3:57:e5:ad:29:c4:f4:3a:28:e7:a5:7b:84: + 36:69:b3:fd:5e:76:bd:a3:2d:99:d3:90:4e:23:28: + 7d:18:63:f1:54:3b:26:9d:76:5b:97:42:b2:ff:ae: + f0:4e:ec:dd:39:95:4e:83:06:7f:e7:49:40:c8:c5: + 01:b2:54:5a:66:1d:3d:fc:f9:e9:3c:0a:9e:81:b8: + 70:f0:01:8b:e4:23:54:7c:c8:ae:f8:90:1e:00:96: + 72:d4:54:cf:61:23:bc:ea:fb:9d:02:95:d1:b6:b9: + 71:3a:69:08:3f:0f:b4:e1:42:c7:88:f5:3f:98:a8: + a7:ba:1c:e0:71:71:ef:58:57:81:50:7a:5c:6b:74: + 46:0e:83:03:98:c3:8e:a8:6e:f2:76:32:6e:27:83: + c2:73:f3:dc:18:e8:b4:93:ea:75:44:6b:04:60:20: + 71:57:87:9d:f3:be:a0:90:23:3d:8a:24:e1:da:21: + db:c3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 4A:A0:AA:58:84:D3:5E:3C + X509v3 Key Usage: + Certificate Sign, CRL Sign + Signature Algorithm: sha1WithRSAEncryption + 5a:ce:87:f9:16:72:15:57:4b:1d:d9:9b:e7:a2:26:30:ec:93: + 67:df:d6:2d:d2:34:af:f7:38:a5:ce:ab:16:b9:ab:2f:7c:35: + cb:ac:d0:0f:b4:4c:2b:fc:80:ef:6b:8c:91:5f:36:76:f7:db: + b3:1b:19:ea:f4:b2:11:fd:61:71:44:bf:28:b3:3a:1d:bf:b3: + 43:e8:9f:bf:dc:31:08:71:b0:9d:8d:d6:34:47:32:90:c6:65: + 24:f7:a0:4a:7c:04:73:8f:39:6f:17:8c:72:b5:bd:4b:c8:7a: + f8:7b:83:c3:28:4e:9c:09:ea:67:3f:b2:67:04:1b:c3:14:da: + f8:e7:49:24:91:d0:1d:6a:fa:61:39:ef:6b:e7:21:75:06:07: + d8:12:b4:21:20:70:42:71:81:da:3c:9a:36:be:a6:5b:0d:6a: + 6c:9a:1f:91:7b:f9:f9:ef:42:ba:4e:4e:9e:cc:0c:8d:94:dc: + d9:45:9c:5e:ec:42:50:63:ae:f4:5d:c4:b1:12:dc:ca:3b:a8: + 2e:9d:14:5a:05:75:b7:ec:d7:63:e2:ba:35:b6:04:08:91:e8: + da:9d:9c:f6:66:b5:18:ac:0a:a6:54:26:34:33:d2:1b:c1:d4: + 7f:1a:3a:8e:0b:aa:32:6e:db:fc:4f:25:9f:d9:32:c7:96:5a: + 70:ac:df:4c +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- + +Thawte Premium Server CA +======================== + +MD5 Fingerprint=06:9F:69:79:16:66:90:02:1B:8C:8C:A2:C3:07:6F:3A +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com + Validity + Not Before: Aug 1 00:00:00 1996 GMT + Not After : Dec 31 23:59:59 2020 GMT + Subject: C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, OU=Certification Services Division, CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d2:36:36:6a:8b:d7:c2:5b:9e:da:81:41:62:8f: + 38:ee:49:04:55:d6:d0:ef:1c:1b:95:16:47:ef:18: + 48:35:3a:52:f4:2b:6a:06:8f:3b:2f:ea:56:e3:af: + 86:8d:9e:17:f7:9e:b4:65:75:02:4d:ef:cb:09:a2: + 21:51:d8:9b:d0:67:d0:ba:0d:92:06:14:73:d4:93: + cb:97:2a:00:9c:5c:4e:0c:bc:fa:15:52:fc:f2:44: + 6e:da:11:4a:6e:08:9f:2f:2d:e3:f9:aa:3a:86:73: + b6:46:53:58:c8:89:05:bd:83:11:b8:73:3f:aa:07: + 8d:f4:42:4d:e7:40:9d:1c:37 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: md5WithRSAEncryption + 26:48:2c:16:c2:58:fa:e8:16:74:0c:aa:aa:5f:54:3f:f2:d7: + c9:78:60:5e:5e:6e:37:63:22:77:36:7e:b2:17:c4:34:b9:f5: + 08:85:fc:c9:01:38:ff:4d:be:f2:16:42:43:e7:bb:5a:46:fb: + c1:c6:11:1f:f1:4a:b0:28:46:c9:c3:c4:42:7d:bc:fa:ab:59: + 6e:d5:b7:51:88:11:e3:a4:85:19:6b:82:4c:a4:0c:12:ad:e9: + a4:ae:3f:f1:c3:49:65:9a:8c:c5:c8:3e:25:b7:94:99:bb:92: + 32:71:07:f0:86:5e:ed:50:27:a6:0d:a6:23:f9:bb:cb:a6:07: + 14:42 +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx +FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD +VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy +dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t +MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB +MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG +A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp +b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl +cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv +bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE +VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ +ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR +uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG +9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI +hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM +pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA +============================= + +MD5 Fingerprint=60:84:7C:5A:CE:DB:0C:D4:CB:A7:E9:FE:02:C6:A9:C0 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 10000010 (0x98968a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA + Validity + Not Before: Dec 17 09:23:49 2002 GMT + Not After : Dec 16 09:15:38 2015 GMT + Subject: C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:98:d2:b5:51:11:7a:81:a6:14:98:71:6d:be:cc: + e7:13:1b:d6:27:0e:7a:b3:6a:18:1c:b6:61:5a:d5: + 61:09:bf:de:90:13:c7:67:ee:dd:f3:da:c5:0c:12: + 9e:35:55:3e:2c:27:88:40:6b:f7:dc:dd:22:61:f5: + c2:c7:0e:f5:f6:d5:76:53:4d:8f:8c:bc:18:76:37: + 85:9d:e8:ca:49:c7:d2:4f:98:13:09:a2:3e:22:88: + 9c:7f:d6:f2:10:65:b4:ee:5f:18:d5:17:e3:f8:c5: + fd:e2:9d:a2:ef:53:0e:85:77:a2:0f:e1:30:47:ee: + 00:e7:33:7d:44:67:1a:0b:51:e8:8b:a0:9e:50:98: + 68:34:52:1f:2e:6d:01:f2:60:45:f2:31:eb:a9:31: + 68:29:bb:7a:41:9e:c6:19:7f:94:b4:51:39:03:7f: + b2:de:a7:32:9b:b4:47:8e:6f:b4:4a:ae:e5:af:b1: + dc:b0:1b:61:bc:99:72:de:e4:89:b7:7a:26:5d:da: + 33:49:5b:52:9c:0e:f5:8a:ad:c3:b8:3d:e8:06:6a: + c2:d5:2a:0b:6c:7b:84:bd:56:05:cb:86:65:92:ec: + 44:2b:b0:8e:b9:dc:70:0b:46:da:ad:bc:63:88:39: + fa:db:6a:fe:23:fa:bc:e4:48:f4:67:2b:6a:11:10: + 21:49 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:TRUE + X509v3 Certificate Policies: + Policy: 2.5.29.32.0 + CPS: http://www.pkioverheid.nl/policies/root-policy + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Key Identifier: + A8:7D:EB:BC:63:A4:74:13:74:00:EC:96:E0:D3:34:C1:2C:BF:6C:F8 + Signature Algorithm: sha1WithRSAEncryption + 05:84:87:55:74:36:61:c1:bb:d1:d4:c6:15:a8:13:b4:9f:a4: + fe:bb:ee:15:b4:2f:06:0c:29:f2:a8:92:a4:61:0d:fc:ab:5c: + 08:5b:51:13:2b:4d:c2:2a:61:c8:f8:09:58:fc:2d:02:b2:39: + 7d:99:66:81:bf:6e:5c:95:45:20:6c:e6:79:a7:d1:d8:1c:29: + fc:c2:20:27:51:c8:f1:7c:5d:34:67:69:85:11:30:c6:00:d2: + d7:f3:d3:7c:b6:f0:31:57:28:12:82:73:e9:33:2f:a6:55:b4: + 0b:91:94:47:9c:fa:bb:7a:42:32:e8:ae:7e:2d:c8:bc:ac:14: + bf:d9:0f:d9:5b:fc:c1:f9:7a:95:e1:7d:7e:96:fc:71:b0:c2: + 4c:c8:df:45:34:c9:ce:0d:f2:9c:64:08:d0:3b:c3:29:c5:b2: + ed:90:04:c1:b1:29:91:c5:30:6f:c1:a9:72:33:cc:fe:5d:16: + 17:2c:11:69:e7:7e:fe:c5:83:08:df:bc:dc:22:3a:2e:20:69: + 23:39:56:60:67:90:8b:2e:76:39:fb:11:88:97:f6:7c:bd:4b: + b8:20:16:67:05:8d:e2:3b:c1:72:3f:94:95:37:c7:5d:b9:9e: + d8:93:a1:17:8f:ff:0c:66:15:c1:24:7c:32:7c:03:1d:3b:a1: + 58:45:32:93 +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO +TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy +MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk +ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn +ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 +9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO +hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U +tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o +BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh +SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww +OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv +cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA +7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k +/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm +eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 +u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy +7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- + +TDC Internet Root CA +==================== + +MD5 Fingerprint=91:F4:03:55:20:A1:F8:63:2C:62:DE:AC:FB:61:1C:8E +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 986490188 (0x3acca54c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, O=TDC Internet, OU=TDC Internet Root CA + Validity + Not Before: Apr 5 16:33:17 2001 GMT + Not After : Apr 5 17:03:17 2021 GMT + Subject: C=DK, O=TDC Internet, OU=TDC Internet Root CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:c4:b8:40:bc:91:d5:63:1f:d7:99:a0:8b:0c:40: + 1e:74:b7:48:9d:46:8c:02:b2:e0:24:5f:f0:19:13: + a7:37:83:6b:5d:c7:8e:f9:84:30:ce:1a:3b:fa:fb: + ce:8b:6d:23:c6:c3:6e:66:9f:89:a5:df:e0:42:50: + 67:fa:1f:6c:1e:f4:d0:05:d6:bf:ca:d6:4e:e4:68: + 60:6c:46:aa:1c:5d:63:e1:07:86:0e:65:00:a7:2e: + a6:71:c6:bc:b9:81:a8:3a:7d:1a:d2:f9:d1:ac:4b: + cb:ce:75:af:dc:7b:fa:81:73:d4:fc:ba:bd:41:88: + d4:74:b3:f9:5e:38:3a:3c:43:a8:d2:95:4e:77:6d: + 13:0c:9d:8f:78:01:b7:5a:20:1f:03:37:35:e2:2c: + db:4b:2b:2c:78:b9:49:db:c4:d0:c7:9c:9c:e4:8a: + 20:09:21:16:56:66:ff:05:ec:5b:e3:f0:cf:ab:24: + 24:5e:c3:7f:70:7a:12:c4:d2:b5:10:a0:b6:21:e1: + 8d:78:69:55:44:69:f5:ca:96:1c:34:85:17:25:77: + e2:f6:2f:27:98:78:fd:79:06:3a:a2:d6:5a:43:c1: + ff:ec:04:3b:ee:13:ef:d3:58:5a:ff:92:eb:ec:ae: + da:f2:37:03:47:41:b6:97:c9:2d:0a:41:22:bb:bb: + e6:a7 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=DK/O=TDC Internet/OU=TDC Internet Root CA/CN=CRL1 + + X509v3 Private Key Usage Period: + Not Before: Apr 5 16:33:17 2001 GMT, Not After: Apr 5 17:03:17 2021 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:6C:64:01:C7:FD:85:6D:AC:C8:DA:9E:50:08:85:08:B5:3C:56:A8:50 + + X509v3 Subject Key Identifier: + 6C:64:01:C7:FD:85:6D:AC:C8:DA:9E:50:08:85:08:B5:3C:56:A8:50 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V5.0:4.0.... + Signature Algorithm: sha1WithRSAEncryption + 4e:43:cc:d1:dd:1d:10:1b:06:7f:b7:a4:fa:d3:d9:4d:fb:23: + 9f:23:54:5b:e6:8b:2f:04:28:8b:b5:27:6d:89:a1:ec:98:69: + dc:e7:8d:26:83:05:79:74:ec:b4:b9:a3:97:c1:35:00:fd:15: + da:39:81:3a:95:31:90:de:97:e9:86:a8:99:77:0c:e5:5a:a0: + 84:ff:12:16:ac:6e:b8:8d:c3:7b:92:c2:ac:2e:d0:7d:28:ec: + b6:f3:60:38:69:6f:3e:d8:04:55:3e:9e:cc:55:d2:ba:fe:bb: + 47:04:d7:0a:d9:16:0a:34:29:f5:58:13:d5:4f:cf:8f:56:4b: + b3:1e:ee:d3:98:79:da:08:1e:0c:6f:b8:f8:16:27:ef:c2:6f: + 3d:f6:a3:4b:3e:0e:e4:6d:6c:db:3b:41:12:9b:bd:0d:47:23: + 7f:3c:4a:d0:af:c0:af:f6:ef:1b:b5:15:c4:eb:83:c4:09:5f: + 74:8b:d9:11:fb:c2:56:b1:3c:f8:70:ca:34:8d:43:40:13:8c: + fd:99:03:54:79:c6:2e:ea:86:a1:f6:3a:d4:09:bc:f4:bc:66: + cc:3d:58:d0:57:49:0a:ee:25:e2:41:ee:13:f9:9b:38:34:d1: + 00:f5:7e:e7:94:1d:fc:69:03:62:b8:99:05:05:3d:6b:78:12: + bd:b0:6f:65 +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE +SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg +Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV +BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl +cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA +vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu +Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a +0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1 +4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN +eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD +R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG +A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu +dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME +Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3 +WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw +HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ +KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO +Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX +wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89 +9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0 +jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38 +aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- + +TDC OCES Root CA +================ + +MD5 Fingerprint=93:7F:90:1C:ED:84:67:17:A4:65:5F:9B:CB:30:02:97 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1044954564 (0x3e48bdc4) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, O=TDC, CN=TDC OCES CA + Validity + Not Before: Feb 11 08:39:30 2003 GMT + Not After : Feb 11 09:09:30 2037 GMT + Subject: C=DK, O=TDC, CN=TDC OCES CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ac:62:f6:61:20:b2:cf:c0:c6:85:d7:e3:79:e6: + cc:ed:f2:39:92:a4:97:2e:64:a3:84:5b:87:9c:4c: + fd:a4:f3:c4:5f:21:bd:56:10:eb:db:2e:61:ec:93: + 69:e3:a3:cc:bd:99:c3:05:fc:06:b8:ca:36:1c:fe: + 90:8e:49:4c:c4:56:9a:2f:56:bc:cf:7b:0c:f1:6f: + 47:a6:0d:43:4d:e2:e9:1d:39:34:cd:8d:2c:d9:12: + 98:f9:e3:e1:c1:4a:7c:86:38:c4:a9:c4:61:88:d2: + 5e:af:1a:26:4d:d5:e4:a0:22:47:84:d9:64:b7:19: + 96:fc:ec:19:e4:b2:97:26:4e:4a:4c:cb:8f:24:8b: + 54:18:1c:48:61:7b:d5:88:68:da:5d:b5:ea:cd:1a: + 30:c1:80:83:76:50:aa:4f:d1:d4:dd:38:f0:ef:16: + f4:e1:0c:50:06:bf:ea:fb:7a:49:a1:28:2b:1c:f6: + fc:15:32:a3:74:6a:8f:a9:c3:62:29:71:31:e5:3b: + a4:60:17:5e:74:e6:da:13:ed:e9:1f:1f:1b:d1:b2: + 68:73:c6:10:34:75:46:10:10:e3:90:00:76:40:cb: + 8b:b7:43:09:21:ff:ab:4e:93:c6:58:e9:a5:82:db: + 77:c4:3a:99:b1:72:95:49:04:f0:b7:2b:fa:7b:59: + 8e:dd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Certificate Policies: + Policy: 1.2.208.169.1.1.1 + CPS: http://www.certifikat.dk/repository + User Notice: + Organization: TDC + Number: 1 + Explicit Text: Certifikater fra denne CA udstedes under OID 1.2.208.169.1.1.1. Certificates from this CA are issued under OID 1.2.208.169.1.1.1. + + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 CRL Distribution Points: + DirName:/C=DK/O=TDC/CN=TDC OCES CA/CN=CRL1 + URI:http://crl.oces.certifikat.dk/oces.crl + + X509v3 Private Key Usage Period: + Not Before: Feb 11 08:39:30 2003 GMT, Not After: Feb 11 09:09:30 2037 GMT + X509v3 Authority Key Identifier: + keyid:60:B5:85:EC:56:64:7E:12:19:27:67:1D:50:15:4B:73:AE:3B:F9:12 + + X509v3 Subject Key Identifier: + 60:B5:85:EC:56:64:7E:12:19:27:67:1D:50:15:4B:73:AE:3B:F9:12 + 1.2.840.113533.7.65.0: + 0...V6.0:4.0.... + Signature Algorithm: sha1WithRSAEncryption + 0a:ba:26:26:46:d3:73:a8:09:f3:6b:0b:30:99:fd:8a:e1:57: + 7a:11:d3:b8:94:d7:09:10:6e:a3:b1:38:03:d1:b6:f2:43:41: + 29:62:a7:72:d8:fb:7c:05:e6:31:70:27:54:18:4e:8a:7c:4e: + e5:d1:ca:8c:78:88:cf:1b:d3:90:8b:e6:23:f8:0b:0e:33:43: + 7d:9c:e2:0a:19:8f:c9:01:3e:74:5d:74:c9:8b:1c:03:e5:18: + c8:01:4c:3f:cb:97:05:5d:98:71:a6:98:6f:b6:7c:bd:37:7f: + be:e1:93:25:6d:6f:f0:0a:ad:17:18:e1:03:bc:07:29:c8:ad: + 26:e8:f8:61:f0:fd:21:09:7e:9a:8e:a9:68:7d:48:62:72:bd: + 00:ea:01:99:b8:06:82:51:81:4e:f1:f5:b4:91:54:b9:23:7a: + 00:9a:9f:5d:8d:e0:3c:64:b9:1a:12:92:2a:c7:82:44:72:39: + dc:e2:3c:c6:d8:55:f5:15:4e:c8:05:0e:db:c6:d0:62:a6:ec: + 15:b4:b5:02:82:db:ac:8c:a2:81:f0:9b:99:31:f5:20:20:a8: + 88:61:0a:07:9f:94:fc:d0:d7:1b:cc:2e:17:f3:04:27:76:67: + eb:54:83:fd:a4:90:7e:06:3d:04:a3:43:2d:da:fc:0b:62:ea: + 2f:5f:62:53 +-----BEGIN CERTIFICATE----- +MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE +SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw +ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU +REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr +2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s +2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU +GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj +dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r +TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB +AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv +c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl +ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu +MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg +T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud +HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD +VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny +bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy +MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ +J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG +SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom +JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO +inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y +caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB +mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ +YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9 +BKNDLdr8C2LqL19iUw== +-----END CERTIFICATE----- + +UTN DATACorp SGC Root CA +======================== + +MD5 Fingerprint=B3:A5:3E:77:21:6D:AC:4A:C0:C9:FB:D5:41:3D:CA:06 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 44:be:0c:8b:50:00:21:b4:11:d3:2a:68:06:a9:ad:69 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN - DATACorp SGC + Validity + Not Before: Jun 24 18:57:21 1999 GMT + Not After : Jun 24 19:06:30 2019 GMT + Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN - DATACorp SGC + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:df:ee:58:10:a2:2b:6e:55:c4:8e:bf:2e:46:09: + e7:e0:08:0f:2e:2b:7a:13:94:1b:bd:f6:b6:80:8e: + 65:05:93:00:1e:bc:af:e2:0f:8e:19:0d:12:47:ec: + ac:ad:a3:fa:2e:70:f8:de:6e:fb:56:42:15:9e:2e: + 5c:ef:23:de:21:b9:05:76:27:19:0f:4f:d6:c3:9c: + b4:be:94:19:63:f2:a6:11:0a:eb:53:48:9c:be:f2: + 29:3b:16:e8:1a:a0:4c:a6:c9:f4:18:59:68:c0:70: + f2:53:00:c0:5e:50:82:a5:56:6f:36:f9:4a:e0:44: + 86:a0:4d:4e:d6:47:6e:49:4a:cb:67:d7:a6:c4:05: + b9:8e:1e:f4:fc:ff:cd:e7:36:e0:9c:05:6c:b2:33: + 22:15:d0:b4:e0:cc:17:c0:b2:c0:f4:fe:32:3f:29: + 2a:95:7b:d8:f2:a7:4e:0f:54:7c:a1:0d:80:b3:09: + 03:c1:ff:5c:dd:5e:9a:3e:bc:ae:bc:47:8a:6a:ae: + 71:ca:1f:b1:2a:b8:5f:42:05:0b:ec:46:30:d1:72: + 0b:ca:e9:56:6d:f5:ef:df:78:be:61:ba:b2:a5:ae: + 04:4c:bc:a8:ac:69:15:97:bd:ef:eb:b4:8c:bf:35: + f8:d4:c3:d1:28:0e:5c:3a:9f:70:18:33:20:77:c4: + a2:af + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 53:32:D1:B3:CF:7F:FA:E0:F1:A0:5D:85:4E:92:D2:9E:45:1D:B4:4F + X509v3 CRL Distribution Points: + URI:http://crl.usertrust.com/UTN-DATACorpSGC.crl + + X509v3 Extended Key Usage: + TLS Web Server Authentication, Microsoft Server Gated Crypto, Netscape Server Gated Crypto + Signature Algorithm: sha1WithRSAEncryption + 27:35:97:00:8a:8b:28:bd:c6:33:30:1e:29:fc:e2:f7:d5:98: + d4:40:bb:60:ca:bf:ab:17:2c:09:36:7f:50:fa:41:dc:ae:96: + 3a:0a:23:3e:89:59:c9:a3:07:ed:1b:37:ad:fc:7c:be:51:49: + 5a:de:3a:0a:54:08:16:45:c2:99:b1:87:cd:8c:68:e0:69:03: + e9:c4:4e:98:b2:3b:8c:16:b3:0e:a0:0c:98:50:9b:93:a9:70: + 09:c8:2c:a3:8f:df:02:e4:e0:71:3a:f1:b4:23:72:a0:aa:01: + df:df:98:3e:14:50:a0:31:26:bd:28:e9:5a:30:26:75:f9:7b: + 60:1c:8d:f3:cd:50:26:6d:04:27:9a:df:d5:0d:45:47:29:6b: + 2c:e6:76:d9:a9:29:7d:32:dd:c9:36:3c:bd:ae:35:f1:11:9e: + 1d:bb:90:3f:12:47:4e:8e:d7:7e:0f:62:73:1d:52:26:38:1c: + 18:49:fd:30:74:9a:c4:e5:22:2f:d8:c0:8d:ed:91:7a:4c:00: + 8f:72:7f:5d:da:dd:1b:8b:45:6b:e7:dd:69:97:a8:c5:56:4c: + 0f:0c:f6:9f:7a:91:37:f6:97:82:e0:dd:71:69:ff:76:3f:60: + 4d:3c:cf:f7:99:f9:c6:57:f4:c9:55:39:78:ba:2c:79:c9:a6: + 88:2b:f4:08 +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB +kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw +IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG +EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD +VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu +dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 +E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ +D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK +4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq +lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW +bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB +o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT +MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js +LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr +BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB +AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj +j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH +KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv +2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 +mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- + +UTN USERFirst Email Root CA +=========================== + +MD5 Fingerprint=D7:34:3D:EF:1D:27:09:28:E1:31:02:5B:13:2B:DD:F7 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 44:be:0c:8b:50:00:24:b4:11:d3:36:25:25:67:c9:89 + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Client Authentication and Email + Validity + Not Before: Jul 9 17:28:50 1999 GMT + Not After : Jul 9 17:36:58 2019 GMT + Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Client Authentication and Email + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b2:39:85:a4:f2:7d:ab:41:3b:62:46:37:ae:cd: + c1:60:75:bc:39:65:f9:4a:1a:47:a2:b9:cc:48:cc: + 6a:98:d5:4d:35:19:b9:a4:42:e5:ce:49:e2:8a:2f: + 1e:7c:d2:31:07:c7:4e:b4:83:64:9d:2e:29:d5:a2: + 64:c4:85:bd:85:51:35:79:a4:4e:68:90:7b:1c:7a: + a4:92:a8:17:f2:98:15:f2:93:cc:c9:a4:32:95:bb: + 0c:4f:30:bd:98:a0:0b:8b:e5:6e:1b:a2:46:fa:78: + bc:a2:6f:ab:59:5e:a5:2f:cf:ca:da:6d:aa:2f:eb: + ac:a1:b3:6a:aa:b7:2e:67:35:8b:79:e1:1e:69:88: + e2:e6:46:cd:a0:a5:ea:be:0b:ce:76:3a:7a:0e:9b: + ea:fc:da:27:5b:3d:73:1f:22:e6:48:61:c6:4c:f3: + 69:b1:a8:2e:1b:b6:d4:31:20:2c:bc:82:8a:8e:a4: + 0e:a5:d7:89:43:fc:16:5a:af:1d:71:d7:11:59:da: + ba:87:0d:af:fa:f3:e1:c2:f0:a4:c5:67:8c:d6:d6: + 54:3a:de:0a:a4:ba:03:77:b3:65:c8:fd:1e:d3:74: + 62:aa:18:ca:68:93:1e:a1:85:7e:f5:47:65:cb:f8: + 4d:57:28:74:d2:34:ff:30:b6:ee:f6:62:30:14:8c: + 2c:eb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 89:82:67:7D:C4:9D:26:70:00:4B:B4:50:48:7C:DE:3D:AE:04:6E:7D + X509v3 CRL Distribution Points: + URI:http://crl.usertrust.com/UTN-USERFirst-ClientAuthenticationandEmail.crl + + X509v3 Extended Key Usage: + TLS Web Client Authentication, E-mail Protection + Signature Algorithm: sha1WithRSAEncryption + b1:6d:61:5d:a6:1a:7f:7c:ab:4a:e4:30:fc:53:6f:25:24:c6: + ca:ed:e2:31:5c:2b:0e:ee:ee:61:55:6f:04:3e:cf:39:de:c5: + 1b:49:94:e4:eb:20:4c:b4:e6:9e:50:2e:72:d9:8d:f5:aa:a3: + b3:4a:da:56:1c:60:97:80:dc:82:a2:ad:4a:bd:8a:2b:ff:0b: + 09:b4:c6:d7:20:04:45:e4:cd:80:01:ba:ba:2b:6e:ce:aa:d7: + 92:fe:e4:af:eb:f4:26:1d:16:2a:7f:6c:30:95:37:2f:33:12: + ac:7f:dd:c7:d1:11:8c:51:98:b2:d0:a3:91:d0:ad:f6:9f:9e: + 83:93:1e:1d:42:b8:46:af:6b:66:f0:9b:7f:ea:e3:03:02:e5: + 02:51:c1:aa:d5:35:9d:72:40:03:89:ba:31:1d:c5:10:68:52: + 9e:df:a2:85:c5:5c:08:a6:78:e6:53:4f:b1:e8:b7:d3:14:9e: + 93:a6:c3:64:e3:ac:7e:71:cd:bc:9f:e9:03:1b:cc:fb:e9:ac: + 31:c1:af:7c:15:74:02:99:c3:b2:47:a6:c2:32:61:d7:c7:6f: + 48:24:51:27:a1:d5:87:55:f2:7b:8f:98:3d:16:9e:ee:75:b6: + f8:d0:8e:f2:f3:c6:ae:28:5b:a7:f0:f3:36:17:fc:c3:05:d3: + ca:03:4a:54 +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB +rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt +Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa +Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV +BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l +dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE +AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B +YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 +hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l +L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm +SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM +1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws +6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw +Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 +aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH +AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u +7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 +xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ +rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim +eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk +USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= +-----END CERTIFICATE----- + +UTN USERFirst Hardware Root CA +============================== + +MD5 Fingerprint=4C:56:41:E5:0D:BB:2B:E8:CA:A3:ED:18:08:AD:43:39 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 44:be:0c:8b:50:00:24:b4:11:d3:36:2a:fe:65:0a:fd + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware + Validity + Not Before: Jul 9 18:10:42 1999 GMT + Not After : Jul 9 18:19:22 2019 GMT + Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b1:f7:c3:38:3f:b4:a8:7f:cf:39:82:51:67:d0: + 6d:9f:d2:ff:58:f3:e7:9f:2b:ec:0d:89:54:99:b9: + 38:99:16:f7:e0:21:79:48:c2:bb:61:74:12:96:1d: + 3c:6a:72:d5:3c:10:67:3a:39:ed:2b:13:cd:66:eb: + 95:09:33:a4:6c:97:b1:e8:c6:ec:c1:75:79:9c:46: + 5e:8d:ab:d0:6a:fd:b9:2a:55:17:10:54:b3:19:f0: + 9a:f6:f1:b1:5d:b6:a7:6d:fb:e0:71:17:6b:a2:88: + fb:00:df:fe:1a:31:77:0c:9a:01:7a:b1:32:e3:2b: + 01:07:38:6e:c3:a5:5e:23:bc:45:9b:7b:50:c1:c9: + 30:8f:db:e5:2b:7a:d3:5b:fb:33:40:1e:a0:d5:98: + 17:bc:8b:87:c3:89:d3:5d:a0:8e:b2:aa:aa:f6:8e: + 69:88:06:c5:fa:89:21:f3:08:9d:69:2e:09:33:9b: + 29:0d:46:0f:8c:cc:49:34:b0:69:51:bd:f9:06:cd: + 68:ad:66:4c:bc:3e:ac:61:bd:0a:88:0e:c8:df:3d: + ee:7c:04:4c:9d:0a:5e:6b:91:d6:ee:c7:ed:28:8d: + ab:4d:87:89:73:d0:6e:a4:d0:1e:16:8b:14:e1:76: + 44:03:7f:63:ac:e4:cd:49:9c:c5:92:f4:ab:32:a1: + 48:5b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + A1:72:5F:26:1B:28:98:43:95:5D:07:37:D5:85:96:9D:4B:D2:C3:45 + X509v3 CRL Distribution Points: + URI:http://crl.usertrust.com/UTN-USERFirst-Hardware.crl + + X509v3 Extended Key Usage: + TLS Web Server Authentication, IPSec End System, IPSec Tunnel, IPSec User + Signature Algorithm: sha1WithRSAEncryption + 47:19:0f:de:74:c6:99:97:af:fc:ad:28:5e:75:8e:eb:2d:67: + ee:4e:7b:2b:d7:0c:ff:f6:de:cb:55:a2:0a:e1:4c:54:65:93: + 60:6b:9f:12:9c:ad:5e:83:2c:eb:5a:ae:c0:e4:2d:f4:00:63: + 1d:b8:c0:6c:f2:cf:49:bb:4d:93:6f:06:a6:0a:22:b2:49:62: + 08:4e:ff:c8:c8:14:b2:88:16:5d:e7:01:e4:12:95:e5:45:34: + b3:8b:69:bd:cf:b4:85:8f:75:51:9e:7d:3a:38:3a:14:48:12: + c6:fb:a7:3b:1a:8d:0d:82:40:07:e8:04:08:90:a1:89:cb:19: + 50:df:ca:1c:01:bc:1d:04:19:7b:10:76:97:3b:ee:90:90:ca: + c4:0e:1f:16:6e:75:ef:33:f8:d3:6f:5b:1e:96:e3:e0:74:77: + 74:7b:8a:a2:6e:2d:dd:76:d6:39:30:82:f0:ab:9c:52:f2:2a: + c7:af:49:5e:7e:c7:68:e5:82:81:c8:6a:27:f9:27:88:2a:d5: + 58:50:95:1f:f0:3b:1c:57:bb:7d:14:39:62:2b:9a:c9:94:92: + 2a:a3:22:0c:ff:89:26:7d:5f:23:2b:47:d7:15:1d:a9:6a:9e: + 51:0d:2a:51:9e:81:f9:d4:3b:5e:70:12:7f:10:32:9c:1e:bb: + 9d:f8:66:a8 +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== +-----END CERTIFICATE----- + +UTN USERFirst Object Root CA +============================ + +MD5 Fingerprint=A7:F2:E4:16:06:41:11:50:30:6B:9C:E3:B4:9C:B0:C9 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 44:be:0c:8b:50:00:24:b4:11:d3:36:2d:e0:b3:5f:1b + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Object + Validity + Not Before: Jul 9 18:31:20 1999 GMT + Not After : Jul 9 18:40:36 2019 GMT + Subject: C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, OU=http://www.usertrust.com, CN=UTN-USERFirst-Object + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:ce:aa:81:3f:a3:a3:61:78:aa:31:00:55:95:11: + 9e:27:0f:1f:1c:df:3a:9b:82:68:30:c0:4a:61:1d: + f1:2f:0e:fa:be:79:f7:a5:23:ef:55:51:96:84:cd: + db:e3:b9:6e:3e:31:d8:0a:20:67:c7:f4:d9:bf:94: + eb:47:04:3e:02:ce:2a:a2:5d:87:04:09:f6:30:9d: + 18:8a:97:b2:aa:1c:fc:41:d2:a1:36:cb:fb:3d:91: + ba:e7:d9:70:35:fa:e4:e7:90:c3:9b:a3:9b:d3:3c: + f5:12:99:77:b1:b7:09:e0:68:e6:1c:b8:f3:94:63: + 88:6a:6a:fe:0b:76:c9:be:f4:22:e4:67:b9:ab:1a: + 5e:77:c1:85:07:dd:0d:6c:bf:ee:06:c7:77:6a:41: + 9e:a7:0f:d7:fb:ee:94:17:b7:fc:85:be:a4:ab:c4: + 1c:31:dd:d7:b6:d1:e4:f0:ef:df:16:8f:b2:52:93: + d7:a1:d4:89:a1:07:2e:bf:e1:01:12:42:1e:1a:e1: + d8:95:34:db:64:79:28:ff:ba:2e:11:c2:e5:e8:5b: + 92:48:fb:47:0b:c2:6c:da:ad:32:83:41:f3:a5:e5: + 41:70:fd:65:90:6d:fa:fa:51:c4:f9:bd:96:2b:19: + 04:2c:d3:6d:a7:dc:f0:7f:6f:83:65:e2:6a:ab:87: + 86:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + DA:ED:64:74:14:9C:14:3C:AB:DD:99:A9:BD:5B:28:4D:8B:3C:C9:D8 + X509v3 CRL Distribution Points: + URI:http://crl.usertrust.com/UTN-USERFirst-Object.crl + + X509v3 Extended Key Usage: + Code Signing, Time Stamping, Microsoft Encrypted File System + Signature Algorithm: sha1WithRSAEncryption + 08:1f:52:b1:37:44:78:db:fd:ce:b9:da:95:96:98:aa:55:64: + 80:b5:5a:40:dd:21:a5:c5:c1:f3:5f:2c:4c:c8:47:5a:69:ea: + e8:f0:35:35:f4:d0:25:f3:c8:a6:a4:87:4a:bd:1b:b1:73:08: + bd:d4:c3:ca:b6:35:bb:59:86:77:31:cd:a7:80:14:ae:13:ef: + fc:b1:48:f9:6b:25:25:2d:51:b6:2c:6d:45:c1:98:c8:8a:56: + 5d:3e:ee:43:4e:3e:6b:27:8e:d0:3a:4b:85:0b:5f:d3:ed:6a: + a7:75:cb:d1:5a:87:2f:39:75:13:5a:72:b0:02:81:9f:be:f0: + 0f:84:54:20:62:6c:69:d4:e1:4d:c6:0d:99:43:01:0d:12:96: + 8c:78:9d:bf:50:a2:b1:44:aa:6a:cf:17:7a:cf:6f:0f:d4:f8: + 24:55:5f:f0:34:16:49:66:3e:50:46:c9:63:71:38:31:62:b8: + 62:b9:f3:53:ad:6c:b5:2b:a2:12:aa:19:4f:09:da:5e:e7:93: + c6:8e:14:08:fe:f0:30:80:18:a0:86:85:4d:c8:7d:d7:8b:03: + fe:6e:d5:f7:9d:16:ac:92:2c:a0:23:e5:9c:91:52:1f:94:df: + 17:94:73:c3:b3:c1:c1:71:05:20:00:78:bd:13:52:1d:a8:3e: + cd:00:1f:c8 +-----BEGIN CERTIFICATE----- +MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB +lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt +T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV +BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc +BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3 +dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP +HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO +KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo +5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+ +pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb +kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC +AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov +L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV +HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN +AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw +NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB +mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU +4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5 +81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR +Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= +-----END CERTIFICATE----- + +Camerfirma Chambers of Commerce Root +==================================== + +MD5 Fingerprint=B0:01:EE:14:D9:AF:29:18:94:76:8E:F1:69:33:2A:84 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Chambers of Commerce Root + Validity + Not Before: Sep 30 16:13:43 2003 GMT + Not After : Sep 30 16:13:44 2037 GMT + Subject: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Chambers of Commerce Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b7:36:55:e5:a5:5d:18:30:e0:da:89:54:91:fc: + c8:c7:52:f8:2f:50:d9:ef:b1:75:73:65:47:7d:1b: + 5b:ba:75:c5:fc:a1:88:24:fa:2f:ed:ca:08:4a:39: + 54:c4:51:7a:b5:da:60:ea:38:3c:81:b2:cb:f1:bb: + d9:91:23:3f:48:01:70:75:a9:05:2a:ad:1f:71:f3: + c9:54:3d:1d:06:6a:40:3e:b3:0c:85:ee:5c:1b:79: + c2:62:c4:b8:36:8e:35:5d:01:0c:23:04:47:35:aa: + 9b:60:4e:a0:66:3d:cb:26:0a:9c:40:a1:f4:5d:98: + bf:71:ab:a5:00:68:2a:ed:83:7a:0f:a2:14:b5:d4: + 22:b3:80:b0:3c:0c:5a:51:69:2d:58:18:8f:ed:99: + 9e:f1:ae:e2:95:e6:f6:47:a8:d6:0c:0f:b0:58:58: + db:c3:66:37:9e:9b:91:54:33:37:d2:94:1c:6a:48: + c9:c9:f2:a5:da:a5:0c:23:f7:23:0e:9c:32:55:5e: + 71:9c:84:05:51:9a:2d:fd:e6:4e:2a:34:5a:de:ca: + 40:37:67:0c:54:21:55:77:da:0a:0c:cc:97:ae:80: + dc:94:36:4a:f4:3e:ce:36:13:1e:53:e4:ac:4e:3a: + 05:ec:db:ae:72:9c:38:8b:d0:39:3b:89:0a:3e:77: + fe:75 + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:12 + X509v3 CRL Distribution Points: + URI:http://crl.chambersign.org/chambersroot.crl + + X509v3 Subject Key Identifier: + E3:94:F5:B1:4D:E9:DB:A1:29:5B:57:8B:4D:76:06:76:E1:D1:A2:8A + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:chambersroot@chambersign.org + X509v3 Issuer Alternative Name: + email:chambersroot@chambersign.org + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.17326.10.3.1 + CPS: http://cps.chambersign.org/cps/chambersroot.html + + Signature Algorithm: sha1WithRSAEncryption + 0c:41:97:c2:1a:86:c0:22:7c:9f:fb:90:f3:1a:d1:03:b1:ef: + 13:f9:21:5f:04:9c:da:c9:a5:8d:27:6c:96:87:91:be:41:90: + 01:72:93:e7:1e:7d:5f:f6:89:c6:5d:a7:40:09:3d:ac:49:45: + 45:dc:2e:8d:30:68:b2:09:ba:fb:c3:2f:cc:ba:0b:df:3f:77: + 7b:46:7d:3a:12:24:8e:96:8f:3c:05:0a:6f:d2:94:28:1d:6d: + 0c:c0:2e:88:22:d5:d8:cf:1d:13:c7:f0:48:d7:d7:05:a7:cf: + c7:47:9e:3b:3c:34:c8:80:4f:d4:14:bb:fc:0d:50:f7:fa:b3: + ec:42:5f:a9:dd:6d:c8:f4:75:cf:7b:c1:72:26:b1:01:1c:5c: + 2c:fd:7a:4e:b4:01:c5:05:57:b9:e7:3c:aa:05:d9:88:e9:07: + 46:41:ce:ef:41:81:ae:58:df:83:a2:ae:ca:d7:77:1f:e7:00: + 3c:9d:6f:8e:e4:32:09:1d:4d:78:34:78:34:3c:94:9b:26:ed: + 4f:71:c6:19:7a:bd:20:22:48:5a:fe:4b:7d:03:b7:e7:58:be: + c6:32:4e:74:1e:68:dd:a8:68:5b:b3:3e:ee:62:7d:d9:80:e8: + 0a:75:7a:b7:ee:b4:65:9a:21:90:e0:aa:d0:98:bc:38:b5:73: + 3c:8b:f8:dc +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg +b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa +MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB +ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw +IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B +AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb +unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d +BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq +7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 +0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX +roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG +A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j +aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p +26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA +BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud +EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN +BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB +AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd +p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi +1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc +XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 +eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu +tGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +Camerfirma Global Chambersign Root +================================== + +MD5 Fingerprint=C5:E6:7B:BF:06:D0:4F:43:ED:C4:7A:65:8A:FB:6B:19 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Global Chambersign Root + Validity + Not Before: Sep 30 16:14:18 2003 GMT + Not After : Sep 30 16:14:18 2037 GMT + Subject: C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, CN=Global Chambersign Root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:a2:70:a2:d0:9f:42:ae:5b:17:c7:d8:7d:cf:14: + 83:fc:4f:c9:a1:b7:13:af:8a:d7:9e:3e:04:0a:92: + 8b:60:56:fa:b4:32:2f:88:4d:a1:60:08:f4:b7:09: + 4e:a0:49:2f:49:d6:d3:df:9d:97:5a:9f:94:04:70: + ec:3f:59:d9:b7:cc:66:8b:98:52:28:09:02:df:c5: + 2f:84:8d:7a:97:77:bf:ec:40:9d:25:72:ab:b5:3f: + 32:98:fb:b7:b7:fc:72:84:e5:35:87:f9:55:fa:a3: + 1f:0e:6f:2e:28:dd:69:a0:d9:42:10:c6:f8:b5:44: + c2:d0:43:7f:db:bc:e4:a2:3c:6a:55:78:0a:77:a9: + d8:ea:19:32:b7:2f:fe:5c:3f:1b:ee:b1:98:ec:ca: + ad:7a:69:45:e3:96:0f:55:f6:e6:ed:75:ea:65:e8: + 32:56:93:46:89:a8:25:8a:65:06:ee:6b:bf:79:07: + d0:f1:b7:af:ed:2c:4d:92:bb:c0:a8:5f:a7:67:7d: + 04:f2:15:08:70:ac:92:d6:7d:04:d2:33:fb:4c:b6: + 0b:0b:fb:1a:c9:c4:8d:03:a9:7e:5c:f2:50:ab:12: + a5:a1:cf:48:50:a5:ef:d2:c8:1a:13:fa:b0:7f:b1: + 82:1c:77:6a:0f:5f:dc:0b:95:8f:ef:43:7e:e6:45: + 09:25 + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:12 + X509v3 CRL Distribution Points: + URI:http://crl.chambersign.org/chambersignroot.crl + + X509v3 Subject Key Identifier: + 43:9C:36:9F:B0:9E:30:4D:C6:CE:5F:AD:10:AB:E5:03:A5:FA:A9:14 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + X509v3 Subject Alternative Name: + email:chambersignroot@chambersign.org + X509v3 Issuer Alternative Name: + email:chambersignroot@chambersign.org + X509v3 Certificate Policies: + Policy: 1.3.6.1.4.1.17326.10.1.1 + CPS: http://cps.chambersign.org/cps/chambersignroot.html + + Signature Algorithm: sha1WithRSAEncryption + 3c:3b:70:91:f9:04:54:27:91:e1:ed:ed:fe:68:7f:61:5d:e5: + 41:65:4f:32:f1:18:05:94:6a:1c:de:1f:70:db:3e:7b:32:02: + 34:b5:0c:6c:a1:8a:7c:a5:f4:8f:ff:d4:d8:ad:17:d5:2d:04: + d1:3f:58:80:e2:81:59:88:be:c0:e3:46:93:24:fe:90:bd:26: + a2:30:2d:e8:97:26:57:35:89:74:96:18:f6:15:e2:af:24:19: + 56:02:02:b2:ba:0f:14:ea:c6:8a:66:c1:86:45:55:8b:be:92: + be:9c:a4:04:c7:49:3c:9e:e8:29:7a:89:d7:fe:af:ff:68:f5: + a5:17:90:bd:ac:99:cc:a5:86:57:09:67:46:db:d6:16:c2:46: + f1:e4:a9:50:f5:8f:d1:92:15:d3:5f:3e:c6:00:49:3a:6e:58: + b2:d1:d1:27:0d:25:c8:32:f8:20:11:cd:7d:32:33:48:94:54: + 4c:dd:dc:79:c4:30:9f:eb:8e:b8:55:b5:d7:88:5c:c5:6a:24: + 3d:b2:d3:05:03:51:c6:07:ef:cc:14:72:74:3d:6e:72:ce:18: + 28:8c:4a:a0:77:e5:09:2b:45:44:47:ac:b7:67:7f:01:8a:05: + 5a:93:be:a1:c1:ff:f8:e7:0e:67:a4:47:49:76:5d:75:90:1a: + f5:26:8f:f0 +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn +MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL +ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo +YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 +MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy +NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G +A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA +A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 +Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s +QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV +eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 +B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh +z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T +AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i +ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w +TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH +MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD +VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE +VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B +AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM +bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi +ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG +VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c +ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ +AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +NetLock Notary (Class A) Root +============================= + +MD5 Fingerprint=86:38:6D:5E:49:63:6C:85:5C:DB:6D:DC:94:B7:D0:F7 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 259 (0x103) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=HU, ST=Hungary, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado + Validity + Not Before: Feb 24 23:14:47 1999 GMT + Not After : Feb 19 23:14:47 2019 GMT + Subject: C=HU, ST=Hungary, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:bc:74:8c:0f:bb:4c:f4:37:1e:a9:05:82:d8:e6: + e1:6c:70:ea:78:b5:6e:d1:38:44:0d:a8:83:ce:5d: + d2:d6:d5:81:c5:d4:4b:e7:5b:94:70:26:db:3b:9d: + 6a:4c:62:f7:71:f3:64:d6:61:3b:3d:eb:73:a3:37: + d9:cf:ea:8c:92:3b:cd:f7:07:dc:66:74:97:f4:45: + 22:dd:f4:5c:e0:bf:6d:f3:be:65:33:e4:15:3a:bf: + db:98:90:55:38:c4:ed:a6:55:63:0b:b0:78:04:f4: + e3:6e:c1:3f:8e:fc:51:78:1f:92:9e:83:c2:fe:d9: + b0:a9:c9:bc:5a:00:ff:a9:a8:98:74:fb:f6:2c:3e: + 15:39:0d:b6:04:55:a8:0e:98:20:42:b3:b1:25:ad: + 7e:9a:6f:5d:53:b1:ab:0c:fc:eb:e0:f3:7a:b3:a8: + b3:ff:46:f6:63:a2:d8:3a:98:7b:b6:ac:85:ff:b0: + 25:4f:74:63:e7:13:07:a5:0a:8f:05:f7:c0:64:6f: + 7e:a7:27:80:96:de:d4:2e:86:60:c7:6b:2b:5e:73: + 7b:17:e7:91:3f:64:0c:d8:4b:22:34:2b:9b:32:f2: + 48:1f:9f:a1:0a:84:7a:e2:c2:ad:97:3d:8e:d5:c1: + f9:56:a3:50:e9:c6:b4:fa:98:a2:ee:95:e6:2a:03: + 8c:df + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:4 + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Netscape Comment: + FIGYELEM! Ezen tanusitvany a NetLock Kft. Altalanos Szolgaltatasi Felteteleiben leirt eljarasok alapjan keszult. A hitelesites folyamatat a NetLock Kft. termekfelelosseg-biztositasa vedi. A digitalis alairas elfogadasanak feltetele az eloirt ellenorzesi eljaras megtetele. Az eljaras leirasa megtalalhato a NetLock Kft. Internet honlapjan a https://www.netlock.net/docs cimen vagy kerheto az ellenorzes@netlock.net e-mail cimen. IMPORTANT! The issuance and the use of this certificate is subject to the NetLock CPS available at https://www.netlock.net/docs or by e-mail at cps@netlock.net. + Signature Algorithm: md5WithRSAEncryption + 48:24:46:f7:ba:56:6f:fa:c8:28:03:40:4e:e5:31:39:6b:26: + 6b:53:7f:db:df:df:f3:71:3d:26:c0:14:0e:c6:67:7b:23:a8: + 0c:73:dd:01:bb:c6:ca:6e:37:39:55:d5:c7:8c:56:20:0e:28: + 0a:0e:d2:2a:a4:b0:49:52:c6:38:07:fe:be:0a:09:8c:d1:98: + cf:ca:da:14:31:a1:4f:d2:39:fc:0f:11:2c:43:c3:dd:ab:93: + c7:55:3e:47:7c:18:1a:00:dc:f3:7b:d8:f2:7f:52:6c:20:f4: + 0b:5f:69:52:f4:ee:f8:b2:29:60:eb:e3:49:31:21:0d:d6:b5: + 10:41:e2:41:09:6c:e2:1a:9a:56:4b:77:02:f6:a0:9b:9a:27: + 87:e8:55:29:71:c2:90:9f:45:78:1a:e1:15:64:3d:d0:0e:d8: + a0:76:9f:ae:c5:d0:2e:ea:d6:0f:56:ec:64:7f:5a:9b:14:58: + 01:27:7e:13:50:c7:6b:2a:e6:68:3c:bf:5c:a0:0a:1b:e1:0e: + 7a:e9:e2:80:c3:e9:e9:f6:fd:6c:11:9e:d0:e5:28:27:2b:54: + 32:42:14:82:75:e6:4a:f0:2b:66:75:63:8c:a2:fb:04:3e:83: + 0e:9b:36:f0:18:e4:26:20:c3:8c:f0:28:07:ad:3c:17:66:88: + b5:fd:b6:88 +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV +MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe +TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 +dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 +N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC +dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu +MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL +b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD +zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi +3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 +WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY +Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi +NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC +ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 +QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 +YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz +aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm +ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg +ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs +amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv +IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 +Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 +ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 +YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg +dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs +b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G +CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO +xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP +0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ +QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk +f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK +8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI +-----END CERTIFICATE----- + +Equifax Secure CA +================= + +MD5 Fingerprint=67:CB:9D:C0:13:24:8A:82:9B:B2:17:1E:D1:1B:EC:D4 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 903804111 (0x35def4cf) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Equifax, OU=Equifax Secure Certificate Authority + Validity + Not Before: Aug 22 16:41:51 1998 GMT + Not After : Aug 22 16:41:51 2018 GMT + Subject: C=US, O=Equifax, OU=Equifax Secure Certificate Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c1:5d:b1:58:67:08:62:ee:a0:9a:2d:1f:08:6d: + 91:14:68:98:0a:1e:fe:da:04:6f:13:84:62:21:c3: + d1:7c:ce:9f:05:e0:b8:01:f0:4e:34:ec:e2:8a:95: + 04:64:ac:f1:6b:53:5f:05:b3:cb:67:80:bf:42:02: + 8e:fe:dd:01:09:ec:e1:00:14:4f:fc:fb:f0:0c:dd: + 43:ba:5b:2b:e1:1f:80:70:99:15:57:93:16:f1:0f: + 97:6a:b7:c2:68:23:1c:cc:4d:59:30:ac:51:1e:3b: + af:2b:d6:ee:63:45:7b:c5:d9:5f:50:d2:e3:50:0f: + 3a:88:e7:bf:14:fd:e0:c7:b9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + DirName:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority/CN=CRL1 + + X509v3 Private Key Usage Period: + Not After: Aug 22 16:41:51 2018 GMT + X509v3 Key Usage: + Certificate Sign, CRL Sign + X509v3 Authority Key Identifier: + keyid:48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4 + + X509v3 Subject Key Identifier: + 48:E6:68:F9:2B:D2:B2:95:D7:47:D8:23:20:10:4F:33:98:90:9F:D4 + X509v3 Basic Constraints: + CA:TRUE + 1.2.840.113533.7.65.0: + 0...V3.0c.... + Signature Algorithm: sha1WithRSAEncryption + 58:ce:29:ea:fc:f7:de:b5:ce:02:b9:17:b5:85:d1:b9:e3:e0: + 95:cc:25:31:0d:00:a6:92:6e:7f:b6:92:63:9e:50:95:d1:9a: + 6f:e4:11:de:63:85:6e:98:ee:a8:ff:5a:c8:d3:55:b2:66:71: + 57:de:c0:21:eb:3d:2a:a7:23:49:01:04:86:42:7b:fc:ee:7f: + a2:16:52:b5:67:67:d3:40:db:3b:26:58:b2:28:77:3d:ae:14: + 77:61:d6:fa:2a:66:27:a0:0d:fa:a7:73:5c:ea:70:f1:94:21: + 65:44:5f:fa:fc:ef:29:68:a9:a2:87:79:ef:79:ef:4f:ac:07: + 77:38 +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- + +NetLock Business (Class B) Root +=============================== + +MD5 Fingerprint=39:16:AA:B9:6A:41:E1:14:69:DF:9E:6C:3B:72:DC:B6 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 105 (0x69) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=HU, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado + Validity + Not Before: Feb 25 14:10:22 1999 GMT + Not After : Feb 20 14:10:22 2019 GMT + Subject: C=HU, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, CN=NetLock Uzleti (Class B) Tanusitvanykiado + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b1:ea:04:ec:20:a0:23:c2:8f:38:60:cf:c7:46: + b3:d5:1b:fe:fb:b9:99:9e:04:dc:1c:7f:8c:4a:81: + 98:ee:a4:d4:ca:8a:17:b9:22:7f:83:0a:75:4c:9b: + c0:69:d8:64:39:a3:ed:92:a3:fd:5b:5c:74:1a:c0: + 47:ca:3a:69:76:9a:ba:e2:44:17:fc:4c:a3:d5:fe: + b8:97:88:af:88:03:89:1f:a4:f2:04:3e:c8:07:0b: + e6:f9:b3:2f:7a:62:14:09:46:14:ca:64:f5:8b:80: + b5:62:a8:d8:6b:d6:71:93:2d:b3:bf:09:54:58:ed: + 06:eb:a8:7b:dc:43:b1:a1:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:4 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Netscape Comment: + FIGYELEM! Ezen tanusitvany a NetLock Kft. Altalanos Szolgaltatasi Felteteleiben leirt eljarasok alapjan keszult. A hitelesites folyamatat a NetLock Kft. termekfelelosseg-biztositasa vedi. A digitalis alairas elfogadasanak feltetele az eloirt ellenorzesi eljaras megtetele. Az eljaras leirasa megtalalhato a NetLock Kft. Internet honlapjan a https://www.netlock.net/docs cimen vagy kerheto az ellenorzes@netlock.net e-mail cimen. IMPORTANT! The issuance and the use of this certificate is subject to the NetLock CPS available at https://www.netlock.net/docs or by e-mail at cps@netlock.net. + Signature Algorithm: md5WithRSAEncryption + 04:db:ae:8c:17:af:f8:0e:90:31:4e:cd:3e:09:c0:6d:3a:b0: + f8:33:4c:47:4c:e3:75:88:10:97:ac:b0:38:15:91:c6:29:96: + cc:21:c0:6d:3c:a5:74:cf:d8:82:a5:39:c3:65:e3:42:70:bb: + 22:90:e3:7d:db:35:76:e1:a0:b5:da:9f:70:6e:93:1a:30:39: + 1d:30:db:2e:e3:7c:b2:91:b2:d1:37:29:fa:b9:d6:17:5c:47: + 4f:e3:1d:38:eb:9f:d5:7b:95:a8:28:9e:15:4a:d1:d1:d0:2b: + 00:97:a0:e2:92:36:2b:63:ac:58:01:6b:33:29:50:86:83:f1: + 01:48 +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD +EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 +OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G +A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh +Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l +dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK +gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX +iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc +Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E +BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G +SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu +b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh +bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv +Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln +aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 +IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph +biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo +ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP +UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj +YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA +bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 +sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa +n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS +NitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- + +NetLock Express (Class C) Root +============================== + +MD5 Fingerprint=4F:EB:F1:F0:70:C2:80:63:5D:58:9F:DA:12:3C:A9:C4 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 104 (0x68) + Signature Algorithm: md5WithRSAEncryption + Issuer: C=HU, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, CN=NetLock Expressz (Class C) Tanusitvanykiado + Validity + Not Before: Feb 25 14:08:11 1999 GMT + Not After : Feb 20 14:08:11 2019 GMT + Subject: C=HU, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, CN=NetLock Expressz (Class C) Tanusitvanykiado + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:eb:ec:b0:6c:61:8a:23:25:af:60:20:e3:d9:9f: + fc:93:0b:db:5d:8d:b0:a1:b3:40:3a:82:ce:fd:75: + e0:78:32:03:86:5a:86:95:91:ed:53:fa:9d:40:fc: + e6:e8:dd:d9:5b:7a:03:bd:5d:f3:3b:0c:c3:51:79: + 9b:ad:55:a0:e9:d0:03:10:af:0a:ba:14:42:d9:52: + 26:11:22:c7:d2:20:cc:82:a4:9a:a9:fe:b8:81:76: + 9d:6a:b7:d2:36:75:3e:b1:86:09:f6:6e:6d:7e:4e: + b7:7a:ec:ae:71:84:f6:04:33:08:25:32:eb:74:ac: + 16:44:c6:e4:40:93:1d:7f:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:4 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + Netscape Cert Type: + SSL CA, S/MIME CA, Object Signing CA + Netscape Comment: + FIGYELEM! Ezen tanusitvany a NetLock Kft. Altalanos Szolgaltatasi Felteteleiben leirt eljarasok alapjan keszult. A hitelesites folyamatat a NetLock Kft. termekfelelosseg-biztositasa vedi. A digitalis alairas elfogadasanak feltetele az eloirt ellenorzesi eljaras megtetele. Az eljaras leirasa megtalalhato a NetLock Kft. Internet honlapjan a https://www.netlock.net/docs cimen vagy kerheto az ellenorzes@netlock.net e-mail cimen. IMPORTANT! The issuance and the use of this certificate is subject to the NetLock CPS available at https://www.netlock.net/docs or by e-mail at cps@netlock.net. + Signature Algorithm: md5WithRSAEncryption + 10:ad:7f:d7:0c:32:80:0a:d8:86:f1:79:98:b5:ad:d4:cd:b3: + 36:c4:96:48:c1:5c:cd:9a:d9:05:2e:9f:be:50:eb:f4:26:14: + 10:2d:d4:66:17:f8:9e:c1:27:fd:f1:ed:e4:7b:4b:a0:6c:b5: + ab:9a:57:70:a6:ed:a0:a4:ed:2e:f5:fd:fc:bd:fe:4d:37:08: + 0c:bc:e3:96:83:22:f5:49:1b:7f:4b:2b:b4:54:c1:80:7c:99: + 4e:1d:d0:8c:ee:d0:ac:e5:92:fa:75:56:fe:64:a0:13:8f:b8: + b8:16:9d:61:05:67:80:c8:d0:d8:a5:07:02:34:98:04:8d:33: + 04:d4 +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx +ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 +b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD +EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X +DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw +DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u +c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr +TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA +OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC +2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW +RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P +AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW +ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 +YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz +b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO +ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB +IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs +b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s +YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg +a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g +SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 +aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg +YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg +Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY +ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g +pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 +Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== + +MD5 Fingerprint=A1:0B:44:B3:CA:10:D8:00:6E:9D:0F:D8:0F:92:0A:D1 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 50:94:6c:ec:18:ea:d5:9c:4d:d5:97:ef:75:8f:a0:ad + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, OU=www.xrampsecurity.com, O=XRamp Security Services Inc, CN=XRamp Global Certification Authority + Validity + Not Before: Nov 1 17:14:04 2004 GMT + Not After : Jan 1 05:37:19 2035 GMT + Subject: C=US, OU=www.xrampsecurity.com, O=XRamp Security Services Inc, CN=XRamp Global Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:98:24:1e:bd:15:b4:ba:df:c7:8c:a5:27:b6:38: + 0b:69:f3:b6:4e:a8:2c:2e:21:1d:5c:44:df:21:5d: + 7e:23:74:fe:5e:7e:b4:4a:b7:a6:ad:1f:ae:e0:06: + 16:e2:9b:5b:d9:67:74:6b:5d:80:8f:29:9d:86:1b: + d9:9c:0d:98:6d:76:10:28:58:e4:65:b0:7f:4a:98: + 79:9f:e0:c3:31:7e:80:2b:b5:8c:c0:40:3b:11:86: + d0:cb:a2:86:36:60:a4:d5:30:82:6d:d9:6e:d0:0f: + 12:04:33:97:5f:4f:61:5a:f0:e4:f9:91:ab:e7:1d: + 3b:bc:e8:cf:f4:6b:2d:34:7c:e2:48:61:1c:8e:f3: + 61:44:cc:6f:a0:4a:a9:94:b0:4d:da:e7:a9:34:7a: + 72:38:a8:41:cc:3c:94:11:7d:eb:c8:a6:8c:b7:86: + cb:ca:33:3b:d9:3d:37:8b:fb:7a:3e:86:2c:e7:73: + d7:0a:57:ac:64:9b:19:eb:f4:0f:04:08:8a:ac:03: + 17:19:64:f4:5a:25:22:8d:34:2c:b2:f6:68:1d:12: + 6d:d3:8a:1e:14:da:c4:8f:a6:e2:23:85:d5:7a:0d: + bd:6a:e0:e9:ec:ec:17:bb:42:1b:67:aa:25:ed:45: + 83:21:fc:c1:c9:7c:d5:62:3e:fa:f2:c5:2d:d3:fd: + d4:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + 1.3.6.1.4.1.311.20.2: + ...C.A + X509v3 Key Usage: + Digital Signature, Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + C6:4F:A2:3D:06:63:84:09:9C:CE:62:E4:04:AC:8D:5C:B5:E9:B6:1B + X509v3 CRL Distribution Points: + URI:http://crl.xrampsecurity.com/XGCA.crl + + 1.3.6.1.4.1.311.21.1: + ... + Signature Algorithm: sha1WithRSAEncryption + 91:15:39:03:01:1b:67:fb:4a:1c:f9:0a:60:5b:a1:da:4d:97: + 62:f9:24:53:27:d7:82:64:4e:90:2e:c3:49:1b:2b:9a:dc:fc: + a8:78:67:35:f1:1d:f0:11:bd:b7:48:e3:10:f6:0d:df:3f:d2: + c9:b6:aa:55:a4:48:ba:02:db:de:59:2e:15:5b:3b:9d:16:7d: + 47:d7:37:ea:5f:4d:76:12:36:bb:1f:d7:a1:81:04:46:20:a3: + 2c:6d:a9:9e:01:7e:3f:29:ce:00:93:df:fd:c9:92:73:89:89: + 64:9e:e7:2b:e4:1c:91:2c:d2:b9:ce:7d:ce:6f:31:99:d3:e6: + be:d2:1e:90:f0:09:14:79:5c:23:ab:4d:d2:da:21:1f:4d:99: + 79:9d:e1:cf:27:9f:10:9b:1c:88:0d:b0:8a:64:41:31:b8:0e: + 6c:90:24:a4:9b:5c:71:8f:ba:bb:7e:1c:1b:db:6a:80:0f:21: + bc:e9:db:a6:b7:40:f4:b2:8b:a9:b1:e4:ef:9a:1a:d0:3d:69: + 99:ee:a8:28:a3:e1:3c:b3:f0:b2:11:9c:cf:7c:40:e6:dd:e7: + 43:7d:a2:d8:3a:b5:a9:8d:f2:34:99:c4:d4:10:e1:06:fd:09: + 84:10:3b:ee:c4:4c:f4:ec:27:7c:42:c2:74:7c:82:8a:09:c9: + b4:03:25:bc +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== + +MD5 Fingerprint=91:DE:06:25:AB:DA:FD:32:17:0C:BB:25:17:2A:84:67 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority + Validity + Not Before: Jun 29 17:06:20 2004 GMT + Not After : Jun 29 17:06:20 2034 GMT + Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:de:9d:d7:ea:57:18:49:a1:5b:eb:d7:5f:48:86: + ea:be:dd:ff:e4:ef:67:1c:f4:65:68:b3:57:71:a0: + 5e:77:bb:ed:9b:49:e9:70:80:3d:56:18:63:08:6f: + da:f2:cc:d0:3f:7f:02:54:22:54:10:d8:b2:81:d4: + c0:75:3d:4b:7f:c7:77:c3:3e:78:ab:1a:03:b5:20: + 6b:2f:6a:2b:b1:c5:88:7e:c4:bb:1e:b0:c1:d8:45: + 27:6f:aa:37:58:f7:87:26:d7:d8:2d:f6:a9:17:b7: + 1f:72:36:4e:a6:17:3f:65:98:92:db:2a:6e:5d:a2: + fe:88:e0:0b:de:7f:e5:8d:15:e1:eb:cb:3a:d5:e2: + 12:a2:13:2d:d8:8e:af:5f:12:3d:a0:08:05:08:b6: + 5c:a5:65:38:04:45:99:1e:a3:60:60:74:c5:41:a5: + 72:62:1b:62:c5:1f:6f:5f:1a:42:be:02:51:65:a8: + ae:23:18:6a:fc:78:03:a9:4d:7f:80:c3:fa:ab:5a: + fc:a1:40:a4:ca:19:16:fe:b2:c8:ef:5e:73:0d:ee: + 77:bd:9a:f6:79:98:bc:b1:07:67:a2:15:0d:dd:a0: + 58:c6:44:7b:0a:3e:62:28:5f:ba:41:07:53:58:cf: + 11:7e:38:74:c5:f8:ff:b5:69:90:8f:84:74:ea:97: + 1b:af + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Subject Key Identifier: + D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3 + X509v3 Authority Key Identifier: + keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3 + DirName:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 32:4b:f3:b2:ca:3e:91:fc:12:c6:a1:07:8c:8e:77:a0:33:06: + 14:5c:90:1e:18:f7:08:a6:3d:0a:19:f9:87:80:11:6e:69:e4: + 96:17:30:ff:34:91:63:72:38:ee:cc:1c:01:a3:1d:94:28:a4: + 31:f6:7a:c4:54:d7:f6:e5:31:58:03:a2:cc:ce:62:db:94:45: + 73:b5:bf:45:c9:24:b5:d5:82:02:ad:23:79:69:8d:b8:b6:4d: + ce:cf:4c:ca:33:23:e8:1c:88:aa:9d:8b:41:6e:16:c9:20:e5: + 89:9e:cd:3b:da:70:f7:7e:99:26:20:14:54:25:ab:6e:73:85: + e6:9b:21:9d:0a:6c:82:0e:a8:f8:c2:0c:fa:10:1e:6c:96:ef: + 87:0d:c4:0f:61:8b:ad:ee:83:2b:95:f8:8e:92:84:72:39:eb: + 20:ea:83:ed:83:cd:97:6e:08:bc:eb:4e:26:b6:73:2b:e4:d3: + f6:4c:fe:26:71:e2:61:11:74:4a:ff:57:1a:87:0f:75:48:2e: + cf:51:69:17:a0:02:12:61:95:d5:d1:40:b2:10:4c:ee:c4:ac: + 10:43:a6:a5:9e:0a:d5:95:62:9a:0d:cf:88:82:c5:32:0c:e4: + 2b:9f:45:e6:0d:9f:28:9c:b1:b9:2a:5a:57:ad:37:0f:af:1d: + 7f:db:bd:9f +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== + +MD5 Fingerprint=32:4A:4B:BB:C8:63:69:9B:BE:74:9A:C6:DD:1D:46:24 +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 0 (0x0) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority + Validity + Not Before: Jun 29 17:39:16 2004 GMT + Not After : Jun 29 17:39:16 2034 GMT + Subject: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:b7:32:c8:fe:e9:71:a6:04:85:ad:0c:11:64:df: + ce:4d:ef:c8:03:18:87:3f:a1:ab:fb:3c:a6:9f:f0: + c3:a1:da:d4:d8:6e:2b:53:90:fb:24:a4:3e:84:f0: + 9e:e8:5f:ec:e5:27:44:f5:28:a6:3f:7b:de:e0:2a: + f0:c8:af:53:2f:9e:ca:05:01:93:1e:8f:66:1c:39: + a7:4d:fa:5a:b6:73:04:25:66:eb:77:7f:e7:59:c6: + 4a:99:25:14:54:eb:26:c7:f3:7f:19:d5:30:70:8f: + af:b0:46:2a:ff:ad:eb:29:ed:d7:9f:aa:04:87:a3: + d4:f9:89:a5:34:5f:db:43:91:82:36:d9:66:3c:b1: + b8:b9:82:fd:9c:3a:3e:10:c8:3b:ef:06:65:66:7a: + 9b:19:18:3d:ff:71:51:3c:30:2e:5f:be:3d:77:73: + b2:5d:06:6c:c3:23:56:9a:2b:85:26:92:1c:a7:02: + b3:e4:3f:0d:af:08:79:82:b8:36:3d:ea:9c:d3:35: + b3:bc:69:ca:f5:cc:9d:e8:fd:64:8d:17:80:33:6e: + 5e:4a:5d:99:c9:1e:87:b4:9d:1a:c0:d5:6e:13:35: + 23:5e:df:9b:5f:3d:ef:d6:f7:76:c2:ea:3e:bb:78: + 0d:1c:42:67:6b:04:d8:f8:d6:da:6f:8b:f2:44:a0: + 01:ab + Exponent: 3 (0x3) + X509v3 extensions: + X509v3 Subject Key Identifier: + BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7 + X509v3 Authority Key Identifier: + keyid:BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7 + DirName:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority + serial:00 + + X509v3 Basic Constraints: + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 05:9d:3f:88:9d:d1:c9:1a:55:a1:ac:69:f3:f3:59:da:9b:01: + 87:1a:4f:57:a9:a1:79:09:2a:db:f7:2f:b2:1e:cc:c7:5e:6a: + d8:83:87:a1:97:ef:49:35:3e:77:06:41:58:62:bf:8e:58:b8: + 0a:67:3f:ec:b3:dd:21:66:1f:c9:54:fa:72:cc:3d:4c:40:d8: + 81:af:77:9e:83:7a:bb:a2:c7:f5:34:17:8e:d9:11:40:f4:fc: + 2c:2a:4d:15:7f:a7:62:5d:2e:25:d3:00:0b:20:1a:1d:68:f9: + 17:b8:f4:bd:8b:ed:28:59:dd:4d:16:8b:17:83:c8:b2:65:c7: + 2d:7a:a5:aa:bc:53:86:6d:dd:57:a4:ca:f8:20:41:0b:68:f0: + f4:fb:74:be:56:5d:7a:79:f5:f9:1d:85:e3:2d:95:be:f5:71: + 90:43:cc:8d:1f:9a:00:0a:87:29:e9:55:22:58:00:23:ea:e3: + 12:43:29:5b:47:08:dd:8c:41:6a:65:06:a8:e5:21:aa:41:b4: + 95:21:95:b9:7d:d1:34:ab:13:d6:ad:bc:dc:e2:3d:39:cd:bd: + 3e:75:70:a1:18:59:03:c9:22:b4:8f:9c:d5:5e:2a:d7:a5:b6: + d4:0a:6d:f8:b7:40:11:46:9a:1f:79:0e:62:bf:0f:97:ec:e0: + 2f:1f:17:94 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- diff --git a/vendor/gems/active_utils-1.0.5/test/test_helper.rb b/vendor/gems/active_utils-1.0.5/test/test_helper.rb new file mode 100644 index 000000000..8f91c69fe --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/test_helper.rb @@ -0,0 +1,12 @@ +#!/usr/bin/env ruby +$:.unshift(File.dirname(__FILE__) + '/../lib') + +require 'rubygems' +require 'bundler' +Bundler.setup + +require 'test/unit' +require 'active_utils' +require 'mocha' + +include ActiveMerchant diff --git a/vendor/gems/active_utils-1.0.5/test/unit/connection_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/connection_test.rb new file mode 100644 index 000000000..7213bf0c0 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/connection_test.rb @@ -0,0 +1,149 @@ +require 'test_helper' + +class ConnectionTest < Test::Unit::TestCase + + def setup + @ok = stub(:code => 200, :message => 'OK', :body => 'success') + + @endpoint = 'https://example.com/tx.php' + @connection = ActiveMerchant::Connection.new(@endpoint) + @connection.logger = stub(:info => nil, :debug => nil, :error => nil) + end + + def test_connection_endpoint_parses_string_to_uri + assert_equal URI.parse(@endpoint), @connection.endpoint + end + + def test_connection_endpoint_accepts_uri + endpoint = URI.parse(@endpoint) + connection = ActiveMerchant::Connection.new(endpoint) + assert_equal endpoint, connection.endpoint + end + + def test_connection_endpoint_raises_uri_error + assert_raises URI::InvalidURIError do + ActiveMerchant::Connection.new("not a URI") + end + end + + def test_successful_get_request + @connection.logger.expects(:info).twice + Net::HTTP.any_instance.expects(:get).with('/tx.php', {}).returns(@ok) + response = @connection.request(:get, nil, {}) + assert_equal 'success', response.body + end + + def test_successful_post_request + Net::HTTP.any_instance.expects(:post).with('/tx.php', 'data', ActiveMerchant::Connection::RUBY_184_POST_HEADERS).returns(@ok) + response = @connection.request(:post, 'data', {}) + assert_equal 'success', response.body + end + + def test_successful_put_request + Net::HTTP.any_instance.expects(:put).with('/tx.php', 'data', {}).returns(@ok) + response = @connection.request(:put, 'data', {}) + assert_equal 'success', response.body + end + + def test_successful_delete_request + Net::HTTP.any_instance.expects(:delete).with('/tx.php', {}).returns(@ok) + response = @connection.request(:delete, nil, {}) + assert_equal 'success', response.body + end + + def test_get_raises_argument_error_if_passed_data + assert_raise(ArgumentError) do + @connection.request(:get, 'data', {}) + end + end + + def test_request_raises_when_request_method_not_supported + assert_raise(ArgumentError) do + @connection.request(:head, nil, {}) + end + end + + + + def test_default_read_timeout + assert_equal ActiveMerchant::Connection::READ_TIMEOUT, @connection.read_timeout + end + + def test_override_read_timeout + @connection.read_timeout = 20 + assert_equal 20, @connection.read_timeout + end + + def test_default_open_timeout + @connection.open_timeout = 20 + assert_equal 20, @connection.open_timeout + end + + def test_default_verify_peer + assert_equal ActiveMerchant::Connection::VERIFY_PEER, @connection.verify_peer + end + + def test_override_verify_peer + @connection.verify_peer = false + assert_equal false, @connection.verify_peer + end + + def test_unrecoverable_exception + @connection.logger.expects(:error).once + Net::HTTP.any_instance.expects(:post).raises(EOFError) + + assert_raises(ActiveMerchant::ConnectionError) do + @connection.request(:post, '') + end + end + + def test_failure_then_success_with_recoverable_exception + @connection.logger.expects(:error).never + Net::HTTP.any_instance.expects(:post).times(2).raises(Errno::ECONNREFUSED).then.returns(@ok) + + assert_nothing_raised do + @connection.request(:post, '') + end + end + + def test_failure_limit_reached + @connection.logger.expects(:error).once + Net::HTTP.any_instance.expects(:post).times(ActiveMerchant::Connection::MAX_RETRIES).raises(Errno::ECONNREFUSED) + + assert_raises(ActiveMerchant::ConnectionError) do + @connection.request(:post, '') + end + end + + def test_failure_then_success_with_retry_safe_enabled + Net::HTTP.any_instance.expects(:post).times(2).raises(EOFError).then.returns(@ok) + + @connection.retry_safe = true + + assert_nothing_raised do + @connection.request(:post, '') + end + end + + def test_mixture_of_failures_with_retry_safe_enabled + Net::HTTP.any_instance.expects(:post).times(3).raises(Errno::ECONNRESET). + raises(Errno::ECONNREFUSED). + raises(EOFError) + + @connection.retry_safe = true + + assert_raises(ActiveMerchant::ConnectionError) do + @connection.request(:post, '') + end + end + + def test_failure_with_ssl_certificate + @connection.logger.expects(:error).once + Net::HTTP.any_instance.expects(:post).raises(OpenSSL::X509::CertificateError) + + assert_raises(ActiveMerchant::ClientCertificateError) do + @connection.request(:post, '') + end + end + +end diff --git a/vendor/gems/active_utils-1.0.5/test/unit/country_code_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/country_code_test.rb new file mode 100644 index 000000000..ce60adb44 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/country_code_test.rb @@ -0,0 +1,31 @@ +require 'test_helper' + +class CountryCodeTest < Test::Unit::TestCase + def test_alpha2_country_code + code = CountryCode.new('CA') + assert_equal 'CA', code.value + assert_equal 'CA', code.to_s + assert_equal :alpha2, code.format + end + + def test_lower_alpha2_country_code + code = CountryCode.new('ca') + assert_equal 'CA', code.value + assert_equal 'CA', code.to_s + assert_equal :alpha2, code.format + end + + def test_alpha2_country_code + code = CountryCode.new('CAN') + assert_equal :alpha3, code.format + end + + def test_numeric_code + code = CountryCode.new('004') + assert_equal :numeric, code.format + end + + def test_invalid_code_format + assert_raise(CountryCodeFormatError){ CountryCode.new('Canada') } + end +end diff --git a/vendor/gems/active_utils-1.0.5/test/unit/country_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/country_test.rb new file mode 100644 index 000000000..62fcb761b --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/country_test.rb @@ -0,0 +1,68 @@ +require 'test_helper' + +class CountryTest < Test::Unit::TestCase + def test_country_from_hash + country = Country.new(:name => 'Canada', :alpha2 => 'CA', :alpha3 => 'CAN', :numeric => '124') + assert_equal 'CA', country.code(:alpha2).value + assert_equal 'CAN', country.code(:alpha3).value + assert_equal '124', country.code(:numeric).value + assert_equal 'Canada', country.to_s + end + + def test_country_for_alpha2_code + country = Country.find('CA') + assert_equal 'CA', country.code(:alpha2).value + assert_equal 'CAN', country.code(:alpha3).value + assert_equal '124', country.code(:numeric).value + assert_equal 'Canada', country.to_s + end + + def test_country_for_alpha3_code + country = Country.find('CAN') + assert_equal 'Canada', country.to_s + end + + def test_country_for_numeric_code + country = Country.find('124') + assert_equal 'Canada', country.to_s + end + + def test_find_country_by_name + country = Country.find('Canada') + assert_equal 'Canada', country.to_s + end + + def test_find_unknown_country_name + assert_raise(InvalidCountryCodeError) do + Country.find('Asskickistan') + end + end + + def test_find_australia + country = Country.find('AU') + assert_equal 'AU', country.code(:alpha2).value + + country = Country.find('Australia') + assert_equal 'AU', country.code(:alpha2).value + end + + def test_find_united_kingdom + country = Country.find('GB') + assert_equal 'GB', country.code(:alpha2).value + + country = Country.find('United Kingdom') + assert_equal 'GB', country.code(:alpha2).value + end + + def test_raise_on_nil_name + assert_raise(InvalidCountryCodeError) do + Country.find(nil) + end + end + + def test_country_names_are_alphabetized + country_names = Country::COUNTRIES.map { | each | each[:name] } + assert_equal(country_names.sort, country_names) + end + +end diff --git a/vendor/gems/active_utils-1.0.5/test/unit/network_connection_retries_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/network_connection_retries_test.rb new file mode 100644 index 000000000..325ea0dbb --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/network_connection_retries_test.rb @@ -0,0 +1,127 @@ +require 'test_helper' +require 'openssl' +require 'net/http' + +class NetworkConnectionRetriesTest < Test::Unit::TestCase + class MyNewError < StandardError + end + + include NetworkConnectionRetries + + def setup + @logger = stubs(:logger) + @requester = stubs(:requester) + @ok = stub(:code => 200, :message => 'OK', :body => 'success') + end + + def test_unrecoverable_exception + assert_raises(ActiveMerchant::ConnectionError) do + retry_exceptions do + raise EOFError + end + end + end + + def test_unrecoverable_exception_logged_if_logger_provided + @logger.expects(:error).once + assert_raises(ActiveMerchant::ConnectionError) do + retry_exceptions :logger => @logger do + raise EOFError + end + end + end + + def test_failure_then_success_with_recoverable_exception + @requester.expects(:post).times(2).raises(Errno::ECONNREFUSED).then.returns(@ok) + + assert_nothing_raised do + retry_exceptions do + @requester.post + end + end + end + + def test_failure_limit_reached + @requester.expects(:post).times(ActiveMerchant::NetworkConnectionRetries::DEFAULT_RETRIES).raises(Errno::ECONNREFUSED) + + assert_raises(ActiveMerchant::ConnectionError) do + retry_exceptions do + @requester.post + end + end + end + + def test_failure_limit_reached_logs_final_error + @logger.expects(:error).once + @requester.expects(:post).times(ActiveMerchant::NetworkConnectionRetries::DEFAULT_RETRIES).raises(Errno::ECONNREFUSED) + + assert_raises(ActiveMerchant::ConnectionError) do + retry_exceptions(:logger => @logger) do + @requester.post + end + end + end + + def test_failure_then_success_with_retry_safe_enabled + @requester.expects(:post).times(2).raises(EOFError).then.returns(@ok) + + assert_nothing_raised do + retry_exceptions :retry_safe => true do + @requester.post + end + end + end + + def test_mixture_of_failures_with_retry_safe_enabled + @requester.expects(:post).times(3).raises(Errno::ECONNRESET). + raises(Errno::ECONNREFUSED). + raises(EOFError) + + assert_raises(ActiveMerchant::ConnectionError) do + retry_exceptions :retry_safe => true do + @requester.post + end + end + end + + def test_failure_with_ssl_certificate + @requester.expects(:post).raises(OpenSSL::X509::CertificateError) + + assert_raises(ActiveMerchant::ClientCertificateError) do + retry_exceptions do + @requester.post + end + end + end + + def test_failure_with_ssl_certificate_logs_error_if_logger_specified + @logger.expects(:error).once + @requester.expects(:post).raises(OpenSSL::X509::CertificateError) + + assert_raises(ActiveMerchant::ClientCertificateError) do + retry_exceptions :logger => @logger do + @requester.post + end + end + end + + def test_failure_with_additional_exceptions_specified + @requester.expects(:post).raises(MyNewError) + + assert_raises(ActiveMerchant::ConnectionError) do + retry_exceptions :connection_exceptions => {MyNewError => "my message"} do + @requester.post + end + end + end + + def test_failure_without_additional_exceptions_specified + @requester.expects(:post).raises(MyNewError) + + assert_raises(MyNewError) do + retry_exceptions do + @requester.post + end + end + end +end diff --git a/vendor/gems/active_utils-1.0.5/test/unit/post_data_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/post_data_test.rb new file mode 100644 index 000000000..dd22426f8 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/post_data_test.rb @@ -0,0 +1,50 @@ +require 'test_helper' + +class MyPost < ActiveMerchant::PostData + self.required_fields = [ :ccnumber, :ccexp, :firstname, :lastname, :username, :password, :order_id, :key, :time ] +end + +class PostDataTest < Test::Unit::TestCase + def teardown + ActiveMerchant::PostData.required_fields = [] + end + + def test_element_assignment + name = 'Cody Fauser' + post = ActiveMerchant::PostData.new + + post[:name] = name + assert_equal name, post[:name] + end + + def test_ignore_blank_fields + post = ActiveMerchant::PostData.new + assert_equal 0, post.keys.size + + post[:name] = '' + assert_equal 0, post.keys.size + + post[:name] = nil + assert_equal 0, post.keys.size + end + + def test_dont_ignore_required_blank_fields + ActiveMerchant::PostData.required_fields = [ :name ] + post = ActiveMerchant::PostData.new + + assert_equal 0, post.keys.size + + post[:name] = '' + assert_equal 1, post.keys.size + assert_equal '', post[:name] + + post[:name] = nil + assert_equal 1, post.keys.size + assert_nil post[:name] + end + + def test_subclass + post = MyPost.new + assert_equal [ :ccnumber, :ccexp, :firstname, :lastname, :username, :password, :order_id, :key, :time ], post.required_fields + end +end diff --git a/vendor/gems/active_utils-1.0.5/test/unit/posts_data_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/posts_data_test.rb new file mode 100644 index 000000000..e0d8b23d5 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/posts_data_test.rb @@ -0,0 +1,35 @@ +require 'test_helper' +require 'active_support/core_ext/class' + +class PostsDataTest < Test::Unit::TestCase + + class SSLPoster + include PostsData + + attr_accessor :logger + end + + def setup + @poster = SSLPoster.new + end + + def test_logger_warns_if_ssl_strict_disabled + @poster.logger = stub() + @poster.logger.expects(:warn).with("PostsDataTest::SSLPoster using ssl_strict=false, which is insecure") + + Connection.any_instance.stubs(:request) + + SSLPoster.ssl_strict = false + @poster.raw_ssl_request(:post, "https://shopify.com", "", {}) + end + + def test_logger_no_warning_if_ssl_strict_enabled + @poster.logger = stub() + @poster.logger.stubs(:warn).never + Connection.any_instance.stubs(:request) + + SSLPoster.ssl_strict = true + @poster.raw_ssl_request(:post, "https://shopify.com", "", {}) + end + +end diff --git a/vendor/gems/active_utils-1.0.5/test/unit/utils_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/utils_test.rb new file mode 100644 index 000000000..6a78ea4f9 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/utils_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class UtilsTest < Test::Unit::TestCase + def test_unique_id_should_be_32_chars_and_alphanumeric + assert_match /^\w{32}$/, ActiveMerchant::Utils.generate_unique_id + end +end diff --git a/vendor/gems/active_utils-1.0.5/test/unit/validateable_test.rb b/vendor/gems/active_utils-1.0.5/test/unit/validateable_test.rb new file mode 100644 index 000000000..d0cf67c76 --- /dev/null +++ b/vendor/gems/active_utils-1.0.5/test/unit/validateable_test.rb @@ -0,0 +1,59 @@ +require 'test_helper' + +class Dood + include ActiveMerchant::Validateable + + attr_accessor :name, :email, :country + + def validate + errors.add "name", "cannot be empty" if name.blank? + errors.add "email", "cannot be empty" if email.blank? + errors.add_to_base "The country cannot be blank" if country.blank? + end + +end + +class ValidateableTest < Test::Unit::TestCase + + def setup + @dood = Dood.new + end + + def test_validation + assert ! @dood.valid? + assert ! @dood.errors.empty? + end + + def test_assigns + @dood = Dood.new(:name => "tobi", :email => "tobi@neech.de", :country => 'DE') + + assert_equal "tobi", @dood.name + assert_equal "tobi@neech.de", @dood.email + assert @dood.valid? + end + + def test_multiple_calls + @dood.name = "tobi" + assert !@dood.valid? + + @dood.email = "tobi@neech.de" + assert !@dood.valid? + + @dood.country = 'DE' + assert @dood.valid? + end + + def test_messages + @dood.valid? + assert_equal "cannot be empty", @dood.errors.on('name') + assert_equal "cannot be empty", @dood.errors.on('email') + assert_equal nil, @dood.errors.on('doesnt_exist') + + end + + def test_full_messages + @dood.valid? + assert_equal ["Email cannot be empty", "Name cannot be empty", "The country cannot be blank"], @dood.errors.full_messages.sort + end + +end diff --git a/vendor/gems/activemerchant-1.33.0/CHANGELOG b/vendor/gems/activemerchant-1.33.0/CHANGELOG new file mode 100644 index 000000000..17ad36b74 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/CHANGELOG @@ -0,0 +1,1143 @@ += ActiveMerchant CHANGELOG + +== Version 1.33.0 (May 30, 2013) + +* Netaxept: Completely revamped to use the "M" service type [rbjordan3, ntalbott] +* Litle: Void authorizations via an auth reversal [jrust] +* Add RBK Money integration [england] +* Direcpay: Update test url [ashish-d] +* PayPal Express gateway: Add support for creating billing agreements [fabiokr] +* PayPal Express gateway: Add reference authorizations [fabiokr] +* Add Cardstream Modern gateway [ExxKA] +* Pin: Fix special headers [duff] +* PayPal Express gateway: Remember the billing agreement id as Response#authorization [duff] +* PayPal Express gateway: Allow an amount of 0 [duff] +* PayPal Express gateway: Reduce parameter requirements [duff] +* Quickpay integration: Update notification parser to handle API v6 [larspind] +* Sage gateway: Deprecate #credit call [duff] +* Update notification generator to better match current notification class [lulalala] +* Paymill gateway: Change .com -> .de [louiskearns] +* Quickpay integration: Fix v6 response parsing [larspind] +* First Data e4: Add TransArmor store/tokenization support [gabetax] +* MerchantWarrior: Format expiration month/year correctly [klebervirgilio] +* Add iconv for ActiveSupport 2.3 under Ruby 2.0 [sanemat] +* Add Transnational gateway [bvandenbos] +* Authorize.Net: Add Check as payment method [andrunix] +* Merchant e-Solutions: Add ref number and recurring support [carlaares] +* Bogus gateway: Add authorization to purchase response [hron] +* Bluepay gateway: Fix Check support; general cleanup [ntalbott] +* Dwolla: Fix security issues and enable guest checkout [capablemonkey, schonfeld] +* SagePay gateway: Per-transaction 3D-secure selection [ExxKA] +* Barclays ePDQ: Handle incorrectly encoded response [jordanwheeler, aprofeit] +* Orbital: Bug fixes; add CustomerEmail, Retry Logic, Managed Billing, and Destination Address [juicedM3 +* Distinguish invalid vs empty issue_numbers on CreditCards [drasch] +* Float Gemfiles to latest Rails [sanemat] +* USA ePay Advanced: Fix Check support [RyanScottLewis] +* Authorize.Net: Match up Check fields better with eCheck.Net requirements [ntalbott] +* Bluepay: Updated to bp20post api [cagerton, melari] +* Net Registry: Deprecate credit method [jduff] +* Sage: Don't include T_customer_number unless it is numeric [melari] +* Auth.net: Don't include cust_id unless it is numeric [melari] +* Epay: Deprecate credit method [melari] +* New PayU.in Integration [PayU, melari] + +== Version 1.32.1 (April 4, 2013) + +* CC5 and Garanti: Remove $KCODE modifications [melari] +* Paymill: Add support for store [ntalbott] +* USA ePay: Fix misspelling of "Aduth" [joelvh, ntalbott] +* Orbital: Fix nil address values throwing exceptions during truncation [melari] + +== Version 1.32.0 (April 1, 2013) + +* Optimal: Submit shipping address with requests [jduff] +* Iridium: Enable reference transactions for authorize [ntalbott] +* Stripe: Add authorize and capture methods [melari] +* Pin: Add a default description if none is specified to fix failures [melari] +* Litle: Add support for passing optional fields in token based transactions [forest] +* Add Finansbank gateway [scamurcuoglu] +* Paymill: Use .com instead of .de for save card url [besi] +* Worldpay integration: Use more robust endpoint urls [nashbridges] +* Braintree Blue: Return CC token in transaction hash [cyu] +* Robokassa: Fix signature for empty amount [ukolovda] +* Worldpay gateway: Fix error messages for some failures [duff] +* Worldpay gateway: Allow settled payments to be refunded [dougal] +* Spreedly: Update urls and terminology [duff] +* Make card brand error more user friendly [oggy] +* DataCash: Update test Mastercard number [jamesshipton] +* DataCash: Update test response fixtures [jamesshipton] +* Pin: Add Pin.js card token support [nagash] +* PayPal Express gateway: Fix error when no address information is in response [pierre] +* Ogone: Use BYPSP for ALIASOPERATION [ntalbott] +* Paymill: Handle error storing card [duff] +* SagePay integration: Add referrer field [melari] +* Pin: Add extra headers [duff] +* Paymill: Add support for store [ntalbott] +* USA ePay Advanced: Fix typo in message credit card data options [joelvh] + +== Version 1.31.1 (February 25, 2013) + +* Cybersource: Bug fixes [natejgreene, jduff] + +== Version 1.31.0 (February 20, 2013) + +* Worldpay: XML encoding is required to be ISO-8859-1 [dougal] +* Worldpay: Add card code for more supported card types [dougal] +* Ogone: Add action option [pwoestelandt] +* PayPal Express gateway: Add support for BuyerEmailOptInEnable [chrisrbnelson] +* Add Paymill gateway [duff] +* Add EVO Canada gateway [alexdunae] +* Fixed credit card and check interface, used correct method for checking payment type [jduff] + +== Version 1.30.0 (February 13, 2013) + +* Add FirstData Global Gateway e4 [frobcode] +* PaymentExpress: Add support for optional fields: ClientType and TxnData [moklett] +* PaymentExpress: Limit MerchantReference/description to 64 chars [moklett] +* Wirecard: description must be no more than 32 characters [moklett] +* Litle: Add support for passing a token to the authorize and purchase methods [forest] +* PayPal Common: Allow searching for transactions by ProfileID [aq1018] +* Add Spreedly Core gateway [duff] +* eWay Gateway: Return proper value for authorization [duff] +* eWay Gateway: Add support for refunds [duff] +* Quickpay: Add support for protocols 5 & 6 [twarberg] +* Banwire gateway: Handle JSON::ParserError [duff] +* Balanced gateway: Fix unspecified marketplace [duff] +* QBMS gateway: Allow partial addresses [duff] +* Authorize.Net CIM: Allow omitting card expiration date [shanebonham] +* Authorize.Net CIM: Add support for extraOptions to createCustomerProfileTransaction [tpiekos] +* Add NETPAY gateway [samlown] +* Balanced gateway: Add amount to the refund method signature [ntalbott] +* Orbital gateway: Fix void method signature [aprofeit, ntalbott] +* Eway Managed: Add 'query_customer' API as #retrieve [cdaloisio] +* NetPay: Fix the signature for void [duff] +* Cybersource: Add check support [bowmande] +* Moneris: Use a capture of $0 for void [ntalbott] +* PayPal Express integration: Fix received_at time zone [ntalbott] +* NAB Transact: Add refund capability [nagash] +* Stripe: Add support for application_fee [duff] +* SagePay: Add support for GiftAidPayment [duff] +* Wirecard: Add support for partial captures [richardblair] +* Add Pin gateway [madpilot] +* Balanced: Added support for on_behalf_of_uri to capture [cwise] +* Litle: Add support for passing an order_source [forest] +* Add Merchant Warrior gateway [pronix, Fodoj, ntalbott] +* Use v4 of the MerchantWare API for voiding transactions [melari] +* Add support for Authorize.net in CA and GB [melari] +* Send customer's IP to Beanstream for fraud review [melari] + +== Version 1.29.3 (December 7, 2012) + +* Braintree Blue: Better wiredump_device support [ntalbott] +* Braintree: Store sets vault id as authorization [ntalbott] +* WorldPay: Fix currencies without fractions like JPY and HUF by rounding down amount [Soleone] + +== Version 1.29.2 (December 7, 2012) + +* Moneris: fix issue with the default options not being merged [jduff] +* Sage Pay: Make 0000 default post code for everyone if missing [BlakeMesdag] + +== Version 1.29.1 (December 5, 2012) + +* Add eWay Rapid 3.0 gateway [ntalbott] +* Fix AVS responses missing attributes [jduff] + +== Version 1.29.0 (November 30, 2012) + +* Authorize.Net gateway: Support description and order_id for capture [ntalbott] +* Add Mercury gateway [adr1anx, opendining] +* Webmoney integration: Add gross, item_id, and amount accessors to notification [fr33z3] +* Fix running tests under ActiveSupport 2.3.14 [ntalbott] +* SagePay Form integration: Remove dependency on ActiveSupport's String#truncate [ntalbott] +* Elavon gateway: Add support for the sales tax parameter [stevestmartin] +* Add WebPay gateway [keikubo] +* iTransact gateway: make void API consistent [frobcode] +* Stripe gateway: Pass city in add_address [npverni] +* Paypal gateway: Add option to change the outstanding balance of a recurring billing profile [mattwhite] +* Mercury gateway: Fix authorizations API [ntalbott] +* Mercury gateway: Support refund properly [ntalbott] +* Braintree Blue gateway: Add support for the recurring flag [ntalbott] +* Add HDFC gateway [ntalbott] +* HDFC gateway: Add more supported currencies [ntalbott] +* HDFC gateway: Add support for passing ECI value [ntalbott] +* HDFC gateway: Allow setting test mode via options [ntalbott] +* HDFC gateway: Pass phone number in UDF3 [ntalbott] +* HDFC gateway: Fix unescaped '&' entity in XML [ntalbott] +* HDFC gateway: More robust entity fixing [ntalbott] +* Add A1Agregator integration [england] +* Refactored handling of #test? and @options [ntalbott] +* Realex gateway: Realex gateway: Fix billing address format [ntalbott] +* Orbital gateway: handle custom AVS response codes [jonm-okc] +* Orbital gateway: Fix infinite connection retry [jonm-okc, ntalbott] +* PayPal integration: Add support for MassPay IPN notifications [damonmorgan] +* Orbital gateway: Fix status of void result [jonm-okc] +* Add Redsys gateway [samlown] +* Cybersource gateway: Add support for subscription credit [fabiokr] +* Use Thor for generators [ntalbott] +* Psigate gateway: Add void support [samuelreh] +* Add Liqpay integration [beorc] +* Paypal Express gateway: Add shipping accessor to response [v-fedorov] + +== Version 1.28.0 (August 10, 2012) + +* PayPal Express: support non standard locale codes [Soleone] +* Litle: allow setting test mode per transaction [jduff] +* Add Banwire gateway [acolin] +* Authorize.Net CIM gateway: Move cardCode after order to comply with the XSD [davetron5000] +* Add WebMoney integration [Mehonoshin] +* EasyPay: Make symmetric with other integrations [nashby] +* Add Paysbuy integration [divineforest] +* Bogus gateway: Use last digit for pass/fail [mipearson] +* Elavon gateway: Separate from Viaklix, implement refund & void [duff] +* Orbital gateway: Update to API version 5.6 and add support for profile requests [rbarazi] + +== Version 1.27.0 (August 10, 2012) + +* Add First Data integration [courtland] +* Add WebPay integration [nashby] +* Add Suomen Maksuturva integration [akonan] +* Payway gateway: Fix card storage [BenZhang] +* Payflow Pro gateway: Add MaxFailPayments support [gregwinn] +* Add Paxum integration [Mehonoshin] +* Add Balanced gateway [mjallday] +* Plug'n Pay gateway: Add tests for partial capture [csaunders] +* Braintree Blue gateway: Add credit card details to responses [dougbradbury] +* PayPal gateway: Support for 'Full' refund type [kurenn] +* Worldpay: fix refund [jduff/omh] +* Add PxPay offsite integration [boourns] +* Wirecard: always capture 'authorization' transaction [ntalbott] +* Add rake task to verify ssl certs [boourns] + +== Version 1.26.0 (July 6, 2012) + +* Orbital gateway: fix broken requests by ensuring the order of XML elements matches their DTD [Soleone] +* CyberSource gateway: clean up formatting [ntalbott] +* Netbilling gateway: Add refund/credit/void support [ntalbott] +* Add PayGate XML gateway [rubyisbeautiful] +* Add PayWay gateway [BenZhang] +* PayWay gateway: Tweaks to make more ActiveMerchant like [ntalbott] +* Netbilling gateway: Fix error handling [ntalbott] +* Netbilling gateway: Add refund/credit/void support [zenom, ntalbott] + +== Version 1.25.0 (July 3, 2012) + +* eWAY gateway: Add support for Diners Club cards [Soleone] +* Orbital gateway: Never send country code for orders outside of US, CA and GB [Soleone] +* Add EasyPay integration [nashby] +* Updating LitleOnline requirement to 8.13.2 to take advantage of better validation and get bugfix for Username [GregDrake] +* USAepay gateway: Add description support [ntalbott] +* Add Paypal Payments Advanced integration [csaunders] +* Authorize.Net gateway: Improve #refund docs [neerajdotname] +* Wirecard gateway: Fix for missing address hash [ntalbott] +* Clean up requires of RubyGems and JSON gems. Rename remote Litle test to match naming conventions [codyfauser] +* Cybersource gateway: Fix updating address only [fabiokr] +* Cybersource gateway: Move email requirement [fabiokr] +* Add the Metrics Global gateway [DanKnox] +* Braintree Blue gateway: Support wiredump_device [moklett] +* Add Fat Zebra gateway [amasses] +* Braintree Blue gateway: Always pass CVV on update [shayfrendt] +* eWAY gateway: Update docs. Require address [juggler] +* Cybersource gateway: Add support for subscriptions [fabiokr] + +== Version 1.24.0 (June 8, 2012) + +* PayPal gateway: Support for incomplete captures [mbulat] +* Moneris gateway: Add support for vault [kenzie] +* NAB Transact gateway: Add support for card descriptors [nagash] +* SagePayForm: truncate long description fields [jnormore] +* Paybox Direct: treat all response codes besides '00000' as failures +[Soleone] +* Deprecate CreditCard#type method in favor of CreditCard#brand [jduff] +* Cybersource gateway: Add subscriptions support [fabiokr, jaredmoody] +* eWay gateway: Improved docs, and more accurate required parameters [juggler] +* Braintree Blue gateway: Always pass CVV on card update [shayfrendt] +* Add Fat Zebra gateway [amasses] +* Braintree Blue gateway: Add support for wiredump_device [moklett] +* Add Metrics Global gateway [DanKnox] +* Cybersource gateway: Do not require email address for subscription operations [fabiokr] +* Cybersource gateway: Fix passing only an address when updating a subscription [fabiokr] +* Wirecard gateway: Fix for missing address; general cleanup [ntalbott] +* Authorize.Net gateway: Document ability to just pass the last four to #refund [neerajdotname] +* Add EasyPay integration [nashby] + +== Version 1.23.0 (May 23, 2012) + +* Add Litle gateway [GregDrake] +* PaymentExpress gateway: add support for BillingId and DpsBillingId for token [mikel] +* 2checkout integration: Add ability to auto settle [craigchristenson] +* 2checkout integration: Switch default mode to single page [craigchristenson] +* Cybersource: Revert - Add retrieve method to pull details on a +stored card [jduff] +* Cybersource: Revert - Add recurring payment support [jduff] +* PaymentExpress: add Cvc2Presence flag when submitting verification +value [jduff] +* SecurePayAU: fix CreditCard check [jduff] +* Barclays: fix order capture [csaunders/ntalbott/jduff] + +== Version 1.22.0 (May 17, 2012) + +* Remove version restriction for money gem [ylansegal] +* Add iTransact XML gateway [motske] +* PayPal Express Gateway: add options[:landing_page] [markus] +* USA ePay: Fix handling of AVS [duff] +* Ogone: Add store method to create an alias without making a purchase [joelcogen] +* Spelling fix: purcahse -> purchase [mnoack] +* ePay: Added more useful results for authorization errors [Dennis O'Connor] +* Add Robokassa integration [nashby] +* PayPal Gateway: Add recurring API [dscataglini] +* Braintree: Add support for :verify_card option on store [brentmc79] +* Moneris: cannot void a preauthorization [eddanger] +* Add Moneris US gateway [eddanger] +* Add Dotpay integration [kacperix] +* Payflow: Add description, comment and comment2 tags [ksnyder] +* Dotpay: Fix field mapping [kacperix] +* Authorize.Net CIM: Optionally add 'order' details to transactions [pote] +* Braintree: Allow including billing address when storing a customer [brentmc79] +* PayPal Gateway: Refactored PaymentDetails & PaymentDetailsItem common code [dscataglini] +* Viaklix/Elavon: Separate "demo accounts" from "test transactions" [mltsy] +* PayPal Gateway: Add transaction_details, balance, authorize_transaction, and manage_pending_transaction API calls [dscataglini] +* PayPal Gateway: Add support for TransactionSearch & DoReferenceTransaction [dscataglini] +* Cybersource: Add recurring payment support [jaredmoory] +* Tidy up gateway lists [ashokak] +* Paybox: remove Iconv usage [ntalbott] +* Dotpay: Add amount mapping, pin setter, and support for test? [kacperix] +* Braintree Blue: Make address country map to alpha2 [ntalbott] +* Use GB as the alpha2 country code for the UK [ntalbott] +* Realex: Handle XML response with unescaped ampersand [ntalbott] +* Add Vindicia gateway [steved555] +* Payment Express: use %w[] for country list [parndt] +* Braintree Blue: Match remote test up with change to :country [braintreeps] +* PayPal Integration: Fix received_at method time parsing [subbarao] +* Add MiGS Gateway [mnoack, nagash] +* Quickpay integration: Fix payment_service_for helper [TheMaster] +* Braintree Blue gateway: Improve update method [brentmc79] +* 2checkout integration: Add mode mapping & line items helper [AlexanderZaytsev] +* USA ePay Advanced gateway: Fix expiration date format. [cctalbott] +* Add ePay integration [ePay] +* 2checkout integration: Add support for single page payment routine [AlexanderZaytsev] +* Ogone: Add support for 3D Secure [rymai, ZenCocoon] +* Stripe gateway: Remove authorize and capture methods since they are not supported [jduff] +* Stripe gateway: default test to false if no livemode parameter is specified [jduff] +* Paybox Direct gateway: 'card absent' and 'do not honour' should be considered failures, not fraudulent [jduff] +* Add Verkkomaksut integration [akonan] +* Remove trailing spaces from generator templates [akonan] +* Payflow gateway: Allow modification of RetryNumDays [jrust] +* Payflow gateway: Don't auto-set start_date on modification [jrust] +* Bluepay gateway: Add ACH & recurring support [jslingerland] +* Orbital gateway: Don't send AVS address details for any country besides US, CA, GB and UK [Soleone] +* Payflow Express gateway: Better amount handling [jduff] +* Barclays gateway: Allow American Express [duff] +* Ogone gateway: Remove duplicated method [ntalbott] +* Cybersource gateway: Add retrieve method to pull details on a stored card [fabiokr] + +== Version 1.21.0 (March 7, 2012) + +* Stripe: Add support for passing IP [collision] +* Merchant e-Solutions: pass expiration date when purchasing with a stored credit card [chrisyoung] +* Braintree: Fix passing custom processor ids to old accounts [maxsilver] +* Authorize.net CIM: Add validation mode option to create_customer_profile_request [jwood] +* eWay Managed: Include transaction number in response params [jamsi] +* Fix various hash ordering issues exposed by Ruby 1.8 [ntalbott] +* Authorize.Net CIM: Add WEB echeck type [deathbob] +* Move Braintree from the gemspec to the Gemfile [ntalbott] +* Add CertoDirect gateway [hron] +* Authorize.Net CIM: Add option for setting a custom delimiter [bmorton] +* Authorize.Net CIM: Add 3.1 response fields [bmorton] +* Authorize.Net CIM: Misc fixes and doc improvements [bmorton] +* Authorize.Net CIM: Fix error when order is blank [KeeperPat] +* Beanstream: Add recurring payments support [castiglione] +* Make ePay password optional [ePay] +* Quickpay: skip testmode if transaction provided [brentmc79] +* Payflow: add additional fields [thorstadt] +* Authorize.Net CIM: Add get_customer_profile_ids [howaboutwe] +* PayPal Express: Add support for BrandName and Custom fields [exviva] +* Payflow: Handle dates with leading zeros [jcoleman] +* Authorize.Net CIM: Add CCV code support & improve tests [tgarnett] +* Add Authorize.Net SIM integration [courtland & rdp] +* Secure Pay AU: Handle periodic payments [tommeier] +* Viaklix: Add discover as a supported card type [waelchatila] +* Improvements to testing infrastructure for integrations [jduff] +* Add NAB Transact (AU) Gateway [tommeier] +* PayPal Express: Add Support for Reference Transactions using BAIDs [kenmazaika] +* Authorize.Net CIM: Add support for optional refund fields [nilmethod] +* SecurePayTech: Fix EnableCSC parameter so CVV codes are checked. [tlconnor] +* SecurePayTech: Add remote tests for CSC checking. [tlconnor] +* Samurai: Add option to retain payment methods once stored [brentmc79] +* PayPal Express Gateway: Add support for Digital Goods / Micropayments [kenmazaika] + + +== Version 1.20.4 (February 22, 2012) + +* Fix json dependency + +== Version 1.20.3 (February 7, 2012) + +* Various fixes to support Ruby 1.9 [wisq] +* SkipJack: Fix partial capture [jduff] +* Optimal Payments: submit region when outside North America [jduff] +* USA ePay: Add void and refund support [duff/ntalbott] +* Add first digits to credit card [codyfauser] +* Orbital: fixes to authentication and order id [Soleone] +* Stripe: fixes to purchase method [duff/ntalbott] + +== Version 1.20.2 (January 16, 2012) + +* Remove authorize/capture support for Stripe [gdb] + +== Version 1.20.1 (December 22, 2011) + +* PayflowExpressUk: Fix parsing street2 from response [odorcicd] +* AuthorizeNet: Support tracking id [odorcicd] +* SagePay Form: Map billing address to shipping address [jduff] + +== Version 1.20.0 (November 14, 2011) + +* Add support for USA ePay Advanced SOAP interface [matthewcalebsmith/jduff] +* Beanstram: fix purchase with Secure Profile [pitr/jduff] +* Orbital: various fixes [Soleone] +* Add Samuari gateway by Fee Fighters [jkrall/odorcicd] +* Lock money gem to 3.7.1 or less since newer versions break in 1.9 [jduff] +* Braintree: handle gateway rejected transactions gracefully [braintreeps/jduff] +* Ogone: support different signature encryptors, custom currency and eci [ZenCocoon/rymai/jduff] +* Payflow Link: use secure token [jduff] +* Added refund method to Exact, Pay Junction and Skip Jack gateways [jduff] +* Elavon: added test url [kylekeesling/jduff] +* Fix redundent errors when credit card is expired [castiglione/jduff] +* Two Checkout: update service url [vampirechicken/jduff] + +== Version 1.18.1 (September 23, 2011) + +* Braintree: allow setting merchant_account_id on initialize [jduff] +* Realex: only send letters and numbers in shipping code field [Soleone] + +== Version 1.18.0 (September 23, 2011) + +* NoChex: Update the URL that payment requests are posted to [caseywhalen/jduff] +* QBMS: fixed test mode check [Soleone] +* Realex: encode avs info with shipping address [Soleone] +* Add Dwolla offsite gateway [armsteadj1/jduff] +* Eway: pass email, customer, description and options to store [moklett/tobi] +* New dependency: active_utils gem [odorcicd] +* Optimal Payments: fix test mode check [jduff] + +== Version 1.17.0 (August 23, 2011) + +* Add Payflow Link integration [jduff] +* Add CardSave gateway [MrJaba/jduff]] +* Quickpay: Support protocal version 4 and fraud parameters [anderslemke/jduff] +* Authorize.net: Add status_recurring [mm1/jduff] +* Paypal Express: Support specifying :items with purchase [sivabudh/jduff] +* ePay: Add Sweden and Norway to supported countries [ePay/jduff] +* Brainreee: Support passing merchant_account_id parameter [braintreeps/jduff] +* Paypal Express: Remove deprecated Address field in favor of ShipToAddress[jduff] +* Add Optimal Payments gateway [jamie/jduff] +* Documentation improvements [dasch/nhemsley/jstorimer/jduff] +* Authorize.Net: Pass through first name, last name, and zip for refunds. [ntalbott] + +== Version 1.16.0 (July 18, 2011) + +* Bogus: Support referenced transactions for #authorize, #purchase, #recurring and +#credit [dasch/jduff] +* Payment Express: Update gateway url [bayan/titanous] +* Moneybookers: Send country and account_name if provided [Soleone] +* Moneris: Add Diners Club and Discover [Soleone] +* Cybersource: add auth_reversal support [jeberly/titanous] +* WorldPay: Update endpoint URLs for offsite gateway [Soleone] +* Worldpay: Add JCB and add Maestro [Soleone] +* Authorize.net: Add Diners Club and JCB [Soleone] +* Quickpay: Add testmode for subscribe and authorize [dasch/jduff] +* Orbital: fix handling of phone numbers. [ntalbott] +* Braintree: Add Diners Club [cody] +* Add ePaymentPlans offsite payment [robertomiranda/Soleone] +* Add Stripe gateway [boucher/titanous] +* Add Paystation gateway [nikz/jduff] +* Bump minimum ActiveSupport version to 2.3.11 [titanous] +* Use securerandom from stdlib not active_support [phlipper/jduff] + +== Version 1.15.0 (May 12, 2011) + +* DirecPay: Fix address to not include address2 twice in some cases [Soleone] +* DirecPay: Send company if available [Soleone] +* Realex: Fix hash signature [ntalbott/Soleone] +* SecurePay AU: Update remote tests [ntalbott] +* SecurePay AU: Fix method arity for #capture, #refund, #credit and #void [Soleone] +* Barclays ePDQ: Make response parsing more robust [Soleone] +* Payflow Express: Add line item support [wolframarnold] +* Payflow Express: Add comment field support [wolframarnold] +* Payflow: Add more optional fields [wolframarnold] +* Beanstream/Paypal: Fix CREDIT_DEPRECATION_MESSAGE errors [Jonathan Rudenberg] +* BraintreeBlue: Return a hash instead of a transaction object [braintreeps] +* BraintreeBlue: Return proper AVS/CVV values [braintreeps] +* Bogus: Add #recurring [trwomey] +* Make Validateable compatible with ActiveModel [CodeMonkeySteve] +* Add DirectEBanking offsite gateway [Gerwin Brunner/Soleone] +* ActiveSupport 3.1 beta support [cgriego] + +== Version 1.14.0 (Apr 29, 2011) + +* SagePayForm: Implement #cancelled? for Return. [wisq] +* Add #cancelled? to Integrations::Return [wisq] +* Bogus gateway: Add refund support and better tests [wisq] +* Beanstream: Add support for storing cards [duffomelia] +* eWay: Add support for storing cards [duffomelia] +* Add validation mode to update profile request [Ken Miller] +* Authorize.net CIM: Add oldLiveMode [ntalbott] +* Authorize.net CIM: Add extra transaction types [Ken Miller] +* JetPay: gateway tweaks [ntalbott] +* Deprecate a bunch more #credit methods [ntalbott] +* RealEx: Add authorize/capture/credit/void [ntalbott] +* SecurePay AU: Add authorize/capture/credit/void [ntalbott] +* PayPal Express: Make response parsing more robust [ntalbott] +* Test deprecation warnings; add deprecation line numbers [ntabott] +* Add Orbital direct gateway [ntalbott] +* Add WorldPay direct gateway [ntalbott] + +== Version 1.13.0 (Apr 19, 2011) + +* Add a Gemfile for optional bundler support [ssoroka] +* Stop using has_rdoc= when rubygems version is 1.7.0 or greater, since it's deprecated [ssoroka] +* Add tax field to braintree [wisq] +* Quickpay: Also add Sweden as supported country [Soleone] +* Adding refund method for gateways that are using the credit method for referenced based refunds, added deprecation worning to the credit method [John Duff] +* Return the Braintree transaction id in the response for void and refund transaction calls [John Duff] +* PayPal Express: Extract phone number from address if no contact phone was sent [Soleone] +* Unify all offsite gateways that verify the signature of Returns or Notifications by always using the #acknowledge method and calling the secret :credential2 [Soleone] +* Valitor: Change name of credential for Return and Notification from :password to :credential2 in symmetry with the other Integrations [Soleone] +* Moneybookers: Add support for tracking token [Soleone] +* Moneybookers: Require credential when creating Notifications instead of adding an argument to #acknowledge [Soleone] +* Moneybookers: Fix Notification to return correct status [Soleone] +* Support default Return class for all Integrations that don't use returns [Soleone] +* Add support for passing additional options when creating a Notification to all Integrations [Soleone] +* Update BraintreeBlue#refund to have consistent method signature [Jonathan Rudenberg] +* Add rails/init.rb for gem campatability in Rails [Rūdolfs Ošiņš] +* Fix Paypal Express response parser [Jonathan Rudenberg] +* Braintree/Transax: Add tax field [wisq] + +== Version 1.12.1 (Mar 21, 2011) + +* Ogone: Make sure response.params is a real Hash [Soleone] +* WorldPay: Fix service_url in production mode [Soleone] + +== Version 1.12.0 (Mar 1, 2011) + +* DirecPay: Send phone number as mobile phone by default [Soleone] +* Support sending line items for PayPal Express transactions [Jonathan Rudenberg] +* Update PayPal Express XML format to latest version [Jonathan Rudenberg] +* Fix custom image header for PayPal Express [mwagg] +* Add InvoiceID and OrderDescription to PayPal Express Authorize and Capture [cody] +* Add Moneybookers integration [Alex Diakov] +* Add QBMS (Quickbooks Merchant Services) gateway [ntalbott] +* Add NMI gateway [ntalbott] +* Make fully compatible with Rails 2 & 3, and Ruby 1.8 & 1.9 [ntalbott] +* Authorize.Net: Only return AVS message for AVS-related reason codes. [ntalbott] +* Add Federated Canada gateway [ntalbott] +* Garanti: Fix text normalization for nil values [Selem Delul] +* Valitor: Always send amount without any decimal places [Soleone] +* Add WorldPay integration [Soleone] + +== Version 1.11.0 (Feb 11, 2011) + +* Bump dependency for activesupport from 2.3.2 to 2.3.8 [Soleone] +* Garanti: Normalize text in xml fields for non-standard characters [Selem Delul] +* Garanti: Make sure order number does not contain illegal characters [Soleone] +* Fix ActionView tests for ActiveSupport 3.0.4 [Soleone] +* DirecPay: Make address information editable by default [Soleone] +* Fix ePDQ credit to expect and handle full authorization [Nathaniel Talbott] +* Add Barclays ePDQ Gateway [Nathaniel Talbott] +* Add default fixture for Garanti and don't use fixture for Garanti [cody] +* Add cms param for ePay [ePay] +* Add Valitor Integration [Nathaniel Talbott] + +== Version 1.10.0 (Jan 20, 2011) + +* PayPal Express: Support returning payer phone number [Soleone] +* Fix ePay to correctly send order number [Soleone] +* Add BluePay Gateway [Nathaniel Talbott] +* Add Quantum Gateway [Joshua Lippiner] +* Add iDEAL/Rabobank gateway [Jonathan Rudenberg] +* SagePayForm: Added send_email_confirmation (default false) to enable confirmation emails [wisq] + +== Version 1.9.4 (Jan 5, 2011) + +* Update Garanti gateway to integrate with new API [Selem Delul] + +== Version 1.9.3 (December 17, 2010) + +* Fix BBS Netaxept to change transaction type from C (for MOTO: mail order telephone order) to M (for credit card orders) [Soleone] +* Fix Iridium and ePay to work with any object that responds to credit card methods not only ActiveMerchant::CreditCard objects + +== Version 1.9.2 (December 9, 2010) + +* Add support for PayPal mobile payments [wisq] +* Add ePay gateway [ePay, Jonathan Rudenberg] +* Allow access to the raw HTTP response [Jonathan Rudenberg] + +== Version 1.9.1 (November 24, 2010) + +* PayPal Express and PayPal Pro: Send JPY currency correctly without decimals [Soleone] +* Netaxept: Make sure password (token) is URL escaped and update remote tests for updated server behavior [Soleone] +* DirecPay: Add support for additional options in Return class and add convenience method to get transaction status update [Soleone] +* Add new alias credit_card.brand for credit_card.type and handle the brand correctly in Netaxept [Soleone] +* Iridium: Do not depend on ExpiryDate class for credit_card [Soleone] +* PayFlow: Use same timeout of 60 seconds in HTTP header and XML for all requests [Soleone] +* PayPal Website Payments Pro CA no longer supports American Express cards [Soleone] +* Updated BIN ranges for Discover to match recent documents [kaunartist] + +== Version 1.9.0 (October 14, 2010) + +* Add support for DirecPay gateway [Soleone] +* Add SagePay Form integration gateway [wisq] +* Allow Return class to include a Notification for gateways that treat the direct response as a notification [wisq] +* Add support for PayboxDirect gateway [Donald Piret] +* Add support for SecureNet gateway [Kal] +* Add support for the Inspire gateway [ryan r. smith] + +== Version 1.8.0 (September 24, 2010) + +* PayPal Express: Add support for billing agreements [Nathaniel Talbott] +* Allow comparing countries [Nathaniel Talbott] +* Iridium: Fix country handling [Nathaniel Talbott] +* Iridium: Fix missing billing address [Nathaniel Talbott] +* Iridium: Do not pass CV2 if not present [Nathaniel Talbott] +* Add Iridium support [Phil Smy] +* Add Netaxept support [Nathaniel Talbott] +* PaymentExpress: Use Card Holder Help Text for the response message [Nathaniel Talbott] +* Sort the country name list [Duff OMelia] + +== Version 1.7.3 (September 14, 2010) + +* Fix SagePay special handling for Japanese YEN currency to not send fractional amounts [Soleone] + +== Version 1.7.2 (August 27, 2010) + +* Update Braintree integration to play nicely with the braintree 2.5.0 gem [Soleone] +* Fix SagePay to not send fractional amounts for Japanese YEN currency [Soleone] + +== Version 1.7.1 (July 28, 2010) + +* Pull in only the necessary components of Active Support. Enables use of ActiveMerchant with Rails 3 [railsjedi] + +== Version 1.7.0 (July 9, 2010) + +* Add support for new Braintree Blue Gateway (using the braintree gem) [Braintree] + +== Version 1.6.0 (July 6, 2010) + +* Add a task rake gateways:hosts to get a list of all outbound hosts and ports [cody] +* Fix test failure in chronopay helper in Ruby 1.9.1 [cody] +* Fix timezone issue in credit card test. [cody] +* Fix failing unit test for Garanti gateway [cody] +* Fix failing CyberSource remote test [Patrick Joyce] +* Support for Garanti Sanal Pos: Turkish bank and billing gateway [Selem Delul] +* Add deprecation note for Money objects to Bogus gateway [Soleone] +* Updated test URL for Merchant eSolutions and added valid remote test credentials [Soleone] +* Add new error class for SSL certificate problems in connection class [Soleone] +* Update valid_month and valid_expiry_year to coerce string arguments to integers [cody] +* Add support for displaying credit cards with PayPal Express. Use the :allow_guest_checkout => true option when setting up the transaction [Edward Ocampo-Gooding] +* Use card_brand method for checking for checks in Sage and Beanstream [cody] +* Add JCB and Diners Club to LinkPoint [Soleone] + +== Version 1.5.1 (February 14, 2010) + +* Cleanup Rakefile, add gemspec and prepare for 1.5.1 release [cody] +* Update copyright dates [cody] +* Work around SkipJack bug by reversing the order of the query params [Soleone] +* Fix uppercase character in autoload of 2Checkout's Notification class [Edward Ocampo-Gooding] +* Detect language used in Chronopay integration based on billing address country [Soleone] +* Better handle international addresses in BeanstreamGateway [Soleone] + +== Version 1.5.0 (February 2, 2010) + +* Fix Gestpay notification to avoid Ruby 1.9 warnings [cody] +* Fix Chronopay notification time parsing for Ruby 1.9 [Joe Van Dyk] +* Set default currency of Braintree to USD [cody] +* Fix QuickPay helper for Ruby 1.9 compat [cody] +* Use String#each_line instead of collect in PaySecureGateway for Ruby 1.9 compat [cody] +* Use String#each_line instead of to_a in SagePayGateway for Ruby 1.9 compat [cody] +* Don't return an array when finding the country code. Fixes issue with Ruby 1.9 [cody] +* Fix custom assertions for Ruby 1.9 [cody] +* Deprecate Money objects [cody] +* Update JCB rejex to catch all valid PANs [pjhyett] +* Remove old TransaXGateway constant [cody] +* Remove old ProtxGateway constant [cody] +* Remove old BrainTree constant [cody] +* Remove AuthorizedNet constant [cody] +* SecurePay changed their delimeter from % to ,. Update gateway to handle changes [Soleone] +* Fix documentation typo in base.rb [mig-hub] +* Add capture test to Linkpoint [Dusty Doris] +* Fix bug in Linkpoint with ternary operator and Ruby 1.9.1 [Dusty Doris] +* Add currency and processor options to Braintree gateway [cbillen] +* Unify API to always look for billing_address/address hash inside of options [stopdropandrew] +* Fix bug with Modern Payments Gateway where failure authorizations appeared to be successful [cody] +* Fix Modern Payments Gateway [cody] +* Use basic SkipJack host for all non-authorization transactions. Fix status method [cody] +* Strip non alpha numeric chars out of MerchantWare order number [cody] +* Parse complete response of Authorize.net CIM gateway [Patrick Joyce] +* Update to PayPal Sandbox URL for testing Payflow Pro Express Checkout. See Express Checkout for Payflow Pro guide [cody] +* Provide a C_STATE value of "Outside United States" for SageGateway when processing international customers [cody] +* PayPal Website Payments Pro Canada supports Amex [cody] +* Add line item support for LinkpointGateway. [Tony Primerano] +* Add support for SallieMae gateway [iamjwc] +* Add support for the JetPay gateway [Phil Ripperger, Peter Williams, cody] +* Add support for advanced SkipJack processors. Pass :advanced => true when constructing gateway [cody] +* Support test option in AuthorizeNetCimGateway [Tim] +* Improve Ogone error messages [cody] +* Add support for :test => true option to OgoneGateway [cody] +* Bump PayPal Version to 59.0 [cody] +* Add amex support to eWay gateway [cody] +* Change Payflow header X-VPS-Timeout -> X-VPS-Client-Timeout [cody] +* Fix typo preventing OgoneGateway from working in production [Nicolas Jacobeus] +* Add support for the Elavon MyVirtualMerchant gateway [jstorimer] +* Fix recurring transactions in Ogone gateway [cody] +* Fix money formatting for Ogone gateway [cody] +* Tweak Ogone gateway to use ActiveMerchant conventions for reference transactions [cody, jstorimer] +* Add support for the Ogone DirectLink payment gateway [Nicolas Jacobeus] +* Add support for the Antigua based FirstPay payment gateway [Phil R] +* Add support for PayPal reference transactions [kevin, John, Rahsun McAfee] +* Add support for the MerchantWARE payment gateway [cody] +* Rename Protx to SagePay [jstorimer] +* Allow test mode for eWay gateway [Duff OMelia] +* Don't use Time.parse for the ExpiryDate [cody] +* Add support for CVV code to Authorize.net CIM [Guy Naor] +* Add shipping address to Authorize.net [Eric Tarn] +* Don't setup the logger by default [cody] +* Refactor ActiveMerchant::Connection out of the PostsData module. Add support for logging and wiredumping requests [cody] +* Assume a valid load path when running tests [cody] +* Use SHIPTOSTREET2 element instead of STREET2 element for Payflow Express Uk address [cody] +* Clean up the test helper [cody] +* Fix DataCash unit test that was making a remote call [cody] +* Don't check Request#test? for remote PaymentExpress tests because their test environment has changed [cody] +* Update Instapay gateway to support capture and add address, order, and invoice fields. Add support for CVV and AVS response [cody] +* Add support for Instapay gateway [brahma] +* Cleanup PaymentExpress reference purchases and turn on AVS [cody] +* Add reference purchases and authorizations to PaymentExpress [mocra] +* Add support for Merchant e-Solutions Gateway [Zac Williams, Robby Russell] +* Fix Braintree unit test [cody] +* Add support for checks to SmartPs gateways [jvoohris] +* Extract SmartPs for Braintree and Transax [mmangino] +* Ruby 1.9 compatibility [bschwartz] +* Update Payflow Express to handle Street2 element [James MacAulay] +* Fix typo in Protx DeliveryState field [cody] +* Ignore Wirecard state unless it is 2 characters [Cody] +* Update Wirecard to make country and state processing more robust [Soleone] +* Update ProTX to use the latest v2.23 protocol [Tekin] + +== Version 1.4.2 (April 24, 2009) + +* Fix typo in Authorize.net CIM [infused] +* Add missing ISO countries [Edward Ocampo-Gooding] +* Add support for Guernsey to country.rb [cody] +* Add American Express to the MonerisGateway [cody] +* Use :words_connector instead of connector in RequiresParameters [cody] +* Fixed CreditCard not validating start_month and start_year when set as string [Tekin] +* Update PostsData to support get requests [cody] +* Fix broken Quickpay remote test [cody] +* Update Quickpay gateway to v3. Add support for offsite integration for Danish Dankort cards [Lars Pind] +* Use default partner id when passed in :partner is blank with PayflowGateway [cody] +* Remove PayflowGateway.certification_id [cody] +* Set Response#test? to true in TrustCommerce gateway when using the demo account in production [cody] +* Correctly set Sage.supported_countries [cody] +* Add BogusGateway#void [Donald Ball] +* Fix PSL gateway capturing [cody] +* Fix failed Visa debit purchases with PSL gateway start date info is present [cody] +* Support personal fixtures file on Windows [cody] +* Clearer variable naming for BraintreeGateway#authorize [Jonathan S. Katz] +* Fix brittle Authorize.net tests [cody] +* Add support for Authorize.net duplicate window [Seamus Abshere] +* Return transaction id for PayPal refunds [jxtps435] +* Allow storage of e-checks with BraintreeGateway [jimiray] +* Add test URL to PayJunction gateway [boomtowndesigngroup] +* More robust parsing for Wirecard gateway [Soleone] +* Pass the issue number to CardStream verbatim and update test card numbers [Soleone] + +== Version 1.4.1 (December 9, 2008) + +* Update CardStream URL. Note that you will also need to update your login id. [cody] + +== Version 1.4.0 (November 27, 2008) + +* Return failed authorization when SkipJack purchase fails [Tron, cody] +* Update README [cody] +* Add metadata to Authorize.net CIM gateway [cody] +* Make ActionViewHelper compatible with changes to concat method in ActionPack [cody] +* Remove PayPal and Payflow Name-Value gateways. PayPal is no longer terminating the Payflow XML API. [cody] +* Don't directly use the inflector in the action view helper [cody] +* Work around Rails Inflector change [cody] +* Add configurable timeouts to PostsData [Michael Koziarski] +* Add valid_sender? method to gateway integrations [Soleone] +* Fix PayPal error parsing [cody] +* Fix MIT-LICENSE [cody] +* Add a payment gateway for Website Payments Pro Canada [cody] +* Fix shipping amount option in Sage gateway [Darrick Wiebe] +* Improved message and error message handling [Soleone] +* Get Wirecard working in the Live environment [Soleone] +* Remove dead code in PayPal Common API files [cody] +* Use the PayPal short error message if the long message is empty [cody] +* Fix unit tests when being run by Cruise Control [cody] +* Add support for PayPal Fraud Review Response [cody] +* Add testing support for German Wirecard Gateway [Soleone] +* Specify required version of ActiveSupport [cody] +* Make ssl_strict a superclass_delegating_accessor so the entire application's validation of SSL certs can be disabled in the event of certificate problem. [cody] +* Make Gateway.application_id a superclass_delegating_accessor so it can be set from outside the subclass definition [cody] +* Add Discover to the list of supported card types for Braintree [cody] +* Add support for Modern Payments gateway [Jeremy Nicoll, cody] +* Add support for EFT/ACH and Interac Online to the BeanstreamGateway [cody] +* Document the SageGateway [cody] +* Add support for echecks with SageGateway. [cody] +* Handle all successful SecurePay AU response codes [cody] +* Get SageGateway working with real test account. Improve test suite. [cody] +* Unify TrustCommerce, Payment Express, and Braintree CC storage [benjamin.curtis] +* Update to use new Payflow Pro URLs [cody] +* Fix missing Content-Type header for Ruby 1.8.4 [cody] +* Fix Authorize.Net CIM response.message [patrick.t.joyce] +* Add JCB and Diners Club as supported cards to SageGateway [cody] +* Add CA country code to Sage gateway's supported countries [cody] +* Add support for Sage Payment Solutions gateway [cody] +* Add test mode detection to Beanstream [cody] +* Add support for Beanstream payment gateway [xiaobozz] +* Add support for PayPal NV Pair API. Will be used to replace the usage of the PayPal SOAP API in ActiveMerchant in the future [Greg Furmanek, cody] +* Protx does support UK Maestro [cody] +* Add tests for length of UK Maestro cards [cody] +* Return all the error messages and codes from paypal responses [cody] +* Fail hard when attempting to capture without a credit card with NetRegistry [cody] +* Add support for the order fields to the create_customer_profile_transaction in Authorize.net CIM. [Patrick T. Joyce] +* Strip invalid characters and limit lengths of Protx customer data [Simon Russell] +* Fix empty start or end dates in Protx [Simon Russell] +* Add support for Authorize.net CIM [Patrick T. Joyce, Ian Lotinsky] +* Add option to skip order review to all PayPal Express gateways [garret.alfert, cody] +* Add capturing partial amounts, fix issue number formatting, fix authorization string when nil values returned, fix parsing of multiple '=' characters, simplify message_from [Simon Russell] +* Fix StartDate in ProtxGatewy [cody] +* Add support for refunds and continuous authority references to DataCashGateway [joel.chippindale] +* Fix gross in HiTrust notification. Don't use Money object in Verifi gateway [cody] +* Initial implementation of Payflow Name-Value API [Greg Furmanek] +* Add support for CyberSource credits [mjuneja] + +== Version 1.3.2 (February 24, 2008) + +* Actually fix the bug by adding extdata element to Payflow Requests [cody] +* Fix bug with adding name to Payflow requests [cody] +* Gateways will now look for CreditCard#brand before looking for CreditCard#type [cody] +* Make before_validate in CreditCard more clear [keith_du...@mac.com, cody] +* Don't send full Australian state names to PayPal [cody] +* Return last_digits that are less than 4 characters long [cody] +* Fix Bug with Authorize.Net ARB Remote Test [patrick.t.joyce] +* Add support for forcing test mode on Secure Pay AU gateway [cody] +* Update Secure Pay Au to meet specs for MessageInfo elements [cody] +* Add support for the Australian Secure Pay payment gateway [cody] +* Allow LinkPoint cancellations for recurring billing. [yanagimoto.shin] +* Add support for Åland Islands to the country list [cody] + +== Version 1.3.1 (January 28, 2008) + +* Rename BrainTreeGateway to BraintreeGateway, but keep alias to old naming for backwards compatibility [cody] + +== Version 1.3.0 (January 28, 2008) + +* Remove attr_readers for url and response from Gateway [cody] +* Remove @url from EfsnetGateway [cody] +* Remove @response instance variable in QuickpayGateway. [cody] +* Remove @response instance variable in PsigateGateway. Don't use billing address for shipping [cody] +* Remove @response instance variable in PaypalGateway. Don't use billing address for shipping. [cody] +* Remove @response instance variable in PayflowGateway [cody] +* Remove @response instance variable in MonerisGateway [cody] +* Remove @response instance variable and don't use billing address for shipping address in LinkpointGateway [cody] +* Remove @response instance variable from ExactGateway [cody] +* Remove @response instance variable from EwayGateway [cody] +* Remove @response instance variable from EfsnetGateway [cody] +* Remove @response instance variable from DataCashGateway [cody] +* Don't use billing_address for shipping_address in CyberSourceGateway [cody] +* Remove @response instance variable from CardStreamGateway [cody] +* Remove @response instance variable from BrainTreeGateway [cody] +* Remove unused deal_with_cc method from BogusGateway [cody] +* Remove test_result_from_cc_number completely from ActiveMerchant [cody] +* Don't use billing_address for shipping_address in Realex [cody] +* Update Realex to add support for cvv data. remove test_result_from_cc_number. [cody] +* Update Protx to add support for avs and cvv data. remove test_result_from_cc_number. [cody] +* Include ActiveMerchant::Utils module in test_helper and use generate_unique_id from the module instead of generate_order_id. [cody] +* Update SecurePay tests to check for avs and cvv data. [cody] +* Update SkipJack to add support for avs and cvv data. remove test_result_from_cc_number. [cody] +* Move generate_unique_id to its own module [cody] +* Update Viaklix to add support for avs and cvv data. remove test_result_from_cc_number. Truncate fields to avoid failure [cody] +* Update PSL Card Gateway to add support for avs and cvv data. remove test_result_from_cc_number. [cody] +* Update PlugNPayGateway to support avs and cvv data. Remove test_result_from_cc_number. [cody] +* Update PaymentExpressGateway to remove test_result_from_cc_number. [cody] +* Update PaySecure to remove test_result_from_cc_number. [cody] +* Update NetbillingGateway to support avs and cvv data. Remove test_result_from_cc_number. [cody] +* Replace all usage of :address with :billing_address in test cases [cody] +* Remove sensitive data from NetRegistryGateway responses. Refactor gateway and tests. Remove test_result_from_cc_number. [cody] +* Update VerifiGateway to support avs and cvv data. Remove test_result_from_cc_number. [cody] +* Small refactoring of UsaEpayGateway [cody] +* Update UsaEpayGateway to support avs and cvv data. Remove test_result_from_cc_number. [cody] +* Update TrustCommerce docs now that the gateway falls back to SSL post when tclink isn't available [cody] +* Change ARB to use correct :address1 key for addresses [cody] +* No need for specialized recurring response for Authorize.net recurring billing [cody] +* Update TransFirst to support avs and cvv data. Remove test_result_from_cc_number. [cody] +* Maintain backwards compatibility with :address option for now in the Payflow gateways [cody] +* Remove test_result_from_cc_number from SecurePayTech. Improve unit test coverage [cody] +* Fix email option in PayflowGateway. Remove support for :address option. :billing_address and :shipping_address must now be passed in separately. [cody] +* Make Bogus gateway's credit() method behave like capture [cody] +* Add update and delete methods to update and delete records stored in the vault. [benjamin.curtis] +* Add support for recurring_inquiry() to the PayflowGateway [dave.my...@contentfree.com] +* Add support for Authorize.net Automated Recurring Billing (ARB) [vkurnavenkov, forestcarlisle, ianlotin...@hotmail.com, patrick.t.joyce] +* Fix laser card regex [ladislav.martincik] +* Cleanup whitepace in README [patrick.t.joyce] +* Update ExactGateway to support avs and cvv data. Remove test_result_from_cc_number. [cody] +* Remove test_result_from_cc_number from eWay gateway. [cody] +* Remove duplicate attr_reader definitions from all gateways [cody] +* Remove useless tests raising Error [cody] +* Update gateway templates [cody] +* Fix Authorize.net test where authorize() was being called instead of purchase(). Perform some cleanup of the tests [ianlotin...@hotmail.com, cody] +* Improve Authorize.net documentation based on the DataCashGateway docs [patrick.t.joyce] +* Update EfsnetGateway to support avs and cvv data. Remove test_result_from_cc_number. [cody] +* Remove test_result_from_cc_number from DataCash. Improve unit test coverage [cody] +* Update CyberSourceGateway to support avs and cvv results. Remove test_result_from_cc_number. [cody] +* Remove match information from CVVResult [cody] +* Remove Response#card_data. The application has access to the information anyway [cody] +* Return the last 4 digits of the card number from the Response instead of the masked number [cody] +* Actually use the shipping address in TrustCommerce [cody] +* Update TrustCommerceGateway to support avs and cvv results. Remove test_result_from_cc_number. Automatically fallback to SSL POST if the TCLink library is not available. Add additional customer information to the requests. [cody] +* Fix remote CardStreamGateway tests [cody] +* Map merchant AVS codes to street and postal match codes [cody] +* Update CardStreamGateway to support avs and cvv data [cody] +* Remove merchant_data hash. Add additional CVV codes [cody] +* Update QuickpayGateway to support merchant_data hash. Remove test_result_from_cc_number. [cody] +* Update LinkpointGateway to support merchant_data hash. Remove test_result_from_cc_number. [cody] +* Update PsigateGateway to support merchant_data hash. Remove test_result_from_cc_number. [cody] +* Update MonerisGateway to support merchant_data hash. Remove test_result_from_cc_number. [cody] +* Remove AVS Message and CVV2 Message from params hash in Authorize.net [cody] +* Update BrainTreeGateway to support merchant_data hash [cody] +* Update PaypalGateway to support merchant_data hash [cody] +* Update Payflow to support merchant_data hash [cody] +* Add card data to PayJunction response. PayJunction does not return the CVV or AVS result codes. Remote test_result_from_cc_number from PayJunction. [cody] +* Rename CCVResult to CVVResult to be more aligned with ActiveMerchant's usage of the term verification value [cody] +* Remove test_result_from_cc_number from Authorize.net in favour of mocking [cody] +* Add merchant_data hash, which contains all of the card_data, avs_result, and ccv_result. [cody] +* Add CCVResult for the Card Code Verification Result. Update Authorize.net to use the new class [cody] +* Rename AVSResult#match_type AVSResult#match [cody] +* Rename AVS::Result class to AVSResult [cody] +* Convert Authorize.net gateway to use the new AVS module [cody] +* Add AVS data to the Response object [cody] +* Fix credentials for remote Authorize.net TEST MODE test [cody] +* Add AVS module and AVS::Result class [cody] +* Update base gateway class RDOC [cody] +* Update the README with the latest list of supported gateways. Update the example in the README to include the verification value, which is now required by the credit card object by default. [cody] +* Handle the return from 2Checkout [cody] +* Automatically determine the credit card type when a type is not provided [cody] +* Revert to initial implementation of LUHN algorithm because it all fits in one simple method [cody] +* Remove unused api_cert_chain.crt file [cody] +* Update PaypalGateway, and PaypalExpressGateway to send requests to the correct endpoints when using API signatures [cody] +* Successful return code for HiTRUST is actually 00 [cody] +* Make ActiveMerchant::Billing::Error a subclass of ActiveMerchant::ActiveMerchantError [cody] +* Handle the return from the offsite payment gateways [cody] +* Default HiTRUST order description to "Store purchase" [cody] +* Fix HiTRUST field names [cody] +* Add support for passing in the locale code [georg.fr...@meandevel.com] +* Add support for the Offsite payment gateway HiTRUST [cody] +* Accept SuccessWithWarning as success [cody] +* Add a link to the LinkPoint staging server docs in remote_linkpoint_test.rb [cody] +* Update Discover regex [cody] +* Match full pan range of Maestro cards from 12 - 19 digits in length [cody] +* Fix errors on base of CreditCard [josh.bassett] +* Update product to use Rubigen instead of stolen Rails generator [cody] +* Mimic directory structure of unit tests in remote tests [cody] +* Restructure the location of the remote tests [cody] +* Ensure DataCash order_id is limited to 30 characters [cody] +* Return the pretty messages from PayJunction based on the return code [cody] +* make CreditCard.require_verification_value = true the default [cody] +* Use existing credit_card helper in credit card tests [cody] +* Return the authrorization number of the original transaction in the SkipJack gateway [cody] +* Update format of line items given to the gateway. Cleanup and uncomment unit tests [cody] +* Add support for the SkipJack gateway [Bill Bereza, cody] +* Make the bogus gateway easier to test by moving messages into constants [cody] +* Add retry logic when connection has been refused for all gateways. Enable safe retries of all connection failures with the PayflowGateway, as it has a unique request header. [cody] +* Catch Timeout::Error when posting data [cody] +* Change order of loading ActionPack for tests since assert_success defined in ActionController::Assertions::DeprecatedAssertions inteferes with ActiveMerchant's definition [cody] +* Catch Errno::ETIMEDOUT and extend open and read timeouts to 60 seconds [cody] +* Add address2 to the billing address of Viaklix transactions [cody] +* Improve Psigate generic error message [cody] +* Fix small errors in Psigate documentation [cody] +* Add Response#fraud_review? query method to the response. Allows gateways to indicate that a payment is pending review by the fraud service [cody] +* Handle Errno::ECONNRESET when posting data [cody] +* Fix broken USA ePay URL [cody] +* Update RequiresParameters to support HashWithIndifferentAccess [cody] +* Add support for SecurePayTech payment gateway [Jasper Bryant-Greene] +* Detect when test credentials are being used with PayJunction [cody] +* Update documentation about TrustCommerce void [cody] +* Add void to TrustCommerce [jesse.c.scott] +* Add support for echecks to the BrainTree gateway [Jeremy Voorhis] +* Fix before_validate and validate methods in CreditCard [rick.denatale] +* Add support for Netbilling payment gateway [cody] +* Pass in N/A for unknown states when a country is present in PaypalGateway [cody] +* Strip non alpha chars from order_id in Payflow gateway, as Paymentech Tampa can't handle them [cody] +* Add support for the PaySecure payment gateway [cody] +* Add support for descriptions in Authorize.net credits [shiva.kaul] +* Great cleanup and improvement of CreditCard code, tests, and docs [James Herdman] + +== Version 1.2.1 + +* Fix remote PayPal tests [cody] + +== Version 1.2.0 + +* Update Linkpoint tests to remove useless pem file [cody] +* Use symbols for CreditCard error messages, since errors have indifferent access [cody] +* Improve CreditCard error messages [George Ogata] +* Change deny to assert_false, and deny_success to assert_failure. Remove Gateway.gateway, as it is available from Base [cody] +* Improve documentation, and test coverage [James Herdman] +* Refactor MonerisGateway, improve test coverage and documentation [James Herdman] +* Add support for crediting to Moneris [James Herdman] +* Send state N/A in Payflow when the state is blank. Fixes UK PayPal Express payments when not providing a state [cody] +* Load remote test credentials from a fixtures file. ActiveMerchant will look for a custom file ~/.active_merchant/fixtures.yml. If the file exists it will be loaded instead of the default fixtures provided by ActiveMerchant. This makes development easier, and removes the risk of committing non-public test account credentials to subversion. [cody] +* Add support for password protected pem files [cody] +* Add support for Concord Efsnet payment gateway [snacktime] +* Fix dependency loading for gateways that are subclasses [cody] +* Add Braintree payment gateway [Michael J. Mangino] +* Add support for PayPal API signatures [Benjamin Curtis, cody] +* Add payment gateway Viaklix [Sal Scotto, cody] +* Add Australian payment gateway NetRegistry [George Ogata] +* Take order email from the options hash instead of the address for CyberSource [cody] +* Use an array for LineItems when calculating tax in CyberSource gateway [cody] +* Add CyberSource gateway [Matt Margolis] +* Sanitize Protx order id [cody] +* Fix support for electron in Protx [cody] +* Add support for Protx [shiftx, cody] +* Use undef_method with a single argument in SecurePay to prevent JRuby from choking on it. [jonathan.l.bartlett] +* Default address_override to 0 for PayPal Website Payments Standard payments. [cody] +* Enhance credit card error messages [manfred] +* Use HashWithIndifferentAccess for CreditCard for compatibility with Rails applications [michael.j.mangino] +* Fix nil exception when no response reason text is found in Authorize.net [cody] +* Add support for PayJunction [Matt Sanders] +* Change billing_address to shipping_address in PayPal Integration helper, as billing_address was incorrect. Addresses passed to billing_address for the PayPal helper will no longer be added to the form. This will break existing code, as the address will not be passed. +* Remove switch patterns from card detection that were eliminated on July 1, 2007 [cody] +* Format the issue number in Payflow requests to always be 2 digits [cody] +* Move application_id to Gateway and Helper class respectively [cody] +* Improve TrustCommerce documentation [cody] +* Add credit to Payflow [cody] +* Add support for the Plug 'N Pay gateway [ryan.norbauer, cody] +* Add support for ItemTotal, Shipping, Handling, and Tax amounts in the PayPal Express and PayPal gateways [baldwindavid, cody] +* Add page customization options to the PaypalExpress, and PayflowExpress gateways [ cpjolicoeur, cody] +* Add Verifi gateway [Paul Hepworth] +* Add a PayflowResponse object with a profile_id accessor method. Return the correct authorization number on recurring actions [cody] +* Add support for an initial transaction with recurring payments [findchris, cody] +* Add support for email receipts to recurring Payflow Payments [Rick Olson] +* Ensure the ButtonSource isn't too long [cody] +* Add ButtonSource to Paypal and PaypalExpress gateways [cody] +* Rename application to application_id and place it on Base, so it can be set once and forgotten about [cody] +* Add ButtonSource field to PayflowExpress gateway [cody] +* Add a field for the bn to the PayPal helper [cody] +* Add remote secure pay test and correctly define test? [cody] +* Undefine unsupported methods from SecurePay [cody] +* Enhance the TransFirst error message for declined transactions [cody] +* Add initial support for TransFirst gateway [cody] +* Deprecate certification_id in Payflow gateways [cody] +* Work around required PayPal state fields for countries that don't require states [cody] +* Add metadata to SecurePay gateway [cody] +* Add initial support for the SecurePay gateway using the Authorize.net translator [cody] +* Add the homepage_url and display_name accessors to each gateway [cody] +* Remove Money dependency from main gateways. Cleanup tests. Add supported_countries class accessor which returns an array of 2 digit iso country codes for which countries the gateway supports accounts in [cody] +* Add American Express card to Psigate [cody] +* Send N/A to PayPal in the PayPal Helper when we don't know the UK county [cody] +* Actually pass the amount of the capture through to Payflow [cody] +* Update ExactGateway test and test mode [cody] +* Remove unused method in PslCardGateway [cody] +* Add updated credit card tests [cody] +* Update and test PslCardGateway [cody] +* Add Laser card type [cody] +* Update Nochex documentation [cody] +* Sanitize the Realex order_id [cody] +* Add support for Irish Realex payment gateway [John Ward, cody] +* Move credit_card helper method to the test_helper [cody] +* Update PayflowExpressResponse to match the interface of the PayflowExpressResponse. Add :no_shipping and :address_override options to PayflowExpress [cody] +* Add a currency option to the Payflow and Paypal gateways [cody] +* PaypalExpress should use the shipping address, not the billing address [cody] +* Allow overriding the user with Payflow so that a vendor and user can be provided when making requests [cody] +* PayPal DirectPayment API requires a UK County to be sent as the state or province. Return N/A as the state when one isn't provided to ensure that PayPal doesn't reject the payment [cody] +* Add ability to perform reference transactions with Payflow [Al Evans, cody] +* Enhance recurring Payflow tests and recurring_inquiry [Al Evans] +* Add recurring payments to Payflow [Rick Olson] +* Improve the error message generated by requires! [cody] +* Update credit card regular expressions and update Quickpay gateway with tests for new cards [cody] +* Add support for token based payments to PaymentExpress [Nik Wakelin] +* Refactor default_currency to the base gateway class [cody] +* Clean unsupported characters from the Quickpay ordernum [cody] +* Call the :sale and :authorization in QuickpayGateway [cody] +* Add Danish gateway Quickpay [cody] +* Remove redundant hash brackets from generator template [cody] +* Add additional options to the PayPal Website Payments Standard Helper [Rick Olson] +* Move generate_unique_id method to Gateway class so other gateways can also use it [cody] +* Allow notification name / value pairs to have a . in the name like checkout.x = 400 [cody] +* Fix PaypalExpressGateway#purchase to have the same method signature as other gateways [cody] +* Cargo cult off the rails unique id generator instead of UUID library [cody] +* Add uuid-1.0.3 for generating random request UUIDs [cody] +* Remove mock_methods and http mock from the library [cody] +* PaypalExpress cannot setup a payment for 0 dollars. If the amount is zero then setup a payment for $1. [cody] +* Small changes to PslCard gateway [cody] +* Fix Money dependency with PslCard gateway [cody] +* Add PslCard payment gateway [MoneySpyder http://moneyspyder.co.uk] +* Scrub the card number, expiry, and CVV code from the response [cody] +* Use test? query for checking test mode [cody] +* Add support for the E-xact Payment Gateway [James Edward Gray II, cody] +* Fix partially broken method of dealing with phone numbers in the PayPal Helper [cody] +* Update remote tests for PaymentExpress [cody] +* Add Content-Type header to PaymentExpress post [cody] +* Use DECLINED as the message for declined transactions in the PaymentExpress remote tests [cody] +* Add JCB as a supported card type for the PaymentExpressGateway [cody] +* Rename DpsGateway to PaymentExpressGateway [cody] +* Add DPS Payment Express gateway (NZ) [dgjones, cody] +* Remove duplicate and incorrect expdate method from Authorize.net [cody] +* Allow authorization and purchase using a billing_id retrieved from TrustCommerce citadel [jesse.c.scott] +* Don't return a frozen string from CreditCard.type? [cody] +* Update remote Psigate test to ensure using a verification value doesn't break anything [cody] +* Update remote Moneris test to ensure using a verification value doesn't break anything [cody] +* Fix Solo issue number with CardStream gateway and improve test coverage [cody] +* Add CardStream gateway [Jonah Fox, Thomas Nichols, cody] +* Verify Peer in PayPal notifications and add account method [cody] + +== Version 1.1.0 + +* Add unique_id option to PayPal mass payments [Haig] +* Fix expiry date in USA ePay [cody] +* Fix PayPal Payments Pro UK with Switch & Solo cards [cody] +* Add reauthorization to PaypalGateway and PaypalExpressGateway [dorrenchen] +* Update DataCash tests and format merchant reference number to meet DataCash's requirements [MoneySpyder, cody] +* Add Datacash gateway [MoneySpyder, cody] +* VERIFY_PEER on all SSL requests [cody] +* Add support for 2Checkout [cody] + +== Version 1.0.3 + +* Add support for PayPal mass payments to the PaypalGateway and the PaypalExpressGateway [Brandon Keepers] +* Add a credit method to Authorize.net [cody] + +== Version 1.0.2 + +* Add support for OrderDescription, Payer, and InvoiceID fields in PaypalGateway [cody] + +== Version 1.0.1 + +* Add support for crediting to PayPal [cody, Haig] + +== Version 1.0.0 + +* Add discover to list of supported card types for Authorize.net +* Fix Psigate crediting [sean.alien8@gmail.com] +* Fix dependency loading of tests +* Add methods for storing credit cards to the Bogus gateway [Jim Kane] +* Fix bugs in expiration dates. [Jim Kane] +* Fixed bugs related to authorized.net [Rick Olson] +* Linkpoint is now a full featured backend for active merchant [Ryan Heneise] +* Added linkpoint support [Ryan Heneise] +* Added trust commerce gateway [Hans Friedrich] +* Removed shipping stuff until there is time to implement it properly +* The library now rejects money amounts which are not either cents as integer or a Money object +* Moneris now uses the same layout as the authorized.net plugin +* Added authorized.net +* Changed default to :test mode. Set to production with ActiveMerchant::Billing::Base.gateway_mode = :production +* More refactoring +* Refactored a bit so that there is space for billing and shipping area. None of the shipping aids are fleshed out yet. Needs more work. +* Added Moneris support +* Credit card in memory object resembling a AR object +* Credit card validation methods as static methods of the credit card object + +== PlanetArgon fork for integrating Merchant eSolutions gateway + diff --git a/vendor/gems/activemerchant-1.33.0/CONTRIBUTORS b/vendor/gems/activemerchant-1.33.0/CONTRIBUTORS new file mode 100644 index 000000000..58bd51f33 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/CONTRIBUTORS @@ -0,0 +1,402 @@ +Protx Gateway + +* Contributed by shiftx (Vincent) + +Verifi Gateway + +* Contributed by Paul Hepworth on 2007-05-12. +* Portions of Verifi Gateway Copyright (c) 2007 Paul Hepworth + +Plug 'N Pay Gateway + +* Contributed by Ryan Norbauer + +PayJunction Gateway + +* Contributed by Matt Sanders + +E-xact Gateway + +* Contributed by James Edward Gray II + +Linkpoint Gateway + +* Portions of the LinkPoint Gateway by Ryan Heneise + +eWay Gateway + +* Originally contributed by Lucas Carlson (mailto:lucas@rufy.com) +* Managed Payments support by Jason Stirk with improvements by Keith Pitt + +CardStream Gateway + +* Portions of the Cardstream gateway by Jonah Fox and Thomas Nichols + +CyberSource Gateway + +* Contributed by Matt Margolis (matt@mattmargolis.net) + +NetRegistry Gateway + +* Originally contributed by George Ogata (mailto: george.ogata@gmail.com) + +DataCash Gateway (March 2, 2007) + +* MoneySpyder, http://moneyspyder.co.uk and E-consultancy, http://www.e-consultancy.com + +PSL Card Gateway (March 27, 2007) + +* MoneySpyder, http://moneyspyder.co.uk + +Viaklix Gateway (Sep 3, 2007) + +* Originally contributed by Sal Scotto + +Braintree Gateway (Sep 4, 2007) + +* Originally contributed by Michael J. Mangino +* Portions of the BrainTree gateway by Jeremy Voorhis + +Concord Efsnet Gateway (Sep 7, 2007) + +* Originally contributed by snacktime + +SecurePayTech Gateway (Oct 23, 2007) + +* Originally contributed by Jasper Bryant-Greene + +SkipJack Gateway (Nov 29, 2007) + +* Originally contributed by Bill Bereza - http://atomicobject.com + +HiTRUST Gateway (Dec 10, 2007) + +* Jaded Pixel + +Payflow NV Gateway (Mar 03, 2008) + +* Greg Furmanek + +PaypalNVGateway (Apr 12, 2008) + +* Greg Furmanek + +Beanstream (May 13, 2008) + +* Created by xiaobozz ( xiaobozzz at gmail dot com ) +* Secure Profiles support by Forrest Zeisler (http://github.com/forrest) + +Sage (June, 2008) + +* Cody + +Modern Payments (June 13, 2008) + +* Initial implementation by Jeremy Nicoll +* Additional portions by Cody Fauser + +Wirecard Gateway (June 30, 2008) + +* Initial implementation by Soleone + +Transax Gateway (May 3, 2009) + +* Mike Mangino + +Merchant E-Solutions Gateway (May 3, 2009) + +* Zac Williams, Robby Russell + +Instapay Gateway (May 3, 2009) + +* Thomas Rideout + +Iridium Gateway (June 13, 2009) + +* Phil Smy + +MerchantWARE (July 7, 2009) + +* Cody Fauser + +FirstPay (July 24, 2009) + +* Phil R + +Ogone (July 20, 2009) + +* Nicolas Jacobeus + +Elavon (August 09, 2009) + +* Jesse Storimer + +JetPay (September 29, 2009) + +* Phil Ripperger, Peter Williams + +SallieMae (October 2, 2009) + +* iamjwc + +Netaxept (February 08, 2010) + +* Nathaniel Talbott + +Garanti (May 05, 2010) + +* Selem Delul (moon@mac.home) + +Braintree Blue Gateway (May 19th, 2010) + +* Braintree (code@getbraintree.com) + +Inspire Gateway (September 27, 2010) + +* ryan r. smith + +SecureNet Gateway (September 27, 2010) + +* Kal + +PayboxDirect Gateway (September 27, 2010) + +* Donald Piret + +SagePay Form Offsite Gateway (October 14, 2010) + +* Adrian Irving-Beer + +DirecPay Gateway (October 14, 2010) + +* Soleone + +ePay Gateway (November 23, 2010) + +* Original code by ePay (epay.dk) +* Refactored by Jonathan Rudenberg + +iDEAL/Rabobank Gateway (January 10, 2011) + +* Original code by Soemirno Kartosoewito +* Refactored by Cody Fauser +* Refactored and updated by Jonathan Rudenberg + +Quantum Gateway + +* Joshua Lippiner +* Refactored by Nathaniel Talbott + +BluePay Gateway + +* Mel Sleight +* Refactored by Nathaniel Talbott + +Valitor Integration (January 2011) + +* Nathaniel Talbott +* Sponsored by Sævar Öfjörð Magnússon + +Barclays ePDQ + +* Original code by Rob W (rfwatson) +* Refactored by Nathaniel Talbott + +Federated Canada + +* Bob Larrick (deathbob) + +NMI + +* Nathaniel Talbott (ntalbott) + +QBMS + +* Will Glozer (wg) + +WorldPay Integration (Feb 17, 2011) + +* Original code by Unknown from this patch: https://jadedpixel.lighthouseapp.com/projects/11599/tickets/3-patch-integration-support-for-worldpay-uk +* Refactored by Soleone + +WorldPay Gateway + +* Original code by Amit kumar (ask4amit@gmail.com) +* Refactored by Nathaniel Talbott (ntalbott) + +Orbital Paymentech Gateway (July, 2009) + +* Sam Vincent - http://ecommerce.versapay.com + +DIRECTebanking - Payment Network AG (May, 2011) + +* Gerwin Brunner (Vilango) + +Stripe + +* Ross Boucher (boucher) + +Paystation (July, 2011) + +* Nik Wakelin (nikz) + +ePaymentPlans offsite gatway (June, 2011) + +* Roberto Miranda (robertomiranda) + +Optimal Payments (August, 2011) + +* Jamie Macey (jamie) + +CardSave (August, 2011) + +* Tom Crinson (MrJaba) + +Dwolla (September, 2011) + +* James Armstead (armsteadj1) + +Samurai (November, 2011) + +* Joshua Krall (jkrall) + +CertoDirect Gateway (February, 2012) + +* Aleksei Gusev (hron) + +Authorize.Net SIM Integration (February, 2012) + +* Roger Pack (rdp) +* Nick Rogers (courtland) + +NAB Transact (AU) Gateway (February, 2012) + +* Tom Meier (tommeier) + +iTransact XML Gateway (March, 2012) + +* Kevin Motschiedler (motske) + +Robokassa Integration (March, 2012) + +* Vasiliy Ermolovich (nashby) + +Moneris US Gateway (March, 2012) + +* Michael Wood (eddanger) + +Dotpay Integration (March, 2012) + +* Przemysław Ciąćka (kacperix) + +Vindicia gateway (April 2012) + +* Steven Davidovitz (steved555) + +MiGS gateway (April 2012) + +* Michael Noack (mnoack) +* Justin Jones (nagash) + +ePay integration (April 2012) + +* Michael (ePay) + +Litle gateway (May 2012) + +* Gregory Drake (GregDrake) + +Fat Zebra gateway (June 2012) + +* Matthew Savage (amasses) + +Metrics Global gateway (June 2012) + +* Dan Knox (DanKnox) + +EasyPay integration (July 2012) + +* Vasiliy Ermolovich (nashby) + +PayGateXML gateway (July 2012) + +* bryan (rubyisbeautiful) + +PayWay gateway (July 2012) + +* Ben Zhang (BenZhang) + +First Data integration (July 2012) + +* Nick Rogers (courtland) + +WebPay integration (July 2012) + +* Vasiliy Ermolovich (nashby) + +Suomen Maksuturva integration (July 2012) + +* Antti Akonniemi (akonan) + +Paxum integration (July 2012) + +* Stanislav Mekhonoshin (Mehonoshin) + +Balanced gateway (July 2012) + +* Marshall Jones (mjallday) + +PayFast integration (October 2012) + +* Vasiliy Ermolovich (nashby) + +A1Agregator (November 2012) + +* Roman Ivanilov (england) + +Liqpay integration (November 2012) + +* beorc + +eWay Rapid 3.0 gateway (December 2012) + +* Nathaniel Talbott (ntalbott) + +FirstData Global Gateway e4 (December 2012) + +* Chris Sheppard (frobcode) + +Spreedly Core gateway (December 2012) + +* Duff OMelia (duff) + +Pin gateway (February 2013) + +* Myles Eftos (madpilot) + +Merchant Warrior (February 2013) + +* Ben Bruscella (benbruscella) +* Дмитрий Василец (pronix) +* Kirill Shirinkin (Fodoj) +* Nathaniel Talbott (ntalbott) + +Paymill (February 2013) + +* Duff O'Melia (duff) + +EVO Canada (February 2013) + +* Alex Dunae (alexdunae) + +Finansbank WebPOS (March 2013) + +* scamurcuoglu + +Cardstream Modern (March 2013) + +* Vincens (ExxKA) + +Transnational (May 2013) + +* Ben VandenBos (bvandenbos) diff --git a/vendor/gems/activemerchant-1.33.0/MIT-LICENSE b/vendor/gems/activemerchant-1.33.0/MIT-LICENSE new file mode 100644 index 000000000..783e60724 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2005-2010 Tobias Luetke + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gems/activemerchant-1.33.0/README.md b/vendor/gems/activemerchant-1.33.0/README.md new file mode 100644 index 000000000..67e157567 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/README.md @@ -0,0 +1,221 @@ +# Active Merchant + +Active Merchant is an extraction from the e-commerce system [Shopify](http://www.shopify.com). +Shopify's requirements for a simple and unified API to access dozens of different payment +gateways with very different internal APIs was the chief principle in designing the library. + +It was developed for usage in Ruby on Rails web applications and integrates seamlessly +as a Rails plugin, but it also works excellently as a stand alone Ruby library. + +Active Merchant has been in production use since June 2006 and is now used in most modern +Ruby applications which deal with financial transactions. It is maintained by the +[Shopify](http://www.shopify.com) and [Spreedly](https://spreedly.com) teams, with much help +from an ever-growing set of contributors. + +See [GettingStarted.md](GettingStarted.md) if you want to learn more about using Active Merchant in your +applications. + +## Installation + +### From Git + +You can check out the latest source from git: + + git clone git://github.com/Shopify/active_merchant.git + +### From RubyGems + +Installation from RubyGems: + + gem install activemerchant + +Or, if you're using Bundler, just add the following to your Gemfile: + + gem 'activemerchant' + +## Usage + +This simple example demonstrates how a purchase can be made using a person's +credit card details. + + require 'rubygems' + require 'active_merchant' + + # Use the TrustCommerce test servers + ActiveMerchant::Billing::Base.mode = :test + + gateway = ActiveMerchant::Billing::TrustCommerceGateway.new( + :login => 'TestMerchant', + :password => 'password') + + # ActiveMerchant accepts all amounts as Integer values in cents + amount = 1000 # $10.00 + + # The card verification value is also known as CVV2, CVC2, or CID + credit_card = ActiveMerchant::Billing::CreditCard.new( + :first_name => 'Bob', + :last_name => 'Bobsen', + :number => '4242424242424242', + :month => '8', + :year => Time.now.year+1, + :verification_value => '000') + + # Validating the card automatically detects the card type + if credit_card.valid? + # Capture $10 from the credit card + response = gateway.purchase(amount, credit_card) + + if response.success? + puts "Successfully charged $#{sprintf("%.2f", amount / 100)} to the credit card #{credit_card.display_number}" + else + raise StandardError, response.message + end + end + +For more in-depth documentation and tutorials, see [GettingStarted.md](GettingStarted.md) and the +[API documentation](http://rubydoc.info/github/Shopify/active_merchant/master/file/README.md). + +## Supported Direct Payment Gateways + +The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) contains a [table of features supported by each gateway](http://github.com/Shopify/active_merchant/wikis/gatewayfeaturematrix). + +* [Authorize.Net](http://www.authorize.net/) - US +* [Authorize.Net CIM](http://www.authorize.net/) - US +* [Balanced](https://www.balancedpayments.com/) - US +* [Banwire](https://www.banwire.com/) - MX +* [Barclays ePDQ](http://www.barclaycard.co.uk/business/accepting-payments/epdq-mpi/) - UK +* [Beanstream.com](http://www.beanstream.com/) - CA +* [BluePay](http://www.bluepay.com/) - US +* [Braintree](http://www.braintreepaymentsolutions.com) - US +* [CardStream](http://www.cardstream.com/) - UK +* [CertoDirect](http://www.certodirect.com/) - BE, BG, CZ, DK, DE, EE, IE, EL, ES, FR, IT, CY, LV, LT, LU, HU, MT, NL, AT, PL, PT, RO, SI, SK, FI, SE, UK +* [CyberSource](http://www.cybersource.com) - US +* [DataCash](http://www.datacash.com/) - UK +* [Efsnet](http://www.concordefsnet.com/) - US +* [Elavon MyVirtualMerchant](http://www.elavon.com) - US, CA +* [ePay](http://www.epay.dk/) - DK, SE, NO +* [EVO Canada](http://www.evocanada.com/) - CA +* [eWAY](http://www.eway.com.au/) - AU +* [eWay Rapid 3.0](http://www.eway.com.au/) - AU +* [E-xact](http://www.e-xact.com) - CA, US +* [Fat Zebra](https://www.fatzebra.com.au) - AU +* [Federated Canada](http://www.federatedcanada.com/) - CA +* [Finansbank WebPOS](https://www.fbwebpos.com/) - US, TR +* [FirstData Global Gateway e4](http://www.firstdata.com) - CA, US +* [FirstPay](http://www.first-pay.com) - US +* [Garanti Sanal POS](https://ccpos.garanti.com.tr/ccRaporlar/garanti/ccReports) - US, TR +* [HDFC](http://www.hdfcbank.com/sme/sme-details/merchant-services/guzh6m0i) - IN +* [Inspire](http://www.inspiregateway.com) - US +* [InstaPay](http://www.instapayllc.com) - US +* [Iridium](http://www.iridiumcorp.co.uk/) - UK, ES +* [iTransact](http://www.itransact.com/) - US +* [JetPay](http://www.jetpay.com) - US +* [LinkPoint](http://www.linkpoint.com/) - US +* [Litle](http://www.litle.com/) - US +* [Merchant e-Solutions](http://merchante-solutions.com/) - US +* [MerchantWare](http://merchantwarehouse.com/merchantware) - US +* [Merchant Warrior] (http://merchantwarrior.com) - AU +* [Mercury](http://www.mercurypay.com) - US +* [MasterCard Internet Gateway Service (MiGS)](http://mastercard.com/mastercardsps) - AU, AE, BD, BN, EG, HK, ID, IN, JO, KW, LB, LK, MU, MV, MY, NZ, OM, PH, QA, SA, SG, TT, VN +* [Modern Payments](http://www.modpay.com) - US +* [Moneris](http://www.moneris.com/) - CA +* [Moneris US](http://www.monerisusa.com/) - US +* [NABTransact](http://www.nab.com.au/nabtransact/) - AU +* [NELiX TransaX Gateway](http://www.nelixtransax.com) - US +* [Netaxept](http://www.betalingsterminal.no/Netthandel-forside) - NO, DK, SE, FI +* [NETbilling](http://www.netbilling.com) - US +* [NetPay](http://www.netpay.com.mx) - MX +* [NetRegistry](http://www.netregistry.com.au) - AU +* [NMI](http://nmi.com/) - US +* [Ogone DirectLink](http://www.ogone.com) - BE, DE, FR, NL, AT, CH +* [Optimal Payments](http://www.optimalpayments.com/) - CA, US, UK +* [Orbital Paymentech](http://chasepaymentech.com/) - CA, US, UK, GB +* [PayBox Direct](http://www.paybox.com) - FR +* [PayFast](https://www.payfast.co.za/) - ZA +* [PayGate PayXML](http://paygate.co.za/) - US, ZA +* [PayJunction](http://www.payjunction.com/) - US +* [PaymentExpress](http://www.paymentexpress.com/) - AU, MY, NZ, SG, ZA, UK, US +* [PAYMILL](https://www.paymill.com) - AD, AT, BE, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GR, HU, IE, IL, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, SE, SI, SK, TR, VA +* [PayPal Express Checkout](https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside) - US, CA, SG, AU +* [PayPal Payflow Pro](https://www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside) - US, CA, SG, AU +* [PayPal Website Payments Pro (UK)](https://www.paypal.com/uk/cgi-bin/webscr?cmd=_wp-pro-overview-outside) - UK +* [PayPal Website Payments Pro (CA)](https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside) - CA +* [PayPal Express Checkout](https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside) - US +* [PayPal Website Payments Pro (US)](https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside) - US +* [PaySecure](http://www.commsecure.com.au/paysecure.shtml) - AU +* [PayWay](https://www.payway.com.au) - AU +* [Pin](http://www.pin.net.au/) - AU +* [Plug'n Pay](http://www.plugnpay.com/) - US +* [Psigate](http://www.psigate.com/) - CA +* [PSL Payment Solutions](http://www.paymentsolutionsltd.com/) - UK +* [Quantum](http://www.quantumgateway.com) - US +* [QuickBooks Merchant Services](http://payments.intuit.com/) - US +* [Quickpay](http://quickpay.dk/) - DK, SE +* [Rabobank Nederland](http://www.rabobank.nl/) - NL +* [Realex](http://www.realexpayments.com/) - IE, UK +* [Redsys](http://www.redsys.es) - ES +* [SagePay](http://www.sagepay.com) - UK +* [Sage Payment Solutions](http://www.sagepayments.com) - US, CA +* [Sallie Mae](http://www.salliemae.com) - US +* [SecureNet](http://www.securenet.com) - US +* [SecurePay](http://securepay.com.au) - AU +* [SecurePay](http://www.securepay.com/) - US +* [SecurePayTech](http://www.securepaytech.com/) - NZ +* [SkipJack](http://www.skipjack.com/) - US, CA +* [Spreedly Core](https://spreedlycore.com/) - AD, AE, AT, AU, BD, BE, BG, BN, CA, CH, CY, CZ, DE, DK, EE, EG, ES, FI, FR, GB, GI, GR, HK, HU, ID, IE, IL, IM, IN, IS, IT, JO, KW, LB, LI, LK, LT, LU, LV, MC, MT, MU, MV, MX, MY, NL, NO, NZ, OM, PH, PL, PT, QA, RO, SA, SE, SG, SI, SK, SM, TR, TT, UM, US, VA, VN, ZA +* [Stripe](https://stripe.com/) - US +* [TransFirst](http://www.transfirst.com/) - US +* [Transnational](http://www.tnbci.com/) - US +* [TrustCommerce](http://www.trustcommerce.com/) - US +* [USA ePay](http://www.usaepay.com/) - US +* [Verifi](http://www.verifi.com/) - US +* [ViaKLIX](http://viaklix.com) - US +* [Vindica](http://www.vindicia.com/) - US, CA, UK, AU, MX, BR, DE, KR, CN, HK +* [WebPay](https://webpay.jp/) - JP +* [Wirecard](http://www.wirecard.com) - DE +* [WorldPay](http://www.worldpay.com) - AU, HK, UK, US + +## Supported Offsite Payment Gateways + +* [2 Checkout](http://www.2checkout.com) +* [A1Agregator](http://a1agregator.ru/) - RU +* [Authorize.Net SIM](http://developer.authorize.net/api/sim/) - US +* [Banca Sella GestPay](https://www.sella.it/banca/ecommerce/gestpay/gestpay.jsp) +* [Chronopay](http://www.chronopay.com) +* [DirecPay](http://www.timesofmoney.com/direcpay/jsp/home.jsp) +* [Direct-eBanking / sofortueberweisung.de by Payment-Networks AG](https://www.payment-network.com/deb_com_en/merchantarea/home) - DE, AT, CH, BE, UK, NL +* [Dotpay](http://dotpay.pl) +* [Dwolla](https://www.dwolla.com/default.aspx) +* [ePay](http://www.epay.dk/epay-payment-solutions/) +* [First Data](https://firstdata.zendesk.com/entries/407522-first-data-global-gateway-e4sm-payment-pages-integration-manual) +* [HiTRUST](http://www.hitrust.com.hk/) +* [Moneybookers](http://www.moneybookers.com) +* [Nochex](http://www.nochex.com) +* [Paxum](https://www.paxum.com/) +* [PayPal Website Payments Standard](https://www.paypal.com/cgi-bin/webscr?cmd#_wp-standard-overview-outside) +* [Paysbuy](https://www.paysbuy.com/) - TH +* [RBK Money](https://rbkmoney.ru/) - RU +* [Robokassa](http://robokassa.ru/) - RU +* [SagePay Form](http://www.sagepay.com/products_services/sage_pay_go/integration/form) +* [Suomen Maksuturva](https://www.maksuturva.fi/services/vendor_services/integration_guidelines.html) +* [Valitor](http://www.valitor.is/) - IS +* [Verkkomaksut](http://www.verkkomaksut.fi) - FI +* [WebMoney](http://www.webmoney.ru) - RU +* [WebPay](http://webpay.by/) +* [WorldPay](http://www.worldpay.com) + +## Contributing + +The source code is hosted at [GitHub](http://github.com/Shopify/active_merchant), and can be fetched using: + + git clone git://github.com/Shopify/active_merchant.git + +Please see the [ActiveMerchant Guide to Contributing](http://github.com/Shopify/active_merchant/wikis/contributing) for +information on adding a new gateway to ActiveMerchant. + +Please don't touch the CHANGELOG in your pull requests, we'll add the appropriate CHANGELOG entries +at release time. + +[![Build Status](https://secure.travis-ci.org/Shopify/active_merchant.png)](http://travis-ci.org/Shopify/active_merchant) + +[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/Shopify/active_merchant) diff --git a/vendor/gems/activemerchant-1.33.0/gem-public_cert.pem b/vendor/gems/activemerchant-1.33.0/gem-public_cert.pem new file mode 100644 index 000000000..c2588d5c2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/gem-public_cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApjb2R5 +ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj +b20wHhcNMDcwMjIyMTcyMTI3WhcNMDgwMjIyMTcyMTI3WjBBMRMwEQYDVQQDDApj +b2R5ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ +FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6T4Iqt5iWvAlU +iXI6L8UO0URQhIC65X/gJ9hL/x4lwSl/ckVm/R/bPrJGmifT+YooFv824N3y/TIX +25o/lZtRj1TUZJK4OCb0aVzosQVxBHSe6rLmxO8cItNTMOM9wn3thaITFrTa1DOQ +O3wqEjvW2L6VMozVfK1MfjL9IGgy0rCnl+2g4Gh4jDDpkLfnMG5CWI6cTCf3C1ye +ytOpWgi0XpOEy8nQWcFmt/KCQ/kFfzBo4QxqJi54b80842EyvzWT9OB7Oew/CXZG +F2yIHtiYxonz6N09vvSzq4CvEuisoUFLKZnktndxMEBKwJU3XeSHAbuS7ix40OKO +WKuI54fHAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW +BBR9QQpefI3oDCAxiqJW/3Gg6jI6qjANBgkqhkiG9w0BAQUFAAOCAQEAs0lX26O+ +HpyMp7WL+SgZuM8k76AjfOHuKajl2GEn3S8pWYGpsa0xu07HtehJhKLiavrfUYeE +qlFtyYMUyOh6/1S2vfkH6VqjX7mWjoi7XKHW/99fkMS40B5SbN+ypAUst+6c5R84 +w390mjtLHpdDE6WQYhS6bFvBN53vK6jG3DLyCJc0K9uMQ7gdHWoxq7RnG92ncQpT +ThpRA+fky5Xt2Q63YJDnJpkYAz79QIama1enSnd4jslKzSl89JS2luq/zioPe/Us +hbyalWR1+HrhgPoSPq7nk+s2FQUBJ9UZFK1lgMzho/4fZgzJwbu+cO8SNuaLS/bj +hPaSTyVU0yCSnw== +-----END CERTIFICATE----- diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant.rb new file mode 100644 index 000000000..aff818bcb --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant.rb @@ -0,0 +1,63 @@ +#-- +# Copyright (c) 2005-2010 Tobias Luetke +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +require 'active_support' +require 'active_support/core_ext/string/inflections' +require 'active_support/core_ext/hash/indifferent_access' +require 'active_support/core_ext/hash/conversions' +require 'active_support/core_ext/object/conversions' +require 'active_support/core_ext/class/attribute' +require 'active_support/core_ext/class/attribute_accessors' +require 'active_support/core_ext/class/delegating_attributes' +require 'active_support/core_ext/module/attribute_accessors' + +begin + require 'active_support/base64' + + unless defined?(Base64) + Base64 = ActiveSupport::Base64 + end + + unless Base64.respond_to?(:strict_encode64) + def Base64.strict_encode64(v) + ActiveSupport::Base64.encode64s(v) + end + end +rescue LoadError + require 'base64' +end + +require 'securerandom' +require 'builder' +require 'cgi' +require 'rexml/document' + +require 'active_utils' +require 'active_merchant/billing' +require 'active_merchant/version' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + autoload :Integrations, 'active_merchant/billing/integrations' + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing.rb new file mode 100644 index 000000000..ee144b1f3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing.rb @@ -0,0 +1,9 @@ +require 'active_merchant/billing/avs_result' +require 'active_merchant/billing/cvv_result' +require 'active_merchant/billing/credit_card_methods' +require 'active_merchant/billing/credit_card_formatting' +require 'active_merchant/billing/credit_card' +require 'active_merchant/billing/base' +require 'active_merchant/billing/check' +require 'active_merchant/billing/response' +require 'active_merchant/billing/gateways' \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/avs_result.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/avs_result.rb new file mode 100644 index 000000000..527c3efa1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/avs_result.rb @@ -0,0 +1,98 @@ +#!ruby19 +# encoding: utf-8 + +module ActiveMerchant + module Billing + # Implements the Address Verification System + # https://www.wellsfargo.com/downloads/pdf/biz/merchant/visa_avs.pdf + # http://en.wikipedia.org/wiki/Address_Verification_System + # http://apps.cybersource.com/library/documentation/dev_guides/CC_Svcs_IG/html/app_avs_cvn_codes.htm#app_AVS_CVN_codes_7891_48375 + # http://imgserver.skipjack.com/imgServer/5293710/AVS%20and%20CVV2.pdf + # http://www.emsecommerce.net/avs_cvv2_response_codes.htm + class AVSResult + MESSAGES = { + 'A' => 'Street address matches, but 5-digit and 9-digit postal code do not match.', + 'B' => 'Street address matches, but postal code not verified.', + 'C' => 'Street address and postal code do not match.', + 'D' => 'Street address and postal code match.', + 'E' => 'AVS data is invalid or AVS is not allowed for this card type.', + 'F' => 'Card member\'s name does not match, but billing postal code matches.', + 'G' => 'Non-U.S. issuing bank does not support AVS.', + 'H' => 'Card member\'s name does not match. Street address and postal code match.', + 'I' => 'Address not verified.', + 'J' => 'Card member\'s name, billing address, and postal code match. Shipping information verified and chargeback protection guaranteed through the Fraud Protection Program.', + 'K' => 'Card member\'s name matches but billing address and billing postal code do not match.', + 'L' => 'Card member\'s name and billing postal code match, but billing address does not match.', + 'M' => 'Street address and postal code match.', + 'N' => 'Street address and postal code do not match.', + 'O' => 'Card member\'s name and billing address match, but billing postal code does not match.', + 'P' => 'Postal code matches, but street address not verified.', + 'Q' => 'Card member\'s name, billing address, and postal code match. Shipping information verified but chargeback protection not guaranteed.', + 'R' => 'System unavailable.', + 'S' => 'U.S.-issuing bank does not support AVS.', + 'T' => 'Card member\'s name does not match, but street address matches.', + 'U' => 'Address information unavailable.', + 'V' => 'Card member\'s name, billing address, and billing postal code match.', + 'W' => 'Street address does not match, but 9-digit postal code matches.', + 'X' => 'Street address and 9-digit postal code match.', + 'Y' => 'Street address and 5-digit postal code match.', + 'Z' => 'Street address does not match, but 5-digit postal code matches.' + } + + # Map vendor's AVS result code to a postal match code + POSTAL_MATCH_CODE = { + 'Y' => %w( D H F H J L M P Q V W X Y Z ), + 'N' => %w( A C K N O ), + 'X' => %w( G S ), + nil => %w( B E I R T U ) + }.inject({}) do |map, (type, codes)| + codes.each { |code| map[code] = type } + map + end + + # Map vendor's AVS result code to a street match code + STREET_MATCH_CODE = { + 'Y' => %w( A B D H J M O Q T V X Y ), + 'N' => %w( C K L N W Z ), + 'X' => %w( G S ), + nil => %w( E F I P R U ) + }.inject({}) do |map, (type, codes)| + codes.each { |code| map[code] = type } + map + end + + attr_reader :code, :message, :street_match, :postal_match + + def self.messages + MESSAGES + end + + def initialize(attrs) + attrs ||= {} + + @code = attrs[:code].upcase unless attrs[:code].blank? + @message = self.class.messages[code] + + if attrs[:street_match].blank? + @street_match = STREET_MATCH_CODE[code] + else + @street_match = attrs[:street_match].upcase + end + + if attrs[:postal_match].blank? + @postal_match = POSTAL_MATCH_CODE[code] + else + @postal_match = attrs[:postal_match].upcase + end + end + + def to_hash + { 'code' => code, + 'message' => message, + 'street_match' => street_match, + 'postal_match' => postal_match + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/base.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/base.rb new file mode 100644 index 000000000..7ee06986b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/base.rb @@ -0,0 +1,56 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Base + # Set ActiveMerchant gateways in test mode. + # + # ActiveMerchant::Billing::Base.gateway_mode = :test + mattr_accessor :gateway_mode + + # Set ActiveMerchant integrations in test mode. + # + # ActiveMerchant::Billing::Base.integration_mode = :test + mattr_accessor :integration_mode + + # Set both the mode of both the gateways and integrations + # at once + mattr_reader :mode + + def self.mode=(mode) + @@mode = mode + self.gateway_mode = mode + self.integration_mode = mode + end + + self.mode = :production + + # Return the matching gateway for the provider + # * bogus: BogusGateway - Does nothing (for testing) + # * moneris: MonerisGateway + # * authorize_net: AuthorizeNetGateway + # * trust_commerce: TrustCommerceGateway + # + # ActiveMerchant::Billing::Base.gateway('moneris').new + def self.gateway(name) + Billing.const_get("#{name.to_s.downcase}_gateway".camelize) + end + + # Return the matching integration module + # You can then get the notification from the module + # * bogus: Bogus - Does nothing (for testing) + # * chronopay: Chronopay + # * paypal: Paypal + # + # chronopay = ActiveMerchant::Billing::Base.integration('chronopay') + # notification = chronopay.notification(raw_post) + # + def self.integration(name) + Billing::Integrations.const_get("#{name.to_s.downcase}".camelize) + end + + # A check to see if we're in test mode + def self.test? + self.gateway_mode == :test + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/check.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/check.rb new file mode 100644 index 000000000..79e99d2ee --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/check.rb @@ -0,0 +1,69 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # The Check object is a plain old Ruby object, similar to CreditCard. It supports validation + # of necessary attributes such as checkholder's name, routing and account numbers, but it is + # not backed by any database. + # + # You may use Check in place of CreditCard with any gateway that supports it. + class Check + include Validateable + + attr_accessor :first_name, :last_name, + :bank_name, :routing_number, :account_number, + :account_holder_type, :account_type, :number + + # Used for Canadian bank accounts + attr_accessor :institution_number, :transit_number + + def name + @name ||= "#{@first_name} #{@last_name}".strip + end + + def name=(value) + return if value.blank? + + @name = value + segments = value.split(' ') + @last_name = segments.pop + @first_name = segments.join(' ') + end + + def validate + [:name, :routing_number, :account_number].each do |attr| + errors.add(attr, "cannot be empty") if self.send(attr).blank? + end + + errors.add(:routing_number, "is invalid") unless valid_routing_number? + + errors.add(:account_holder_type, "must be personal or business") if + !account_holder_type.blank? && !%w[business personal].include?(account_holder_type.to_s) + + errors.add(:account_type, "must be checking or savings") if + !account_type.blank? && !%w[checking savings].include?(account_type.to_s) + end + + def type + 'check' + end + + # Routing numbers may be validated by calculating a checksum and dividing it by 10. The + # formula is: + # (3(d1 + d4 + d7) + 7(d2 + d5 + d8) + 1(d3 + d6 + d9))mod 10 = 0 + # See http://en.wikipedia.org/wiki/Routing_transit_number#Internal_checksums + def valid_routing_number? + d = routing_number.to_s.split('').map(&:to_i).select { |d| (0..9).include?(d) } + case d.size + when 9 then + checksum = ((3 * (d[0] + d[3] + d[6])) + + (7 * (d[1] + d[4] + d[7])) + + (d[2] + d[5] + d[8])) % 10 + case checksum + when 0 then true + else false + end + else false + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card.rb new file mode 100644 index 000000000..953d79849 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card.rb @@ -0,0 +1,278 @@ +require 'time' +require 'date' +require 'active_merchant/billing/expiry_date' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # A +CreditCard+ object represents a physical credit card, and is capable of validating the various + # data associated with these. + # + # At the moment, the following credit card types are supported: + # + # * Visa + # * MasterCard + # * Discover + # * American Express + # * Diner's Club + # * JCB + # * Switch + # * Solo + # * Dankort + # * Maestro + # * Forbrugsforeningen + # * Laser + # + # For testing purposes, use the 'bogus' credit card brand. This skips the vast majority of + # validations, allowing you to focus on your core concerns until you're ready to be more concerned + # with the details of particular credit cards or your gateway. + # + # == Testing With CreditCard + # Often when testing we don't care about the particulars of a given card brand. When using the 'test' + # mode in your {Gateway}, there are six different valid card numbers: 1, 2, 3, 'success', 'fail', + # and 'error'. + # + # For details, see {CreditCardMethods::ClassMethods#valid_number?} + # + # == Example Usage + # cc = CreditCard.new( + # :first_name => 'Steve', + # :last_name => 'Smith', + # :month => '9', + # :year => '2010', + # :brand => 'visa', + # :number => '4242424242424242' + # ) + # + # cc.valid? # => true + # cc.display_number # => XXXX-XXXX-XXXX-4242 + # + class CreditCard + include CreditCardMethods + include Validateable + + cattr_accessor :require_verification_value + self.require_verification_value = true + + # Returns or sets the credit card number. + # + # @return [String] + attr_accessor :number + + # Returns or sets the expiry month for the card. + # + # @return [Integer] + attr_accessor :month + + # Returns or sets the expiry year for the card. + # + # @return [Integer] + attr_accessor :year + + # Returns or sets the credit card brand. + # + # Valid card types are + # + # * +'visa'+ + # * +'master'+ + # * +'discover'+ + # * +'american_express'+ + # * +'diners_club'+ + # * +'jcb'+ + # * +'switch'+ + # * +'solo'+ + # * +'dankort'+ + # * +'maestro'+ + # * +'forbrugsforeningen'+ + # * +'laser'+ + # + # Or, if you wish to test your implementation, +'bogus'+. + # + # @return (String) the credit card brand + attr_accessor :brand + + # Returns or sets the first name of the card holder. + # + # @return [String] + attr_accessor :first_name + + # Returns or sets the last name of the card holder. + # + # @return [String] + attr_accessor :last_name + + # Required for Switch / Solo cards + attr_accessor :start_month, :start_year, :issue_number + + # Returns or sets the card verification value. + # + # This attribute is optional but recommended. The verification value is + # a {card security code}[http://en.wikipedia.org/wiki/Card_security_code]. If provided, + # the gateway will attempt to validate the value. + # + # @return [String] the verification value + attr_accessor :verification_value + + def type + self.class.deprecated "CreditCard#type is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand instead." + brand + end + + def type=(value) + self.class.deprecated "CreditCard#type is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand instead." + self.brand = value + end + + # Provides proxy access to an expiry date object + # + # @return [ExpiryDate] + def expiry_date + ExpiryDate.new(@month, @year) + end + + # Returns whether the credit card has expired. + # + # @return +true+ if the card has expired, +false+ otherwise + def expired? + expiry_date.expired? + end + + # Returns whether either the +first_name+ or the +last_name+ attributes has been set. + def name? + first_name? || last_name? + end + + # Returns whether the +first_name+ attribute has been set. + def first_name? + @first_name.present? + end + + # Returns whether the +last_name+ attribute has been set. + def last_name? + @last_name.present? + end + + # Returns the full name of the card holder. + # + # @return [String] the full name of the card holder + def name + [@first_name, @last_name].compact.join(' ') + end + + def name=(full_name) + names = full_name.split + self.last_name = names.pop + self.first_name = names.join(" ") + end + + def verification_value? + !@verification_value.blank? + end + + # Returns a display-friendly version of the card number. + # + # All but the last 4 numbers are replaced with an "X", and hyphens are + # inserted in order to improve legibility. + # + # @example + # credit_card = CreditCard.new(:number => "2132542376824338") + # credit_card.display_number # "XXXX-XXXX-XXXX-4338" + # + # @return [String] a display-friendly version of the card number + def display_number + self.class.mask(number) + end + + def first_digits + self.class.first_digits(number) + end + + def last_digits + self.class.last_digits(number) + end + + # Validates the credit card details. + # + # Any validation errors are added to the {#errors} attribute. + def validate + validate_essential_attributes + + # Bogus card is pretty much for testing purposes. Lets just skip these extra tests if its used + return if brand == 'bogus' + + validate_card_brand + validate_card_number + validate_verification_value + validate_switch_or_solo_attributes + end + + def self.requires_verification_value? + require_verification_value + end + + private + + def before_validate #:nodoc: + self.month = month.to_i + self.year = year.to_i + self.start_month = start_month.to_i unless start_month.nil? + self.start_year = start_year.to_i unless start_year.nil? + self.number = number.to_s.gsub(/[^\d]/, "") + self.brand.downcase! if brand.respond_to?(:downcase) + self.brand = self.class.brand?(number) if brand.blank? + end + + def validate_card_number #:nodoc: + if number.blank? + errors.add :number, "is required" + elsif !CreditCard.valid_number?(number) + errors.add :number, "is not a valid credit card number" + end + + unless errors.on(:number) || errors.on(:brand) + errors.add :brand, "does not match the card number" unless CreditCard.matching_brand?(number, brand) + end + end + + def validate_card_brand #:nodoc: + errors.add :brand, "is required" if brand.blank? && number.present? + errors.add :brand, "is invalid" unless brand.blank? || CreditCard.card_companies.keys.include?(brand) + end + + alias_method :validate_card_type, :validate_card_brand + + def validate_essential_attributes #:nodoc: + errors.add :first_name, "cannot be empty" if @first_name.blank? + errors.add :last_name, "cannot be empty" if @last_name.blank? + + if @month.to_i.zero? || @year.to_i.zero? + errors.add :month, "is required" if @month.to_i.zero? + errors.add :year, "is required" if @year.to_i.zero? + else + errors.add :month, "is not a valid month" unless valid_month?(@month) + errors.add :year, "expired" if expired? + errors.add :year, "is not a valid year" unless expired? || valid_expiry_year?(@year) + end + end + + def validate_switch_or_solo_attributes #:nodoc: + if %w[switch solo].include?(brand) + unless valid_month?(@start_month) && valid_start_year?(@start_year) || valid_issue_number?(@issue_number) + if @issue_number.blank? + errors.add :start_month, "is invalid" unless valid_month?(@start_month) + errors.add :start_year, "is invalid" unless valid_start_year?(@start_year) + errors.add :issue_number, "cannot be empty" + else + errors.add :issue_number, "is invalid" unless valid_issue_number?(@issue_number) + end + end + end + end + + def validate_verification_value #:nodoc: + if CreditCard.requires_verification_value? + errors.add :verification_value, "is required" unless verification_value? + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_formatting.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_formatting.rb new file mode 100644 index 000000000..126207b14 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_formatting.rb @@ -0,0 +1,21 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module CreditCardFormatting + + # This method is used to format numerical information pertaining to credit cards. + # + # format(2005, :two_digits) # => "05" + # format(05, :four_digits) # => "0005" + def format(number, option) + return '' if number.blank? + + case option + when :two_digits ; sprintf("%.2i", number.to_i)[-2..-1] + when :four_digits ; sprintf("%.4i", number.to_i)[-4..-1] + else number + end + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_methods.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_methods.rb new file mode 100644 index 000000000..fef4bf16c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/credit_card_methods.rb @@ -0,0 +1,143 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # Convenience methods that can be included into a custom Credit Card object, such as an ActiveRecord based Credit Card object. + module CreditCardMethods + CARD_COMPANIES = { + 'visa' => /^4\d{12}(\d{3})?$/, + 'master' => /^(5[1-5]\d{4}|677189)\d{10}$/, + 'discover' => /^(6011|65\d{2}|64[4-9]\d)\d{12}|(62\d{14})$/, + 'american_express' => /^3[47]\d{13}$/, + 'diners_club' => /^3(0[0-5]|[68]\d)\d{11}$/, + 'jcb' => /^35(28|29|[3-8]\d)\d{12}$/, + 'switch' => /^6759\d{12}(\d{2,3})?$/, + 'solo' => /^6767\d{12}(\d{2,3})?$/, + 'dankort' => /^5019\d{12}$/, + 'maestro' => /^(5[06-8]|6\d)\d{10,17}$/, + 'forbrugsforeningen' => /^600722\d{10}$/, + 'laser' => /^(6304|6706|6709|6771(?!89))\d{8}(\d{4}|\d{6,7})?$/ + } + + def self.included(base) + base.extend(ClassMethods) + end + + def valid_month?(month) + (1..12).include?(month.to_i) + end + + def valid_expiry_year?(year) + (Time.now.year..Time.now.year + 20).include?(year.to_i) + end + + def valid_start_year?(year) + year.to_s =~ /^\d{4}$/ && year.to_i > 1987 + end + + def valid_issue_number?(number) + number.to_s =~ /^\d{1,2}$/ + end + + module ClassMethods + # Returns true if it validates. Optionally, you can pass a card brand as an argument and + # make sure it is of the correct brand. + # + # References: + # - http://perl.about.com/compute/perl/library/nosearch/P073000.htm + # - http://www.beachnet.com/~hstiles/cardtype.html + def valid_number?(number) + valid_test_mode_card_number?(number) || + valid_card_number_length?(number) && + valid_checksum?(number) + end + + # Regular expressions for the known card companies. + # + # References: + # - http://en.wikipedia.org/wiki/Credit_card_number + # - http://www.barclaycardbusiness.co.uk/information_zone/processing/bin_rules.html + def card_companies + CARD_COMPANIES + end + + # Returns a string containing the brand of card from the list of known information below. + # Need to check the cards in a particular order, as there is some overlap of the allowable ranges + #-- + # TODO Refactor this method. We basically need to tighten up the Maestro Regexp. + # + # Right now the Maestro regexp overlaps with the MasterCard regexp (IIRC). If we can tighten + # things up, we can boil this whole thing down to something like... + # + # def brand?(number) + # return 'visa' if valid_test_mode_card_number?(number) + # card_companies.find([nil]) { |brand, regexp| number =~ regexp }.first.dup + # end + # + def brand?(number) + return 'bogus' if valid_test_mode_card_number?(number) + + card_companies.reject { |c,p| c == 'maestro' }.each do |company, pattern| + return company.dup if number =~ pattern + end + + return 'maestro' if number =~ card_companies['maestro'] + + return nil + end + + def type?(number) + deprecated "CreditCard#type? is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand? instead." + brand?(number) + end + + def first_digits(number) + number.to_s.slice(0,6) + end + + def last_digits(number) + number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1) + end + + def mask(number) + "XXXX-XXXX-XXXX-#{last_digits(number)}" + end + + # Checks to see if the calculated brand matches the specified brand + def matching_brand?(number, brand) + brand?(number) == brand + end + + def matching_type?(number, brand) + deprecated "CreditCard#matching_type? is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#matching_brand? instead." + matching_brand?(number, brand) + end + + def deprecated(message) + warn(Kernel.caller[1] + message) + end + + private + + def valid_card_number_length?(number) #:nodoc: + number.to_s.length >= 12 + end + + def valid_test_mode_card_number?(number) #:nodoc: + ActiveMerchant::Billing::Base.test? && + %w[1 2 3 success failure error].include?(number.to_s) + end + + # Checks the validity of a card number by use of the the Luhn Algorithm. + # Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details. + def valid_checksum?(number) #:nodoc: + sum = 0 + for i in 0..number.length + weight = number[-1 * (i + 2), 1].to_i * (2 - (i % 2)) + sum += (weight < 10) ? weight : weight - 9 + end + + (number[-1,1].to_i == (10 - sum % 10) % 10) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/cvv_result.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/cvv_result.rb new file mode 100644 index 000000000..edd2d5086 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/cvv_result.rb @@ -0,0 +1,38 @@ +module ActiveMerchant + module Billing + # Result of the Card Verification Value check + # http://www.bbbonline.org/eExport/doc/MerchantGuide_cvv2.pdf + # Check additional codes from cybersource website + class CVVResult + + MESSAGES = { + 'D' => 'Suspicious transaction', + 'I' => 'Failed data validation check', + 'M' => 'Match', + 'N' => 'No Match', + 'P' => 'Not Processed', + 'S' => 'Should have been present', + 'U' => 'Issuer unable to process request', + 'X' => 'Card does not support verification' + } + + def self.messages + MESSAGES + end + + attr_reader :code, :message + + def initialize(code) + @code = code.upcase unless code.blank? + @message = MESSAGES[@code] + end + + def to_hash + { + 'code' => code, + 'message' => message + } + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/expiry_date.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/expiry_date.rb new file mode 100644 index 000000000..4ab1fb00a --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/expiry_date.rb @@ -0,0 +1,34 @@ +require 'date' + +module ActiveMerchant + module Billing + class CreditCard + class ExpiryDate #:nodoc: + attr_reader :month, :year + def initialize(month, year) + @month = month.to_i + @year = year.to_i + end + + def expired? #:nodoc: + Time.now.utc > expiration + end + + def expiration #:nodoc: + begin + Time.utc(year, month, month_days, 23, 59, 59) + rescue ArgumentError + Time.at(0).utc + end + end + + private + def month_days + mdays = [nil,31,28,31,30,31,30,31,31,30,31,30,31] + mdays[2] = 29 if Date.leap?(year) + mdays[month] + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateway.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateway.rb new file mode 100644 index 000000000..976e175cb --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateway.rb @@ -0,0 +1,177 @@ +require 'net/http' +require 'net/https' +require 'active_merchant/billing/response' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # + # == Description + # The Gateway class is the base class for all ActiveMerchant gateway implementations. + # + # The standard list of gateway functions that most concrete gateway subclasses implement is: + # + # * purchase(money, creditcard, options = {}) + # * authorize(money, creditcard, options = {}) + # * capture(money, authorization, options = {}) + # * void(identification, options = {}) + # * credit(money, identification, options = {}) + # + # Some gateways include features for recurring billing + # + # * recurring(money, creditcard, options = {}) + # + # Some gateways also support features for storing credit cards: + # + # * store(creditcard, options = {}) + # * unstore(identification, options = {}) + # + # === Gateway Options + # The options hash consists of the following options: + # + # * :order_id - The order number + # * :ip - The IP address of the customer making the purchase + # * :customer - The name, customer number, or other information that identifies the customer + # * :invoice - The invoice number + # * :merchant - The name or description of the merchant offering the product + # * :description - A description of the transaction + # * :email - The email address of the customer + # * :currency - The currency of the transaction. Only important when you are using a currency that is not the default with a gateway that supports multiple currencies. + # * :billing_address - A hash containing the billing address of the customer. + # * :shipping_address - A hash containing the shipping address of the customer. + # + # The :billing_address, and :shipping_address hashes can have the following keys: + # + # * :name - The full name of the customer. + # * :company - The company name of the customer. + # * :address1 - The primary street address of the customer. + # * :address2 - Additional line of address information. + # * :city - The city of the customer. + # * :state - The state of the customer. The 2 digit code for US and Canadian addresses. The full name of the state or province for foreign addresses. + # * :country - The [ISO 3166-1-alpha-2 code](http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm) for the customer. + # * :zip - The zip or postal code of the customer. + # * :phone - The phone number of the customer. + # + # == Implmenting new gateways + # + # See the {ActiveMerchant Guide to Contributing}[https://github.com/Shopify/active_merchant/wiki/Contributing] + # + class Gateway + include PostsData + include RequiresParameters + include CreditCardFormatting + include Utils + + DEBIT_CARDS = [ :switch, :solo ] + CURRENCIES_WITHOUT_FRACTIONS = [ 'JPY', 'HUF', 'TWD' ] + CREDIT_DEPRECATION_MESSAGE = "Support for using credit to refund existing transactions is deprecated and will be removed from a future release of ActiveMerchant. Please use the refund method instead." + + cattr_reader :implementations + @@implementations = [] + + def self.inherited(subclass) + super + @@implementations << subclass + end + + # The format of the amounts used by the gateway + # :dollars => '12.50' + # :cents => '1250' + class_attribute :money_format + self.money_format = :dollars + + # The default currency for the transactions if no currency is provided + class_attribute :default_currency + + # The countries of merchants the gateway supports + class_attribute :supported_countries + self.supported_countries = [] + + # The supported card types for the gateway + class_attribute :supported_cardtypes + self.supported_cardtypes = [] + + class_attribute :homepage_url + class_attribute :display_name + + class_attribute :test_url, :live_url + + class_attribute :abstract_class + + self.abstract_class = false + + # The application making the calls to the gateway + # Useful for things like the PayPal build notation (BN) id fields + superclass_delegating_accessor :application_id + self.application_id = 'ActiveMerchant' + + attr_reader :options + + # Use this method to check if your gateway of interest supports a credit card of some type + def self.supports?(card_type) + supported_cardtypes.include?(card_type.to_sym) + end + + def self.card_brand(source) + result = source.respond_to?(:brand) ? source.brand : source.type + result.to_s.downcase + end + + def card_brand(source) + self.class.card_brand(source) + end + + # Initialize a new gateway. + # + # See the documentation for the gateway you will be using to make sure there are no other + # required options. + def initialize(options = {}) + @options = options + end + + # Are we running in test mode? + def test? + (@options.has_key?(:test) ? @options[:test] : Base.test?) + end + + private # :nodoc: all + + def name + self.class.name.scan(/\:\:(\w+)Gateway/).flatten.first + end + + def amount(money) + return nil if money.nil? + cents = if money.respond_to?(:cents) + deprecated "Support for Money objects is deprecated and will be removed from a future release of ActiveMerchant. Please use an Integer value in cents" + money.cents + else + money + end + + if money.is_a?(String) + raise ArgumentError, 'money amount must be a positive Integer in cents.' + end + + if self.money_format == :cents + cents.to_s + else + sprintf("%.2f", cents.to_f / 100) + end + end + + def localized_amount(money, currency) + amount = amount(money) + CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s) ? amount.split('.').first : amount + end + + def currency(money) + money.respond_to?(:currency) ? money.currency : self.default_currency + end + + def requires_start_date_or_issue_number?(credit_card) + return false if card_brand(credit_card).blank? + DEBIT_CARDS.include?(card_brand(credit_card).to_sym) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways.rb new file mode 100644 index 000000000..a9bebd1b8 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways.rb @@ -0,0 +1,17 @@ +module ActiveMerchant + module Billing + autoload :Gateway, 'active_merchant/billing/gateway' + + Dir[File.dirname(__FILE__) + '/gateways/**/*.rb'].each do |f| + # Get camelized class name + filename = File.basename(f, '.rb') + # Add _gateway suffix + gateway_name = filename + '_gateway' + # Camelize the string to get the class name + gateway_class = gateway_name.camelize + + # Register for autoloading + autoload gateway_class, f + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net.rb new file mode 100644 index 000000000..9ab415a14 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net.rb @@ -0,0 +1,724 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # For more information on the Authorize.Net Gateway please visit their {Integration Center}[http://developer.authorize.net/] + # + # The login and password are not the username and password you use to + # login to the Authorize.Net Merchant Interface. Instead, you will + # use the API Login ID as the login and Transaction Key as the + # password. + # + # ==== How to Get Your API Login ID and Transaction Key + # + # 1. Log into the Merchant Interface + # 2. Select Settings from the Main Menu + # 3. Click on API Login ID and Transaction Key in the Security section + # 4. Type in the answer to the secret question configured on setup + # 5. Click Submit + # + # ==== Automated Recurring Billing (ARB) + # + # Automated Recurring Billing (ARB) is an optional service for submitting and managing recurring, or subscription-based, transactions. + # + # To use recurring, update_recurring, cancel_recurring and status_recurring ARB must be enabled for your account. + # + # Information about ARB is available on the {Authorize.Net website}[http://www.authorize.net/solutions/merchantsolutions/merchantservices/automatedrecurringbilling/]. + # Information about the ARB API is available at the {Authorize.Net Integration Center}[http://developer.authorize.net/] + class AuthorizeNetGateway < Gateway + API_VERSION = '3.1' + + class_attribute :arb_test_url, :arb_live_url + + self.test_url = "https://test.authorize.net/gateway/transact.dll" + self.live_url = "https://secure.authorize.net/gateway/transact.dll" + + self.arb_test_url = 'https://apitest.authorize.net/xml/v1/request.api' + self.arb_live_url = 'https://api.authorize.net/xml/v1/request.api' + + class_attribute :duplicate_window + + APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4 + + RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3 + AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE = 5, 6, 38 + + self.default_currency = 'USD' + + self.supported_countries = ['US', 'CA', 'GB'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + self.homepage_url = 'http://www.authorize.net/' + self.display_name = 'Authorize.Net' + + CARD_CODE_ERRORS = %w( N S ) + AVS_ERRORS = %w( A E N R W Z ) + AVS_REASON_CODES = %w(27 45) + + AUTHORIZE_NET_ARB_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' + + RECURRING_ACTIONS = { + :create => 'ARBCreateSubscription', + :update => 'ARBUpdateSubscription', + :cancel => 'ARBCancelSubscription', + :status => 'ARBGetSubscriptionStatus' + } + + # Creates a new AuthorizeNetGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The Authorize.Net API Login ID (REQUIRED) + # * :password -- The Authorize.Net Transaction Key. (REQUIRED) + # * :test -- +true+ or +false+. If true, perform transactions against the test server. + # Otherwise, perform transactions against the production server. + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Performs an authorization, which reserves the funds on the customer's credit card, but does not + # charge the card. + # + # ==== Parameters + # + # * money -- The amount to be authorized as an Integer value in cents. + # * paysource -- The CreditCard or Check details for the transaction. + # * options -- A hash of optional parameters. + def authorize(money, paysource, options = {}) + post = {} + add_currency_code(post, money, options) + add_invoice(post, options) + add_payment_source(post, paysource, options) + add_address(post, options) + add_customer_data(post, options) + add_duplicate_window(post) + + commit('AUTH_ONLY', money, post) + end + + # Perform a purchase, which is essentially an authorization and capture in a single operation. + # + # ==== Parameters + # + # * money -- The amount to be purchased as an Integer value in cents. + # * paysource -- The CreditCard or Check details for the transaction. + # * options -- A hash of optional parameters. + def purchase(money, paysource, options = {}) + post = {} + add_currency_code(post, money, options) + add_invoice(post, options) + add_payment_source(post, paysource, options) + add_address(post, options) + add_customer_data(post, options) + add_duplicate_window(post) + + commit('AUTH_CAPTURE', money, post) + end + + # Captures the funds from an authorized transaction. + # + # ==== Parameters + # + # * money -- The amount to be captured as an Integer value in cents. + # * authorization -- The authorization returned from the previous authorize request. + def capture(money, authorization, options = {}) + post = {:trans_id => authorization} + add_customer_data(post, options) + add_invoice(post, options) + commit('PRIOR_AUTH_CAPTURE', money, post) + end + + # Void a previous transaction + # + # ==== Parameters + # + # * authorization - The authorization returned from the previous authorize request. + def void(authorization, options = {}) + post = {:trans_id => authorization} + add_duplicate_window(post) + commit('VOID', nil, post) + end + + # Refund a transaction. + # + # This transaction indicates to the gateway that + # money should flow from the merchant to the customer. + # + # ==== Parameters + # + # * money -- The amount to be credited to the customer as an Integer value in cents. + # * identification -- The ID of the original transaction against which the refund is being issued. + # * options -- A hash of parameters. + # + # ==== Options + # + # * :card_number -- The credit card number the refund is being issued to. (REQUIRED) + # You can either pass the last four digits of the card number or the full card number. + # * :first_name -- The first name of the account being refunded. + # * :last_name -- The last name of the account being refunded. + # * :zip -- The postal code of the account being refunded. + def refund(money, identification, options = {}) + requires!(options, :card_number) + + post = { :trans_id => identification, + :card_num => options[:card_number] + } + + post[:first_name] = options[:first_name] if options[:first_name] + post[:last_name] = options[:last_name] if options[:last_name] + post[:zip] = options[:zip] if options[:zip] + + add_invoice(post, options) + add_duplicate_window(post) + + commit('CREDIT', money, post) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + # Create a recurring payment. + # + # This transaction creates a new Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled. + # + # ==== Parameters + # + # * money -- The amount to be charged to the customer at each interval as an Integer value in cents. + # * creditcard -- The CreditCard details for the transaction. + # * options -- A hash of parameters. + # + # ==== Options + # + # * :interval -- A hash containing information about the interval of time between payments. Must + # contain the keys :length and :unit. :unit can be either :months or :days. + # If :unit is :months then :length must be an integer between 1 and 12 inclusive. + # If :unit is :days then :length must be an integer between 7 and 365 inclusive. + # For example, to charge the customer once every three months the hash would be + # +:interval => { :unit => :months, :length => 3 }+ (REQUIRED) + # * :duration -- A hash containing keys for the :start_date the subscription begins (also the date the + # initial billing occurs) and the total number of billing :occurences or payments for the subscription. (REQUIRED) + def recurring(money, creditcard, options={}) + requires!(options, :interval, :duration, :billing_address) + requires!(options[:interval], :length, [:unit, :days, :months]) + requires!(options[:duration], :start_date, :occurrences) + requires!(options[:billing_address], :first_name, :last_name) + + options[:credit_card] = creditcard + options[:amount] = money + + request = build_recurring_request(:create, options) + recurring_commit(:create, request) + end + + # Update a recurring payment's details. + # + # This transaction updates an existing Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled + # and the subscription must have already been created previously by calling +recurring()+. The ability to change certain + # details about a recurring payment is dependent on transaction history and cannot be determined until after calling + # +update_recurring()+. See the ARB XML Guide for such conditions. + # + # ==== Parameters + # + # * options -- A hash of parameters. + # + # ==== Options + # + # * :subscription_id -- A string containing the :subscription_id of the recurring payment already in place + # for a given credit card. (REQUIRED) + def update_recurring(options={}) + requires!(options, :subscription_id) + request = build_recurring_request(:update, options) + recurring_commit(:update, request) + end + + # Cancel a recurring payment. + # + # This transaction cancels an existing Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled + # and the subscription must have already been created previously by calling recurring() + # + # ==== Parameters + # + # * subscription_id -- A string containing the +subscription_id+ of the recurring payment already in place + # for a given credit card. (REQUIRED) + def cancel_recurring(subscription_id) + request = build_recurring_request(:cancel, :subscription_id => subscription_id) + recurring_commit(:cancel, request) + end + + # Get Subscription Status of a recurring payment. + # + # This transaction gets the status of an existing Automated Recurring Billing (ARB) subscription. Your account must have ARB enabled. + # + # ==== Parameters + # + # * subscription_id -- A string containing the +subscription_id+ of the recurring payment already in place + # for a given credit card. (REQUIRED) + def status_recurring(subscription_id) + request = build_recurring_request(:status, :subscription_id => subscription_id) + recurring_commit(:status, request) + end + + private + + def commit(action, money, parameters) + parameters[:amount] = amount(money) unless action == 'VOID' + + # Only activate the test_request when the :test option is passed in + parameters[:test_request] = @options[:test] ? 'TRUE' : 'FALSE' + + url = test? ? self.test_url : self.live_url + data = ssl_post url, post_data(action, parameters) + + response = parse(data) + response[:action] = action + + message = message_from(response) + + # Return the response. The authorization can be taken out of the transaction_id + # Test Mode on/off is something we have to parse from the response text. + # It usually looks something like this + # + # (TESTMODE) Successful Sale + test_mode = test? || message =~ /TESTMODE/ + + Response.new(success?(response), message, response, + :test => test_mode, + :authorization => response[:transaction_id], + :fraud_review => fraud_review?(response), + :avs_result => { :code => response[:avs_result_code] }, + :cvv_result => response[:card_code] + ) + end + + def success?(response) + response[:response_code] == APPROVED + end + + def fraud_review?(response) + response[:response_code] == FRAUD_REVIEW + end + + def parse(body) + fields = split(body) + + results = { + :response_code => fields[RESPONSE_CODE].to_i, + :response_reason_code => fields[RESPONSE_REASON_CODE], + :response_reason_text => fields[RESPONSE_REASON_TEXT], + :avs_result_code => fields[AVS_RESULT_CODE], + :transaction_id => fields[TRANSACTION_ID], + :card_code => fields[CARD_CODE_RESPONSE_CODE] + } + results + end + + def post_data(action, parameters = {}) + post = {} + + post[:version] = API_VERSION + post[:login] = @options[:login] + post[:tran_key] = @options[:password] + post[:relay_response] = "FALSE" + post[:type] = action + post[:delim_data] = "TRUE" + post[:delim_char] = "," + post[:encap_char] = "$" + post[:solution_ID] = application_id if application_id.present? && application_id != "ActiveMerchant" + + request = post.merge(parameters).collect { |key, value| "x_#{key}=#{CGI.escape(value.to_s)}" }.join("&") + request + end + + def add_currency_code(post, money, options) + post[:currency_code] = options[:currency] || currency(money) + end + + def add_invoice(post, options) + post[:invoice_num] = options[:order_id] + post[:description] = options[:description] + end + + def add_creditcard(post, creditcard) + post[:card_num] = creditcard.number + post[:card_code] = creditcard.verification_value if creditcard.verification_value? + post[:exp_date] = expdate(creditcard) + post[:first_name] = creditcard.first_name + post[:last_name] = creditcard.last_name + end + + def add_payment_source(params, source, options={}) + if card_brand(source) == "check" + add_check(params, source, options) + else + add_creditcard(params, source) + end + end + + def add_check(post, check, options) + post[:method] = "ECHECK" + post[:bank_name] = check.bank_name + post[:bank_aba_code] = check.routing_number + post[:bank_acct_num] = check.account_number + post[:bank_acct_type] = check.account_type + post[:echeck_type] = "WEB" + post[:bank_acct_name] = check.name + post[:bank_check_number] = check.number if check.number.present? + post[:recurring_billing] = (options[:recurring] ? "TRUE" : "FALSE") + end + + def add_customer_data(post, options) + if options.has_key? :email + post[:email] = options[:email] + post[:email_customer] = false + end + + if options.has_key? :customer + post[:cust_id] = options[:customer] if Float(options[:customer]) rescue nil + end + + if options.has_key? :ip + post[:customer_ip] = options[:ip] + end + end + + # x_duplicate_window won't be sent by default, because sending it changes the response. + # "If this field is present in the request with or without a value, an enhanced duplicate transaction response will be sent." + # (as of 2008-12-30) http://www.authorize.net/support/AIM_guide_SCC.pdf + def add_duplicate_window(post) + unless duplicate_window.nil? + post[:duplicate_window] = duplicate_window + end + end + + def add_address(post, options) + if address = options[:billing_address] || options[:address] + post[:address] = address[:address1].to_s + post[:company] = address[:company].to_s + post[:phone] = address[:phone].to_s + post[:zip] = address[:zip].to_s + post[:city] = address[:city].to_s + post[:country] = address[:country].to_s + post[:state] = address[:state].blank? ? 'n/a' : address[:state] + end + + if address = options[:shipping_address] + post[:ship_to_first_name] = address[:first_name].to_s + post[:ship_to_last_name] = address[:last_name].to_s + post[:ship_to_address] = address[:address1].to_s + post[:ship_to_company] = address[:company].to_s + post[:ship_to_phone] = address[:phone].to_s + post[:ship_to_zip] = address[:zip].to_s + post[:ship_to_city] = address[:city].to_s + post[:ship_to_country] = address[:country].to_s + post[:ship_to_state] = address[:state].blank? ? 'n/a' : address[:state] + end + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def message_from(results) + if results[:response_code] == DECLINED + return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code]) + if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code]) + return AVSResult.messages[ results[:avs_result_code] ] + end + end + + (results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '') + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + + "#{month}#{year[-2..-1]}" + end + + def split(response) + response[1..-2].split(/\$,\$/) + end + + # ARB + + # Builds recurring billing request + def build_recurring_request(action, options = {}) + unless RECURRING_ACTIONS.include?(action) + raise StandardError, "Invalid Automated Recurring Billing Action: #{action}" + end + + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct!(:xml, :version => '1.0', :encoding => 'utf-8') + xml.tag!("#{RECURRING_ACTIONS[action]}Request", :xmlns => AUTHORIZE_NET_ARB_NAMESPACE) do + add_arb_merchant_authentication(xml) + # Merchant-assigned reference ID for the request + xml.tag!('refId', options[:ref_id]) if options[:ref_id] + send("build_arb_#{action}_subscription_request", xml, options) + end + end + + # Contains the merchant’s payment gateway account authentication information + def add_arb_merchant_authentication(xml) + xml.tag!('merchantAuthentication') do + xml.tag!('name', @options[:login]) + xml.tag!('transactionKey', @options[:password]) + end + end + + # Builds body for ARBCreateSubscriptionRequest + def build_arb_create_subscription_request(xml, options) + # Subscription + add_arb_subscription(xml, options) + + xml.target! + end + + # Builds body for ARBUpdateSubscriptionRequest + def build_arb_update_subscription_request(xml, options) + xml.tag!('subscriptionId', options[:subscription_id]) + # Adds Subscription + add_arb_subscription(xml, options) + + xml.target! + end + + # Builds body for ARBCancelSubscriptionRequest + def build_arb_cancel_subscription_request(xml, options) + xml.tag!('subscriptionId', options[:subscription_id]) + + xml.target! + end + + # Builds body for ARBGetSubscriptionStatusRequest + def build_arb_status_subscription_request(xml, options) + xml.tag!('subscriptionId', options[:subscription_id]) + + xml.target! + end + + # Adds subscription information + def add_arb_subscription(xml, options) + xml.tag!('subscription') do + # Merchant-assigned name for the subscription (optional) + xml.tag!('name', options[:subscription_name]) if options[:subscription_name] + # Contains information about the payment schedule + add_arb_payment_schedule(xml, options) + # The amount to be billed to the customer + # for each payment in the subscription + xml.tag!('amount', amount(options[:amount])) if options[:amount] + if trial = options[:trial] + # The amount to be charged for each payment during a trial period (conditional) + xml.tag!('trialAmount', amount(trial[:amount])) if trial[:amount] + end + # Contains either the customer’s credit card + # or bank account payment information + add_arb_payment(xml, options) + # Contains order information (optional) + add_arb_order(xml, options) + # Contains information about the customer + add_arb_customer(xml, options) + # Contains the customer's billing address information + add_arb_address(xml, 'billTo', options[:billing_address]) + # Contains the customer's shipping address information (optional) + add_arb_address(xml, 'shipTo', options[:shipping_address]) + end + end + + # Adds information about the interval of time between payments + def add_arb_interval(xml, options) + interval = options[:interval] + return unless interval + xml.tag!('interval') do + # The measurement of time, in association with the Interval Unit, + # that is used to define the frequency of the billing occurrences + xml.tag!('length', interval[:length]) + # The unit of time, in association with the Interval Length, + # between each billing occurrence + xml.tag!('unit', interval[:unit].to_s) + end + end + + # Adds information about the subscription duration + def add_arb_duration(xml, options) + duration = options[:duration] + return unless duration + # The date the subscription begins + # (also the date the initial billing occurs) + xml.tag!('startDate', duration[:start_date]) if duration[:start_date] + # Number of billing occurrences or payments for the subscription + xml.tag!('totalOccurrences', duration[:occurrences]) if duration[:occurrences] + end + + def add_arb_payment_schedule(xml, options) + return unless options[:interval] || options[:duration] + xml.tag!('paymentSchedule') do + # Contains information about the interval of time between payments + add_arb_interval(xml, options) + add_arb_duration(xml, options) + if trial = options[:trial] + # Number of billing occurrences or payments in the trial period (optional) + xml.tag!('trialOccurrences', trial[:occurrences]) if trial[:occurrences] + end + end + end + + # Adds customer's credit card or bank account payment information + def add_arb_payment(xml, options) + return unless options[:credit_card] || options[:bank_account] + xml.tag!('payment') do + # Contains the customer’s credit card information + add_arb_credit_card(xml, options) + # Contains the customer’s bank account information + add_arb_bank_account(xml, options) + end + end + + # Adds customer’s credit card information + # Note: This element should only be included + # when the payment method is credit card. + def add_arb_credit_card(xml, options) + credit_card = options[:credit_card] + return unless credit_card + xml.tag!('creditCard') do + # The credit card number used for payment of the subscription + xml.tag!('cardNumber', credit_card.number) + # The expiration date of the credit card used for the subscription + xml.tag!('expirationDate', arb_expdate(credit_card)) + end + end + + # Adds customer’s bank account information + # Note: This element should only be included + # when the payment method is bank account. + def add_arb_bank_account(xml, options) + bank_account = options[:bank_account] + return unless bank_account + xml.tag!('bankAccount') do + # The type of bank account used for payment of the subscription + xml.tag!('accountType', bank_account[:account_type]) + # The routing number of the customer’s bank + xml.tag!('routingNumber', bank_account[:routing_number]) + # The bank account number used for payment of the subscription + xml.tag!('accountNumber', bank_account[:account_number]) + # The full name of the individual associated + # with the bank account number + xml.tag!('nameOfAccount', bank_account[:name_of_account]) + # The full name of the individual associated + # with the bank account number (optional) + xml.tag!('bankName', bank_account[:bank_name]) if bank_account[:bank_name] + # The type of electronic check transaction used for the subscription + xml.tag!('echeckType', bank_account[:echeck_type]) + end + end + + # Adds order information (optional) + def add_arb_order(xml, options) + order = options[:order] + return unless order + xml.tag!('order') do + # Merchant-assigned invoice number for the subscription (optional) + xml.tag!('invoiceNumber', order[:invoice_number]) + # Description of the subscription (optional) + xml.tag!('description', order[:description]) + end + end + + # Adds information about the customer + def add_arb_customer(xml, options) + customer = options[:customer] + return unless customer + xml.tag!('customer') do + xml.tag!('type', customer[:type]) if customer[:type] + xml.tag!('id', customer[:id]) if customer[:id] + xml.tag!('email', customer[:email]) if customer[:email] + xml.tag!('phoneNumber', customer[:phone_number]) if customer[:phone_number] + xml.tag!('faxNumber', customer[:fax_number]) if customer[:fax_number] + add_arb_drivers_license(xml, options) + xml.tag!('taxId', customer[:tax_id]) if customer[:tax_id] + end + end + + # Adds the customer's driver's license information (conditional) + def add_arb_drivers_license(xml, options) + return unless customer = options[:customer] + return unless drivers_license = customer[:drivers_license] + xml.tag!('driversLicense') do + # The customer's driver's license number + xml.tag!('number', drivers_license[:number]) + # The customer's driver's license state + xml.tag!('state', drivers_license[:state]) + # The customer's driver's license date of birth + xml.tag!('dateOfBirth', drivers_license[:date_of_birth]) + end + end + + # Adds address information + def add_arb_address(xml, container_name, address) + return if address.blank? + xml.tag!(container_name) do + xml.tag!('firstName', address[:first_name]) + xml.tag!('lastName', address[:last_name]) + xml.tag!('company', address[:company]) + xml.tag!('address', address[:address1]) + xml.tag!('city', address[:city]) + xml.tag!('state', address[:state]) + xml.tag!('zip', address[:zip]) + xml.tag!('country', address[:country]) + end + end + + def arb_expdate(credit_card) + sprintf('%04d-%02d', credit_card.year, credit_card.month) + end + + def recurring_commit(action, request) + url = test? ? arb_test_url : arb_live_url + xml = ssl_post(url, request, "Content-Type" => "text/xml") + + response = recurring_parse(action, xml) + + message = response[:message] || response[:text] + test_mode = test? || message =~ /Test Mode/ + success = response[:result_code] == 'Ok' + + Response.new(success, message, response, + :test => test_mode, + :authorization => response[:subscription_id] + ) + end + + def recurring_parse(action, xml) + response = {} + xml = REXML::Document.new(xml) + root = REXML::XPath.first(xml, "//#{RECURRING_ACTIONS[action]}Response") || + REXML::XPath.first(xml, "//ErrorResponse") + if root + root.elements.to_a.each do |node| + recurring_parse_element(response, node) + end + end + + response + end + + def recurring_parse_element(response, node) + if node.has_elements? + node.elements.each{|e| recurring_parse_element(response, e) } + else + response[node.name.underscore.to_sym] = node.text + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net_cim.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net_cim.rb new file mode 100644 index 000000000..26bcf32f5 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/authorize_net_cim.rb @@ -0,0 +1,956 @@ +# -*- coding: utf-8 -*- +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # ==== Customer Information Manager (CIM) + # + # The Authorize.Net Customer Information Manager (CIM) is an optional additional service that allows you to store sensitive payment information on + # Authorize.Net's servers, simplifying payments for returning customers and recurring transactions. It can also help with Payment Card Industry (PCI) + # Data Security Standard compliance, since customer data is no longer stored locally. + # + # To use the AuthorizeNetCimGateway CIM must be enabled for your account. + # + # Information about CIM is available on the {Authorize.Net website}[http://www.authorize.net/solutions/merchantsolutions/merchantservices/cim/]. + # Information about the CIM API is available at the {Authorize.Net Integration Center}[http://developer.authorize.net/] + # + # ==== Login and Password + # + # The login and password are not the username and password you use to + # login to the Authorize.Net Merchant Interface. Instead, you will + # use the API Login ID as the login and Transaction Key as the + # password. + # + # ==== How to Get Your API Login ID and Transaction Key + # + # 1. Log into the Merchant Interface + # 2. Select Settings from the Main Menu + # 3. Click on API Login ID and Transaction Key in the Security section + # 4. Type in the answer to the secret question configured on setup + # 5. Click Submit + class AuthorizeNetCimGateway < Gateway + self.test_url = 'https://apitest.authorize.net/xml/v1/request.api' + self.live_url = 'https://api.authorize.net/xml/v1/request.api' + + AUTHORIZE_NET_CIM_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' + + CIM_ACTIONS = { + :create_customer_profile => 'createCustomerProfile', + :create_customer_payment_profile => 'createCustomerPaymentProfile', + :create_customer_shipping_address => 'createCustomerShippingAddress', + :get_customer_profile => 'getCustomerProfile', + :get_customer_profile_ids => 'getCustomerProfileIds', + :get_customer_payment_profile => 'getCustomerPaymentProfile', + :get_customer_shipping_address => 'getCustomerShippingAddress', + :delete_customer_profile => 'deleteCustomerProfile', + :delete_customer_payment_profile => 'deleteCustomerPaymentProfile', + :delete_customer_shipping_address => 'deleteCustomerShippingAddress', + :update_customer_profile => 'updateCustomerProfile', + :update_customer_payment_profile => 'updateCustomerPaymentProfile', + :update_customer_shipping_address => 'updateCustomerShippingAddress', + :create_customer_profile_transaction => 'createCustomerProfileTransaction', + :validate_customer_payment_profile => 'validateCustomerPaymentProfile' + } + + CIM_TRANSACTION_TYPES = { + :auth_capture => 'profileTransAuthCapture', + :auth_only => 'profileTransAuthOnly', + :capture_only => 'profileTransCaptureOnly', + :prior_auth_capture => 'profileTransPriorAuthCapture', + :refund => 'profileTransRefund', + :void => 'profileTransVoid' + } + + CIM_VALIDATION_MODES = { + :none => 'none', + :test => 'testMode', + :live => 'liveMode', + :old => 'oldLiveMode' + } + + BANK_ACCOUNT_TYPES = { + :checking => 'checking', + :savings => 'savings', + :business_checking => 'businessChecking' + } + + ECHECK_TYPES = { + :ccd => 'CCD', + :ppd => 'PPD', + :web => 'WEB' + } + + self.homepage_url = 'http://www.authorize.net/' + self.display_name = 'Authorize.Net CIM' + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # Creates a new AuthorizeNetCimGateway + # + # The gateway requires that a valid API Login ID and Transaction Key be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The Authorize.Net API Login ID (REQUIRED) + # * :password -- The Authorize.Net Transaction Key. (REQUIRED) + # * :test -- +true+ or +false+. If true, perform transactions against the test server. + # Otherwise, perform transactions against the production server. + # * :delimiter -- The delimiter used in the direct response. Default is ',' (comma). + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Creates a new customer profile along with any customer payment profiles and customer shipping addresses + # for the customer profile. + # + # Returns a Response with the Customer Profile ID of the new customer profile in the authorization field. + # It is *CRITICAL* that you save this ID. There is no way to retrieve this through the API. You will not + # be able to create another Customer Profile with the same information. + # + # + # + # ==== Options + # + # * :profile -- A hash containing at least one of the CONDITIONAL profile options below (REQUIRED) + # + # ==== Profile + # + # * :email -- Email address associated with the customer profile (CONDITIONAL) + # * :description -- Description of the customer or customer profile (CONDITIONAL) + # * :merchant_customer_id -- Merchant assigned ID for the customer (CONDITIONAL) + # * :payment_profile -- A hash containing the elements of the new payment profile (optional) + # + # ==== Payment Profile + # + # * :payment -- A hash containing information on payment. Either :credit_card or :bank_account (optional) + def create_customer_profile(options) + requires!(options, :profile) + requires!(options[:profile], :email) unless options[:profile][:merchant_customer_id] || options[:profile][:description] + requires!(options[:profile], :description) unless options[:profile][:email] || options[:profile][:merchant_customer_id] + requires!(options[:profile], :merchant_customer_id) unless options[:profile][:description] || options[:profile][:email] + + request = build_request(:create_customer_profile, options) + commit(:create_customer_profile, request) + end + + # Creates a new customer payment profile for an existing customer profile. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer the payment profile will be added to. (REQUIRED) + # * :payment_profile -- A hash containing the elements of the new payment profile (REQUIRED) + # + # ==== Payment Profile + # + # * :payment -- A hash containing information on payment. Either :credit_card or :bank_account (REQUIRED) + def create_customer_payment_profile(options) + requires!(options, :customer_profile_id) + requires!(options, :payment_profile) + requires!(options[:payment_profile], :payment) + + request = build_request(:create_customer_payment_profile, options) + commit(:create_customer_payment_profile, request) + end + + # Creates a new customer shipping address for an existing customer profile. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer the payment profile will be added to. (REQUIRED) + # * :address -- A hash containing the elements of the shipping address (REQUIRED) + def create_customer_shipping_address(options) + requires!(options, :customer_profile_id) + requires!(options, :address) + + request = build_request(:create_customer_shipping_address, options) + commit(:create_customer_shipping_address, request) + end + + # Deletes an existing customer profile along with all associated customer payment profiles and customer shipping addresses. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer to be deleted. (REQUIRED) + def delete_customer_profile(options) + requires!(options, :customer_profile_id) + + request = build_request(:delete_customer_profile, options) + commit(:delete_customer_profile, request) + end + + # Deletes a customer payment profile from an existing customer profile. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer with the payment profile to be deleted. (REQUIRED) + # * :customer_payment_profile_id -- The Payment Profile ID of the payment profile to be deleted. (REQUIRED) + def delete_customer_payment_profile(options) + requires!(options, :customer_profile_id) + requires!(options, :customer_payment_profile_id) + + request = build_request(:delete_customer_payment_profile, options) + commit(:delete_customer_payment_profile, request) + end + + # Deletes a customer shipping address from an existing customer profile. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer with the payment profile to be deleted. (REQUIRED) + # * :customer_address_id -- The Shipping Address ID of the shipping address to be deleted. (REQUIRED) + def delete_customer_shipping_address(options) + requires!(options, :customer_profile_id) + requires!(options, :customer_address_id) + + request = build_request(:delete_customer_shipping_address, options) + commit(:delete_customer_shipping_address, request) + end + + # Retrieves an existing customer profile along with all the associated customer payment profiles and customer shipping addresses. + # + # Returns a Response whose params hash contains all the profile information. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer to retrieve. (REQUIRED) + def get_customer_profile(options) + requires!(options, :customer_profile_id) + + request = build_request(:get_customer_profile, options) + commit(:get_customer_profile, request) + end + + def get_customer_profile_ids(options = {}) + request = build_request(:get_customer_profile_ids, options) + commit(:get_customer_profile_ids, request) + end + + # Retrieve a customer payment profile for an existing customer profile. + # + # Returns a Response whose params hash contains all the payment profile information. Sensitive information such as credit card + # numbers will be masked. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer with the payment profile to be retrieved. (REQUIRED) + # * :customer_payment_profile_id -- The Payment Profile ID of the payment profile to be retrieved. (REQUIRED) + def get_customer_payment_profile(options) + requires!(options, :customer_profile_id) + requires!(options, :customer_payment_profile_id) + + request = build_request(:get_customer_payment_profile, options) + commit(:get_customer_payment_profile, request) + end + + # Retrieve a customer shipping address for an existing customer profile. + # + # Returns a Response whose params hash contains all the shipping address information. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer with the payment profile to be retrieved. (REQUIRED) + # * :customer_address_id -- The Shipping Address ID of the shipping address to be retrieved. (REQUIRED) + def get_customer_shipping_address(options) + requires!(options, :customer_profile_id) + requires!(options, :customer_address_id) + + request = build_request(:get_customer_shipping_address, options) + commit(:get_customer_shipping_address, request) + end + + # Updates an existing customer profile. + # + # Warning: if you do not provide a parameter in the :payment_profile hash, it is automatically set to nil at + # Authorize.Net. You will most likely want to first get the profile hash using get_customer_profile and then only change the + # elements you wish to change. + # + # ==== Options + # + # * :profile -- A hash containing the values the Customer Profile should be updated to. (REQUIRED) + # + # ==== Profile + # + # * :customer_profile_id -- The Customer Profile ID of the customer profile to update. (REQUIRED) + def update_customer_profile(options) + requires!(options, :profile) + requires!(options[:profile], :customer_profile_id) + + request = build_request(:update_customer_profile, options) + commit(:update_customer_profile, request) + end + + # Updates a customer payment profile for an existing customer profile. + # + # Warning: if you do not provide a parameter in the :payment_profile hash, it is automatically set to nil at + # Authorize.Net. You will most likely want to first get the profile hash using get_customer_payment_profile and then only + # change the elements you wish to change. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer with the payment profile to be updated. (REQUIRED) + # * :payment_profile -- A hash containing the values the Customer Payment Profile should be updated to. (REQUIRED) + # + # ==== Payment Profile + # + # * :customer_payment_profile_id -- The Customer Payment Profile ID of the Customer Payment Profile to update. (REQUIRED) + def update_customer_payment_profile(options) + requires!(options, :customer_profile_id, :payment_profile) + requires!(options[:payment_profile], :customer_payment_profile_id) + + request = build_request(:update_customer_payment_profile, options) + commit(:update_customer_payment_profile, request) + end + + # Updates a customer shipping address for an existing customer profile. + # + # Warning: if you do not provide a parameter in the :address hash, it is automatically set to nil at + # Authorize.Net. You will most likely want to first get the profile hash using get_customer_shipping_address and then only + # change the elements you wish to change. + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer with the payment profile to be updated. (REQUIRED) + # * :address -- A hash containing the values the Customer Shipping Address should be updated to. (REQUIRED) + # + # ==== Address + # + # * :customer_address_id -- The Customer Address ID of the Customer Payment Profile to update. (REQUIRED) + def update_customer_shipping_address(options) + requires!(options, :customer_profile_id, :address) + requires!(options[:address], :customer_address_id) + + request = build_request(:update_customer_shipping_address, options) + commit(:update_customer_shipping_address, request) + end + + # Creates a new payment transaction from an existing customer profile + # + # This is what is used to charge a customer whose information you have stored in a Customer Profile. + # + # Returns a Response object that contains the result of the transaction in params['direct_response'] + # + # ==== Options + # + # * :transaction -- A hash containing information on the transaction that is being requested. (REQUIRED) + # + # ==== Transaction + # + # * :type -- The type of transaction. Can be either :auth_only, :capture_only, :auth_capture, :prior_auth_capture, :refund or :void. (REQUIRED) + # * :amount -- The amount for the tranaction. Formatted with a decimal. For example "4.95" (CONDITIONAL) + # - :type == :void (NOT USED) + # - :type == :refund (OPTIONAL) + # - :type == (:auth_only, :capture_only, :auth_capture, :prior_auth_capture) (REQUIRED) + # + # * :customer_profile_id -- The Customer Profile ID of the customer to use in this transaction. (CONDITIONAL) + # - :type == (:void, :prior_auth_capture) (OPTIONAL) + # - :type == :refund (CONDITIONAL - required if masked information is not being submitted [see below]) + # - :type == (:auth_only, :capture_only, :auth_capture) (REQUIRED) + # + # * :customer_payment_profile_id -- The Customer Payment Profile ID of the Customer Payment Profile to use in this transaction. (CONDITIONAL) + # - :type == (:void, :prior_auth_capture) (OPTIONAL) + # - :type == :refund (CONDITIONAL - required if masked information is not being submitted [see below]) + # - :type == (:auth_only, :capture_only, :auth_capture) (REQUIRED) + # + # * :trans_id -- The payment gateway assigned transaction ID of the original transaction (CONDITIONAL): + # - :type = (:void, :refund, :prior_auth_capture) (REQUIRED) + # - :type = (:auth_only, :capture_only, :auth_capture) (NOT USED) + # + # * :card_code -- CVV/CCV code (OPTIONAL) + # - :type = (:void, :refund, :prior_auth_capture) (NOT USED) + # - :type = (:auth_only, :capture_only, :auth_capture) (OPTIONAL) + # + # * :customer_shipping_address_id -- Payment gateway assigned ID associated with the customer shipping address (CONDITIONAL) + # - :type = (:void, :refund) (OPTIONAL) + # - :type = (:auth_only, :capture_only, :auth_capture) (NOT USED) + # - :type = (:prior_auth_capture) (OPTIONAL) + # + # ==== For :type == :refund only + # * :credit_card_number_masked -- (CONDITIONAL - requied for credit card refunds is :customer_profile_id AND :customer_payment_profile_id are missing) + # * :bank_routing_number_masked && :bank_account_number_masked -- (CONDITIONAL - requied for electronic check refunds is :customer_profile_id AND :customer_payment_profile_id are missing) (NOT ABLE TO TEST - I keep getting "ACH transactions are not accepted by this merchant." when trying to make a payment and, until that's possible I can't refund (wiseleyb@gmail.com)) + def create_customer_profile_transaction(options) + requires!(options, :transaction) + requires!(options[:transaction], :type) + case options[:transaction][:type] + when :void + requires!(options[:transaction], :trans_id) + when :refund + requires!(options[:transaction], :trans_id) && + ( + (options[:transaction][:customer_profile_id] && options[:transaction][:customer_payment_profile_id]) || + options[:transaction][:credit_card_number_masked] || + (options[:transaction][:bank_routing_number_masked] && options[:transaction][:bank_account_number_masked]) + ) + when :prior_auth_capture + requires!(options[:transaction], :amount, :trans_id) + else + requires!(options[:transaction], :amount, :customer_profile_id, :customer_payment_profile_id) + end + request = build_request(:create_customer_profile_transaction, options) + commit(:create_customer_profile_transaction, request) + end + + # Creates a new payment transaction for refund from an existing customer profile + # + # This is what is used to refund a transaction you have stored in a Customer Profile. + # + # Returns a Response object that contains the result of the transaction in params['direct_response'] + # + # ==== Options + # + # * :transaction -- A hash containing information on the transaction that is being requested. (REQUIRED) + # + # ==== Transaction + # + # * :amount -- The total amount to be refunded (REQUIRED) + # + # * :customer_profile_id -- The Customer Profile ID of the customer to use in this transaction. (CONDITIONAL :customer_payment_profile_id must be included if used) + # * :customer_payment_profile_id -- The Customer Payment Profile ID of the Customer Payment Profile to use in this transaction. (CONDITIONAL :customer_profile_id must be included if used) + # + # * :credit_card_number_masked -- Four Xs follwed by the last four digits of the credit card (CONDITIONAL - used if customer_profile_id and customer_payment_profile_id aren't given) + # + # * :bank_routing_number_masked -- The last four gidits of the routing number to be refunded (CONDITIONAL - must be used with :bank_account_number_masked) + # * :bank_account_number_masked -- The last four digis of the bank account number to be refunded, Ex. XXXX1234 (CONDITIONAL - must be used with :bank_routing_number_masked) + # + # * :tax - A hash containing tax information for the refund (OPTIONAL - :amount, :name (31 characters), :description (255 characters)) + # * :duty - A hash containting duty information for the refund (OPTIONAL - :amount, :name (31 characters), :description (255 characters)) + # * :shipping - A hash containing shipping information for the refund (OPTIONAL - :amount, :name (31 characters), :description (255 characters)) + def create_customer_profile_transaction_for_refund(options) + requires!(options, :transaction) + options[:transaction][:type] = :refund + requires!(options[:transaction], :trans_id) + requires!(options[:transaction], :amount) + request = build_request(:create_customer_profile_transaction, options) + commit(:create_customer_profile_transaction, request) + end + + # Creates a new payment transaction for void from an existing customer profile + # + # This is what is used to void a transaction you have stored in a Customer Profile. + # + # Returns a Response object that contains the result of the transaction in params['direct_response'] + # + # ==== Options + # + # * :transaction -- A hash containing information on the transaction that is being requested. (REQUIRED) + # + # ==== Transaction + # + # * :trans_id -- The payment gateway assigned transaction id of the original transaction. (REQUIRED) + # * :customer_profile_id -- The Customer Profile ID of the customer to use in this transaction. + # * :customer_payment_profile_id -- The Customer Payment Profile ID of the Customer Payment Profile to use in this transaction. + # * :customer_shipping_address_id -- Payment gateway assigned ID associated with the customer shipping address. + def create_customer_profile_transaction_for_void(options) + requires!(options, :transaction) + options[:transaction][:type] = :void + requires!(options[:transaction], :trans_id) + request = build_request(:create_customer_profile_transaction, options) + commit(:create_customer_profile_transaction, request) + end + + # Verifies an existing customer payment profile by generating a test transaction + # + # Returns a Response object that contains the result of the transaction in params['direct_response'] + # + # ==== Options + # + # * :customer_profile_id -- The Customer Profile ID of the customer to use in this transaction. (REQUIRED) + # * :customer_payment_profile_id -- The Customer Payment Profile ID of the Customer Payment Profile to be verified. (REQUIRED) + # * :customer_address_id -- The Customer Address ID of the Customer Shipping Address to be verified. (OPTIONAL) + # * :card_code -- If the payment profile is a credit card, the CCV/CVV code to validate with (OPTIONAL) + # * :validation_mode -- :live or :test In Test Mode, only field validation is performed. (REQUIRED + # In Live Mode, a transaction is generated and submitted to the processor with the amount of $0.01. If successful, the transaction is immediately voided. (REQUIRED) + def validate_customer_payment_profile(options) + requires!(options, :customer_profile_id, :customer_payment_profile_id, :validation_mode) + + request = build_request(:validate_customer_payment_profile, options) + commit(:validate_customer_payment_profile, request) + end + + private + + def expdate(credit_card) + if credit_card.year.present? && credit_card.month.present? + sprintf('%04d-%02d', credit_card.year, credit_card.month) + else + 'XXXX' + end + end + + def build_request(action, options = {}) + unless CIM_ACTIONS.include?(action) + raise StandardError, "Invalid Customer Information Manager Action: #{action}" + end + + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct!(:xml, :version => '1.0', :encoding => 'utf-8') + xml.tag!("#{CIM_ACTIONS[action]}Request", :xmlns => AUTHORIZE_NET_CIM_NAMESPACE) do + add_merchant_authentication(xml) + # Merchant-assigned reference ID for the request + xml.tag!('refId', options[:ref_id]) if options[:ref_id] + # Order options + add_order(xml, options[:order]) if options[:order] + send("build_#{action}_request", xml, options) + end + end + + # Contains the merchant’s payment gateway account authentication information + def add_merchant_authentication(xml) + xml.tag!('merchantAuthentication') do + xml.tag!('name', @options[:login]) + xml.tag!('transactionKey', @options[:password]) + end + end + + def build_create_customer_profile_request(xml, options) + add_profile(xml, options[:profile]) + + xml.tag!('validationMode', CIM_VALIDATION_MODES[options[:validation_mode]]) if options[:validation_mode] + + if options.has_key?(:payment_profile) + xml.tag!('paymentProfile') do + add_payment_profile(xml, options[:payment_profile]) + end + end + + xml.target! + end + + def build_create_customer_payment_profile_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + + xml.tag!('paymentProfile') do + add_payment_profile(xml, options[:payment_profile]) + end + + xml.tag!('validationMode', CIM_VALIDATION_MODES[options[:validation_mode]]) if options[:validation_mode] + + xml.target! + end + + def build_create_customer_shipping_address_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + + xml.tag!('address') do + add_address(xml, options[:address]) + end + + xml.target! + end + + def build_delete_customer_profile_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + xml.target! + end + + def build_delete_customer_payment_profile_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + xml.tag!('customerPaymentProfileId', options[:customer_payment_profile_id]) + xml.target! + end + + def build_delete_customer_shipping_address_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + xml.tag!('customerAddressId', options[:customer_address_id]) + xml.target! + end + + def build_get_customer_profile_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + xml.target! + end + + def build_get_customer_profile_ids_request(xml, options) + xml.target! + end + + def build_get_customer_payment_profile_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + xml.tag!('customerPaymentProfileId', options[:customer_payment_profile_id]) + xml.target! + end + + def build_get_customer_shipping_address_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + xml.tag!('customerAddressId', options[:customer_address_id]) + xml.target! + end + + def build_update_customer_profile_request(xml, options) + add_profile(xml, options[:profile], true) + + xml.target! + end + + def build_update_customer_payment_profile_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + + xml.tag!('paymentProfile') do + add_payment_profile(xml, options[:payment_profile]) + end + + xml.tag!('validationMode', CIM_VALIDATION_MODES[options[:validation_mode]]) if options[:validation_mode] + + xml.target! + end + + def build_update_customer_shipping_address_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + + xml.tag!('address') do + add_address(xml, options[:address]) + end + + xml.target! + end + + def build_create_customer_profile_transaction_request(xml, options) + options[:extra_options] ||= {} + options[:extra_options].merge!('x_test_request' => 'TRUE') if @options[:test] + + add_transaction(xml, options[:transaction]) + tag_unless_blank(xml, 'extraOptions', format_extra_options(options[:extra_options])) + + xml.target! + end + + def build_validate_customer_payment_profile_request(xml, options) + xml.tag!('customerProfileId', options[:customer_profile_id]) + xml.tag!('customerPaymentProfileId', options[:customer_payment_profile_id]) + xml.tag!('customerShippingAddressId', options[:customer_address_id]) if options[:customer_address_id] + tag_unless_blank(xml, 'cardCode', options[:card_code]) + xml.tag!('validationMode', CIM_VALIDATION_MODES[options[:validation_mode]]) if options[:validation_mode] + + xml.target! + end + + # :merchant_customer_id (Optional) + # :description (Optional) + # :email (Optional) + # :payment_profiles (Optional) + def add_profile(xml, profile, update = false) + xml.tag!('profile') do + # Merchant assigned ID for the customer. Up to 20 characters. (optional) + xml.tag!('merchantCustomerId', profile[:merchant_customer_id]) if profile[:merchant_customer_id] + # Description of the customer. Up to 255 Characters (optional) + xml.tag!('description', profile[:description]) if profile[:description] + # Email Address for the customer. Up to 255 Characters (optional) + xml.tag!('email', profile[:email]) if profile[:email] + + if update + xml.tag!('customerProfileId', profile[:customer_profile_id]) + else + add_payment_profiles(xml, profile[:payment_profiles]) if profile[:payment_profiles] + add_ship_to_list(xml, profile[:ship_to_list]) if profile[:ship_to_list] + end + end + end + + def add_transaction(xml, transaction) + unless CIM_TRANSACTION_TYPES.include?(transaction[:type]) + raise StandardError, "Invalid Customer Information Manager Transaction Type: #{transaction[:type]}" + end + + xml.tag!('transaction') do + xml.tag!(CIM_TRANSACTION_TYPES[transaction[:type]]) do + # The amount to be billed to the customer + case transaction[:type] + when :void + tag_unless_blank(xml,'customerProfileId', transaction[:customer_profile_id]) + tag_unless_blank(xml,'customerPaymentProfileId', transaction[:customer_payment_profile_id]) + tag_unless_blank(xml,'customerShippingAddressId', transaction[:customer_shipping_address_id]) + xml.tag!('transId', transaction[:trans_id]) + when :refund + #TODO - add lineItems field + xml.tag!('amount', transaction[:amount]) + tag_unless_blank(xml, 'customerProfileId', transaction[:customer_profile_id]) + tag_unless_blank(xml, 'customerPaymentProfileId', transaction[:customer_payment_profile_id]) + tag_unless_blank(xml, 'customerShippingAddressId', transaction[:customer_shipping_address_id]) + tag_unless_blank(xml, 'creditCardNumberMasked', transaction[:credit_card_number_masked]) + tag_unless_blank(xml, 'bankRoutingNumberMasked', transaction[:bank_routing_number_masked]) + tag_unless_blank(xml, 'bankAccountNumberMasked', transaction[:bank_account_number_masked]) + xml.tag!('transId', transaction[:trans_id]) + add_tax(xml, transaction[:tax]) if transaction[:tax] + add_duty(xml, transaction[:duty]) if transaction[:duty] + add_shipping(xml, transaction[:shipping]) if transaction[:shipping] + when :prior_auth_capture + xml.tag!('amount', transaction[:amount]) + xml.tag!('transId', transaction[:trans_id]) + else + xml.tag!('amount', transaction[:amount]) + xml.tag!('customerProfileId', transaction[:customer_profile_id]) + xml.tag!('customerPaymentProfileId', transaction[:customer_payment_profile_id]) + xml.tag!('approvalCode', transaction[:approval_code]) if transaction[:type] == :capture_only + end + add_order(xml, transaction[:order]) if transaction[:order].present? + unless [:void,:refund,:prior_auth_capture].include?(transaction[:type]) + tag_unless_blank(xml, 'cardCode', transaction[:card_code]) + end + end + end + end + + def add_tax(xml, tax) + xml.tag!('tax') do + xml.tag!('amount', tax[:amount]) if tax[:amount] + xml.tag!('name', tax[:name]) if tax[:name] + xml.tag!('description', tax[:description]) if tax[:description] + end + end + + def add_duty(xml, duty) + xml.tag!('duty') do + xml.tag!('amount', duty[:amount]) if duty[:amount] + xml.tag!('name', duty[:name]) if duty[:name] + xml.tag!('description', duty[:description]) if duty[:description] + end + end + + def add_shipping(xml, shipping) + xml.tag!('shipping') do + xml.tag!('amount', shipping[:amount]) if shipping[:amount] + xml.tag!('name', shipping[:name]) if shipping[:name] + xml.tag!('description', shipping[:description]) if shipping[:description] + end + end + + def add_order(xml, order) + xml.tag!('order') do + xml.tag!('invoiceNumber', order[:invoice_number]) if order[:invoice_number] + xml.tag!('description', order[:description]) if order[:description] + xml.tag!('purchaseOrderNumber', order[:purchase_order_number]) if order[:purchase_order_number] + end + end + + def add_payment_profiles(xml, payment_profiles) + xml.tag!('paymentProfiles') do + add_payment_profile(xml, payment_profiles) + end + end + + # :customer_type => 'individual or business', # Optional + # :bill_to => @address, + # :payment => @payment + def add_payment_profile(xml, payment_profile) + # 'individual' or 'business' (optional) + xml.tag!('customerType', payment_profile[:customer_type]) if payment_profile[:customer_type] + + if payment_profile[:bill_to] + xml.tag!('billTo') do + add_address(xml, payment_profile[:bill_to]) + end + end + + if payment_profile[:payment] + xml.tag!('payment') do + add_credit_card(xml, payment_profile[:payment][:credit_card]) if payment_profile[:payment].has_key?(:credit_card) + add_bank_account(xml, payment_profile[:payment][:bank_account]) if payment_profile[:payment].has_key?(:bank_account) + add_drivers_license(xml, payment_profile[:payment][:drivers_license]) if payment_profile[:payment].has_key?(:drivers_license) + # This element is only required for Wells Fargo SecureSource eCheck.Net merchants + # The customer's Social Security Number or Tax ID + xml.tag!('taxId', payment_profile[:payment]) if payment_profile[:payment].has_key?(:tax_id) + end + end + + xml.tag!('customerPaymentProfileId', payment_profile[:customer_payment_profile_id]) if payment_profile[:customer_payment_profile_id] + end + + def add_ship_to_list(xml, ship_to_list) + xml.tag!('shipToList') do + add_address(xml, ship_to_list) + end + end + + def add_address(xml, address) + xml.tag!('firstName', address[:first_name]) + xml.tag!('lastName', address[:last_name]) + xml.tag!('company', address[:company]) + xml.tag!('address', address[:address1]) if address[:address1] + xml.tag!('address', address[:address]) if address[:address] + xml.tag!('city', address[:city]) + xml.tag!('state', address[:state]) + xml.tag!('zip', address[:zip]) + xml.tag!('country', address[:country]) + xml.tag!('phoneNumber', address[:phone_number]) if address[:phone_number] + xml.tag!('faxNumber', address[:fax_number]) if address[:fax_number] + + xml.tag!('customerAddressId', address[:customer_address_id]) if address[:customer_address_id] + end + + # Adds customer’s credit card information + # Note: This element should only be included + # when the payment method is credit card. + def add_credit_card(xml, credit_card) + return unless credit_card + xml.tag!('creditCard') do + # The credit card number used for payment of the subscription + xml.tag!('cardNumber', credit_card.number) + # The expiration date of the credit card used for the subscription + xml.tag!('expirationDate', expdate(credit_card)) + # Note that Authorize.net does not save CVV codes as part of the + # payment profile. Any transactions/validations after the payment + # profile is created that wish to use CVV verification must pass + # the CVV code to authorize.net again. + xml.tag!('cardCode', credit_card.verification_value) if credit_card.verification_value? + end + end + + # Adds customer’s bank account information + # Note: This element should only be included + # when the payment method is bank account. + def add_bank_account(xml, bank_account) + raise StandardError, "Invalid Bank Account Type: #{bank_account[:account_type]}" unless BANK_ACCOUNT_TYPES.include?(bank_account[:account_type]) + raise StandardError, "Invalid eCheck Type: #{bank_account[:echeck_type]}" unless ECHECK_TYPES.include?(bank_account[:echeck_type]) + + xml.tag!('bankAccount') do + # The type of bank account + xml.tag!('accountType', BANK_ACCOUNT_TYPES[bank_account[:account_type]]) + # The routing number of the customer’s bank + xml.tag!('routingNumber', bank_account[:routing_number]) + # The bank account number + xml.tag!('accountNumber', bank_account[:account_number]) + # The full name of the individual associated + # with the bank account number + xml.tag!('nameOnAccount', bank_account[:name_on_account]) + # The type of electronic check transaction + xml.tag!('echeckType', ECHECK_TYPES[bank_account[:echeck_type]]) + # The full name of the individual associated + # with the bank account number (optional) + xml.tag!('bankName', bank_account[:bank_name]) if bank_account[:bank_name] + end + end + + # Adds customer’s driver's license information + # Note: This element is only required for + # Wells Fargo SecureSource eCheck.Net merchants + def add_drivers_license(xml, drivers_license) + xml.tag!('driversLicense') do + # The state of the customer's driver's license + # A valid two character state code + xml.tag!('state', drivers_license[:state]) + # The customer’s driver's license number + xml.tag!('number', drivers_license[:number]) + # The date of birth listed on the customer's driver's license + # YYYY-MM-DD + xml.tag!('dateOfBirth', drivers_license[:date_of_birth]) + end + end + + def commit(action, request) + url = test? ? test_url : live_url + xml = ssl_post(url, request, "Content-Type" => "text/xml") + + response_params = parse(action, xml) + + message = response_params['messages']['message']['text'] + test_mode = test? || message =~ /Test Mode/ + success = response_params['messages']['result_code'] == 'Ok' + response_params['direct_response'] = parse_direct_response(response_params['direct_response']) if response_params['direct_response'] + transaction_id = response_params['direct_response']['transaction_id'] if response_params['direct_response'] + + Response.new(success, message, response_params, + :test => test_mode, + :authorization => transaction_id || response_params['customer_profile_id'] || (response_params['profile'] ? response_params['profile']['customer_profile_id'] : nil) + ) + end + + def tag_unless_blank(xml, tag_name, data) + xml.tag!(tag_name, data) unless data.blank? || data.nil? + end + + def format_extra_options(options) + options.map{ |k, v| "#{k}=#{v}" }.join(',') unless options.nil? + end + + def parse_direct_response(params) + delimiter = @options[:delimiter] || ',' + direct_response = {'raw' => params} + direct_response_fields = params.split(delimiter) + direct_response.merge( + { + 'response_code' => direct_response_fields[0], + 'response_subcode' => direct_response_fields[1], + 'response_reason_code' => direct_response_fields[2], + 'message' => direct_response_fields[3], + 'approval_code' => direct_response_fields[4], + 'avs_response' => direct_response_fields[5], + 'transaction_id' => direct_response_fields[6], + 'invoice_number' => direct_response_fields[7], + 'order_description' => direct_response_fields[8], + 'amount' => direct_response_fields[9], + 'method' => direct_response_fields[10], + 'transaction_type' => direct_response_fields[11], + 'customer_id' => direct_response_fields[12], + 'first_name' => direct_response_fields[13], + 'last_name' => direct_response_fields[14], + 'company' => direct_response_fields[15], + 'address' => direct_response_fields[16], + 'city' => direct_response_fields[17], + 'state' => direct_response_fields[18], + 'zip_code' => direct_response_fields[19], + 'country' => direct_response_fields[20], + 'phone' => direct_response_fields[21], + 'fax' => direct_response_fields[22], + 'email_address' => direct_response_fields[23], + 'ship_to_first_name' => direct_response_fields[24], + 'ship_to_last_name' => direct_response_fields[25], + 'ship_to_company' => direct_response_fields[26], + 'ship_to_address' => direct_response_fields[27], + 'ship_to_city' => direct_response_fields[28], + 'ship_to_state' => direct_response_fields[29], + 'ship_to_zip_code' => direct_response_fields[30], + 'ship_to_country' => direct_response_fields[31], + 'tax' => direct_response_fields[32], + 'duty' => direct_response_fields[33], + 'freight' => direct_response_fields[34], + 'tax_exempt' => direct_response_fields[35], + 'purchase_order_number' => direct_response_fields[36], + 'md5_hash' => direct_response_fields[37], + 'card_code' => direct_response_fields[38], + 'cardholder_authentication_verification_response' => direct_response_fields[39], + # The following direct response fields are only available in version 3.1 of the + # transaction response. Check your merchant account settings for details. + 'account_number' => direct_response_fields[50] || '', + 'card_type' => direct_response_fields[51] || '', + 'split_tender_id' => direct_response_fields[52] || '', + 'requested_amount' => direct_response_fields[53] || '', + 'balance_on_card' => direct_response_fields[54] || '', + } + ) + end + + def parse(action, xml) + xml = REXML::Document.new(xml) + root = REXML::XPath.first(xml, "//#{CIM_ACTIONS[action]}Response") || + REXML::XPath.first(xml, "//ErrorResponse") + if root + response = parse_element(root) + end + + response + end + + def parse_element(node) + if node.has_elements? + response = {} + node.elements.each{ |e| + key = e.name.underscore + value = parse_element(e) + if response.has_key?(key) + if response[key].is_a?(Array) + response[key].push(value) + else + response[key] = [response[key], value] + end + else + response[key] = parse_element(e) + end + } + else + response = node.text + end + + response + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/balanced.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/balanced.rb new file mode 100644 index 000000000..a768fb38d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/balanced.rb @@ -0,0 +1,467 @@ +require 'json' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + # For more information on Balanced visit https://www.balancedpayments.com + # or visit #balanced on irc.freenode.net + # + # Instantiate a instance of BalancedGateway by passing through your + # Balanced API key secret. + # + # ==== To obtain an API key of your own + # + # 1. Visit https://www.balancedpayments.com + # 2. Click "Get started" + # 3. The next screen will give you a test API key of your own + # 4. When you're ready to generate a production API key click the "Go + # live" button on the Balanced dashboard and fill in your marketplace + # details. + # + # ==== Overview + # + # Balanced provides a RESTful API, all entities within Balanced are + # represented by their respective URIs, these are returned in the + # `authorization` parameter of the Active Merchant Response object. + # + # All Response objects will contain a hash property called `params` which + # holds the raw JSON dictionary returned by Balanced. You can find + # properties about the operation performed and the object that represents + # it within this hash. + # + # All operations within Balanced are tied to an account, as such, when you + # perform an `authorization` or a `capture` with a new credit card you + # must ensure you also pass the `:email` property within the `options` + # parameter. + # + # For more details about Balanced's API visit: + # https://www.balancedpayments.com/docs + # + # ==== Terminology & Transaction Flow + # + # * An `authorization` operation will return a Hold URI. An `authorization` + # within Balanced is valid until the `expires_at` property. You can see the + # exact date of the expiry on the Response object by inspecting the + # property `response.params['expires_at']`. The resulting Hold may be + # `capture`d or `void`ed at any time before the `expires_at` date for + # any amount up to the full amount of the original `authorization`. + # * A `capture` operation will return a Debit URI. You must pass the URI of + # the previously performed `authorization` + # * A `purchase` will create a Hold and Debit in a single operation and + # return the URI of the resulting Debit. + # * A `void` operation must be performed on an existing `authorization` + # and will result in releasing the funds reserved by the + # `authorization`. + # * The `refund` operation must be performed on a previously captured + # Debit URI. You may refund any fraction of the original amount of the + # debit up to the original total. + # + class BalancedGateway < Gateway + VERSION = '1.0.0' + + TEST_URL = LIVE_URL = 'https://api.balancedpayments.com' + + # The countries the gateway supports merchants from as 2 digit ISO + # country codes + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'https://www.balancedpayments.com/' + self.display_name = 'Balanced' + self.money_format = :cents + + class Error < StandardError + attr_reader :response + + def initialize(response, msg=nil) + @response = response + super(msg || response['description']) + end + end + + class CardDeclined < Error + end + + # Creates a new BalancedGateway + # + # The gateway requires that a valid api_key be passed in the +options+ + # hash. + # + # ==== Options + # + # * :login -- The Balanced API Secret (REQUIRED) + def initialize(options = {}) + requires!(options, :login) + super + initialize_marketplace(options[:marketplace] || load_marketplace) + end + + # Performs an authorization (Hold in Balanced nonclementure), which + # reserves the funds on the customer's credit card, but does not charge + # the card. An authorization is valid until the `expires_at` field in + # the params Hash passes. See `response.params['expires_at']`. The exact + # amount of time until an authorization expires depends on the card + # issuer. + # + # If you pass a previously tokenized `credit_card` URI the only other + # parameter required is `money`. If you pass `credit_card` as a hash of + # credit card information you must also pass `options` with a `:email` + # entry. + # + # ==== Parameters + # + # * money -- The amount to be authorized as an Integer value in cents. + # * credit_card -- A hash of credit card details for this + # transaction or the URI of a card previously stored in Balanced. + # * options -- A hash of optional parameters. + # + # ==== Options + # + # If you are passing a new credit card you must pass one of these two + # parameters + # + # * email -- the email address of user associated with this + # purchase. + # * account_uri -- `account_uri` is the URI of an existing + # Balanced account. + def authorize(money, credit_card, options = {}) + if credit_card.respond_to?(:number) + requires!(options, :email) unless options[:account_uri] + end + + post = {} + post[:amount] = money + post[:description] = options[:description] + + create_or_find_account(post, options) + add_credit_card(post, credit_card, options) + add_address(credit_card, options) + + create_transaction(:post, @holds_uri, post) + rescue Error => ex + failed_response(ex.response) + end + + # Perform a purchase, which is an authorization and capture in a single + # operation. + # + # ==== Parameters + # + # * money -- The amount to be purchased as an Integer value in cents. + # * credit_card -- A hash of credit card details for this + # transaction or the URI of a card previously stored in Balanced. + # * options -- A hash of optional parameters. + # + # ==== Options + # + # If you are passing a new credit card you must pass one of these two + # parameters + # + # * email -- the email address of user associated with this + # purchase. + # * account_uri -- `account_uri` is the URI of an existing + # Balanced account. + def purchase(money, credit_card, options = {}) + if credit_card.respond_to?('number') + requires!(options, :email) unless options[:account_uri] + end + + post = {} + post[:amount] = money + post[:description] = options[:description] + + create_or_find_account(post, options) + add_credit_card(post, credit_card, options) + add_address(credit_card, options) + + create_transaction(:post, @debits_uri, post) + rescue Error => ex + failed_response(ex.response) + end + + # Captures the funds from an authorized transaction (Hold). + # + # ==== Parameters + # + # * money -- The amount to be captured as an Integer value in + # cents. If omitted the full amount of the original authorization + # transaction will be captured. + # * authorization -- The uri of an authorization returned from + # an authorize request. + # + # ==== Options + # + # * description -- A string that will be displayed on the + # Balanced dashboard + def capture(money, authorization, options = {}) + post = {} + post[:hold_uri] = authorization + post[:amount] = money if money + post[:description] = options[:description] if options[:description] + post[:on_behalf_of_uri] = options[:on_behalf_of_uri] if options[:on_behalf_of_uri] + + create_transaction(:post, @debits_uri, post) + rescue Error => ex + failed_response(ex.response) + end + + # Void a previous authorization (Hold) + # + # ==== Parameters + # + # * authorization -- The uri of the authorization returned from + # an `authorize` request. + def void(authorization) + post = {} + post[:is_void] = true + + create_transaction(:put, authorization, post) + rescue Error => ex + failed_response(ex.response) + end + + # Refund a transaction. + # + # Returns the money debited from a card to the card from the + # marketplace's escrow balance. + # + # ==== Parameters + # + # * debit_uri -- The uri of the original transaction against + # which the refund is being issued. + # * options -- A hash of parameters. + # + # ==== Options + # + # * `:amount` -- specify an amount if you want to perform a + # partial refund. This value will default to the total amount of the + # debit that has not been refunded so far. + def refund(amount, debit_uri = "deprecated", options = {}) + if(debit_uri == "deprecated" || debit_uri.kind_of?(Hash)) + deprecated "Calling the refund method without an amount parameter is deprecated and will be removed in a future version." + return refund(options[:amount], amount, options) + end + + requires!(debit_uri) + post = {} + post[:debit_uri] = debit_uri + post[:amount] = amount + post[:description] = options[:description] + create_transaction(:post, @refunds_uri, post) + rescue Error => ex + failed_response(ex.response) + end + + # Stores a card and email address + # + # ==== Parameters + # + # * credit_card -- + def store(credit_card, options = {}) + requires!(options, :email) + post = {} + account_uri = create_or_find_account(post, options) + if credit_card.respond_to? :number + add_credit_card(post, credit_card, options) + else + associate_card_to_account(account_uri, credit_card) + credit_card + end + rescue Error => ex + failed_response(ex.response) + end + + private + + # Load URIs for this marketplace by inspecting the marketplace object + # returned from the uri. http://en.wikipedia.org/wiki/HATEOAS + def load_marketplace + response = http_request(:get, '/v1/marketplaces') + if error?(response) + raise Error.new(response, 'Invalid login credentials supplied') + end + response['items'][0] + end + + def initialize_marketplace(marketplace) + @marketplace_uri = marketplace['uri'] + @holds_uri = marketplace['holds_uri'] + @debits_uri = marketplace['debits_uri'] + @cards_uri = marketplace['cards_uri'] + @accounts_uri = marketplace['accounts_uri'] + @refunds_uri = marketplace['refunds_uri'] + end + + def create_or_find_account(post, options) + account_uri = nil + + if options.has_key? :account_uri + account_uri = options[:account_uri] + end + + if account_uri == nil + post[:email_address] = options[:email] + + # create an account + response = http_request(:post, @accounts_uri, post) + + if response.has_key? 'uri' + account_uri = response['uri'] + elsif error?(response) + # lookup account from Balanced, account_uri should be in the + # exception in a dictionary called extras + account_uri = response['extras']['account_uri'] + end + end + + post[:account_uri] = account_uri + + account_uri + end + + def add_address(credit_card, options) + return unless credit_card.kind_of?(Hash) + if address = options[:billing_address] || options[:address] + credit_card[:street_address] = address[:address1] if address[:address1] + credit_card[:street_address] += ' ' + address[:address2] if address[:address2] + credit_card[:postal_code] = address[:zip] if address[:zip] + credit_card[:country] = address[:country] if address[:country] + end + end + + def add_credit_card(post, credit_card, options) + if credit_card.respond_to? :number + card = {} + card[:card_number] = credit_card.number + card[:expiration_month] = credit_card.month + card[:expiration_year] = credit_card.year + card[:security_code] = credit_card.verification_value if credit_card.verification_value? + card[:name] = credit_card.name if credit_card.name + + add_address(card, options) + + response = http_request(:post, @cards_uri, card) + if error?(response) + raise CardDeclined, response + end + card_uri = response['uri'] + + associate_card_to_account(post[:account_uri], card_uri) + + post[:card_uri] = card_uri + elsif credit_card.kind_of?(String) + post[:card_uri] = credit_card + end + + post[:card_uri] + end + + def associate_card_to_account(account_uri, card_uri) + http_request(:put, account_uri, :card_uri => card_uri) + end + + def http_request(method, url, parameters={}, meta={}) + begin + if method == :get + raw_response = ssl_get(LIVE_URL + url, headers(meta)) + else + raw_response = ssl_request(method, + LIVE_URL + url, + post_data(parameters), + headers(meta)) + end + parse(raw_response) + rescue ResponseError => e + raw_response = e.response.body + response_error(raw_response) + rescue JSON::ParserError + json_error(raw_response) + end + end + + def create_transaction(method, url, parameters, meta={}) + response = http_request(method, url, parameters, meta) + success = !error?(response) + + Response.new(success, + (success ? "Transaction approved" : response["description"]), + response, + :test => (@marketplace_uri.index("TEST") ? true : false), + :authorization => response["uri"] + ) + end + + def failed_response(response) + is_test = false + if @marketplace_uri + is_test = (@marketplace_uri.index("TEST") ? true : false) + end + + Response.new(false, + response["description"], + response, + :test => is_test + ) + end + + def parse(body) + JSON.parse(body) + end + + def response_error(raw_response) + begin + parse(raw_response) + rescue JSON::ParserError + json_error(raw_response) + end + end + + def json_error(raw_response) + msg = 'Invalid response received from the Balanced API. Please contact support@balancedpayments.com if you continue to receive this message.' + msg += " (The raw response returned by the API was #{raw_response.inspect})" + { + "error" => { + "message" => msg + } + } + end + + def error?(response) + response.key?('status_code') + end + + def post_data(params) + return nil unless params + + params.map do |key, value| + next if value.blank? + if value.is_a?(Hash) + h = {} + value.each do |k, v| + h["#{key}[#{k}]"] = v unless v.blank? + end + post_data(h) + else + "#{key}=#{CGI.escape(value.to_s)}" + end + end.compact.join("&") + end + + def headers(meta={}) + @@ua ||= JSON.dump({ + :bindings_version => ActiveMerchant::VERSION, + :lang => 'ruby', + :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})", + :lib_version => BalancedGateway::VERSION, + :platform => RUBY_PLATFORM, + :publisher => 'active_merchant' + }) + + { + "Authorization" => "Basic " + Base64.encode64(@options[:login].to_s + ":").strip, + "User-Agent" => "Balanced/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}", + "X-Balanced-User-Agent" => @@ua, + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/banwire.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/banwire.rb new file mode 100644 index 000000000..b7b63adde --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/banwire.rb @@ -0,0 +1,105 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class BanwireGateway < Gateway + URL = 'https://banwire.com/api.pago_pro' + + self.supported_countries = ['MX'] + self.supported_cardtypes = [:visa, :master, :american_express] + self.homepage_url = 'http://www.banwire.com/' + self.display_name = 'Banwire' + + def initialize(options = {}) + requires!(options, :login) + super + end + + def purchase(money, creditcard, options = {}) + post = {} + add_response_type(post) + add_customer_data(post, options) + add_order_data(post, options) + add_creditcard(post, creditcard) + add_address(post, creditcard, options) + add_customer_data(post, options) + add_amount(post, money, options) + + commit(money, post) + end + + private + + def add_response_type(post) + post[:response_format] = "JSON" + end + + def add_customer_data(post, options) + post[:user] = @options[:login] + post[:phone] = options[:billing_address][:phone] + post[:mail] = options[:email] + end + + def add_order_data(post, options) + post[:reference] = options[:order_id] + post[:concept] = options[:description] + end + + def add_address(post, creditcard, options) + post[:address] = options[:billing_address][:address1] + post[:post_code] = options[:billing_address][:zip] + end + + def add_creditcard(post, creditcard) + post[:card_num] = creditcard.number + post[:card_name] = creditcard.name + post[:card_type] = card_brand(creditcard) + post[:card_exp] = "#{sprintf("%02d", creditcard.month)}/#{"#{creditcard.year}"[-2, 2]}" + post[:card_ccv2] = creditcard.verification_value + end + + def add_amount(post, money, options) + post[:ammount] = amount(money) + post[:currency] = options[:currency] + end + + def card_brand(card) + brand = super + ({"master" => "mastercard", "american_express" => "amex"}[brand] || brand) + end + + def parse(body) + JSON.parse(body) + end + + def commit(money, parameters) + raw_response = ssl_post(URL, post_data(parameters)) + begin + response = parse(raw_response) + rescue JSON::ParserError + response = json_error(raw_response) + end + + Response.new(success?(response), + response["message"], + response, + :test => test?, + :authorization => response["code_auth"]) + end + + def success?(response) + (response["response"] == "ok") + end + + def post_data(parameters = {}) + parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def json_error(raw_response) + msg = 'Invalid response received from the Banwire API. Please contact Banwire support if you continue to receive this message.' + msg += " (The raw response returned by the API was #{raw_response.inspect})" + { + "message" => msg + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/barclays_epdq.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/barclays_epdq.rb new file mode 100644 index 000000000..5d686df86 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/barclays_epdq.rb @@ -0,0 +1,314 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class BarclaysEpdqGateway < Gateway + self.test_url = 'https://secure2.mde.epdq.co.uk:11500' + self.live_url = 'https://secure2.epdq.co.uk:11500' + + self.supported_countries = ['GB'] + self.default_currency = 'GBP' + self.supported_cardtypes = [:visa, :master, :american_express, :maestro, :switch ] + self.money_format = :cents + self.homepage_url = 'http://www.barclaycard.co.uk/business/accepting-payments/epdq-mpi/' + self.display_name = 'Barclays ePDQ' + + def initialize(options = {}) + requires!(options, :login, :password, :client_id) + super + end + + def authorize(money, creditcard, options = {}) + document = Document.new(self, @options) do + add_order_form(options[:order_id]) do + add_consumer(options) do + add_creditcard(creditcard) + end + add_transaction(:PreAuth, money) + end + end + + commit(document) + end + + def purchase(money, creditcard, options = {}) + # disable fraud checks if this is a repeat order: + if options[:payment_number] && (options[:payment_number] > 1) + no_fraud = true + else + no_fraud = options[:no_fraud] + end + document = Document.new(self, @options, :no_fraud => no_fraud) do + add_order_form(options[:order_id], options[:group_id]) do + add_consumer(options) do + add_creditcard(creditcard) + end + add_transaction(:Auth, money, options) + end + end + commit(document) + end + + # authorization is your unique order ID, not the authorization + # code returned by ePDQ + def capture(money, authorization, options = {}) + document = Document.new(self, @options) do + add_order_form(authorization) do + add_transaction(:PostAuth, money) + end + end + + commit(document) + end + + # authorization is your unique order ID, not the authorization + # code returned by ePDQ + def credit(money, creditcard_or_authorization, options = {}) + if creditcard_or_authorization.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, creditcard_or_authorization, options) + else + credit_new_order(money, creditcard_or_authorization, options) + end + end + + def refund(money, authorization, options = {}) + credit_existing_order(money, authorization, options) + end + + def void(authorization, options = {}) + document = Document.new(self, @options) do + add_order_form(authorization) do + add_transaction(:Void) + end + end + + commit(document) + end + + private + def credit_new_order(money, creditcard, options) + document = Document.new(self, @options) do + add_order_form do + add_consumer(options) do + add_creditcard(creditcard) + end + add_transaction(:Credit, money) + end + end + + commit(document) + end + + def credit_existing_order(money, authorization, options) + order_id, _ = authorization.split(":") + document = Document.new(self, @options) do + add_order_form(order_id) do + add_transaction(:Credit, money) + end + end + + commit(document) + end + + def parse(body) + parser = Parser.new(body) + response = parser.parse + Response.new(response[:success], response[:message], response, + :test => test?, + :authorization => response[:authorization], + :avs_result => response[:avsresponse], + :cvv_result => response[:cvv_result], + :order_id => response[:order_id], + :raw_response => response[:raw_response] + ) + end + + def commit(document) + url = (test? ? self.test_url : self.live_url) + data = ssl_post(url, document.to_xml) + parse(data) + end + + class Parser + def initialize(response) + @response = response + end + + def parse + require 'iconv' unless String.method_defined?(:encode) + if String.method_defined?(:encode) + doc = REXML::Document.new(@response.encode("UTF-8", "ISO-8859-1")) + else + ic = Iconv.new('UTF-8', 'ISO-8859-1') + doc = REXML::Document.new(ic.iconv(@response)) + end + + auth_type = find(doc, "//Transaction/Type").to_s + + message = find(doc, "//Message/Text") + if message.blank? + message = find(doc, "//Transaction/CardProcResp/CcReturnMsg") + end + + case auth_type + when 'Credit', 'Void' + success = find(doc, "//CcReturnMsg") == "Approved." + else + success = find(doc, "//Transaction/AuthCode").present? + end + + { + :success => success, + :message => message, + :transaction_id => find(doc, "//Transaction/Id"), + :avs_result => find(doc, "//Transaction/AvsRespCode"), + :cvv_result => find(doc, "//Transaction/Cvv2Resp"), + :authorization => find(doc, "//OrderFormDoc/Id"), + :raw_response => @response + } + end + + def find(doc, xpath) + REXML::XPath.first(doc, xpath).try(:text) + end + end + + class Document + attr_reader :type, :xml + + PAYMENT_INTERVALS = { + :days => 'D', + :months => 'M' + } + + EPDQ_CARD_TYPES = { + :visa => 1, + :master => 2, + :switch => 9, + :maestro => 10, + } + + def initialize(gateway, options = {}, document_options = {}, &block) + @gateway = gateway + @options = options + @document_options = document_options + @xml = Builder::XmlMarkup.new(:indent => 2) + build(&block) + end + + def to_xml + @xml.target! + end + + def build(&block) + xml.instruct!(:xml, :version => '1.0') + xml.EngineDocList do + xml.DocVersion "1.0" + xml.EngineDoc do + xml.ContentType "OrderFormDoc" + xml.User do + xml.Name(@options[:login]) + xml.Password(@options[:password]) + xml.ClientId({ :DataType => "S32" }, @options[:client_id]) + end + xml.Instructions do + if @document_options[:no_fraud] + xml.Pipeline "PaymentNoFraud" + else + xml.Pipeline "Payment" + end + end + instance_eval(&block) + end + end + end + + def add_order_form(order_id=nil, group_id=nil, &block) + xml.OrderFormDoc do + xml.Mode 'P' + xml.Id(order_id) if order_id + xml.GroupId(group_id) if group_id + instance_eval(&block) + end + end + + def add_consumer(options=nil, &block) + xml.Consumer do + if options + xml.Email(options[:email]) if options[:email] + billing_address = options[:billing_address] || options[:address] + if billing_address + xml.BillTo do + xml.Location do + xml.Address do + xml.Street1 billing_address[:address1] + xml.Street2 billing_address[:address2] + xml.City billing_address[:city] + xml.StateProv billing_address[:state] + xml.PostalCode billing_address[:zip] + xml.Country billing_address[:country_code] + end + end + end + end + end + instance_eval(&block) + end + end + + def add_creditcard(creditcard) + xml.PaymentMech do + xml.CreditCard do + xml.Type({ :DataType => 'S32' }, EPDQ_CARD_TYPES[creditcard.brand.to_sym]) + xml.Number creditcard.number + xml.Expires({ :DataType => 'ExpirationDate', :Locale => 826 }, format_expiry_date(creditcard)) + if creditcard.verification_value.present? + xml.Cvv2Indicator 1 + xml.Cvv2Val creditcard.verification_value + else + xml.Cvv2Indicator 5 + end + xml.IssueNum(creditcard.issue_number) if creditcard.issue_number.present? + end + end + end + + def add_transaction(auth_type, amount = nil, options = {}) + @auth_type = auth_type + xml.Transaction do + xml.Type @auth_type.to_s + if options[:payment_number] && options[:payment_number] > 1 + xml.CardholderPresentCode({ :DataType => 'S32' }, 8) + else + xml.CardholderPresentCode({ :DataType => 'S32' }, 7) + end + if options[:payment_number] + xml.PaymentNumber({ :DataType => 'S32' }, options[:payment_number]) + end + if options[:total_payments] + xml.TotalNumberPayments({ :DataType => 'S32' }, options[:total_payments]) + end + if amount + xml.CurrentTotals do + xml.Totals do + xml.Total({ :DataType => 'Money', :Currency => 826 }, amount) + end + end + end + end + end + + # date must be formatted MM/YY + def format_expiry_date(creditcard) + month_str = "%02d" % creditcard.month + if match = creditcard.year.to_s.match(/^\d{2}(\d{2})$/) + year_str = "%02d" % match[1].to_i + else + year_str = "%02d" % creditcard.year + end + "#{month_str}/#{year_str}" + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream.rb new file mode 100644 index 000000000..edc3bb11f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream.rb @@ -0,0 +1,169 @@ +require File.dirname(__FILE__) + '/beanstream/beanstream_core' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # This class implements the Canadian {Beanstream}[http://www.beanstream.com] payment gateway. + # It is also named TD Canada Trust Online Mart payment gateway. + # To learn more about the specification of Beanstream gateway, please read the OM_Direct_Interface_API.pdf, + # which you can get from your Beanstream account or get from me by email. + # + # == Supported transaction types by Beanstream: + # * +P+ - Purchase + # * +PA+ - Pre Authorization + # * +PAC+ - Pre Authorization Completion + # + # == Secure Payment Profiles: + # BeanStream supports payment profiles (vaults). This allows you to store cc information with BeanStream and process subsequent transactions with a customer id. + # Secure Payment Profiles must be enabled on your account (must be done over the phone). + # Your API Access Passcode must be set in Administration => account settings => order settings. + # To learn more about storing credit cards with the Beanstream gateway, please read the BEAN_Payment_Profiles.pdf (I had to phone BeanStream to request it.) + # + # == Notes + # * Adding of order products information is not implemented. + # * Ensure that country and province data is provided as a code such as "CA", "US", "QC". + # * login is the Beanstream merchant ID, username and password should be enabled in your Beanstream account and passed in using the :user and :password options. + # * Test your app with your true merchant id and test credit card information provided in the api pdf document. + # * Beanstream does not allow Payment Profiles to be deleted with their API. The accounts are 'closed', but have to be deleted manually. + # + # Example authorization (Beanstream PA transaction type): + # + # twenty = 2000 + # gateway = BeanstreamGateway.new( + # :login => '100200000', + # :user => 'xiaobozz', + # :password => 'password' + # ) + # + # credit_card = CreditCard.new( + # :number => '4030000010001234', + # :month => 8, + # :year => 2011, + # :first_name => 'xiaobo', + # :last_name => 'zzz', + # :verification_value => 137 + # ) + # response = gateway.authorize(twenty, credit_card, + # :order_id => '1234', + # :billing_address => { + # :name => 'xiaobo zzz', + # :phone => '555-555-5555', + # :address1 => '1234 Levesque St.', + # :address2 => 'Apt B', + # :city => 'Montreal', + # :state => 'QC', + # :country => 'CA', + # :zip => 'H2C1X8' + # }, + # :email => 'xiaobozzz@example.com', + # :subtotal => 800, + # :shipping => 100, + # :tax1 => 100, + # :tax2 => 100, + # :custom => 'reference one' + # ) + class BeanstreamGateway < Gateway + include BeanstreamCore + + def authorize(money, source, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_source(post, source) + add_address(post, options) + add_transaction_type(post, :authorization) + add_customer_ip(post, options) + commit(post) + end + + def purchase(money, source, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_source(post, source) + add_address(post, options) + add_transaction_type(post, purchase_action(source)) + add_customer_ip(post, options) + commit(post) + end + + def void(authorization, options = {}) + reference, amount, type = split_auth(authorization) + + post = {} + add_reference(post, reference) + add_original_amount(post, amount) + add_transaction_type(post, void_action(type)) + commit(post) + end + + def recurring(money, source, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, source) + add_address(post, options) + add_transaction_type(post, purchase_action(source)) + add_recurring_type(post, options) + commit(post) + end + + def update_recurring(amount, source, options = {}) + post = {} + add_recurring_amount(post, amount) + add_recurring_invoice(post, options) + add_credit_card(post, source) + add_address(post, options) + add_recurring_operation_type(post, :update) + add_recurring_service(post, options) + recurring_commit(post) + end + + def cancel_recurring(options = {}) + post = {} + add_recurring_operation_type(post, :cancel) + add_recurring_service(post, options) + recurring_commit(post) + end + + def interac + @interac ||= BeanstreamInteracGateway.new(@options) + end + + # To match the other stored-value gateways, like TrustCommerce, + # store and unstore need to be defined + def store(credit_card, options = {}) + post = {} + add_address(post, options) + add_credit_card(post, credit_card) + add_secure_profile_variables(post,options) + commit(post, true) + end + + #can't actually delete a secure profile with the supplicaed API. This function sets the status of the profile to closed (C). + #Closed profiles will have to removed manually. + def delete(vault_id) + update(vault_id, false, {:status => "C"}) + end + + alias_method :unstore, :delete + + # Update the values (such as CC expiration) stored at + # the gateway. The CC number must be supplied in the + # CreditCard object. + def update(vault_id, credit_card, options = {}) + post = {} + add_address(post, options) + add_credit_card(post, credit_card) + options.merge!({:vault_id => vault_id, :operation => secure_profile_action(:modify)}) + add_secure_profile_variables(post,options) + commit(post, true) + end + + private + def build_response(*args) + Response.new(*args) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb new file mode 100644 index 000000000..79ca7c5a6 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb @@ -0,0 +1,393 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module BeanstreamCore + RECURRING_URL = 'https://www.beanstream.com/scripts/recurring_billing.asp' + SECURE_PROFILE_URL = 'https://www.beanstream.com/scripts/payment_profile.asp' + + SP_SERVICE_VERSION = '1.1' + + TRANSACTIONS = { + :authorization => 'PA', + :purchase => 'P', + :capture => 'PAC', + :refund => 'R', + :void => 'VP', + :check_purchase => 'D', + :check_refund => 'C', + :void_purchase => 'VP', + :void_refund => 'VR' + } + + PROFILE_OPERATIONS = { + :new => 'N', + :modify => 'M' + } + + CVD_CODES = { + '1' => 'M', + '2' => 'N', + '3' => 'I', + '4' => 'S', + '5' => 'U', + '6' => 'P' + } + + AVS_CODES = { + '0' => 'R', + '5' => 'I', + '9' => 'I' + } + + PERIODS = { + :days => 'D', + :weeks => 'W', + :months => 'M', + :years => 'Y' + } + + PERIODICITIES = { + :daily => [:days, 1], + :weekly => [:weeks, 1], + :biweekly => [:weeks, 2], + :monthly => [:months, 1], + :bimonthly => [:months, 2], + :yearly => [:years, 1] + } + + RECURRING_OPERATION = { + :update => 'M', + :cancel => 'C' + } + + def self.included(base) + base.default_currency = 'CAD' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + base.supported_countries = ['CA'] + + # The card types supported by the payment gateway + base.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + + # The homepage URL of the gateway + base.homepage_url = 'http://www.beanstream.com/' + base.live_url = 'https://www.beanstream.com/scripts/process_transaction.asp' + + # The name of the gateway + base.display_name = 'Beanstream.com' + end + + # Only :login is required by default, + # which is the merchant's merchant ID. If you'd like to perform void, + # capture or refund transactions then you'll also need to add a username + # and password to your account under administration -> account settings -> + # order settings -> Use username/password validation + def initialize(options = {}) + requires!(options, :login) + super + end + + def capture(money, authorization, options = {}) + reference, amount, type = split_auth(authorization) + + post = {} + add_amount(post, money) + add_reference(post, reference) + add_transaction_type(post, :capture) + commit(post) + end + + def refund(money, source, options = {}) + post = {} + reference, amount, type = split_auth(source) + add_reference(post, reference) + add_transaction_type(post, refund_action(type)) + add_amount(post, money) + commit(post) + end + + def credit(money, source, options = {}) + deprecated Gateway::CREDIT_DEPRECATION_MESSAGE + refund(money, source, options) + end + + private + def purchase_action(source) + if source.is_a?(Check) + :check_purchase + else + :purchase + end + end + + def add_customer_ip(post, options) + post[:customerIP] = options[:ip] if options[:ip] + end + + def void_action(original_transaction_type) + (original_transaction_type == TRANSACTIONS[:refund]) ? :void_refund : :void_purchase + end + + def refund_action(type) + (type == TRANSACTIONS[:check_purchase]) ? :check_refund : :refund + end + + def secure_profile_action(type) + PROFILE_OPERATIONS[type] || PROFILE_OPERATIONS[:new] + end + + def split_auth(string) + string.split(";") + end + + def add_amount(post, money) + post[:trnAmount] = amount(money) + end + + def add_original_amount(post, amount) + post[:trnAmount] = amount + end + + def add_reference(post, reference) + post[:adjId] = reference + end + + def add_address(post, options) + prepare_address_for_non_american_countries(options) + + if billing_address = options[:billing_address] || options[:address] + post[:ordName] = billing_address[:name] + post[:ordEmailAddress] = options[:email] + post[:ordPhoneNumber] = billing_address[:phone] + post[:ordAddress1] = billing_address[:address1] + post[:ordAddress2] = billing_address[:address2] + post[:ordCity] = billing_address[:city] + post[:ordProvince] = billing_address[:state] + post[:ordPostalCode] = billing_address[:zip] + post[:ordCountry] = billing_address[:country] + end + if shipping_address = options[:shipping_address] + post[:shipName] = shipping_address[:name] + post[:shipEmailAddress] = options[:email] + post[:shipPhoneNumber] = shipping_address[:phone] + post[:shipAddress1] = shipping_address[:address1] + post[:shipAddress2] = shipping_address[:address2] + post[:shipCity] = shipping_address[:city] + post[:shipProvince] = shipping_address[:state] + post[:shipPostalCode] = shipping_address[:zip] + post[:shipCountry] = shipping_address[:country] + post[:shippingMethod] = shipping_address[:shipping_method] + post[:deliveryEstimate] = shipping_address[:delivery_estimate] + end + end + + def prepare_address_for_non_american_countries(options) + [ options[:billing_address], options[:shipping_address] ].compact.each do |address| + unless ['US', 'CA'].include?(address[:country]) + address[:state] = '--' + address[:zip] = '000000' unless address[:zip] + end + end + end + + def add_invoice(post, options) + post[:trnOrderNumber] = options[:order_id] + post[:trnComments] = options[:description] + post[:ordItemPrice] = amount(options[:subtotal]) + post[:ordShippingPrice] = amount(options[:shipping]) + post[:ordTax1Price] = amount(options[:tax1] || options[:tax]) + post[:ordTax2Price] = amount(options[:tax2]) + post[:ref1] = options[:custom] + end + + def add_credit_card(post, credit_card) + if credit_card + post[:trnCardOwner] = credit_card.name + post[:trnCardNumber] = credit_card.number + post[:trnExpMonth] = format(credit_card.month, :two_digits) + post[:trnExpYear] = format(credit_card.year, :two_digits) + post[:trnCardCvd] = credit_card.verification_value + end + end + + def add_check(post, check) + # The institution number of the consumer’s financial institution. Required for Canadian dollar EFT transactions. + post[:institutionNumber] = check.institution_number + + # The bank transit number of the consumer’s bank account. Required for Canadian dollar EFT transactions. + post[:transitNumber] = check.transit_number + + # The routing number of the consumer’s bank account. Required for US dollar EFT transactions. + post[:routingNumber] = check.routing_number + + # The account number of the consumer’s bank account. Required for both Canadian and US dollar EFT transactions. + post[:accountNumber] = check.account_number + end + + def add_secure_profile_variables(post, options = {}) + post[:serviceVersion] = SP_SERVICE_VERSION + post[:responseFormat] = 'QS' + post[:cardValidation] = (options[:cardValidation].to_i == 1) || '0' + + post[:operationType] = options[:operationType] || options[:operation] || secure_profile_action(:new) + post[:customerCode] = options[:billing_id] || options[:vault_id] || false + post[:status] = options[:status] + end + + def add_recurring_amount(post, money) + post[:amount] = amount(money) + end + + def add_recurring_invoice(post, options) + post[:rbApplyTax1] = options[:apply_tax1] + post[:rbApplyTax2] = options[:apply_tax2] + end + + def add_recurring_operation_type(post, operation) + post[:operationType] = RECURRING_OPERATION[operation] + end + + def add_recurring_service(post, options) + post[:serviceVersion] = '1.0' + post[:merchantId] = @options[:login] + post[:passCode] = @options[:recurring_api_key] + post[:rbAccountId] = options[:account_id] + end + + def add_recurring_type(post, options) + # XXX requires! + post[:trnRecurring] = 1 + period, increment = interval(options) + post[:rbBillingPeriod] = PERIODS[period] + post[:rbBillingIncrement] = increment + + if options.include? :start_date + post[:rbCharge] = 0 + post[:rbFirstBilling] = options[:start_date].strftime('%m%d%Y') + end + + if count = options[:occurrences] || options[:payments] + post[:rbExpiry] = (options[:start_date] || Date.current).advance(period => count).strftime('%m%d%Y') + end + end + + def interval(options) + if options.include? :periodicity + requires!(options, [:periodicity, *PERIODICITIES.keys]) + PERIODICITIES[options[:periodicity]] + elsif options.include? :interval + interval = options[:interval] + if interval.respond_to? :parts + parts = interval.parts + raise ArgumentError.new("Cannot recur with mixed interval (#{interval}). Use only one of: days, weeks, months or years") if parts.length > 1 + parts.first + elsif interval.kind_of? Hash + requires!(interval, :unit) + unit, length = interval.values_at(:unit, :length) + length ||= 1 + [unit, length] + end + end + end + + def parse(body) + results = {} + if !body.nil? + body.split(/&/).each do |pair| + key, val = pair.split(/\=/) + results[key.to_sym] = val.nil? ? nil : CGI.unescape(val) + end + end + + # Clean up the message text if there is any + if results[:messageText] + results[:messageText].gsub!(/
  • /, "") + results[:messageText].gsub!(/(\.)?
    /, ". ") + results[:messageText].strip! + end + + results + end + + def recurring_parse(data) + REXML::Document.new(data).root.elements.to_a.inject({}) do |response, element| + response[element.name.to_sym] = element.text + response + end + end + + def commit(params, use_profile_api = false) + post(post_data(params,use_profile_api),use_profile_api) + end + + def recurring_commit(params) + recurring_post(post_data(params, false)) + end + + def post(data, use_profile_api=nil) + response = parse(ssl_post((use_profile_api ? SECURE_PROFILE_URL : self.live_url), data)) + response[:customer_vault_id] = response[:customerCode] if response[:customerCode] + build_response(success?(response), message_from(response), response, + :test => test? || response[:authCode] == "TEST", + :authorization => authorization_from(response), + :cvv_result => CVD_CODES[response[:cvdId]], + :avs_result => { :code => (AVS_CODES.include? response[:avsId]) ? AVS_CODES[response[:avsId]] : response[:avsId] } + ) + end + + def recurring_post(data) + response = recurring_parse(ssl_post(RECURRING_URL, data)) + build_response(recurring_success?(response), recurring_message_from(response), response) + end + + def authorization_from(response) + "#{response[:trnId]};#{response[:trnAmount]};#{response[:trnType]}" + end + + def message_from(response) + response[:messageText] || response[:responseMessage] + end + + def recurring_message_from(response) + response[:message] + end + + def success?(response) + response[:responseType] == 'R' || response[:trnApproved] == '1' || response[:responseCode] == '1' + end + + def recurring_success?(response) + response[:code] == '1' + end + + def add_source(post, source) + if source.is_a?(String) or source.is_a?(Integer) + post[:customerCode] = source + else + card_brand(source) == "check" ? add_check(post, source) : add_credit_card(post, source) + end + end + + def add_transaction_type(post, action) + post[:trnType] = TRANSACTIONS[action] + end + + def post_data(params, use_profile_api) + params[:requestType] = 'BACKEND' + if use_profile_api + params[:merchantId] = @options[:login] + params[:passCode] = @options[:secure_profile_api_key] + else + params[:username] = @options[:user] if @options[:user] + params[:password] = @options[:password] if @options[:password] + params[:merchant_id] = @options[:login] + end + params[:vbvEnabled] = '0' + params[:scEnabled] = '0' + + params.reject{|k, v| v.blank?}.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream_interac.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream_interac.rb new file mode 100644 index 000000000..2caa3b7a7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/beanstream_interac.rb @@ -0,0 +1,54 @@ +require File.dirname(__FILE__) + '/beanstream/beanstream_core' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class BeanstreamInteracResponse < Response + def redirect + params['pageContents'] + end + end + + class BeanstreamInteracGateway < Gateway + include BeanstreamCore + + # Confirm a transaction posted back from the bank to Beanstream. + # Confirming a transaction does not require any credentials, + # and in an application with many merchants sharing a funded + # URL the application may not yet know which merchant the + # post back is for until the response of the confirmation is + # received, which contains the order number. + def self.confirm(transaction) + gateway = new(:login => '') + gateway.confirm(transaction) + end + + def purchase(money, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_address(post, options) + add_interac_details(post, options) + add_transaction_type(post, :purchase) + commit(post) + end + + # Confirm a transaction posted back from the bank to Beanstream. + def confirm(transaction) + post(transaction) + end + + private + + def add_interac_details(post, options) + address = options[:billing_address] || options[:address] || {} + post[:trnCardOwner] = address[:name] + post[:paymentMethod] = 'IO' + end + + def build_response(*args) + BeanstreamInteracResponse.new(*args) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/blue_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/blue_pay.rb new file mode 100644 index 000000000..1a8d169a0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/blue_pay.rb @@ -0,0 +1,503 @@ +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class BluePayGateway < Gateway + class_attribute :rebilling_url, :ignore_http_status + + self.live_url = 'https://secure.bluepay.com/interfaces/bp20post' + self.rebilling_url = 'https://secure.bluepay.com/interfaces/bp20rebadmin' + + self.ignore_http_status = true + + CARD_CODE_ERRORS = %w( N S ) + AVS_ERRORS = %w( A E N R W Z ) + AVS_REASON_CODES = %w(27 45) + + FRAUD_REVIEW_STATUSES = %w( E 0 ) + + FIELD_MAP = { + 'TRANS_ID' => :transaction_id, + 'STATUS' => :response_code, + 'AVS' => :avs_result_code, + 'CVV2'=> :card_code, + 'AUTH_CODE' => :authorization, + 'MESSAGE' => :message, + 'REBID' => :rebid, + 'TRANS_TYPE' => :trans_type, + 'PAYMENT_ACCOUNT_MASK' => :acct_mask, + 'CARD_TYPE' => :card_type, + } + + REBILL_FIELD_MAP = { + 'REBILL_ID' => :rebill_id, + 'ACCOUNT_ID'=> :account_id, + 'USER_ID' => :user_id, + 'TEMPLATE_ID' => :template_id, + 'STATUS' => :status, + 'CREATION_DATE' => :creation_date, + 'NEXT_DATE' => :next_date, + 'LAST_DATE' => :last_date, + 'SCHED_EXPR' => :schedule, + 'CYCLES_REMAIN' => :cycles_remain, + 'REB_AMOUNT' => :rebill_amount, + 'NEXT_AMOUNT' => :next_amount, + 'USUAL_DATE' => :undoc_usual_date, # Not found in the bp20rebadmin API doc. + } + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + self.homepage_url = 'http://www.bluepay.com/' + self.display_name = 'BluePay' + self.money_format = :dollars + + # Creates a new BluepayGateway + # + # The gateway requires that a valid Account ID and Secret Key be passed + # in the +options+ hash. + # + # ==== Options + # + # * :account_id -- The BluePay gateway Account ID (REQUIRED) + # * :secret_key -- The BluePay gateway Secret Key (REQUIRED) + # * :test -- set to true for TEST mode or false for LIVE mode + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Performs an authorization, which reserves the funds on the customer's credit card. This does not actually take funds from the customer + # This is referred to an AUTH transaction in BluePay + # + # ==== Parameters + # + # * money -- The amount to be authorized as an Integer value in cents. + # * payment_object -- This can either be one of three things: + # A CreditCard object, + # A Check object, + # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction. + # * options -- A hash of optional parameters. + def authorize(money, payment_object, options = {}) + post = {} + add_payment_method(post, payment_object) + add_invoice(post, options) + add_address(post, options) + add_customer_data(post, options) + add_rebill(post, options) if options[:rebill] + add_duplicate_override(post, options) + post[:TRANS_TYPE] = 'AUTH' + commit('AUTH_ONLY', money, post) + end + + # Perform a purchase, which is essentially an authorization and capture in a single operation. + # This is referred to a SALE transaction in BluePay + # + # ==== Parameters + # + # * money -- The amount to be purchased as an Integer value in cents. + # * payment_object -- This can either be one of three things: + # A CreditCard object, + # A Check object, + # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction. + # * options -- A hash of optional parameters., + def purchase(money, payment_object, options = {}) + post = {} + add_payment_method(post, payment_object) + add_invoice(post, options) + add_address(post, options) + add_customer_data(post, options) + add_rebill(post, options) if options[:rebill] + add_duplicate_override(post, options) + post[:TRANS_TYPE] = 'SALE' + commit('AUTH_CAPTURE', money, post) + end + + # Captures the funds from an authorize transaction. + # This is referred to a CAPTURE transaction in BluePay + # + # ==== Parameters + # + # * money -- The amount to be captured as an Integer value in cents. + # * identification -- The Master ID, or token, returned from the previous authorize transaction. + def capture(money, identification, options = {}) + post = {} + add_address(post, options) + add_customer_data(post, options) + post[:MASTER_ID] = identification + post[:TRANS_TYPE] = 'CAPTURE' + commit('PRIOR_AUTH_CAPTURE', money, post) + end + + # Void a previous transaction + # This is referred to a VOID transaction in BluePay + # + # ==== Parameters + # + # * identification - The Master ID, or token, returned from a previous authorize transaction. + def void(identification, options = {}) + post = {} + post[:MASTER_ID] = identification + post[:TRANS_TYPE] = 'VOID' + commit('VOID', nil, post) + end + + # Performs a credit. + # + # This transaction indicates that money should flow from the merchant to the customer. + # + # ==== Parameters + # + # * money -- The amount to be credited to the customer as an Integer value in cents. + # * payment_object -- This can either be one of three things: + # A CreditCard object, + # A Check object, + # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction. + # If the payment_object is a token, then the transaction type will reverse a previous capture or purchase transaction, returning the funds to the customer. If the amount is nil, a full credit will be processed. This is referred to a REFUND transaction in BluePay. + # If the payment_object is either a CreditCard or Check object, then the transaction type will be an unmatched credit placing funds in the specified account. This is referred to a CREDIT transaction in BluePay. + # * options -- A hash of parameters. + def refund(money, identification, options = {}) + if(identification && !identification.kind_of?(String)) + deprecated "refund should only be used to refund a referenced transaction" + return credit(money, identification, options) + end + + post = {} + post[:PAYMENT_ACCOUNT] = '' + post[:MASTER_ID] = identification + post[:TRANS_TYPE] = 'REFUND' + post[:NAME1] = (options[:first_name] ? options[:first_name] : "") + post[:NAME2] = options[:last_name] if options[:last_name] + post[:ZIP] = options[:zip] if options[:zip] + add_invoice(post, options) + add_address(post, options) + add_customer_data(post, options) + commit('CREDIT', money, post) + end + + def credit(money, payment_object, options = {}) + if(payment_object && payment_object.kind_of?(String)) + deprecated "credit should only be used to credit a payment method" + return refund(money, payment_object, options) + end + + post = {} + post[:PAYMENT_ACCOUNT] = '' + add_payment_method(post, payment_object) + post[:TRANS_TYPE] = 'CREDIT' + + post[:NAME1] = (options[:first_name] ? options[:first_name] : "") + post[:NAME2] = options[:last_name] if options[:last_name] + post[:ZIP] = options[:zip] if options[:zip] + add_invoice(post, options) + add_address(post, options) + add_customer_data(post, options) + commit('CREDIT', money, post) + end + + # Create a new recurring payment. + # + # ==== Parameters + # + # * money -- The amount to charge the customer at the time of the recurring payment setup, in cents. Set to zero if you do not want the customer to be charged at this time. + # * payment_object -- This can either be one of three things: + # A CreditCard object, + # A Check object, + # or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction. + # * options -- A hash of optional parameters., + + # ==== Options + # + # * :rebill_start_date is a string that tells the gateway when to start the rebill. (REQUIRED) + # Has two valid formats: + # "YYYY-MM-DD HH:MM:SS" Hours, minutes, and seconds are optional. + # "XX UNITS" Relative date as explained below. Marked from the time of the + # transaction (i.e.: 10 DAYS, 1 MONTH, 1 YEAR) + # * :rebill_expression is the period of time in-between rebillings. (REQUIRED) + # It uses the same "XX UNITS" format as rebill_start_date, explained above. + # Optional parameters include: + # * rebill_cycles: Number of times to rebill. Don't send or set to nil for infinite rebillings (or + # until canceled). + # * rebill_amount: Amount to rebill. Defaults to amount of transaction for rebillings. + # + # For example, to charge the customer $19.95 now and then charge $39.95 in 60 days every 3 months for 5 times, the options hash would be as follows: + # :rebill_start_date => '60 DAYS', + # :rebill_expression => '3 MONTHS', + # :rebill_cycles => '5', + # :rebill_amount => '39.95' + # A money object of 1995 cents would be passed into the 'money' parameter. + def recurring(money, payment_object, options = {}) + requires!(options, :rebill_start_date, :rebill_expression) + options[:rebill] = true + if money + purchase(money, payment_object, options) + else + authorize(money, payment_object, options) + end + end + + # View a recurring payment + # + # This will pull data associated with a current recurring billing + # + # ==== Parameters + # + # * rebill_id -- A string containing the rebill_id of the recurring billing that is already active (REQUIRED) + def status_recurring(rebill_id) + post = {} + requires!(rebill_id) + post[:REBILL_ID] = rebill_id + post[:TRANS_TYPE] = 'GET' + commit('rebill', 'nil', post) + end + + # Update a recurring payment's details. + # + # This transaction updates an existing recurring billing + # + # ==== Options + # + # * :rebill_id -- The 12 digit rebill ID used to update a particular rebilling cycle. (REQUIRED) + # * :rebill_amount -- A string containing the new rebilling amount. + # * :rebill_next_date -- A string containing the new rebilling next date. + # * :rebill_expression -- A string containing the new rebilling expression. + # * :rebill_cycles -- A string containing the new rebilling cycles. + # * :rebill_next_amount -- A string containing the next rebilling amount to charge the customer. This ONLY affects the next scheduled charge; all other rebillings will continue at the regular (rebill_amount) amount. + # Take a look above at the recurring_payment method for similar examples on how to use. + def update_recurring(options = {}) + post = {} + requires!(options, :rebill_id) + post[:REBILL_ID] = options[:rebill_id] + post[:TRANS_TYPE] = 'SET' + post[:REB_AMOUNT] = amount(options[:rebill_amount]) if options[:rebill_amount] + post[:NEXT_DATE] = options[:rebill_next_date] + post[:REB_EXPR] = options[:rebill_expression] + post[:REB_CYCLES] = options[:rebill_cycles] + post[:NEXT_AMOUNT] = options[:rebill_next_amount] + commit('rebill', 'nil', post) + end + + # Cancel a recurring payment. + # + # This transaction cancels an existing recurring billing. + # + # ==== Parameters + # + # * rebill_id -- A string containing the rebill_id of the recurring billing that you wish to cancel/stop (REQUIRED) + def cancel_recurring(rebill_id) + post = {} + requires!(rebill_id) + post[:REBILL_ID] = rebill_id + post[:TRANS_TYPE] = 'SET' + post[:STATUS] = 'stopped' + commit('rebill', 'nil', post) + end + + private + + def commit(action, money, fields) + fields[:AMOUNT] = amount(money) unless(fields[:TRANS_TYPE] == 'VOID' || action == 'rebill') + fields[:MODE] = (test? ? 'TEST' : 'LIVE') + fields[:ACCOUNT_ID] = @options[:login] + + if action == 'rebill' + url = rebilling_url + fields[:TAMPER_PROOF_SEAL] = calc_rebill_tps(fields) + else + url = live_url + fields[:TAMPER_PROOF_SEAL] = calc_tps(amount(money), fields) + end + parse(ssl_post(url, post_data(action, fields))) + end + + def parse_recurring(response_fields, opts={}) # expected status? + parsed = {} + response_fields.each do |k,v| + mapped_key = REBILL_FIELD_MAP.include?(k) ? REBILL_FIELD_MAP[k] : k + parsed[mapped_key] = v + end + + success = parsed[:status] != 'error' + message = parsed[:status] + + Response.new(success, message, parsed, + :test => test?, + :authorization => parsed[:rebill_id]) + end + + def parse(body) + # The bp20api has max one value per form field. + response_fields = Hash[CGI::parse(body).map{|k,v| [k.upcase,v.first]}] + + if response_fields.include? "REBILL_ID" + return parse_recurring(response_fields) + end + + parsed = {} + response_fields.each do |k,v| + mapped_key = FIELD_MAP.include?(k) ? FIELD_MAP[k] : k + parsed[mapped_key] = v + end + + # normalize message + message = message_from(parsed) + success = parsed[:response_code] == '1' + Response.new(success, message, parsed, + :test => test?, + :authorization => (parsed[:rebid] && parsed[:rebid] != '' ? parsed[:rebid] : parsed[:transaction_id]), + :fraud_review => FRAUD_REVIEW_STATUSES.include?(parsed[:response_code]), + :avs_result => { :code => parsed[:avs_result_code] }, + :cvv_result => parsed[:card_code] + ) + end + + def message_from(parsed) + message = parsed[:message] + if(parsed[:response_code].to_i == 2) + if CARD_CODE_ERRORS.include?(parsed[:card_code]) + message = CVVResult.messages[parsed[:card_code]] + elsif AVS_ERRORS.include?(parsed[:avs_result_code]) + message = AVSResult.messages[ parsed[:avs_result_code] ] + else + message = message.chomp('.') + end + elsif message == "Missing ACCOUNT_ID" + message = "The merchant login ID or password is invalid" + elsif message =~ /Approved/ + message = "This transaction has been approved" + elsif message =~ /Expired/ + message = "The credit card has expired" + end + message + end + + def add_invoice(post, options) + post[:ORDER_ID] = options[:order_id] + post[:INVOICE_ID] = options[:invoice] + post[:invoice_num] = options[:order_id] + post[:MEMO] = options[:description] + post[:description] = options[:description] + end + + def add_payment_method(post, payment_object) + post[:MASTER_ID] = '' + case payment_object + when String + post[:MASTER_ID] = payment_object + when Check + add_check(post, payment_object) + else + add_creditcard(post, payment_object) + end + end + + def add_creditcard(post, creditcard) + post[:PAYMENT_TYPE] = 'CREDIT' + post[:PAYMENT_ACCOUNT] = creditcard.number + post[:CARD_CVV2] = creditcard.verification_value + post[:CARD_EXPIRE] = expdate(creditcard) + post[:NAME1] = creditcard.first_name + post[:NAME2] = creditcard.last_name + end + + CHECK_ACCOUNT_TYPES = { + "checking" => "C", + "savings" => "S" + } + + def add_check(post, check) + post[:PAYMENT_TYPE] = 'ACH' + post[:PAYMENT_ACCOUNT] = [CHECK_ACCOUNT_TYPES[check.account_type], check.routing_number, check.account_number].join(":") + post[:NAME1] = check.first_name + post[:NAME2] = check.last_name + end + + def add_customer_data(post, options) + post[:EMAIL] = options[:email] + post[:CUSTOM_ID] = options[:customer] + end + + def add_duplicate_override(post, options) + post[:DUPLICATE_OVERRIDE] = options[:duplicate_override] + end + + def add_address(post, options) + if address = (options[:shipping_address] || options[:billing_address] || options[:address]) + post[:NAME1] = address[:first_name] + post[:NAME2] = address[:last_name] + post[:ADDR1] = address[:address1] + post[:ADDR2] = address[:address2] + post[:COMPANY_NAME] = address[:company] + post[:PHONE] = address[:phone] + post[:CITY] = address[:city] + post[:STATE] = (address[:state].blank? ? 'n/a' : address[:state]) + post[:ZIP] = address[:zip] + post[:COUNTRY] = address[:country] + end + end + + def add_rebill(post, options) + post[:DO_REBILL] = '1' + post[:REB_AMOUNT] = amount(options[:rebill_amount]) + post[:REB_FIRST_DATE] = options[:rebill_start_date] + post[:REB_EXPR] = options[:rebill_expression] + post[:REB_CYCLES] = options[:rebill_cycles] + end + + def post_data(action, parameters = {}) + post = {} + post[:version] = '1' + post[:login] = '' + post[:tran_key] = '' + post[:relay_response] = "FALSE" + post[:type] = action + post[:delim_data] = "TRUE" + post[:delim_char] = "," + post[:encap_char] = "$" + post[:card_num] = '4111111111111111' + post[:exp_date] = '1212' + post[:solution_ID] = application_id if(application_id && application_id != "ActiveMerchant") + post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def expdate(creditcard) + year = format(creditcard.year, :two_digits) + month = format(creditcard.month, :two_digits) + + "#{month}#{year}" + end + + def calc_tps(amount, post) + post[:NAME1] ||= '' + Digest::MD5.hexdigest( + [ + @options[:password], + @options[:login], + post[:TRANS_TYPE], + amount, + post[:MASTER_ID], + post[:NAME1], + post[:PAYMENT_ACCOUNT] + ].join("") + ) + end + + def calc_rebill_tps(post) + Digest::MD5.hexdigest( + [ + @options[:password], + @options[:login], + post[:TRANS_TYPE], + post[:REBILL_ID] + ].join("") + ) + end + + def handle_response(response) + if ignore_http_status || (200...300).include?(response.code.to_i) + return response.body + end + raise ResponseError.new(response) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/bogus.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/bogus.rb new file mode 100644 index 000000000..3a23de6e8 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/bogus.rb @@ -0,0 +1,142 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # Bogus Gateway + class BogusGateway < Gateway + AUTHORIZATION = '53433' + + SUCCESS_MESSAGE = "Bogus Gateway: Forced success" + FAILURE_MESSAGE = "Bogus Gateway: Forced failure" + ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error" + CREDIT_ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error" + UNSTORE_ERROR_MESSAGE = "Bogus Gateway: Use trans_id ending in 1 for success, 2 for exception and anything else for error" + CAPTURE_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success" + VOID_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success" + REFUND_ERROR_MESSAGE = "Bogus Gateway: Use trans_id number ending in 1 for exception, 2 for error and anything else for success" + + self.supported_countries = ['US'] + self.supported_cardtypes = [:bogus] + self.homepage_url = 'http://example.com' + self.display_name = 'Bogus' + + def authorize(money, credit_card_or_reference, options = {}) + money = amount(money) + case normalize(credit_card_or_reference) + when /1$/ + Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION ) + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money, :error => FAILURE_MESSAGE }, :test => true) + else + raise Error, ERROR_MESSAGE + end + end + + def purchase(money, credit_card_or_reference, options = {}) + money = amount(money) + case normalize(credit_card_or_reference) + when /1$/, AUTHORIZATION + Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true, :authorization => AUTHORIZATION) + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true) + else + raise Error, ERROR_MESSAGE + end + end + + def recurring(money, credit_card_or_reference, options = {}) + money = amount(money) + case normalize(credit_card_or_reference) + when /1$/ + Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true) + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true) + else + raise Error, ERROR_MESSAGE + end + end + + def credit(money, credit_card_or_reference, options = {}) + if credit_card_or_reference.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + return refund(money, credit_card_or_reference, options) + end + + money = amount(money) + case normalize(credit_card_or_reference) + when /1$/ + Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true ) + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true) + else + raise Error, CREDIT_ERROR_MESSAGE + end + end + + def refund(money, reference, options = {}) + money = amount(money) + case reference + when /1$/ + raise Error, REFUND_ERROR_MESSAGE + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true) + else + Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true) + end + end + + def capture(money, reference, options = {}) + money = amount(money) + case reference + when /1$/ + raise Error, CAPTURE_ERROR_MESSAGE + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true) + else + Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true) + end + end + + def void(reference, options = {}) + case reference + when /1$/ + raise Error, VOID_ERROR_MESSAGE + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:authorization => reference, :error => FAILURE_MESSAGE }, :test => true) + else + Response.new(true, SUCCESS_MESSAGE, {:authorization => reference}, :test => true) + end + end + + def store(credit_card_or_reference, options = {}) + case normalize(credit_card_or_reference) + when /1$/ + Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION) + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true) + else + raise Error, ERROR_MESSAGE + end + end + + def unstore(reference, options = {}) + case reference + when /1$/ + Response.new(true, SUCCESS_MESSAGE, {}, :test => true) + when /2$/ + Response.new(false, FAILURE_MESSAGE, {:error => FAILURE_MESSAGE },:test => true) + else + raise Error, UNSTORE_ERROR_MESSAGE + end + end + + private + + def normalize(credit_card_or_reference) + if credit_card_or_reference.respond_to?(:number) + credit_card_or_reference.number + else + credit_card_or_reference.to_s + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree.rb new file mode 100644 index 000000000..6167d6be6 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree.rb @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + '/braintree/braintree_common' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class BraintreeGateway < Gateway + include BraintreeCommon + + self.abstract_class = true + + def self.new(options={}) + if options.has_key?(:login) + BraintreeOrangeGateway.new(options) + else + BraintreeBlueGateway.new(options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree/braintree_common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree/braintree_common.rb new file mode 100644 index 000000000..a4d08f583 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree/braintree_common.rb @@ -0,0 +1,9 @@ +module BraintreeCommon + def self.included(base) + base.supported_countries = ['US'] + base.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club] + base.homepage_url = 'http://www.braintreepaymentsolutions.com' + base.display_name = 'Braintree' + base.default_currency = 'USD' + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_blue.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_blue.rb new file mode 100644 index 000000000..78f225773 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_blue.rb @@ -0,0 +1,401 @@ +require File.dirname(__FILE__) + '/braintree/braintree_common' + +begin + require "braintree" +rescue LoadError + raise "Could not load the braintree gem. Use `gem install braintree` to install it." +end + +raise "Need braintree gem 2.x.y. Run `gem install braintree --version '~>2.0'` to get the correct version." unless Braintree::Version::Major == 2 + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # For more information on the Braintree Gateway please visit their + # {Developer Portal}[https://www.braintreepayments.com/developers] + # + # ==== About this implementation + # + # This implementation leverages the Braintree-authored ruby gem: + # https://github.com/braintree/braintree_ruby + # + # ==== Debugging Information + # + # Setting an ActiveMerchant +wiredump_device+ will automatically + # configure the Braintree logger (via the Braintree gem's + # configuration) when the BraintreeBlueGateway is instantiated. + # Additionally, the log level will be set to +DEBUG+. Therefore, + # all you have to do is set the +wiredump_device+ and you'll + # get your debug output from your HTTP interactions with the + # remote gateway. (Don't enable this in production.) + # + # For example: + # + # ActiveMerchant::Billing::BraintreeBlueGateway.wiredump_device = Logger.new(STDOUT) + # # => # + # + # Braintree::Configuration.logger + # # => (some other logger, created by default by the gem) + # + # Braintree::Configuration.logger.level + # # => 1 (INFO) + # + # ActiveMerchant::Billing::BraintreeBlueGateway.new(:merchant_id => 'x', :public_key => 'x', :private_key => 'x') + # + # Braintree::Configuration.logger + # # => # + # + # Braintree::Configuration.logger.level + # # => 0 (DEBUG) + # + # Alternatively, you can avoid setting the +wiredump_device+ + # and set +Braintree::Configuration.logger+ and/or + # +Braintree::Configuration.logger.level+ directly. + class BraintreeBlueGateway < Gateway + include BraintreeCommon + + self.display_name = 'Braintree (Blue Platform)' + + def initialize(options = {}) + requires!(options, :merchant_id, :public_key, :private_key) + @merchant_account_id = options[:merchant_account_id] + + super + + Braintree::Configuration.merchant_id = options[:merchant_id] + Braintree::Configuration.public_key = options[:public_key] + Braintree::Configuration.private_key = options[:private_key] + Braintree::Configuration.environment = (options[:environment] || (test? ? :sandbox : :production)).to_sym + Braintree::Configuration.custom_user_agent = "ActiveMerchant #{ActiveMerchant::VERSION}" + + if wiredump_device + Braintree::Configuration.logger = ((Logger === wiredump_device) ? wiredump_device : Logger.new(wiredump_device)) + Braintree::Configuration.logger.level = Logger::DEBUG + else + Braintree::Configuration.logger.level = Logger::WARN + end + end + + def authorize(money, credit_card_or_vault_id, options = {}) + create_transaction(:sale, money, credit_card_or_vault_id, options) + end + + def capture(money, authorization, options = {}) + commit do + result = Braintree::Transaction.submit_for_settlement(authorization, amount(money).to_s) + Response.new(result.success?, message_from_result(result)) + end + end + + def purchase(money, credit_card_or_vault_id, options = {}) + authorize(money, credit_card_or_vault_id, options.merge(:submit_for_settlement => true)) + end + + def credit(money, credit_card_or_vault_id, options = {}) + create_transaction(:credit, money, credit_card_or_vault_id, options) + end + + def refund(*args) + # legacy signature: #refund(transaction_id, options = {}) + # new signature: #refund(money, transaction_id, options = {}) + money, transaction_id, _ = extract_refund_args(args) + money = amount(money).to_s if money + + commit do + result = Braintree::Transaction.refund(transaction_id, money) + Response.new(result.success?, message_from_result(result), + {:braintree_transaction => (transaction_hash(result.transaction) if result.success?)}, + {:authorization => (result.transaction.id if result.success?)} + ) + end + end + + def void(authorization, options = {}) + commit do + result = Braintree::Transaction.void(authorization) + Response.new(result.success?, message_from_result(result), + {:braintree_transaction => (transaction_hash(result.transaction) if result.success?)}, + {:authorization => (result.transaction.id if result.success?)} + ) + end + end + + def store(creditcard, options = {}) + commit do + parameters = { + :first_name => creditcard.first_name, + :last_name => creditcard.last_name, + :email => options[:email], + :credit_card => { + :number => creditcard.number, + :cvv => creditcard.verification_value, + :expiration_month => creditcard.month.to_s.rjust(2, "0"), + :expiration_year => creditcard.year.to_s + } + } + result = Braintree::Customer.create(merge_credit_card_options(parameters, options)) + Response.new(result.success?, message_from_result(result), + { + :braintree_customer => (customer_hash(result.customer) if result.success?), + :customer_vault_id => (result.customer.id if result.success?) + }, + :authorization => (result.customer.id if result.success?) + ) + end + end + + def update(vault_id, creditcard, options = {}) + braintree_credit_card = nil + commit do + braintree_credit_card = Braintree::Customer.find(vault_id).credit_cards.detect { |cc| cc.default? } + return Response.new(false, 'Braintree::NotFoundError') if braintree_credit_card.nil? + + options.merge!(:update_existing_token => braintree_credit_card.token) + credit_card_params = merge_credit_card_options({ + :credit_card => { + :number => creditcard.number, + :cvv => creditcard.verification_value, + :expiration_month => creditcard.month.to_s.rjust(2, "0"), + :expiration_year => creditcard.year.to_s + } + }, options)[:credit_card] + + result = Braintree::Customer.update(vault_id, + :first_name => creditcard.first_name, + :last_name => creditcard.last_name, + :email => options[:email], + :credit_card => credit_card_params + ) + Response.new(result.success?, message_from_result(result), + :braintree_customer => (customer_hash(Braintree::Customer.find(vault_id)) if result.success?), + :customer_vault_id => (result.customer.id if result.success?) + ) + end + end + + def unstore(customer_vault_id) + commit do + Braintree::Customer.delete(customer_vault_id) + Response.new(true, "OK") + end + end + alias_method :delete, :unstore + + private + + def merge_credit_card_options(parameters, options) + valid_options = {} + options.each do |key, value| + valid_options[key] = value if [:update_existing_token, :verify_card, :verification_merchant_account_id].include?(key) + end + + parameters[:credit_card] ||= {} + parameters[:credit_card].merge!(:options => valid_options) + parameters[:credit_card][:billing_address] = map_address(options[:billing_address]) if options[:billing_address] + parameters + end + + def map_address(address) + return {} if address.nil? + mapped = { + :street_address => address[:address1], + :extended_address => address[:address2], + :company => address[:company], + :locality => address[:city], + :region => address[:state], + :postal_code => address[:zip], + } + if(address[:country] || address[:country_code_alpha2]) + mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2]) + elsif address[:country_name] + mapped[:country_name] = address[:country_name] + elsif address[:country_code_alpha3] + mapped[:country_code_alpha3] = address[:country_code_alpha3] + elsif address[:country_code_numeric] + mapped[:country_code_numeric] = address[:country_code_numeric] + end + mapped + end + + def commit(&block) + yield + rescue Braintree::BraintreeError => ex + Response.new(false, ex.class.to_s) + end + + def message_from_result(result) + if result.success? + "OK" + elsif result.errors.size == 0 && result.credit_card_verification + "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})" + else + result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ") + end + end + + def create_transaction(transaction_type, money, credit_card_or_vault_id, options) + transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options) + + commit do + result = Braintree::Transaction.send(transaction_type, transaction_params) + response_params, response_options, avs_result, cvv_result = {}, {}, {}, {} + if result.success? + response_params[:braintree_transaction] = transaction_hash(result.transaction) + response_params[:customer_vault_id] = result.transaction.customer_details.id + response_options[:authorization] = result.transaction.id + end + if result.transaction + response_options[:avs_result] = { + :code => nil, :message => nil, + :street_match => result.transaction.avs_street_address_response_code, + :postal_match => result.transaction.avs_postal_code_response_code + } + response_options[:cvv_result] = result.transaction.cvv_response_code + if result.transaction.status == "gateway_rejected" + message = "Transaction declined - gateway rejected" + else + message = "#{result.transaction.processor_response_code} #{result.transaction.processor_response_text}" + end + else + message = message_from_result(result) + end + response = Response.new(result.success?, message, response_params, response_options) + response.cvv_result['message'] = '' + response + end + end + + def extract_refund_args(args) + options = args.extract_options! + + # money, transaction_id, options + if args.length == 1 # legacy signature + return nil, args[0], options + elsif args.length == 2 + return args[0], args[1], options + else + raise ArgumentError, "wrong number of arguments (#{args.length} for 2)" + end + end + + def customer_hash(customer) + credit_cards = customer.credit_cards.map do |cc| + { + "bin" => cc.bin, + "expiration_date" => cc.expiration_date, + "token" => cc.token, + "last_4" => cc.last_4, + "card_type" => cc.card_type, + "masked_number" => cc.masked_number + } + end + + { + "email" => customer.email, + "first_name" => customer.first_name, + "last_name" => customer.last_name, + "credit_cards" => credit_cards, + "id" => customer.id + } + end + + def transaction_hash(transaction) + if transaction.vault_customer + vault_customer = { + } + vault_customer["credit_cards"] = transaction.vault_customer.credit_cards.map do |cc| + { + "bin" => cc.bin + } + end + else + vault_customer = nil + end + + customer_details = { + "id" => transaction.customer_details.id, + "email" => transaction.customer_details.email + } + + billing_details = { + "street_address" => transaction.billing_details.street_address, + "extended_address" => transaction.billing_details.extended_address, + "company" => transaction.billing_details.company, + "locality" => transaction.billing_details.locality, + "region" => transaction.billing_details.region, + "postal_code" => transaction.billing_details.postal_code, + "country_name" => transaction.billing_details.country_name, + } + + shipping_details = { + "street_address" => transaction.shipping_details.street_address, + "extended_address" => transaction.shipping_details.extended_address, + "company" => transaction.shipping_details.company, + "locality" => transaction.shipping_details.locality, + "region" => transaction.shipping_details.region, + "postal_code" => transaction.shipping_details.postal_code, + "country_name" => transaction.shipping_details.country_name, + } + credit_card_details = { + "masked_number" => transaction.credit_card_details.masked_number, + "bin" => transaction.credit_card_details.bin, + "last_4" => transaction.credit_card_details.last_4, + "card_type" => transaction.credit_card_details.card_type, + "token" => transaction.credit_card_details.token + } + + { + "order_id" => transaction.order_id, + "status" => transaction.status, + "credit_card_details" => credit_card_details, + "customer_details" => customer_details, + "billing_details" => billing_details, + "shipping_details" => shipping_details, + "vault_customer" => vault_customer, + "merchant_account_id" => transaction.merchant_account_id + } + end + + def create_transaction_parameters(money, credit_card_or_vault_id, options) + parameters = { + :amount => amount(money).to_s, + :order_id => options[:order_id], + :customer => { + :id => options[:store] == true ? "" : options[:store], + :email => options[:email] + }, + :options => { + :store_in_vault => options[:store] ? true : false, + :submit_for_settlement => options[:submit_for_settlement] + } + } + + if merchant_account_id = (options[:merchant_account_id] || @merchant_account_id) + parameters[:merchant_account_id] = merchant_account_id + end + + if options[:recurring] + parameters[:recurring] = true + end + + if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer) + parameters[:customer_id] = credit_card_or_vault_id + else + parameters[:customer].merge!( + :first_name => credit_card_or_vault_id.first_name, + :last_name => credit_card_or_vault_id.last_name + ) + parameters[:credit_card] = { + :number => credit_card_or_vault_id.number, + :cvv => credit_card_or_vault_id.verification_value, + :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"), + :expiration_year => credit_card_or_vault_id.year.to_s + } + end + parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address] + parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address] + parameters + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_orange.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_orange.rb new file mode 100644 index 000000000..16e24beea --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/braintree_orange.rb @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + '/smart_ps.rb' +require File.dirname(__FILE__) + '/braintree/braintree_common' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class BraintreeOrangeGateway < SmartPs + include BraintreeCommon + + self.display_name = 'Braintree (Orange Platform)' + + self.live_url = self.test_url = 'https://secure.braintreepaymentgateway.com/api/transact.php' + + def add_processor(post, options) + post[:processor_id] = options[:processor] unless options[:processor].nil? + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_save.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_save.rb new file mode 100644 index 000000000..7bd9ee8e4 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_save.rb @@ -0,0 +1,23 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class CardSaveGateway < IridiumGateway + #CardSave lets you handle failovers on payments by providing 3 gateways in case one happens to be down + #URLS = ['https://gw1.cardsaveonlinepayments.com:4430/','https://gw2.cardsaveonlinepayments.com:4430/','https://gw3.cardsaveonlinepayments.com:4430/'] + + self.money_format = :cents + self.default_currency = 'GBP' + self.supported_cardtypes = [ :visa, :switch, :maestro, :master, :solo, :american_express, :jcb ] + self.supported_countries = [ 'GB' ] + self.homepage_url = 'http://www.cardsave.net/' + self.display_name = 'CardSave' + + def initialize(options={}) + super + @test_url = 'https://gw1.cardsaveonlinepayments.com:4430/' + @live_url = 'https://gw1.cardsaveonlinepayments.com:4430/' + end + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream.rb new file mode 100644 index 000000000..30dc8897f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream.rb @@ -0,0 +1,225 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # + # CardStream supports the following credit cards, which are auto-detected by + # the gateway based on the card number used: + # * AM American Express + # * Diners Club + # * Electron + # * JCB + # * UK Maestro + # * Maestro International + # * Mastercard + # * Solo + # * Style + # * Switch + # * Visa Credit + # * Visa Debit + # * Visa Purchasing + # + class CardStreamGateway < Gateway + self.live_url = self.test_url = 'https://gateway.cardstream.com/process.ashx' + + self.money_format = :cents + self.default_currency = 'GBP' + self.supported_countries = ['GB'] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover, :jcb, :maestro, :solo, :switch] + self.homepage_url = 'http://www.cardstream.com/' + self.display_name = 'CardStream' + + APPROVED = '00' + + CURRENCY_CODES = { + "AUD"=> '036', + "CAD"=> '124', + "CZK"=> '203', + "DKK"=> '208', + "HKD"=> '344', + "ICK"=> '352', + "JPY"=> '392', + "NOK"=> '578', + "SGD"=> '702', + "SEK"=> '752', + "CHF"=> '756', + "GBP"=> '826', + "USD"=> '840', + "EUR"=> '978' + } + + TRANSACTIONS = { + :purchase => 'ESALE_KEYED', + :refund => 'EREFUND_KEYED', + :authorization => 'ESALE_KEYED' + } + + CVV_CODE = { + '0' => 'U', + '1' => 'P', + '2' => 'M', + '4' => 'N' + } + + # 0 - No additional information available. + # 1 - Postcode not checked. + # 2 - Postcode matched. + # 4 - Postcode not matched. + # 8 - Postcode partially matched. + AVS_POSTAL_MATCH = { + "0" => nil, + "1" => nil, + "2" => "Y", + "4" => "N", + "8" => "N" + } + + # 0 - No additional information available. + # 1 - Address numeric not checked. + # 2 - Address numeric matched. + # 4 - Address numeric not matched. + # 8 - Address numeric partially matched. + AVS_STREET_MATCH = { + "0" => nil, + "1" => nil, + "2" => "Y", + "4" => "N", + "8" => "N" + } + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card, options = {}) + requires!(options, :order_id) + + post = {} + + add_amount(post, money, options) + add_invoice(post, money, credit_card, options) + add_credit_card(post, credit_card) + add_address(post, options) + add_customer_data(post, options) + + commit(:purchase, post) + end + + private + + def add_amount(post, money, options) + add_pair(post, :Amount, amount(money), :required => true) + add_pair(post, :CurrencyCode, currency_code(options[:currency] || currency(money)), :required => true) + end + + def add_customer_data(post, options) + add_pair(post, :BillingEmail, options[:email]) + add_pair(post, :BillingPhoneNumber, options[:phone]) + end + + def add_address(post, options) + address = options[:billing_address] || options[:address] + + return if address.nil? + + add_pair(post, :BillingStreet, address[:address1]) + add_pair(post, :BillingHouseNumber, address[:address2]) + add_pair(post, :BillingCity, address[:city]) + add_pair(post, :BillingState, address[:state]) + add_pair(post, :BillingPostCode, address[:zip]) + end + + def add_invoice(post, money, credit_card, options) + add_pair(post, :TransactionUnique, options[:order_id], :required => true) + add_pair(post, :OrderDesc, options[:description] || options[:order_id], :required => true) + + if [ 'american_express', 'diners_club' ].include?(card_brand(credit_card).to_s) + add_pair(post, :AEIT1Quantity, 1) + add_pair(post, :AEIT1Description, (options[:description] || options[:order_id]).slice(0, 15)) + add_pair(post, :AEIT1GrossValue, amount(money)) + end + end + + def add_credit_card(post, credit_card) + add_pair(post, :CardName, credit_card.name, :required => true) + add_pair(post, :CardNumber, credit_card.number, :required => true) + + add_pair(post, :ExpiryDateMM, format(credit_card.month, :two_digits), :required => true) + add_pair(post, :ExpiryDateYY, format(credit_card.year, :two_digits), :required => true) + + if requires_start_date_or_issue_number?(credit_card) + add_pair(post, :StartDateMM, format(credit_card.start_month, :two_digits)) + add_pair(post, :StartDateYY, format(credit_card.start_year, :two_digits)) + + add_pair(post, :IssueNumber, credit_card.issue_number) + end + + add_pair(post, :CV2, credit_card.verification_value) + end + + def commit(action, parameters) + response = parse( ssl_post(self.live_url, post_data(action, parameters)) ) + + Response.new(response[:response_code] == APPROVED, message_from(response), response, + :test => test?, + :authorization => response[:cross_reference], + :cvv_result => CVV_CODE[ response[:avscv2_response_code].to_s[0, 1] ], + :avs_result => { + :street_match => AVS_STREET_MATCH[ response[:avscv2_response_code].to_s[2, 1] ], + :postal_match => AVS_POSTAL_MATCH[ response[:avscv2_response_code].to_s[1, 1] ] + } + ) + end + + def message_from(results) + results[:response_code] == APPROVED ? "APPROVED" : results[:message] + end + + def post_data(action, parameters = {}) + parameters.update( + :MerchantPassword => @options[:password], + :MerchantID => @options[:login], + :MessageType => TRANSACTIONS[action], + :CallBack => "disable", + :DuplicateDelay => "0", + :EchoCardType => "YES", + :EchoAmount => "YES", + :EchoAVSCV2ResponseCode => "YES", + :ReturnAVSCV2Message => "YES", + :CountryCode => '826' # 826 for UK based merchant + ) + + add_pair(parameters, :Dispatch, action == :authorization ? "LATER" : "NOW") + + parameters.collect { |key, value| "VP#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + # VPCrossReference + # The value in VPCrossReference on a success transaction will contain + # a unique reference that you may use to run future transactions. + # Please note that cross reference transactions must come a static IP + # addressed that has been pre-registered with Cardstream. To + # register an IP address please send it to support@cardstream.com + # with your Cardstream issued merchant ID and it will be added to + # your account. + def parse(body) + result = {} + pairs = body.split("&") + pairs.each do |pair| + a = pair.split("=") + result[a[0].gsub(/^VP/,'').underscore.to_sym] = a[1] + end + + result + end + + def currency_code(currency) + CURRENCY_CODES[currency] + end + + def add_pair(post, key, value, options = {}) + post[key] = value if !value.blank? || options[:required] + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream_modern.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream_modern.rb new file mode 100644 index 000000000..1d3393fa2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/card_stream_modern.rb @@ -0,0 +1,155 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class CardStreamModernGateway < Gateway + self.test_url = self.live_url = 'https://gateway.cardstream.com/direct/' + self.money_format = :cents + self.default_currency = 'GBP' + self.supported_countries = ['GB'] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover, :jcb, :maestro, :solo, :switch] + self.homepage_url = 'http://www.cardstream.com/' + self.display_name = 'CardStream' + + def initialize(options = {}) + requires!(options, :login) + if(options[:threeDSRequired]) + @threeDSRequired = options[:threeDSRequired] + else + @threeDSRequired = 'N' + end + super + end + + def authorize(money, creditcard, options = {}) + post = {} + add_amount(post, money, options) + add_invoice(post, creditcard, money, options) + add_creditcard(post, creditcard) + add_address(post, creditcard, options) + add_customer_data(post, options) + commit('PREAUTH', post) + end + + def purchase(money, creditcard, options = {}) + post = {} + add_amount(post, money, options) + add_invoice(post, creditcard, money, options) + add_creditcard(post, creditcard) + add_address(post, creditcard, options) + add_customer_data(post, options) + commit('SALE', post) + end + + def capture(money, authorization, options = {}) + post = {} + add_pair(post, :xref, authorization) + add_amount(post, money, options) + commit('SALE', post) + end + + def refund(money, authorization, options = {}) + post = {} + add_pair(post, :xref, authorization) + add_amount(post, money, options) + commit('REFUND', post) + end + + def void(authorization, options = {}) + post = {} + add_pair(post, :xref, authorization) + commit('REFUND', post) + end + + private + + def add_amount(post, money, options) + add_pair(post, :amount, amount(money), :required => true) + add_pair(post, :currencyCode, options[:currency] || self.default_currency) + end + + def add_customer_data(post, options) + address = options[:billing_address] || options[:address] + add_pair(post, :customerPostCode, address[:zip]) + add_pair(post, :customerEmail, options[:email]) + add_pair(post, :customerPhone, options[:phone]) + end + + def add_address(post, creditcard, options) + address = options[:billing_address] || options[:address] + + return if address.nil? + + add_pair(post, :customerAddress, address[:address1] + " " + (address[:address2].nil? ? "" : address[:address2]) ) + add_pair(post, :customerPostCode, address[:zip]) + end + + def add_invoice(post, credit_card, money, options) + add_pair(post, :transactionUnique, options[:order_id], :required => true) + add_pair(post, :orderRef, options[:description] || options[:order_id], :required => true) + if [ 'american_express', 'diners_club' ].include?(card_brand(credit_card).to_s) + add_pair(post, :item1Quantity, 1) + add_pair(post, :item1Description, (options[:description] || options[:order_id]).slice(0, 15)) + add_pair(post, :item1GrossValue, amount(money)) + end + end + + def add_creditcard(post, credit_card) + add_pair(post, :customerName, credit_card.name, :required => true) + add_pair(post, :cardNumber, credit_card.number, :required => true) + + add_pair(post, :cardExpiryMonth, format(credit_card.month, :two_digits), :required => true) + add_pair(post, :cardExpiryYear, format(credit_card.year, :two_digits), :required => true) + + if requires_start_date_or_issue_number?(credit_card) + add_pair(post, :cardStartMonth, format(credit_card.start_month, :two_digits)) + add_pair(post, :cardStartYear, format(credit_card.start_year, :two_digits)) + + add_pair(post, :cardIssueNumber, credit_card.issue_number) + end + + add_pair(post, :cardCVV, credit_card.verification_value) + end + + def parse(body) + result = {} + pairs = body.split("&") + pairs.each do |pair| + a = pair.split("=") + result[a[0].to_sym] = CGI.unescape(a[1]) + end + result + end + + def commit(action, parameters) + response = parse( ssl_post(self.live_url, post_data(action, parameters)) ) + + Response.new(response[:responseCode] == "0", + response[:responseCode] == "0" ? "APPROVED" : response[:responseMessage], + response, + :test => test?, + :authorization => response[:xref], + :avs_result => { + :street_match => response[:addressCheck], + :postal_match => response[:postcodeCheck], + }, + :cvv_result => response[:cv2Check] + ) + end + + def post_data(action, parameters = {}) + parameters.update( + :merchantID => @options[:login], + :action => action, + :type => '1', #Ecommerce + :countryCode => self.supported_countries[0], + :threeDSRequired => @threeDSRequired #Disable 3d secure by default + ) + parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def add_pair(post, key, value, options = {}) + post[key] = value if !value.blank? || options[:required] + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cc5.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cc5.rb new file mode 100644 index 000000000..4d315243c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cc5.rb @@ -0,0 +1,156 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # CC5 API is used by many banks in Turkey. Extend this base class to provide + # concrete implementations. + class CC5Gateway < Gateway + self.default_currency = 'TRY' + + CURRENCY_CODES = { + 'TRY' => 949, + 'YTL' => 949, + 'TRL' => 949, + 'TL' => 949, + 'USD' => 840, + 'EUR' => 978, + 'GBP' => 826, + 'JPY' => 392 + } + + def initialize(options = {}) + requires!(options, :login, :password, :client_id) + super + end + + def purchase(money, creditcard, options = {}) + commit(build_sale_request('Auth', money, creditcard, options)) + end + + def authorize(money, creditcard, options = {}) + commit(build_sale_request('PreAuth', money, creditcard, options)) + end + + def capture(money, authorization, options = {}) + commit(build_capture_request(money, authorization, options)) + end + + protected + + def build_sale_request(type, money, creditcard, options = {}) + requires!(options, :order_id) + + xml = Builder::XmlMarkup.new :indent => 2 + + xml.tag! 'CC5Request' do + add_login_tags(xml) + xml.tag! 'OrderId', options[:order_id] + xml.tag! 'Type', type + xml.tag! 'Number', creditcard.number + xml.tag! 'Expires', [format(creditcard.month, :two_digits), format(creditcard.year, :two_digits)].join('/') + xml.tag! 'Cvv2Val', creditcard.verification_value + add_amount_tags(money, options, xml) + xml.tag! 'Email', options[:email] if options[:email] + + if(address = (options[:billing_address] || options[:address])) + xml.tag! 'BillTo' do + add_address(xml, address) + end + xml.tag! 'ShipTo' do + add_address(xml, address) + end + end + + end + + xml.target! + end + + def build_capture_request(money, authorization, options = {}) + xml = Builder::XmlMarkup.new :indent => 2 + + xml.tag! 'CC5Request' do + add_login_tags(xml) + xml.tag! 'OrderId', authorization + xml.tag! 'Type', 'PostAuth' + add_amount_tags(money, options, xml) + end + end + + def add_address(xml, address) + xml.tag! 'Name', normalize(address[:name]) + xml.tag! 'Street1', normalize(address[:address1]) + xml.tag! 'Street2', normalize(address[:address2]) if address[:address2] + xml.tag! 'City', normalize(address[:city]) + xml.tag! 'PostalCode', address[:zip] + xml.tag! 'Country', normalize(address[:country]) + xml.tag! 'Company', normalize(address[:company]) + xml.tag! 'TelVoice', address[:phone].to_s.gsub(/[^0-9]/, '') if address[:phone] + end + + def add_login_tags(xml) + xml.tag! 'Name', @options[:login] + xml.tag! 'Password', @options[:password] + xml.tag! 'ClientId', @options[:client_id] + xml.tag! 'Mode', (test? ? 'T' : 'P') + end + + def add_amount_tags(money, options, xml) + xml.tag! 'Total', amount(money) + xml.tag! 'Currency', currency_code(options[:currency] || currency(money)) + end + + def currency_code(currency) + (CURRENCY_CODES[currency] || CURRENCY_CODES[default_currency]) + end + + def commit(request) + raw_response = ssl_post((test? ? self.test_url : self.live_url), "DATA=" + request) + + response = parse(raw_response) + + success = success?(response) + + Response.new( + success, + (success ? 'Approved' : "Declined (Reason: #{response[:proc_return_code]} - #{response[:err_msg]})"), + response, + :test => test?, + :authorization => response[:order_id] + ) + end + + def parse(body) + xml = REXML::Document.new(body) + + response = {} + xml.root.elements.to_a.each do |node| + parse_element(response, node) + end + response + end + + def parse_element(response, node) + if node.has_elements? + node.elements.each{|element| parse_element(response, element) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + def success?(response) + (response[:response] == "Approved") + end + + def normalize(text) + return unless text + + if ActiveSupport::Inflector.method(:transliterate).arity == -2 + ActiveSupport::Inflector.transliterate(text,'') + elsif RUBY_VERSION >= '1.9' + text.gsub(/[^\x00-\x7F]+/, '') + else + ActiveSupport::Inflector.transliterate(text).to_s + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/certo_direct.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/certo_direct.rb new file mode 100644 index 000000000..a77fc780a --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/certo_direct.rb @@ -0,0 +1,277 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class CertoDirectGateway < Gateway + self.live_url = self.test_url = "https://secure.certodirect.com/gateway/process/v2" + + self.supported_countries = [ + "BE", "BG", "CZ", "DK", "DE", "EE", "IE", "EL", "ES", "FR", + "IT", "CY", "LV", "LT", "LU", "HU", "MT", "NL", "AT", "PL", + "PT", "RO", "SI", "SK", "FI", "SE", "GB" + ] + + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.certodirect.com/' + self.display_name = 'CertoDirect' + + # Creates a new CertoDirectGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The CertoDirect Shop ID (REQUIRED) + # * :password -- The CertoDirect Shop Password. (REQUIRED) + # * :test -- +true+ or +false+. If true, perform transactions against the test server. + # Otherwise, perform transactions against the production server. + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Perform a purchase, which is essentially an authorization and capture in a single operation. + # + # ==== Parameters + # + # * money -- The amount to be purchased as an Integer value in cents. + # * credit_card -- The CreditCard details for the transaction. + # * options -- A hash of optional parameters. + def purchase(money, credit_card, options = {}) + requires!(options, :email, :currency, :ip, :description) + + commit(build_sale_request(money, credit_card, options)) + end + + # Refund a transaction. + # + # This transaction indicates to the gateway that + # money should flow from the merchant to the customer. + # + # ==== Parameters + # + # * money -- The amount to be credited to the customer as an Integer value in cents. + # * identification -- The ID of the original order against which the refund is being issued. + # * options -- A hash of parameters. + def refund(money, identification, options = {}) + requires!(options, :reason) + + commit(build_refund_request(money, identification, options)) + end + + # Performs an authorization, which reserves the funds on the customer's credit card, but does not + # charge the card. + # + # ==== Parameters + # + # * money -- The amount to be authorized as an Integer value in cents. + # * credit_card -- The CreditCard details for the transaction. + # * options -- A hash of optional parameters. + def authorize(money, credit_card, options = {}) + requires!(options, :email, :currency, :ip, :description) + + commit(build_authorize_request(money, credit_card, options)) + end + + # Captures the funds from an authorized transaction. + # + # ==== Parameters + # + # * money -- The amount to be captured as an Integer value in cents. + # * identification -- The authorization returned from the previous authorize request. + def capture(money, identification, options = {}) + commit(build_capture_request(money, identification)) + end + + # Void a previous transaction + # + # ==== Parameters + # + # * money -- The amount to be captured as an Integer value in cents. + # * identification - The authorization returned from the previous authorize request. + def void(money, identification, options = {}) + commit(build_void_request(money, identification)) + end + + # Create a recurring payment. + # + # ==== Parameters + # + # * options -- A hash of parameters. + # + # ==== Options + # + def recurring(identification, options={}) + commit(build_recurring_request(identification, options)) + end + + + private + + def commit(request_xml) + begin + response = Hash.from_xml(ssl_post(self.live_url, request_xml, headers)) + Response.new(success?(response), + message(response), + response, + :test => test?, + :authorization => authorization(response)) + rescue ResponseError => e + raise e unless e.response.code == '403' + response = Hash.from_xml(e.response.body)['response'] + Response.new(false, message(response), {}, :test => test?) + end + end + + def build_sale_request(money, credit_card, options) + build_request_xml('Sale') do |xml| + add_order(xml, money, credit_card, options) + end + end + + def build_authorize_request(money, credit_card, options) + build_request_xml('Authorize') do |xml| + add_order(xml, money, credit_card, options) + end + end + + def build_refund_request(money, identification, options) + build_request_xml('Refund') do |xml| + add_reference_info(xml, money, identification, options) + xml.tag! 'reason', options[:reason] + end + end + + def build_capture_request(money, identification) + build_request_xml('Capture') do |xml| + add_reference_info(xml, money, identification, options) + end + end + + def build_void_request(money, identification) + build_request_xml('Void') do |xml| + add_reference_info(xml, money, identification, options) + end + end + + def build_recurring_request(identification, options) + build_request_xml('Sale') do |xml| + xml.tag! 'order' do |xml| + xml.tag!('test', 'true') if test? + xml.tag! 'initial_order_id', identification, :type => 'integer' + + add_order_details(xml, options[:amount], options) if has_any_order_details_key?(options) + add_address(xml, 'billing_address', options[:billing_address]) if options[:billing_address] + add_address(xml, 'shipping_address', options[:shipping_address]) if options[:shipping_address] + end + end + end + + def build_request_xml(type, &block) + xml = Builder::XmlMarkup.new(:indent => 2) + xml.tag! 'transaction' do + xml.tag! 'type', type + yield(xml) + end + xml.target! + end + + def add_order(xml, money, credit_card, options) + xml.tag! 'order' do + xml.tag!('test', 'true') if test? + + xml.tag!('return_url', options[:return_url]) if options[:return_url] + xml.tag!('cancel_url', options[:cancel_url]) if options[:cancel_url] + + xml.tag! 'payment_method_type', 'CreditCard' + xml.tag! 'payment_method' do + xml.tag! 'number', credit_card.number + xml.tag! 'exp_month', "%02i" % credit_card.month + xml.tag! 'exp_year', credit_card.year + xml.tag! 'holder', credit_card.name + xml.tag! 'verification_value', credit_card.verification_value + end + + add_order_details(xml, money, options) + add_address(xml, 'billing_address', options[:billing_address]) if options[:billing_address] + add_address(xml, 'shipping_address', options[:shipping_address]) if options[:shipping_address] + end + end + + def add_order_details(xml, money, options) + xml.tag! 'details' do + xml.tag!('amount', localized_amount(money, options[:currency]), :type => 'decimal') if money + xml.tag!('currency', options[:currency]) if options[:currency] + xml.tag!('email', options[:email]) if options[:email] + xml.tag!('ip', options[:ip]) if options[:ip] + xml.tag!('shipping', options[:shipping], :type => 'decimal') if options[:shipping] + xml.tag!('description', options[:description]) if options[:description] + end + end + + def add_reference_info(xml, money, identification, options) + xml.tag! 'order_id', identification, :type => 'integer' + xml.tag! 'amount', localized_amount(money, options[:currency]), :type => 'decimal' + end + + def add_address(xml, address_type, address) + xml.tag! address_type do + xml.tag! 'address', address[:address1] + xml.tag! 'city', address[:city] + xml.tag! 'country', address[:country] + xml.tag! 'first_name', address[:first_name] + xml.tag! 'last_name', address[:last_name] + xml.tag! 'state', address[:state] + xml.tag! 'phone', address[:phone] + xml.tag! 'zip', address[:zip] + end + end + + def has_any_order_details_key?(options) + [ :currency, :amount, :email, :ip, :shipping, :description ].any? do |key| + options.has_key?(key) + end + end + + def success?(response) + %w(completed forwarding).include?(state(response)) and + status(response) == 'success' + end + + def error?(response) + response['errors'] + end + + def state(response) + response["transaction"].try(:[], "state") + end + + def status(response) + response['transaction'].try(:[], 'response').try(:[], 'status') + end + + def authorization(response) + error?(response) ? nil : response["transaction"]["order"]['id'].to_s + end + + def message(response) + return response['errors'].join('; ') if error?(response) + + if state(response) == 'completed' + response["transaction"]["response"]["message"] + else + response['transaction']['message'] + end + end + + def headers + { 'authorization' => basic_auth, + 'Accept' => 'application/xml', + 'Content-Type' => 'application/xml' } + end + + def basic_auth + 'Basic ' + ["#{@options[:login]}:#{@options[:password]}"].pack('m').delete("\r\n") + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cyber_source.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cyber_source.rb new file mode 100644 index 000000000..d9110cd47 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/cyber_source.rb @@ -0,0 +1,614 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # See the remote and mocked unit test files for example usage. Pay special + # attention to the contents of the options hash. + # + # Initial setup instructions can be found in + # http://cybersource.com/support_center/implementation/downloads/soap_api/SOAP_toolkits.pdf + # + # Debugging + # If you experience an issue with this gateway be sure to examine the + # transaction information from a general transaction search inside the + # CyberSource Business Center for the full error messages including field + # names. + # + # Important Notes + # * For checks you can purchase and store. + # * AVS and CVV only work against the production server. You will always + # get back X for AVS and no response for CVV against the test server. + # * Nexus is the list of states or provinces where you have a physical + # presence. Nexus is used to calculate tax. Leave blank to tax everyone. + # * If you want to calculate VAT for overseas customers you must supply a + # registration number in the options hash as vat_reg_number. + # * productCode is a value in the line_items hash that is used to tell + # CyberSource what kind of item you are selling. It is used when + # calculating tax/VAT. + # * All transactions use dollar values. + class CyberSourceGateway < Gateway + self.test_url = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor' + self.live_url = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor' + + XSD_VERSION = "1.69" + + # visa, master, american_express, discover + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.supported_countries = ['US'] + self.default_currency = 'USD' + self.homepage_url = 'http://www.cybersource.com' + self.display_name = 'CyberSource' + + # map credit card to the CyberSource expected representation + @@credit_card_codes = { + :visa => '001', + :master => '002', + :american_express => '003', + :discover => '004' + } + + # map response codes to something humans can read + @@response_codes = { + :r100 => "Successful transaction", + :r101 => "Request is missing one or more required fields" , + :r102 => "One or more fields contains invalid data", + :r150 => "General failure", + :r151 => "The request was received but a server time-out occurred", + :r152 => "The request was received, but a service timed out", + :r200 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the AVS check", + :r201 => "The issuing bank has questions about the request", + :r202 => "Expired card", + :r203 => "General decline of the card", + :r204 => "Insufficient funds in the account", + :r205 => "Stolen or lost card", + :r207 => "Issuing bank unavailable", + :r208 => "Inactive card or card not authorized for card-not-present transactions", + :r209 => "American Express Card Identifiction Digits (CID) did not match", + :r210 => "The card has reached the credit limit", + :r211 => "Invalid card verification number", + :r221 => "The customer matched an entry on the processor's negative file", + :r230 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check", + :r231 => "Invalid account number", + :r232 => "The card type is not accepted by the payment processor", + :r233 => "General decline by the processor", + :r234 => "A problem exists with your CyberSource merchant configuration", + :r235 => "The requested amount exceeds the originally authorized amount", + :r236 => "Processor failure", + :r237 => "The authorization has already been reversed", + :r238 => "The authorization has already been captured", + :r239 => "The requested transaction amount must match the previous transaction amount", + :r240 => "The card type sent is invalid or does not correlate with the credit card number", + :r241 => "The request ID is invalid", + :r242 => "You requested a capture, but there is no corresponding, unused authorization record.", + :r243 => "The transaction has already been settled or reversed", + :r244 => "The bank account number failed the validation check", + :r246 => "The capture or credit is not voidable because the capture or credit information has already been submitted to your processor", + :r247 => "You requested a credit for a capture that was previously voided", + :r250 => "The request was received, but a time-out occurred with the payment processor", + :r254 => "Your CyberSource account is prohibited from processing stand-alone refunds", + :r255 => "Your CyberSource account is not configured to process the service in the country you specified" + } + + # These are the options that can be used when creating a new CyberSource + # Gateway object. + # + # :login => your username + # + # :password => the transaction key you generated in the Business Center + # + # :test => true sets the gateway to test mode + # + # :vat_reg_number => your VAT registration number + # + # :nexus => "WI CA QC" sets the states/provinces where you have a physical + # presense for tax purposes + # + # :ignore_avs => true don't want to use AVS so continue processing even + # if AVS would have failed + # + # :ignore_cvv => true don't want to use CVV so continue processing even + # if CVV would have failed + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Request an authorization for an amount from CyberSource + # + # You must supply an :order_id in the options hash + def authorize(money, creditcard_or_reference, options = {}) + requires!(options, :order_id) + setup_address_hash(options) + commit(build_auth_request(money, creditcard_or_reference, options), options ) + end + + def auth_reversal(money, identification, options = {}) + commit(build_auth_reversal_request(money, identification, options), options) + end + + # Capture an authorization that has previously been requested + def capture(money, authorization, options = {}) + setup_address_hash(options) + commit(build_capture_request(money, authorization, options), options) + end + + # Purchase is an auth followed by a capture + # You must supply an order_id in the options hash + def purchase(money, payment_method_or_reference, options = {}) + requires!(options, :order_id) + setup_address_hash(options) + commit(build_purchase_request(money, payment_method_or_reference, options), options) + end + + def void(identification, options = {}) + commit(build_void_request(identification, options), options) + end + + def refund(money, identification, options = {}) + commit(build_refund_request(money, identification, options), options) + end + + # Adds credit to a subscription (stand alone credit). + def credit(money, reference, options = {}) + requires!(options, :order_id) + commit(build_credit_request(money, reference, options), options) + end + + # Stores a customer subscription/profile with type "on-demand". + # To charge the card while creating a profile, pass + # options[:setup_fee] => money + def store(payment_method, options = {}) + requires!(options, :order_id) + setup_address_hash(options) + commit(build_create_subscription_request(payment_method, options), options) + end + + # Updates a customer subscription/profile + def update(reference, creditcard, options = {}) + requires!(options, :order_id) + setup_address_hash(options) + commit(build_update_subscription_request(reference, creditcard, options), options) + end + + # Removes a customer subscription/profile + def unstore(reference, options = {}) + requires!(options, :order_id) + commit(build_delete_subscription_request(reference, options), options) + end + + # Retrieves a customer subscription/profile + def retrieve(reference, options = {}) + requires!(options, :order_id) + commit(build_retrieve_subscription_request(reference, options), options) + end + + # CyberSource requires that you provide line item information for tax + # calculations. If you do not have prices for each item or want to + # simplify the situation then pass in one fake line item that costs the + # subtotal of the order + # + # The line_item hash goes in the options hash and should look like + # + # :line_items => [ + # { + # :declared_value => '1', + # :quantity => '2', + # :code => 'default', + # :description => 'Giant Walrus', + # :sku => 'WA323232323232323' + # }, + # { + # :declared_value => '6', + # :quantity => '1', + # :code => 'default', + # :description => 'Marble Snowcone', + # :sku => 'FAKE1232132113123' + # } + # ] + # + # This functionality is only supported by this particular gateway may + # be changed at any time + def calculate_tax(creditcard, options) + requires!(options, :line_items) + setup_address_hash(options) + commit(build_tax_calculation_request(creditcard, options), options) + end + + private + + # Create all address hash key value pairs so that we still function if we + # were only provided with one or two of them + def setup_address_hash(options) + options[:billing_address] = options[:billing_address] || options[:address] || {} + options[:shipping_address] = options[:shipping_address] || {} + end + + def build_auth_request(money, creditcard_or_reference, options) + xml = Builder::XmlMarkup.new :indent => 2 + add_payment_method_or_subscription(xml, money, creditcard_or_reference, options) + add_auth_service(xml) + add_business_rules_data(xml) + xml.target! + end + + def build_tax_calculation_request(creditcard, options) + xml = Builder::XmlMarkup.new :indent => 2 + add_address(xml, creditcard, options[:billing_address], options, false) + add_address(xml, creditcard, options[:shipping_address], options, true) + add_line_item_data(xml, options) + add_purchase_data(xml, 0, false, options) + add_tax_service(xml) + add_business_rules_data(xml) + xml.target! + end + + def build_capture_request(money, authorization, options) + order_id, request_id, request_token = authorization.split(";") + options[:order_id] = order_id + + xml = Builder::XmlMarkup.new :indent => 2 + add_purchase_data(xml, money, true, options) + add_capture_service(xml, request_id, request_token) + add_business_rules_data(xml) + xml.target! + end + + def build_purchase_request(money, payment_method_or_reference, options) + xml = Builder::XmlMarkup.new :indent => 2 + add_payment_method_or_subscription(xml, money, payment_method_or_reference, options) + if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check' + add_check_service(xml) + else + add_purchase_service(xml, options) + add_business_rules_data(xml) + end + xml.target! + end + + def build_void_request(identification, options) + order_id, request_id, request_token = identification.split(";") + options[:order_id] = order_id + + xml = Builder::XmlMarkup.new :indent => 2 + add_void_service(xml, request_id, request_token) + xml.target! + end + + def build_auth_reversal_request(money, identification, options) + order_id, request_id, request_token = identification.split(";") + options[:order_id] = order_id + xml = Builder::XmlMarkup.new :indent => 2 + add_purchase_data(xml, money, true, options) + add_auth_reversal_service(xml, request_id, request_token) + xml.target! + end + + def build_refund_request(money, identification, options) + order_id, request_id, request_token = identification.split(";") + options[:order_id] = order_id + + xml = Builder::XmlMarkup.new :indent => 2 + add_purchase_data(xml, money, true, options) + add_credit_service(xml, request_id, request_token) + + xml.target! + end + + def build_credit_request(money, reference, options) + xml = Builder::XmlMarkup.new :indent => 2 + + add_purchase_data(xml, money, true, options) + add_subscription(xml, options, reference) + add_credit_service(xml) + + xml.target! + end + + def build_create_subscription_request(payment_method, options) + options[:subscription] = (options[:subscription] || {}).merge(:frequency => "on-demand", :amount => 0, :automatic_renew => false) + + xml = Builder::XmlMarkup.new :indent => 2 + add_address(xml, payment_method, options[:billing_address], options) + add_purchase_data(xml, options[:setup_fee] || 0, true, options) + if card_brand(payment_method) == 'check' + add_check(xml, payment_method) + add_check_payment_method(xml) + add_check_service(xml, options) if options[:setup_fee] + else + add_creditcard(xml, payment_method) + add_creditcard_payment_method(xml) + add_purchase_service(xml, options) if options[:setup_fee] + end + add_subscription(xml, options) + add_subscription_create_service(xml, options) + add_business_rules_data(xml) + xml.target! + end + + def build_update_subscription_request(reference, creditcard, options) + xml = Builder::XmlMarkup.new :indent => 2 + add_address(xml, creditcard, options[:billing_address], options) unless options[:billing_address].blank? + add_purchase_data(xml, options[:setup_fee], true, options) unless options[:setup_fee].blank? + add_creditcard(xml, creditcard) if creditcard + add_creditcard_payment_method(xml) if creditcard + add_subscription(xml, options, reference) + add_subscription_update_service(xml, options) + add_business_rules_data(xml) + xml.target! + end + + def build_delete_subscription_request(reference, options) + xml = Builder::XmlMarkup.new :indent => 2 + add_subscription(xml, options, reference) + add_subscription_delete_service(xml, options) + xml.target! + end + + def build_retrieve_subscription_request(reference, options) + xml = Builder::XmlMarkup.new :indent => 2 + add_subscription(xml, options, reference) + add_subscription_retrieve_service(xml, options) + xml.target! + end + + def add_business_rules_data(xml) + xml.tag! 'businessRules' do + xml.tag!('ignoreAVSResult', 'true') if @options[:ignore_avs] + xml.tag!('ignoreCVResult', 'true') if @options[:ignore_cvv] + end + end + + def add_line_item_data(xml, options) + options[:line_items].each_with_index do |value, index| + xml.tag! 'item', {'id' => index} do + xml.tag! 'unitPrice', amount(value[:declared_value]) + xml.tag! 'quantity', value[:quantity] + xml.tag! 'productCode', value[:code] || 'shipping_only' + xml.tag! 'productName', value[:description] + xml.tag! 'productSKU', value[:sku] + end + end + end + + def add_merchant_data(xml, options) + xml.tag! 'merchantID', @options[:login] + xml.tag! 'merchantReferenceCode', options[:order_id] + xml.tag! 'clientLibrary' ,'Ruby Active Merchant' + xml.tag! 'clientLibraryVersion', VERSION + xml.tag! 'clientEnvironment' , RUBY_PLATFORM + end + + def add_purchase_data(xml, money = 0, include_grand_total = false, options={}) + xml.tag! 'purchaseTotals' do + xml.tag! 'currency', options[:currency] || currency(money) + xml.tag!('grandTotalAmount', amount(money)) if include_grand_total + end + end + + def add_address(xml, payment_method, address, options, shipTo = false) + requires!(options, :email) + + xml.tag! shipTo ? 'shipTo' : 'billTo' do + xml.tag! 'firstName', payment_method.first_name if payment_method + xml.tag! 'lastName', payment_method.last_name if payment_method + xml.tag! 'street1', address[:address1] + xml.tag! 'street2', address[:address2] unless address[:address2].blank? + xml.tag! 'city', address[:city] + xml.tag! 'state', address[:state] + xml.tag! 'postalCode', address[:zip] + xml.tag! 'country', address[:country] + xml.tag! 'company', address[:company] unless address[:company].blank? + xml.tag! 'companyTaxID', address[:companyTaxID] unless address[:company_tax_id].blank? + xml.tag! 'phoneNumber', address[:phone_number] unless address[:phone_number].blank? + xml.tag! 'email', options[:email] + xml.tag! 'driversLicenseNumber', options[:drivers_license_number] unless options[:drivers_license_number].blank? + xml.tag! 'driversLicenseState', options[:drivers_license_state] unless options[:drivers_license_state].blank? + end + end + + def add_creditcard(xml, creditcard) + xml.tag! 'card' do + xml.tag! 'accountNumber', creditcard.number + xml.tag! 'expirationMonth', format(creditcard.month, :two_digits) + xml.tag! 'expirationYear', format(creditcard.year, :four_digits) + xml.tag!('cvNumber', creditcard.verification_value) unless (@options[:ignore_cvv] || creditcard.verification_value.blank? ) + xml.tag! 'cardType', @@credit_card_codes[card_brand(creditcard).to_sym] + end + end + + def add_check(xml, check) + xml.tag! 'check' do + xml.tag! 'accountNumber', check.account_number + xml.tag! 'accountType', check.account_type[0] + xml.tag! 'bankTransitNumber', check.routing_number + end + end + + def add_tax_service(xml) + xml.tag! 'taxService', {'run' => 'true'} do + xml.tag!('nexus', @options[:nexus]) unless @options[:nexus].blank? + xml.tag!('sellerRegistration', @options[:vat_reg_number]) unless @options[:vat_reg_number].blank? + end + end + + def add_auth_service(xml) + xml.tag! 'ccAuthService', {'run' => 'true'} + end + + def add_capture_service(xml, request_id, request_token) + xml.tag! 'ccCaptureService', {'run' => 'true'} do + xml.tag! 'authRequestID', request_id + xml.tag! 'authRequestToken', request_token + end + end + + def add_purchase_service(xml, options) + xml.tag! 'ccAuthService', {'run' => 'true'} + xml.tag! 'ccCaptureService', {'run' => 'true'} + end + + def add_void_service(xml, request_id, request_token) + xml.tag! 'voidService', {'run' => 'true'} do + xml.tag! 'voidRequestID', request_id + xml.tag! 'voidRequestToken', request_token + end + end + + def add_auth_reversal_service(xml, request_id, request_token) + xml.tag! 'ccAuthReversalService', {'run' => 'true'} do + xml.tag! 'authRequestID', request_id + xml.tag! 'authRequestToken', request_token + end + end + + def add_credit_service(xml, request_id = nil, request_token = nil) + xml.tag! 'ccCreditService', {'run' => 'true'} do + xml.tag! 'captureRequestID', request_id if request_id + xml.tag! 'captureRequestToken', request_token if request_token + end + end + + def add_check_service(xml) + xml.tag! 'ecDebitService', {'run' => 'true'} + end + + def add_subscription_create_service(xml, options) + xml.tag! 'paySubscriptionCreateService', {'run' => 'true'} + end + + def add_subscription_update_service(xml, options) + xml.tag! 'paySubscriptionUpdateService', {'run' => 'true'} + end + + def add_subscription_delete_service(xml, options) + xml.tag! 'paySubscriptionDeleteService', {'run' => 'true'} + end + + def add_subscription_retrieve_service(xml, options) + xml.tag! 'paySubscriptionRetrieveService', {'run' => 'true'} + end + + def add_subscription(xml, options, reference = nil) + options[:subscription] ||= {} + + xml.tag! 'recurringSubscriptionInfo' do + if reference + _, subscription_id, _ = reference.split(";") + xml.tag! 'subscriptionID', subscription_id + end + + xml.tag! 'status', options[:subscription][:status] if options[:subscription][:status] + xml.tag! 'amount', options[:subscription][:amount] if options[:subscription][:amount] + xml.tag! 'numberOfPayments', options[:subscription][:occurrences] if options[:subscription][:occurrences] + xml.tag! 'automaticRenew', options[:subscription][:automatic_renew] if options[:subscription][:automatic_renew] + xml.tag! 'frequency', options[:subscription][:frequency] if options[:subscription][:frequency] + xml.tag! 'startDate', options[:subscription][:start_date].strftime("%Y%m%d") if options[:subscription][:start_date] + xml.tag! 'endDate', options[:subscription][:end_date].strftime("%Y%m%d") if options[:subscription][:end_date] + xml.tag! 'approvalRequired', options[:subscription][:approval_required] || false + xml.tag! 'event', options[:subscription][:event] if options[:subscription][:event] + xml.tag! 'billPayment', options[:subscription][:bill_payment] if options[:subscription][:bill_payment] + end + end + + def add_creditcard_payment_method(xml) + xml.tag! 'subscription' do + xml.tag! 'paymentMethod', "credit card" + end + end + + def add_check_payment_method(xml) + xml.tag! 'subscription' do + xml.tag! 'paymentMethod', "check" + end + end + + def add_payment_method_or_subscription(xml, money, payment_method_or_reference, options) + if payment_method_or_reference.is_a?(String) + add_purchase_data(xml, money, true, options) + add_subscription(xml, options, payment_method_or_reference) + elsif card_brand(payment_method_or_reference) == 'check' + add_address(xml, payment_method_or_reference, options[:billing_address], options) + add_purchase_data(xml, money, true, options) + add_check(xml, payment_method_or_reference) + else + add_address(xml, payment_method_or_reference, options[:billing_address], options) + add_purchase_data(xml, money, true, options) + add_creditcard(xml, payment_method_or_reference) + end + end + + # Where we actually build the full SOAP request using builder + def build_request(body, options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! 's:Envelope', {'xmlns:s' => 'http://schemas.xmlsoap.org/soap/envelope/'} do + xml.tag! 's:Header' do + xml.tag! 'wsse:Security', {'s:mustUnderstand' => '1', 'xmlns:wsse' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'} do + xml.tag! 'wsse:UsernameToken' do + xml.tag! 'wsse:Username', @options[:login] + xml.tag! 'wsse:Password', @options[:password], 'Type' => 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText' + end + end + end + xml.tag! 's:Body', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do + xml.tag! 'requestMessage', {'xmlns' => "urn:schemas-cybersource-com:transaction-data-#{XSD_VERSION}"} do + add_merchant_data(xml, options) + xml << body + end + end + end + xml.target! + end + + # Contact CyberSource, make the SOAP request, and parse the reply into a + # Response object + def commit(request, options) + response = parse(ssl_post(test? ? self.test_url : self.live_url, build_request(request, options))) + + success = response[:decision] == "ACCEPT" + message = @@response_codes[('r' + response[:reasonCode]).to_sym] rescue response[:message] + authorization = success ? [ options[:order_id], response[:requestID], response[:requestToken] ].compact.join(";") : nil + + Response.new(success, message, response, + :test => test?, + :authorization => authorization, + :avs_result => { :code => response[:avsCode] }, + :cvv_result => response[:cvCode] + ) + end + + # Parse the SOAP response + # Technique inspired by the Paypal Gateway + def parse(xml) + reply = {} + xml = REXML::Document.new(xml) + if root = REXML::XPath.first(xml, "//c:replyMessage") + root.elements.to_a.each do |node| + case node.name + when 'c:reasonCode' + reply[:message] = reply(node.text) + else + parse_element(reply, node) + end + end + elsif root = REXML::XPath.first(xml, "//soap:Fault") + parse_element(reply, root) + reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}" + end + return reply + end + + def parse_element(reply, node) + if node.has_elements? + node.elements.each{|e| parse_element(reply, e) } + else + if node.parent.name =~ /item/ + parent = node.parent.name + (node.parent.attributes["id"] ? "_" + node.parent.attributes["id"] : '') + reply[(parent + '_' + node.name).to_sym] = node.text + else + reply[node.name.to_sym] = node.text + end + end + return reply + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/data_cash.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/data_cash.rb new file mode 100644 index 000000000..2c62302dd --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/data_cash.rb @@ -0,0 +1,591 @@ +module ActiveMerchant + module Billing + class DataCashGateway < Gateway + self.default_currency = 'GBP' + self.supported_countries = ['GB'] + + # From the DataCash docs; Page 13, the following cards are + # usable: + # American Express, ATM, Carte Blanche, Diners Club, Discover, + # EnRoute, GE Capital, JCB, Laser, Maestro, Mastercard, Solo, + # Switch, Visa, Visa Delta, VISA Electron, Visa Purchasing + # + # Note continuous authority is only supported for :visa, :master and :american_express card types + self.supported_cardtypes = [ :visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :switch, :solo, :laser ] + + self.homepage_url = 'http://www.datacash.com/' + self.display_name = 'DataCash' + + # Datacash server URLs + self.test_url = 'https://testserver.datacash.com/Transaction' + self.live_url = 'https://mars.transaction.datacash.com/Transaction' + + # Different Card Transaction Types + AUTH_TYPE = 'auth' + CANCEL_TYPE = 'cancel' + FULFILL_TYPE = 'fulfill' + PRE_TYPE = 'pre' + REFUND_TYPE = 'refund' + TRANSACTION_REFUND_TYPE = 'txn_refund' + + # Constant strings for use in the ExtendedPolicy complex element for + # CV2 checks + POLICY_ACCEPT = 'accept' + POLICY_REJECT = 'reject' + + # Datacash success code + DATACASH_SUCCESS = '1' + + # Creates a new DataCashGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The Datacash account login. + # * :password -- The Datacash account password. + # * :test => +true+ or +false+ -- Use the test or live Datacash url. + # + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Perform a purchase, which is essentially an authorization and capture in a single operation. + # + # ==== Parameters + # * money The amount to be authorized as an Integer value in cents. + # * authorization_or_credit_card:: The continuous authority reference or CreditCard details for the transaction. + # * options A hash of optional parameters. + # * :order_id A unique reference for this order (corresponds to merchantreference in datacash documentation) + # * :set_up_continuous_authority + # Set to true to set up a recurring historic transaction account be set up. + # Only supported for :visa, :master and :american_express card types + # See http://www.datacash.com/services/recurring/historic.php for more details of historic transactions. + # * :address:: billing address for card + # + # The continuous authority reference will be available in response#params['ca_reference'] if you have requested one + def purchase(money, authorization_or_credit_card, options = {}) + requires!(options, :order_id) + + if authorization_or_credit_card.is_a?(String) + request = build_purchase_or_authorization_request_with_continuous_authority_reference_request(AUTH_TYPE, money, authorization_or_credit_card, options) + else + request = build_purchase_or_authorization_request_with_credit_card_request(AUTH_TYPE, money, authorization_or_credit_card, options) + end + + commit(request) + end + + # Performs an authorization, which reserves the funds on the customer's credit card, but does not + # charge the card. + # + # ==== Parameters + # + # * money The amount to be authorized as an Integer value in cents. + # * authorization_or_credit_card:: The continuous authority reference or CreditCard details for the transaction. + # * options A hash of optional parameters. + # * :order_id A unique reference for this order (corresponds to merchantreference in datacash documentation) + # * :set_up_continuous_authority:: + # Set to true to set up a recurring historic transaction account be set up. + # Only supported for :visa, :master and :american_express card types + # See http://www.datacash.com/services/recurring/historic.php for more details of historic transactions. + # * :address:: billing address for card + # + # The continuous authority reference will be available in response#params['ca_reference'] if you have requested one + def authorize(money, authorization_or_credit_card, options = {}) + requires!(options, :order_id) + + if authorization_or_credit_card.is_a?(String) + request = build_purchase_or_authorization_request_with_continuous_authority_reference_request(AUTH_TYPE, money, authorization_or_credit_card, options) + else + request = build_purchase_or_authorization_request_with_credit_card_request(PRE_TYPE, money, authorization_or_credit_card, options) + end + + commit(request) + end + + # Captures the funds from an authorized transaction. + # + # ==== Parameters + # + # * money -- The amount to be captured as anInteger value in cents. + # * authorization -- The authorization returned from the previous authorize request. + def capture(money, authorization, options = {}) + commit(build_void_or_capture_request(FULFILL_TYPE, money, authorization, options)) + end + + # Void a previous transaction + # + # ==== Parameters + # + # * authorization - The authorization returned from the previous authorize request. + def void(authorization, options = {}) + request = build_void_or_capture_request(CANCEL_TYPE, nil, authorization, options) + + commit(request) + end + + # Refund to a card + # + # ==== Parameters + # + # * money The amount to be refunded as an Integer value in cents. Set to nil for a full refund on existing transaction. + # * reference_or_credit_card The credit card you want to refund OR the datacash_reference for the existing transaction you are refunding + # * options Are ignored when refunding via reference to an existing transaction, otherwise + # * :order_id A unique reference for this order (corresponds to merchantreference in datacash documentation) + # * :address:: billing address for card + def credit(money, reference_or_credit_card, options = {}) + if reference_or_credit_card.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, reference_or_credit_card) + else + request = build_refund_request(money, reference_or_credit_card, options) + commit(request) + end + end + + def refund(money, reference, options = {}) + commit(build_transaction_refund_request(money, reference)) + end + + private + # Create the xml document for a 'cancel' or 'fulfill' transaction. + # + # Final XML should look like: + # + # + # 99000001 + # ****** + # + # + # + # 25.00 + # + # + # 4900200000000001 + # A6 + # fulfill + # + # + # + # + # Parameters: + # * type must be FULFILL_TYPE or CANCEL_TYPE + # * money - optional - Integer value in cents + # * authorization - the Datacash authorization from a previous succesful authorize transaction + # * options + # * order_id - A unique reference for the transaction + # + # Returns: + # -Builder xml document + # + def build_void_or_capture_request(type, money, authorization, options) + reference, auth_code, ca_reference = authorization.to_s.split(';') + + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! :Request do + add_authentication(xml) + + xml.tag! :Transaction do + xml.tag! :HistoricTxn do + xml.tag! :reference, reference + xml.tag! :authcode, auth_code + xml.tag! :method, type + end + + if money + xml.tag! :TxnDetails do + xml.tag! :merchantreference, format_reference_number(options[:order_id]) + xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money) + end + end + end + end + xml.target! + end + + # Create the xml document for an 'auth' or 'pre' transaction with a credit card + # + # Final XML should look like: + # + # + # + # 99000000 + # ******* + # + # + # + # 123456 + # 10.00 + # + # + # + # 4444********1111 + # 03/04 + # + # Flat 7 + # 89 Jumble + # Street + # Mytown + # AV12FR + # 123 + # + # + # + # + # + # + # + # auth + # + # + # + # + # Parameters: + # -type must be 'auth' or 'pre' + # -money - A money object with the price and currency + # -credit_card - The credit_card details to use + # -options: + # :order_id is the merchant reference number + # :billing_address is the billing address for the cc + # :address is the delivery address + # + # Returns: + # -xml: Builder document containing the markup + # + def build_purchase_or_authorization_request_with_credit_card_request(type, money, credit_card, options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! :Request do + add_authentication(xml) + + xml.tag! :Transaction do + if options[:set_up_continuous_authority] + xml.tag! :ContAuthTxn, :type => 'setup' + end + xml.tag! :CardTxn do + xml.tag! :method, type + add_credit_card(xml, credit_card, options[:billing_address]) + end + xml.tag! :TxnDetails do + xml.tag! :merchantreference, format_reference_number(options[:order_id]) + xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money) + end + end + end + xml.target! + end + + # Create the xml document for an 'auth' or 'pre' transaction with + # continuous authorization + # + # Final XML should look like: + # + # + # + # + # + # 3851231 + # cont_auth + # 18.50 + # + # + # 4500200040925092 + # auth + # + # + # + # 99000001 + # mypasswd + # + # + # + # Parameters: + # -type must be 'auth' or 'pre' + # -money - A money object with the price and currency + # -authorization - The authorization containing a continuous authority reference previously set up on a credit card + # -options: + # :order_id is the merchant reference number + # + # Returns: + # -xml: Builder document containing the markup + # + def build_purchase_or_authorization_request_with_continuous_authority_reference_request(type, money, authorization, options) + reference, auth_code, ca_reference = authorization.to_s.split(';') + raise ArgumentError, "The continuous authority reference is required for continuous authority transactions" if ca_reference.blank? + + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! :Request do + add_authentication(xml) + xml.tag! :Transaction do + xml.tag! :ContAuthTxn, :type => 'historic' + xml.tag! :HistoricTxn do + xml.tag! :reference, ca_reference + xml.tag! :method, type + end + xml.tag! :TxnDetails do + xml.tag! :merchantreference, format_reference_number(options[:order_id]) + xml.tag! :amount, amount(money), :currency => options[:currency] || currency(money) + xml.tag! :capturemethod, 'cont_auth' + end + end + end + xml.target! + end + + # Create the xml document for a full or partial refund transaction with + # + # Final XML should look like: + # + # + # + # 99000001 + # ******* + # + # + # + # txn_refund + # 12345678 + # + # + # 10.00 + # + # + # + # + def build_transaction_refund_request(money, reference) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! :Request do + add_authentication(xml) + xml.tag! :Transaction do + xml.tag! :HistoricTxn do + xml.tag! :reference, reference + xml.tag! :method, TRANSACTION_REFUND_TYPE + end + unless money.nil? + xml.tag! :TxnDetails do + xml.tag! :amount, amount(money) + end + end + end + end + xml.target! + end + + # Create the xml document for a full or partial refund with + # + # Final XML should look like: + # + # + # + # 99000001 + # ***** + # + # + # + # + # 633300*********1 + # 04/06 + # 01/04 + # + # refund + # + # + # 1000001 + # 95.99 + # + # + # + def build_refund_request(money, credit_card, options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! :Request do + add_authentication(xml) + xml.tag! :Transaction do + xml.tag! :CardTxn do + xml.tag! :method, REFUND_TYPE + add_credit_card(xml, credit_card, options[:billing_address]) + end + xml.tag! :TxnDetails do + xml.tag! :merchantreference, format_reference_number(options[:order_id]) + xml.tag! :amount, amount(money) + end + end + end + xml.target! + end + + + # Adds the authentication element to the passed builder xml doc + # + # Parameters: + # -xml: Builder document that is being built up + # + # Returns: + # -none: The results is stored in the passed xml document + # + def add_authentication(xml) + xml.tag! :Authentication do + xml.tag! :client, @options[:login] + xml.tag! :password, @options[:password] + end + end + + # Add credit_card details to the passed XML Builder doc + # + # Parameters: + # -xml: Builder document that is being built up + # -credit_card: ActiveMerchant::Billing::CreditCard object + # -billing_address: Hash containing all of the billing address details + # + # Returns: + # -none: The results is stored in the passed xml document + # + def add_credit_card(xml, credit_card, address) + + xml.tag! :Card do + + # DataCash calls the CC number 'pan' + xml.tag! :pan, credit_card.number + xml.tag! :expirydate, format_date(credit_card.month, credit_card.year) + + # optional values - for Solo etc + if [ 'switch', 'solo' ].include?(card_brand(credit_card).to_s) + + xml.tag! :issuenumber, credit_card.issue_number unless credit_card.issue_number.blank? + + if !credit_card.start_month.blank? && !credit_card.start_year.blank? + xml.tag! :startdate, format_date(credit_card.start_month, credit_card.start_year) + end + end + + xml.tag! :Cv2Avs do + xml.tag! :cv2, credit_card.verification_value if credit_card.verification_value? + if address + xml.tag! :street_address1, address[:address1] unless address[:address1].blank? + xml.tag! :street_address2, address[:address2] unless address[:address2].blank? + xml.tag! :street_address3, address[:address3] unless address[:address3].blank? + xml.tag! :street_address4, address[:address4] unless address[:address4].blank? + xml.tag! :postcode, address[:zip] unless address[:zip].blank? + end + + # The ExtendedPolicy defines what to do when the passed data + # matches, or not... + # + # All of the following elements MUST be present for the + # xml to be valid (or can drop the ExtendedPolicy and use + # a predefined one + xml.tag! :ExtendedPolicy do + xml.tag! :cv2_policy, + :notprovided => POLICY_REJECT, + :notchecked => POLICY_REJECT, + :matched => POLICY_ACCEPT, + :notmatched => POLICY_REJECT, + :partialmatch => POLICY_REJECT + xml.tag! :postcode_policy, + :notprovided => POLICY_ACCEPT, + :notchecked => POLICY_ACCEPT, + :matched => POLICY_ACCEPT, + :notmatched => POLICY_REJECT, + :partialmatch => POLICY_ACCEPT + xml.tag! :address_policy, + :notprovided => POLICY_ACCEPT, + :notchecked => POLICY_ACCEPT, + :matched => POLICY_ACCEPT, + :notmatched => POLICY_REJECT, + :partialmatch => POLICY_ACCEPT + end + end + end + end + + # Send the passed data to DataCash for processing + # + # Parameters: + # -request: The XML data that is to be sent to Datacash + # + # Returns: + # - ActiveMerchant::Billing::Response object + # + def commit(request) + response = parse(ssl_post(test? ? self.test_url : self.live_url, request)) + + Response.new(response[:status] == DATACASH_SUCCESS, response[:reason], response, + :test => test?, + :authorization => "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}" + ) + end + + # Returns a date string in the format Datacash expects + # + # Parameters: + # -month: integer, the month + # -year: integer, the year + # + # Returns: + # -String: date in MM/YY format + # + def format_date(month, year) + "#{format(month,:two_digits)}/#{format(year, :two_digits)}" + end + + # Parse the datacash response and create a Response object + # + # Parameters: + # -body: The XML returned from Datacash + # + # Returns: + # -a hash with all of the values returned in the Datacash XML response + # + def parse(body) + + response = {} + xml = REXML::Document.new(body) + root = REXML::XPath.first(xml, "//Response") + + root.elements.to_a.each do |node| + parse_element(response, node) + end + + response + end + + # Parse an xml element + # + # Parameters: + # -response: The hash that the values are being returned in + # -node: The node that is currently being read + # + # Returns: + # - none (results are stored in the passed hash) + def parse_element(response, node) + if node.has_elements? + node.elements.each{|e| parse_element(response, e) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + def format_reference_number(number) + number.to_s.gsub(/[^A-Za-z0-9]/, '').rjust(6, "0").first(30) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/efsnet.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/efsnet.rb new file mode 100644 index 000000000..fcf28d8e0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/efsnet.rb @@ -0,0 +1,230 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + class EfsnetGateway < Gateway + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.concordefsnet.com/' + self.display_name = 'Efsnet' + + self.test_url = 'https://testefsnet.concordebiz.com/efsnet.dll' + self.live_url = 'https://efsnet.concordebiz.com/efsnet.dll' + + # login is your Store ID + # password is your Store Key + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, creditcard, options = {}) + request = build_credit_card_request(money, creditcard, options) + commit(:credit_card_authorize, request) + end + + def purchase(money, creditcard, options = {}) + request = build_credit_card_request(money, creditcard, options) + commit(:credit_card_charge, request) + end + + def capture(money, identification, options = {}) + request = build_refund_or_settle_request(money, identification, options) + commit(:credit_card_settle, request) + end + + def credit(money, identification_or_credit_card, options = {}) + if identification_or_credit_card.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + # Perform authorization reversal + refund(money, identification_or_credit_card, options) + else + # Perform credit + request = build_credit_card_request(money, identification_or_credit_card, options) + commit(:credit_card_credit, request) + end + end + + def refund(money, reference, options = {}) + # Perform authorization reversal + request = build_refund_or_settle_request(money, reference, options) + commit(:credit_card_refund, request) + end + + def void(identification, options = {}) + requires!(options, :order_id) + original_transaction_id, original_transaction_amount = identification.split(";") + commit(:void_transaction, {:reference_number => format_reference_number(options[:order_id]), :transaction_id => original_transaction_id}) + end + + def voice_authorize(money, authorization_code, creditcard, options = {}) + options[:authorization_number] = authorization_code + request = build_credit_card_request(money, creditcard, options) + commit(:credit_card_voice_authorize, request) + end + + def force(money, authorization_code, creditcard, options = {}) + options[:authorization_number] = authorization_code + request = build_credit_card_request(money, creditcard, options) + commit(:credit_card_capture, request) + end + + def system_check + commit(:system_check, {}) + end + + private + + def build_refund_or_settle_request(money, identification, options = {}) + original_transaction_id, original_transaction_amount = identification.split(";") + + requires!(options, :order_id) + + post = { + :reference_number => format_reference_number(options[:order_id]), + :transaction_amount => amount(money), + :original_transaction_amount => original_transaction_amount, + :original_transaction_id => original_transaction_id, + :client_ip_address => options[:ip] + } + end + + def build_credit_card_request(money, creditcard, options = {}) + requires!(options, :order_id) + + post = { + :reference_number => format_reference_number(options[:order_id]), + :authorization_number => options[:authorization_number], + :transaction_amount => amount(money), + :client_ip_address => options[:ip] + + } + add_creditcard(post,creditcard) + add_address(post,options) + post + end + + def format_reference_number(number) + number.to_s.slice(0,12) + end + + def add_address(post,options) + if address = options[:billing_address] || options[:address] + if address[:address2] + post[:billing_address] = address[:address1].to_s << ' ' << address[:address2].to_s + else + post[:billing_address] = address[:address1].to_s + end + post[:billing_city] = address[:city].to_s + post[:billing_state] = address[:state].blank? ? 'n/a' : address[:state] + post[:billing_postal_code] = address[:zip].to_s + post[:billing_country] = address[:country].to_s + end + + if address = options[:shipping_address] + if address[:address2] + post[:shipping_address] = address[:address1].to_s << ' ' << address[:address2].to_s + else + post[:shipping_address] = address[:address1].to_s + end + post[:shipping_city] = address[:city].to_s + post[:shipping_state] = address[:state].blank? ? 'n/a' : address[:state] + post[:shipping_postal_code] = address[:zip].to_s + post[:shipping_country] = address[:country].to_s + end + end + + def add_creditcard(post, creditcard) + post[:billing_name] = creditcard.name if creditcard.name + post[:account_number] = creditcard.number + post[:card_verification_value] = creditcard.verification_value if creditcard.verification_value? + post[:expiration_month] = sprintf("%.2i", creditcard.month) + post[:expiration_year] = sprintf("%.4i", creditcard.year)[-2..-1] + end + + + def commit(action, parameters) + response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(action, parameters), 'Content-Type' => 'text/xml')) + + Response.new(success?(response), message_from(response[:result_message]), response, + :test => test?, + :authorization => authorization_from(response, parameters), + :avs_result => { :code => response[:avs_response_code] }, + :cvv_result => response[:cvv_response_code] + ) + end + + def success?(response) + response[:response_code] == '0' + end + + def authorization_from(response, params) + [ response[:transaction_id], params[:transaction_amount] ].compact.join(';') + end + + def parse(xml) + response = {} + + xml = REXML::Document.new(xml) + + xml.elements.each('//Reply//TransactionReply/*') do |node| + + response[node.name.underscore.to_sym] = normalize(node.text) + + end unless xml.root.nil? + + response + end + + def post_data(action, parameters = {}) + xml = REXML::Document.new("") + root = xml.add_element("Request") + root.attributes["StoreID"] = options[:login] + root.attributes["StoreKey"] = options[:password] + root.attributes["ApplicationID"] = 'ot 1.0' + transaction = root.add_element(action.to_s.camelize) + + actions[action].each do |key| + transaction.add_element(key).text = parameters[key.underscore.to_sym] unless parameters[key.underscore.to_sym].blank? + end + + xml.to_s + end + + def message_from(message) + return 'Unspecified error' if message.blank? + message.gsub(/[^\w]/, ' ').split.join(" ").capitalize + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def actions + ACTIONS + end + + CREDIT_CARD_FIELDS = %w(AuthorizationNumber ClientIpAddress BillingAddress BillingCity BillingState BillingPostalCode BillingCountry BillingName CardVerificationValue ExpirationMonth ExpirationYear ReferenceNumber TransactionAmount AccountNumber ) + + ACTIONS = { + :credit_card_authorize => CREDIT_CARD_FIELDS, + :credit_card_charge => CREDIT_CARD_FIELDS, + :credit_card_voice_authorize => CREDIT_CARD_FIELDS, + :credit_card_capture => CREDIT_CARD_FIELDS, + :credit_card_credit => CREDIT_CARD_FIELDS + ["OriginalTransactionAmount"], + :credit_card_refund => %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress), + :void_transaction => %w(ReferenceNumber TransactionID), + :credit_card_settle => %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress), + :system_check => %w(SystemCheck), + } + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/elavon.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/elavon.rb new file mode 100644 index 000000000..ddc4559b9 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/elavon.rb @@ -0,0 +1,312 @@ +require File.dirname(__FILE__) + '/viaklix' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # = Elavon Virtual Merchant Gateway + # + # == Example use: + # + # gateway = ActiveMerchant::Billing::ElavonGateway.new( + # :login => "my_virtual_merchant_id", + # :password => "my_virtual_merchant_pin", + # :user => "my_virtual_merchant_user_id" # optional + # ) + # + # # set up credit card obj as in main ActiveMerchant example + # creditcard = ActiveMerchant::Billing::CreditCard.new( + # :type => 'visa', + # :number => '41111111111111111', + # :month => 10, + # :year => 2011, + # :first_name => 'Bob', + # :last_name => 'Bobsen' + # ) + # + # # run request + # response = gateway.purchase(1000, creditcard) # authorize and capture 10 USD + # + # puts response.success? # Check whether the transaction was successful + # puts response.message # Retrieve the message returned by Elavon + # puts response.authorization # Retrieve the unique transaction ID returned by Elavon + # + class ElavonGateway < Gateway + class_attribute :test_url, :live_url, :delimiter, :actions + + self.test_url = 'https://demo.myvirtualmerchant.com/VirtualMerchantDemo/process.do' + self.live_url = 'https://www.myvirtualmerchant.com/VirtualMerchant/process.do' + + self.display_name = 'Elavon MyVirtualMerchant' + self.supported_countries = ['US', 'CA'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.elavon.com/' + + self.delimiter = "\n" + self.actions = { + :purchase => 'CCSALE', + :credit => 'CCCREDIT', + :refund => 'CCRETURN', + :authorize => 'CCAUTHONLY', + :capture => 'CCFORCE', + :void => 'CCVOID' + } + + # Initialize the Gateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- Merchant ID + # * :password -- PIN + # * :user -- Specify a subuser of the account (optional) + # * :test => +true+ or +false+ -- Force test transactions + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Make a purchase + def purchase(money, creditcard, options = {}) + form = {} + add_salestax(form, options) + add_invoice(form, options) + add_creditcard(form, creditcard) + add_address(form, options) + add_customer_data(form, options) + add_test_mode(form, options) + commit(:purchase, money, form) + end + + # Authorize a credit card for a given amount. + # + # ==== Parameters + # * money - The amount to be authorized as an Integer value in cents. + # * credit_card - The CreditCard details for the transaction. + # * options + # * :billing_address - The billing address for the cardholder. + def authorize(money, creditcard, options = {}) + form = {} + add_salestax(form, options) + add_invoice(form, options) + add_creditcard(form, creditcard) + add_address(form, options) + add_customer_data(form, options) + add_test_mode(form, options) + commit(:authorize, money, form) + end + + # Capture authorized funds from a credit card. + # + # ==== Parameters + # * money - The amount to be captured as an Integer value in cents. + # * authorization - The approval code returned from the initial authorization. + # * options + # * :credit_card - The CreditCard details from the initial transaction (required). + def capture(money, authorization, options = {}) + requires!(options, :credit_card) + + form = {} + add_salestax(form, options) + add_approval_code(form, authorization) + add_invoice(form, options) + add_creditcard(form, options[:credit_card]) + add_customer_data(form, options) + add_test_mode(form, options) + commit(:capture, money, form) + end + + # Refund a transaction. + # + # This transaction indicates to the gateway that + # money should flow from the merchant to the customer. + # + # ==== Parameters + # + # * money -- The amount to be credited to the customer as an Integer value in cents. + # * identification -- The ID of the original transaction against which the refund is being issued. + # * options -- A hash of parameters. + def refund(money, identification, options = {}) + form = {} + add_txn_id(form, identification) + add_test_mode(form, options) + commit(:refund, money, form) + end + + # Void a previous transaction + # + # ==== Parameters + # + # * authorization - The authorization returned from the previous request. + def void(identification, options = {}) + form = {} + add_txn_id(form, identification) + add_test_mode(form, options) + commit(:void, nil, form) + end + + # Make a credit to a card. Use the refund method if you'd like to credit using + # previous transaction + # + # ==== Parameters + # * money - The amount to be credited as an Integer value in cents. + # * creditcard - The credit card to be credited. + # * options + def credit(money, creditcard, options = {}) + if creditcard.is_a?(String) + raise ArgumentError, "Reference credits are not supported. Please supply the original credit card or use the #refund method." + end + + form = {} + add_invoice(form, options) + add_creditcard(form, creditcard) + add_address(form, options) + add_customer_data(form, options) + add_test_mode(form, options) + commit(:credit, money, form) + end + + + private + def add_invoice(form,options) + form[:invoice_number] = (options[:order_id] || options[:invoice]).to_s.slice(0, 10) + form[:description] = options[:description].to_s.slice(0, 255) + end + + def add_approval_code(form, authorization) + form[:approval_code] = authorization.split(';').first + end + + def add_txn_id(form, authorization) + form[:txn_id] = authorization.split(';').last + end + + def authorization_from(response) + [response['approval_code'], response['txn_id']].join(';') + end + + def add_creditcard(form, creditcard) + form[:card_number] = creditcard.number + form[:exp_date] = expdate(creditcard) + + if creditcard.verification_value? + add_verification_value(form, creditcard) + end + + form[:first_name] = creditcard.first_name.to_s.slice(0, 20) + form[:last_name] = creditcard.last_name.to_s.slice(0, 30) + end + + def add_verification_value(form, creditcard) + form[:cvv2cvc2] = creditcard.verification_value + form[:cvv2cvc2_indicator] = '1' + end + + def add_customer_data(form, options) + form[:email] = options[:email].to_s.slice(0, 100) unless options[:email].blank? + form[:customer_code] = options[:customer].to_s.slice(0, 10) unless options[:customer].blank? + end + + def add_salestax(form, options) + form[:salestax] = options[:tax] if options[:tax].present? + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + "#{month}#{year[2..3]}" + end + + def add_address(form,options) + billing_address = options[:billing_address] || options[:address] + + if billing_address + form[:avs_address] = billing_address[:address1].to_s.slice(0, 30) + form[:address2] = billing_address[:address2].to_s.slice(0, 30) + form[:avs_zip] = billing_address[:zip].to_s.slice(0, 10) + form[:city] = billing_address[:city].to_s.slice(0, 30) + form[:state] = billing_address[:state].to_s.slice(0, 10) + form[:company] = billing_address[:company].to_s.slice(0, 50) + form[:phone] = billing_address[:phone].to_s.slice(0, 20) + form[:country] = billing_address[:country].to_s.slice(0, 50) + end + + if shipping_address = options[:shipping_address] + first_name, last_name = parse_first_and_last_name(shipping_address[:name]) + form[:ship_to_first_name] = first_name.to_s.slice(0, 20) + form[:ship_to_last_name] = last_name.to_s.slice(0, 30) + form[:ship_to_address1] = shipping_address[:address1].to_s.slice(0, 30) + form[:ship_to_address2] = shipping_address[:address2].to_s.slice(0, 30) + form[:ship_to_city] = shipping_address[:city].to_s.slice(0, 30) + form[:ship_to_state] = shipping_address[:state].to_s.slice(0, 10) + form[:ship_to_company] = shipping_address[:company].to_s.slice(0, 50) + form[:ship_to_country] = shipping_address[:country].to_s.slice(0, 50) + form[:ship_to_zip] = shipping_address[:zip].to_s.slice(0, 10) + end + end + + def parse_first_and_last_name(value) + name = value.to_s.split(' ') + + last_name = name.pop || '' + first_name = name.join(' ') + [ first_name, last_name ] + end + + def add_test_mode(form, options) + form[:test_mode] = 'TRUE' if options[:test_mode] + end + + def message_from(response) + success?(response) ? response['result_message'] : response['errorMessage'] + end + + def success?(response) + !response.has_key?('errorMessage') + end + + def commit(action, money, parameters) + parameters[:amount] = amount(money) + parameters[:transaction_type] = self.actions[action] + + response = parse( ssl_post(test? ? self.test_url : self.live_url, post_data(parameters)) ) + + Response.new(response['result'] == '0', message_from(response), response, + :test => @options[:test] || test?, + :authorization => authorization_from(response), + :avs_result => { :code => response['avs_response'] }, + :cvv_result => response['cvv2_response'] + ) + end + + def post_data(parameters) + result = preamble + result.merge!(parameters) + result.collect { |key, value| "ssl_#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def preamble + result = { + 'merchant_id' => @options[:login], + 'pin' => @options[:password], + 'show_form' => 'false', + 'result_format' => 'ASCII' + } + + result['user_id'] = @options[:user] unless @options[:user].blank? + result + end + + def parse(msg) + resp = {} + msg.split(self.delimiter).collect{|li| + key, value = li.split("=") + resp[key.strip.gsub(/^ssl_/, '')] = value.to_s.strip + } + resp + end + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/epay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/epay.rb new file mode 100644 index 000000000..ff242f9d9 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/epay.rb @@ -0,0 +1,275 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class EpayGateway < Gateway + API_HOST = 'ssl.ditonlinebetalingssystem.dk' + self.live_url = 'https://' + API_HOST + '/remote/payment' + + self.default_currency = 'DKK' + self.money_format = :cents + self.supported_cardtypes = [:dankort, :forbrugsforeningen, :visa, :master, + :american_express, :diners_club, :jcb, :maestro] + self.supported_countries = ['DK', 'SE', 'NO'] + self.homepage_url = 'http://epay.dk/' + self.display_name = 'ePay' + + CURRENCY_CODES = { + :ADP => '020', :AED => '784', :AFA => '004', :ALL => '008', :AMD => '051', + :ANG => '532', :AOA => '973', :ARS => '032', :AUD => '036', :AWG => '533', + :AZM => '031', :BAM => '977', :BBD => '052', :BDT => '050', :BGL => '100', + :BGN => '975', :BHD => '048', :BIF => '108', :BMD => '060', :BND => '096', + :BOB => '068', :BOV => '984', :BRL => '986', :BSD => '044', :BTN => '064', + :BWP => '072', :BYR => '974', :BZD => '084', :CAD => '124', :CDF => '976', + :CHF => '756', :CLF => '990', :CLP => '152', :CNY => '156', :COP => '170', + :CRC => '188', :CUP => '192', :CVE => '132', :CYP => '196', :CZK => '203', + :DJF => '262', :DKK => '208', :DOP => '214', :DZD => '012', :ECS => '218', + :ECV => '983', :EEK => '233', :EGP => '818', :ERN => '232', :ETB => '230', + :EUR => '978', :FJD => '242', :FKP => '238', :GBP => '826', :GEL => '981', + :GHC => '288', :GIP => '292', :GMD => '270', :GNF => '324', :GTQ => '320', + :GWP => '624', :GYD => '328', :HKD => '344', :HNL => '340', :HRK => '191', + :HTG => '332', :HUF => '348', :IDR => '360', :ILS => '376', :INR => '356', + :IQD => '368', :IRR => '364', :ISK => '352', :JMD => '388', :JOD => '400', + :JPY => '392', :KES => '404', :KGS => '417', :KHR => '116', :KMF => '174', + :KPW => '408', :KRW => '410', :KWD => '414', :KYD => '136', :KZT => '398', + :LAK => '418', :LBP => '422', :LKR => '144', :LRD => '430', :LSL => '426', + :LTL => '440', :LVL => '428', :LYD => '434', :MAD => '504', :MDL => '498', + :MGF => '450', :MKD => '807', :MMK => '104', :MNT => '496', :MOP => '446', + :MRO => '478', :MTL => '470', :MUR => '480', :MVR => '462', :MWK => '454', + :MXN => '484', :MXV => '979', :MYR => '458', :MZM => '508', :NAD => '516', + :NGN => '566', :NIO => '558', :NOK => '578', :NPR => '524', :NZD => '554', + :OMR => '512', :PAB => '590', :PEN => '604', :PGK => '598', :PHP => '608', + :PKR => '586', :PLN => '985', :PYG => '600', :QAR => '634', :ROL => '642', + :RUB => '643', :RUR => '810', :RWF => '646', :SAR => '682', :SBD => '090', + :SCR => '690', :SDD => '736', :SEK => '752', :SGD => '702', :SHP => '654', + :SIT => '705', :SKK => '703', :SLL => '694', :SOS => '706', :SRG => '740', + :STD => '678', :SVC => '222', :SYP => '760', :SZL => '748', :THB => '764', + :TJS => '972', :TMM => '795', :TND => '788', :TOP => '776', :TPE => '626', + :TRL => '792', :TRY => '949', :TTD => '780', :TWD => '901', :TZS => '834', + :UAH => '980', :UGX => '800', :USD => '840', :UYU => '858', :UZS => '860', + :VEB => '862', :VND => '704', :VUV => '548', :XAF => '950', :XCD => '951', + :XOF => '952', :XPF => '953', :YER => '886', :YUM => '891', :ZAR => '710', + :ZMK => '894', :ZWD => '716' + } + + # login: merchant number + # password: referrer url (for authorize authentication) + def initialize(options = {}) + requires!(options, :login) + super + end + + def authorize(money, credit_card_or_reference, options = {}) + post = {} + + add_amount(post, money, options) + add_invoice(post, options) + add_creditcard_or_reference(post, credit_card_or_reference) + add_instant_capture(post, false) + + commit(:authorize, post) + end + + def purchase(money, credit_card_or_reference, options = {}) + post = {} + + add_amount(post, money, options) + add_creditcard_or_reference(post, credit_card_or_reference) + add_invoice(post, options) + add_instant_capture(post, true) + + commit(:authorize, post) + end + + def capture(money, authorization, options = {}) + post = {} + + add_reference(post, authorization) + add_amount_without_currency(post, money) + + commit(:capture, post) + end + + def void(identification, options = {}) + post = {} + + add_reference(post, identification) + + commit(:void, post) + end + + def refund(money, identification, options = {}) + post = {} + + add_amount_without_currency(post, money) + add_reference(post, identification) + + commit(:credit, post) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + private + + def add_amount(post, money, options) + post[:amount] = amount(money) + post[:currency] = CURRENCY_CODES[(options[:currency] || currency(money)).to_sym] + end + + def add_amount_without_currency(post, money) + post[:amount] = amount(money) + end + + def add_reference(post, identification) + post[:transaction] = identification + end + + def add_invoice(post, options) + post[:orderid] = format_order_number(options[:order_id]) + end + + def add_creditcard(post, credit_card) + post[:cardno] = credit_card.number + post[:cvc] = credit_card.verification_value + post[:expmonth] = credit_card.month + post[:expyear] = credit_card.year + end + + def add_creditcard_or_reference(post, credit_card_or_reference) + if credit_card_or_reference.respond_to?(:number) + add_creditcard(post, credit_card_or_reference) + else + add_reference(post, credit_card_or_reference.to_s) + end + end + + def add_instant_capture(post, option) + post[:instantcapture] = option ? 1 : 0 + end + + def commit(action, params) + response = send("do_#{action}", params) + + if action == :authorize + Response.new response['accept'].to_i == 1, + response['errortext'], + response, + :test => test?, + :authorization => response['tid'] + else + Response.new response['result'] == 'true', + messages(response['epay'], response['pbs']), + response, + :test => test?, + :authorization => params[:transaction] + end + end + + def messages(epay, pbs = nil) + response = "ePay: #{epay}" + response << " PBS: #{pbs}" if pbs + return response + end + + def soap_post(method, params) + data = xml_builder(params, method) + headers = make_headers(data, method) + REXML::Document.new(ssl_post('https://' + API_HOST + '/remote/payment.asmx', data, headers)) + end + + def do_authorize(params) + headers = {} + headers['Referer'] = (options[:password] || "activemerchant.org") + + response = raw_ssl_request(:post, 'https://' + API_HOST + '/auth/default.aspx', authorize_post_data(params), headers) + + # Authorize gives the response back by redirecting with the values in + # the URL query + if location = response['Location'] + query = CGI::parse(URI.parse(location.gsub(' ', '%20')).query) + else + return { + 'accept' => '0', + 'errortext' => 'ePay did not respond as expected. Please try again.', + 'response_code' => response.code, + 'response_message' => response.message + } + end + + result = {} + query.each_pair do |k,v| + result[k] = v.is_a?(Array) && v.size == 1 ? v[0] : v # make values like ['v'] into 'v' + end + result + end + + def do_capture(params) + response = soap_post('capture', params) + { + 'result' => response.elements['//captureResponse/captureResult'].text, + 'pbs' => response.elements['//captureResponse/pbsResponse'].text, + 'epay' => response.elements['//captureResponse/epayresponse'].text + } + end + + def do_credit(params) + response = soap_post('credit', params) + { + 'result' => response.elements['//creditResponse/creditResult'].text, + 'pbs' => response.elements['//creditResponse/pbsresponse'].text, + 'epay' => response.elements['//creditResponse/epayresponse'].text + } + end + + def do_void(params) + response = soap_post('delete', params) + { + 'result' => response.elements['//deleteResponse/deleteResult'].text, + 'epay' => response.elements['//deleteResponse/epayresponse'].text + } + end + + def make_headers(data, soap_call) + { + 'Content-Type' => 'text/xml; charset=utf-8', + 'Host' => API_HOST, + 'Content-Length' => data.size.to_s, + 'SOAPAction' => self.live_url + '/' + soap_call + } + end + + def xml_builder(params, soap_call) + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct! + xml.tag! 'soap:Envelope', { 'xmlns:xsi' => 'http://schemas.xmlsoap.org/soap/envelope/', + 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', + 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/' } do + xml.tag! 'soap:Body' do + xml.tag! soap_call, { 'xmlns' => self.live_url } do + xml.tag! 'merchantnumber', @options[:login] + xml.tag! 'transactionid', params[:transaction] + xml.tag! 'amount', params[:amount].to_s if soap_call != 'delete' + end + end + end + xml.target! + end + + def authorize_post_data(params = {}) + params[:language] = '2' + params[:cms] = 'activemerchant' + params[:accepturl] = 'https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?accept=1' + params[:declineurl] = 'https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?decline=1' + params[:merchantnumber] = @options[:login] + + params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + # Limited to 20 digits max + def format_order_number(number) + number.to_s.gsub(/[^\w_]/, '').rjust(4, "0")[0...20] + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/evo_ca.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/evo_ca.rb new file mode 100644 index 000000000..c2f76883e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/evo_ca.rb @@ -0,0 +1,308 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # === EVO Canada payment gateway. + # + # EVO returns two different identifiers for most transactions, the + # +authcode+ and the +transactionid+. Since +transactionid+ is used more + # often (i.e. for {#capture}, {#refund}, {#void} and {#update}) we store it in the + # Response#authorization attribute. The +authcode+ from the merchant + # account is accessible via {Response#params}. + # + # Two different but related response messages are also returned from EVO. + # The message indicated by EVO's response_code parameter is returned as + # {Response#message} (Those messages can be seen in the {MESSAGES} hash.) + # The other, shorter message is available via {Response#params}. + # + # It's recommended to save the contents of the {Response#params} in your + # transaction log for future reference. + # + # === Sample Use + # + # gateway = ActiveMerchant::Billing::EvoCaGateway.new(username: 'demo', password: 'password') + # + # response = gateway.authorize(1000, credit_card, options) + # + # puts response.authorization # the transactionid + # puts response.params['authcode'] # the authcode from the merchant account + # puts response.message # the 'pretty' response message + # puts response.params['responsetext'] # the 'terse' response message + # + # gateway.capture(1000, response.authorization) + # gateway.update(response.authorization, shipping_carrier: 'fedex') + # gateway.refund(500, response.authorization) + # + class EvoCaGateway < Gateway + self.test_url = 'https://secure.evoepay.com/api/transact.php' + self.live_url = 'https://secure.evoepay.com/api/transact.php' + + self.supported_countries = ['CA'] + self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover] + self.money_format = :dollars + self.homepage_url = 'http://www.evocanada.com/' + self.display_name = 'EVO Canada' + + APPROVED, DECLINED, ERROR = 1, 2, 3 + + MESSAGES = { + 100 => 'Transaction was approved', + 200 => 'Transaction was declined by processor', + 201 => 'Do not honor', + 202 => 'Insufficient funds', + 203 => 'Over limit', + 204 => 'Transaction not allowed', + 220 => 'Incorrect payment data', + 221 => 'No such card issuer', + 222 => 'No card number on file with issuer', + 223 => 'Expired card', + 224 => 'Invalid expiration date', + 225 => 'Invalid card security code', + 240 => 'Call issuer for futher information', + 250 => 'Pick up card', + 251 => 'Lost card', + 252 => 'Stolen card', + 253 => 'Fraudulant card', + 260 => 'Declined with further instructions available', + 261 => 'Declined - stop all recurring payments', + 262 => 'Declined - stop this recurring program', + 263 => 'Declined - updated cardholder data available', + 264 => 'Declined - retry in a few days', + 300 => 'Transaction was rejected by gateway', + 400 => 'Transaction error returned by processor', + 410 => 'Invalid merchant configuration', + 411 => 'Merchant account is inactive', + 420 => 'Communication error', + 421 => 'Communication error with issuer', + 430 => 'Duplicate transaction at processor', + 440 => 'Processor format error', + 441 => 'Invalid transaction information', + 460 => 'Processor feature not available', + 461 => 'Unsupported card type' + } + + # This gateway requires that a valid username and password be passed + # in the +options+ hash. + # + # === Required Options + # + # * :username + # * :password + def initialize(options = {}) + requires!(options, :username, :password) + super + end + + # Transaction sales are submitted and immediately flagged for settlement. + # These transactions will automatically be settled. + # + # Payment source can be either a {CreditCard} or {Check}. + # + # === Additional Options + # In addition to the standard options, this gateway supports + # + # * :tracking_number - Shipping tracking number + # * :shipping_carrier - ups/fedex/dhl/usps + # * :po_number - Purchase order + # * :tax - Tax amount + # * :shipping - Shipping cost + def purchase(money, credit_card_or_check, options = {}) + post = {} + add_invoice(post, options) + add_order(post, options) + add_paymentmethod(post, credit_card_or_check) + add_address(post, options) + add_customer_data(post, options) + commit('sale', money, post) + end + + # Transaction authorizations are authorized immediately but are not + # flagged for settlement. These transactions must be flagged for + # settlement using the _capture_ transaction type. Authorizations + # typically remain activate for three to seven business days. + # + # Payment source must be a {CreditCard}. + def authorize(money, credit_card, options = {}) + post = {} + add_invoice(post, options) + add_order(post, options) + add_paymentmethod(post, credit_card) + add_address(post, options) + add_customer_data(post, options) + commit('auth', money, post) + end + + # Transaction captures flag existing _authorizations_ for settlement. Only + # authorizations can be captured. Captures can be submitted for an amount + # equal to or less than the original authorization. + # + # The authorization parameter is the transaction ID, retrieved + # from Response#authorization. See EvoCaGateway#purchase for the + # options. + def capture(money, authorization, options = {}) + post = { + :amount => amount(money), + :transactionid => authorization + } + add_order(post, options) + commit('capture', money, post) + end + + # Transaction refunds will reverse a previously settled transaction. If + # the transaction has not been settled, it must be _voided_ instead of + # refunded. + # + # The identification parameter is the transaction ID, retrieved + # from {Response#authorization}. + def refund(money, identification) + post = {:transactionid => identification} + commit('refund', money, post) + end + + # Transaction credits apply a negative amount to the cardholder's card. + # In most situations credits are disabled as transaction refunds should + # be used instead. + # + # Note that this is different from a {#refund} (which is usually what + # you'll be looking for). + def credit(money, credit_card, options = {}) + post = {} + add_invoice(post, options) + add_order(post, options) + add_paymentmethod(post, credit_card) + add_address(post, options) + add_customer_data(post, options) + commit('credit', money, post) + end + + # Transaction voids will cancel an existing sale or captured + # authorization. In addition, non-captured authorizations can be voided to + # prevent any future capture. Voids can only occur if the transaction has + # not been settled. + # + # The identification parameter is the transaction ID, retrieved + # from {Response#authorization}. + def void(identification) + post = {:transactionid => identification} + commit('void', nil, post) + end + + # Transaction updates can be used to update previous transactions with + # specific order information, such as a tracking number and shipping + # carrier. See EvoCaGateway#purchase for options. + # + # The identification parameter is the transaction ID, retrieved + # from {Response#authorization}. + def update(identification, options) + post = {:transactionid => identification} + add_order(post, options) + commit('update', nil, post) + end + + private + + def add_customer_data(post, options) + post[:email] = options[:email] + post[:ipaddress] = options[:ip] + end + + def add_address(post, options) + if address = options[:billing_address] || options[:address] + post[:firstname] = address[:first_name] + post[:lastname] = address[:last_name] + post[:address1] = address[:address1] + post[:address2] = address[:address2] + post[:company] = address[:company] + post[:phone] = address[:phone] + post[:city] = address[:city] + post[:state] = address[:state] + post[:zip] = address[:zip] + post[:country] = address[:country] + end + + if address = options[:shipping_address] + post[:shipping_firstname] = address[:first_name] + post[:shipping_lastname] = address[:last_name] + post[:shipping_address1] = address[:address1] + post[:shipping_address2] = address[:address2] + post[:shipping_company] = address[:company] + post[:shipping_zip] = address[:zip] + post[:shipping_city] = address[:city] + post[:shipping_state] = address[:state] + post[:shipping_country] = address[:country] + end + end + + def add_order(post, options) + post[:orderid] = options[:order_id] + post[:tracking_number] = options[:tracking_number] + post[:shipping_carrier] = options[:shipping_carrier] + end + + def add_invoice(post, options) + post[:orderdescription] = options[:description] + post[:ponumber] = options[:po_number] + post[:shipping] = amount(options[:shipping]) + post[:tax] = amount(options[:tax]) + end + + def add_paymentmethod(post, payment) + if card_brand(payment)=='check' + post[:payment] = 'check' + post[:checkname] = payment.name + post[:checkaba] = payment.routing_number + post[:checkaccount] = payment.account_number + post[:account_holder_type] = payment.account_holder_type + post[:account_type] = payment.account_type + else + post[:payment] = 'creditcard' + post[:ccnumber] = payment.number + post[:ccexp] = "#{format(payment.month, :two_digits)}#{format(payment.year, :two_digits)}" + post[:cvv] = payment.verification_value + end + end + + def parse(body) + fields = {} + CGI::parse(body).each do |k, v| + fields[k.to_s] = v.kind_of?(Array) ? v[0] : v + end + fields + end + + def success?(response) + response['response'].to_i == APPROVED + end + + def commit(action, money, parameters) + parameters[:amount] = amount(money) unless action == 'void' + + data = ssl_post self.live_url, post_data(action, parameters) + response = parse(data) + message = message_from(response) + + Response.new(success?(response), message, response, + :test => test?, + :authorization => response['transactionid'], + :avs_result => { :code => response['avsresponse'] }, + :cvv_result => response['cvvresponse'] + ) + end + + def message_from(response) + MESSAGES.fetch(response['response_code'].to_i, false) || response['message'] + end + + def post_data(action, parameters = {}) + post = {:type => action} + + if test? + post[:username] = 'demo' + post[:password] = 'password' + else + post[:username] = options[:username] + post[:password] = options[:password] + end + post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" unless value.nil? }.compact.join("&") + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway.rb new file mode 100644 index 000000000..e21a1c071 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway.rb @@ -0,0 +1,225 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # Public: For more information on the Eway Gateway please visit their + # {Developers Area}[http://www.eway.com.au/developers/api/direct-payments] + class EwayGateway < Gateway + self.live_url = 'https://www.eway.com.au' + + self.money_format = :cents + self.supported_countries = ['AU'] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club] + self.homepage_url = 'http://www.eway.com.au/' + self.display_name = 'eWAY' + + # Public: Create a new Eway Gateway. + # options - A hash of options: + # :login - Your Customer ID. + # :password - Your XML Refund Password that you + # specified on the Eway site. (optional) + def initialize(options = {}) + requires!(options, :login) + super + end + + def purchase(money, creditcard, options = {}) + requires_address!(options) + + post = {} + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_id(post) + add_invoice_data(post, options) + add_non_optional_data(post) + add_amount(post, money) + post[:CustomerEmail] = options[:email] + + commit(purchase_url(post[:CVN]), money, post) + end + + def refund(money, authorization, options={}) + post = {} + + add_customer_id(post) + add_amount(post, money) + add_non_optional_data(post) + post[:OriginalTrxnNumber] = authorization + post[:RefundPassword] = @options[:password] + post[:CardExpiryMonth] = nil + post[:CardExpiryYear] = nil + + commit(refund_url, money, post) + end + + private + def requires_address!(options) + raise ArgumentError.new("Missing eWay required parameters: address or billing_address") unless (options.has_key?(:address) or options.has_key?(:billing_address)) + end + + def add_creditcard(post, creditcard) + post[:CardNumber] = creditcard.number + post[:CardExpiryMonth] = sprintf("%.2i", creditcard.month) + post[:CardExpiryYear] = sprintf("%.4i", creditcard.year)[-2..-1] + post[:CustomerFirstName] = creditcard.first_name + post[:CustomerLastName] = creditcard.last_name + post[:CardHoldersName] = creditcard.name + + post[:CVN] = creditcard.verification_value if creditcard.verification_value? + end + + def add_address(post, options) + if address = options[:billing_address] || options[:address] + post[:CustomerAddress] = [ address[:address1], address[:address2], address[:city], address[:state], address[:country] ].compact.join(', ') + post[:CustomerPostcode] = address[:zip] + end + end + + def add_customer_id(post) + post[:CustomerID] = @options[:login] + end + + def add_invoice_data(post, options) + post[:CustomerInvoiceRef] = options[:order_id] + post[:CustomerInvoiceDescription] = options[:description] + end + + def add_amount(post, money) + post[:TotalAmount] = amount(money) + end + + def add_non_optional_data(post) + post[:Option1] = nil + post[:Option2] = nil + post[:Option3] = nil + post[:TrxnNumber] = nil + end + + def commit(url, money, parameters) + raw_response = ssl_post(url, post_data(parameters)) + response = parse(raw_response) + + Response.new(success?(response), + message_from(response[:ewaytrxnerror]), + response, + :authorization => response[:ewaytrxnnumber], + :test => test? + ) + end + + def success?(response) + response[:ewaytrxnstatus] == "True" + end + + def parse(xml) + response = {} + xml = REXML::Document.new(xml) + xml.elements.each('//ewayResponse/*') do |node| + response[node.name.downcase.to_sym] = normalize(node.text) + end unless xml.root.nil? + + response + end + + def post_data(parameters = {}) + xml = REXML::Document.new + root = xml.add_element("ewaygateway") + + parameters.each do |key, value| + root.add_element("eway#{key}").text = value + end + xml.to_s + end + + def message_from(message) + return '' if message.blank? + MESSAGES[message[0,2]] || message + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def purchase_url(cvn) + suffix = test? ? 'xmltest/testpage.asp' : 'xmlpayment.asp' + gateway_part = cvn ? 'gateway_cvn' : 'gateway' + "#{live_url}/#{gateway_part}/#{suffix}" + end + + def refund_url + suffix = test? ? 'xmltest/refund_test.asp' : 'xmlpaymentrefund.asp' + "#{live_url}/gateway/#{suffix}" + end + + MESSAGES = { + "00" => "Transaction Approved", + "01" => "Refer to Issuer", + "02" => "Refer to Issuer, special", + "03" => "No Merchant", + "04" => "Pick Up Card", + "05" => "Do Not Honour", + "06" => "Error", + "07" => "Pick Up Card, Special", + "08" => "Honour With Identification", + "09" => "Request In Progress", + "10" => "Approved For Partial Amount", + "11" => "Approved, VIP", + "12" => "Invalid Transaction", + "13" => "Invalid Amount", + "14" => "Invalid Card Number", + "15" => "No Issuer", + "16" => "Approved, Update Track 3", + "19" => "Re-enter Last Transaction", + "21" => "No Action Taken", + "22" => "Suspected Malfunction", + "23" => "Unacceptable Transaction Fee", + "25" => "Unable to Locate Record On File", + "30" => "Format Error", + "31" => "Bank Not Supported By Switch", + "33" => "Expired Card, Capture", + "34" => "Suspected Fraud, Retain Card", + "35" => "Card Acceptor, Contact Acquirer, Retain Card", + "36" => "Restricted Card, Retain Card", + "37" => "Contact Acquirer Security Department, Retain Card", + "38" => "PIN Tries Exceeded, Capture", + "39" => "No Credit Account", + "40" => "Function Not Supported", + "41" => "Lost Card", + "42" => "No Universal Account", + "43" => "Stolen Card", + "44" => "No Investment Account", + "51" => "Insufficient Funds", + "52" => "No Cheque Account", + "53" => "No Savings Account", + "54" => "Expired Card", + "55" => "Incorrect PIN", + "56" => "No Card Record", + "57" => "Function Not Permitted to Cardholder", + "58" => "Function Not Permitted to Terminal", + "59" => "Suspected Fraud", + "60" => "Acceptor Contact Acquirer", + "61" => "Exceeds Withdrawal Limit", + "62" => "Restricted Card", + "63" => "Security Violation", + "64" => "Original Amount Incorrect", + "66" => "Acceptor Contact Acquirer, Security", + "67" => "Capture Card", + "75" => "PIN Tries Exceeded", + "82" => "CVV Validation Error", + "90" => "Cutoff In Progress", + "91" => "Card Issuer Unavailable", + "92" => "Unable To Route Transaction", + "93" => "Cannot Complete, Violation Of The Law", + "94" => "Duplicate Transaction", + "96" => "System Error" + } + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_managed.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_managed.rb new file mode 100644 index 000000000..2dcae353a --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_managed.rb @@ -0,0 +1,291 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class EwayManagedGateway < Gateway + self.test_url = 'https://www.eway.com.au/gateway/ManagedPaymentService/test/managedCreditCardPayment.asmx' + self.live_url = 'https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['AU'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master] + + self.default_currency = 'AUD' + + #accepted money format + self.money_format = :cents + + # The homepage URL of the gateway + self.homepage_url = 'http://www.eway.com.au/' + + # The name of the gateway + self.display_name = 'eWay Managed Payments' + + def initialize(options = {}) + requires!(options, :login, :username, :password) + + # eWay returns 500 code for faults, which AM snaffles. + # So, we tell it to allow them. + options[:ignore_http_status] = true + super + end + + # add a new customer CC to your eway account and return unique ManagedCustomerID + # supports storing details required by eway see "add_creditcard" and "add_address" + def store(creditcard, options = {}) + post = {} + + # Handle our required fields + requires!(options, :billing_address) + + # Handle eWay specific required fields. + billing_address = options[:billing_address] + eway_requires!(billing_address) + + add_creditcard(post, creditcard) + add_address(post, billing_address) + add_misc_fields(post, options) + + commit("CreateCustomer", post) + end + + def update(billing_id, creditcard, options={}) + post = {} + + # Handle our required fields + requires!(options, :billing_address) + + # Handle eWay specific required fields. + billing_address = options[:billing_address] + eway_requires!(billing_address) + + post[:managedCustomerID]=billing_id + add_creditcard(post, creditcard) + add_address(post, billing_address) + add_misc_fields(post, options) + + commit("UpdateCustomer", post) + end + + # Process a payment in the given amount against the stored credit card given by billing_id + # + # ==== Parameters + # + # * money -- The amount to be purchased as an Integer value in cents. + # * billing_id -- The eWay provided card/customer token to charge (managedCustomerID) + # * options -- A hash of optional parameters. + # + # ==== Options + # + # * :order_id -- The order number, passed to eWay as the "Invoice Reference" + # * :invoice -- The invoice number, passed to eWay as the "Invoice Reference" unless :order_id is also given + # * :description -- A description of the payment, passed to eWay as the "Invoice Description" + def purchase(money, billing_id, options={}) + post = {} + post[:managedCustomerID] = billing_id.to_s + post[:amount]=money + add_invoice(post, options) + + commit("ProcessPayment", post) + end + + # Get customer's stored credit card details given by billing_id + # + # ==== Parameters + # + # * billing_id -- The eWay provided card/customer token to charge (managedCustomerID) + def retrieve(billing_id) + post = {} + post[:managedCustomerID] = billing_id.to_s + + commit("QueryCustomer", post) + end + + # TODO: eWay API also provides QueryPayment + + private + + def eway_requires!(hash) + raise ArgumentError.new("Missing eWay required parameter in `billing_address`: title") unless hash.has_key?(:title) + raise ArgumentError.new("Missing eWay required parameter in `billing_address`: country") unless hash.has_key?(:country) + end + + def add_address(post, address) + post[:Address] = address[:address1].to_s + post[:Phone] = address[:phone].to_s + post[:PostCode] = address[:zip].to_s + post[:Suburb] = address[:city].to_s + post[:Country] = address[:country].to_s.downcase + post[:State] = address[:state].to_s + post[:Mobile] = address[:mobile].to_s + post[:Fax] = address[:fax].to_s + end + + def add_misc_fields(post, options) + post[:CustomerRef]=options[:billing_address][:customer_ref] || options[:customer] + post[:Title]=options[:billing_address][:title] + post[:Company]=options[:billing_address][:company] + post[:JobDesc]=options[:billing_address][:job_desc] + post[:Email]=options[:billing_address][:email] || options[:email] + post[:URL]=options[:billing_address][:url] + post[:Comments]=options[:description] + end + + def add_invoice(post, options) + post[:invoiceReference] = options[:order_id] || options[:invoice] + post[:invoiceDescription] = options[:description] + end + + + # add credit card details to be stored by eway. NOTE eway requires "title" field + def add_creditcard(post, creditcard) + post[:CCNumber] = creditcard.number + post[:CCExpiryMonth] = sprintf("%.2i", creditcard.month) + post[:CCExpiryYear] = sprintf("%.4i", creditcard.year)[-2..-1] + post[:CCNameOnCard] = creditcard.name + post[:FirstName] = creditcard.first_name + post[:LastName] = creditcard.last_name + end + + def parse(body) + reply = {} + xml = REXML::Document.new(body) + if root = REXML::XPath.first(xml, "//soap:Fault") then + reply=parse_fault(root) + else + if root = REXML::XPath.first(xml, '//ProcessPaymentResponse/ewayResponse') then + # Successful payment + reply=parse_purchase(root) + else + if root = REXML::XPath.first(xml, '//QueryCustomerResult') then + reply=parse_query_customer(root) + else + if root = REXML::XPath.first(xml, '//CreateCustomerResult') then + reply[:message]='OK' + reply[:CreateCustomerResult]=root.text + reply[:success]=true + else + if root = REXML::XPath.first(xml, '//UpdateCustomerResult') then + if root.text.downcase == 'true' then + reply[:message]='OK' + reply[:success]=true + else + # ERROR: This state should never occur. If there is a problem, + # a soap:Fault will be returned. The presence of this + # element always means a success. + raise StandardError, "Unexpected \"false\" in UpdateCustomerResult" + end + else + # ERROR: This state should never occur currently. We have handled + # responses for all the methods which we support. + raise StandardError, "Unexpected response" + end + end + end + end + end + return reply + end + + def parse_fault(node) + reply={} + reply[:message]=REXML::XPath.first(node, '//soap:Reason/soap:Text').text + reply[:success]=false + reply + end + + def parse_purchase(node) + reply={} + reply[:message]=REXML::XPath.first(node, '//ewayTrxnError').text + reply[:success]=(REXML::XPath.first(node, '//ewayTrxnStatus').text == 'True') + reply[:auth_code]=REXML::XPath.first(node, '//ewayAuthCode').text + reply[:transaction_number]=REXML::XPath.first(node, '//ewayTrxnNumber').text + reply + end + + def parse_query_customer(node) + reply={} + reply[:message]='OK' + reply[:success]=true + reply[:CCNumber]=REXML::XPath.first(node, '//CCNumber').text + reply[:CCName]=REXML::XPath.first(node, '//CCName').text + reply[:CCExpiryMonth]=REXML::XPath.first(node, '//CCExpiryMonth').text + reply[:CCExpiryYear]=REXML::XPath.first(node, '//CCExpiryYear').text + reply + end + + def commit(action, post) + raw = begin + ssl_post(test? ? self.test_url : self.live_url, soap_request(post, action), 'Content-Type' => 'application/soap+xml; charset=utf-8') + rescue ResponseError => e + e.response.body + end + response = parse(raw) + + EwayResponse.new(response[:success], response[:message], response, + :test => test?, + :authorization => response[:auth_code] + ) + end + + # Where we build the full SOAP 1.2 request using builder + def soap_request(arguments, action) + # eWay demands all fields be sent, but contain an empty string if blank + post = case action + when 'QueryCustomer' + arguments + when 'ProcessPayment' + default_payment_fields.merge(arguments) + when 'CreateCustomer' + default_customer_fields.merge(arguments) + when 'UpdateCustomer' + default_customer_fields.merge(arguments) + end + + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! 'soap12:Envelope', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', 'xmlns:soap12' => 'http://www.w3.org/2003/05/soap-envelope'} do + xml.tag! 'soap12:Header' do + xml.tag! 'eWAYHeader', {'xmlns' => 'https://www.eway.com.au/gateway/managedpayment'} do + xml.tag! 'eWAYCustomerID', @options[:login] + xml.tag! 'Username', @options[:username] + xml.tag! 'Password', @options[:password] + end + end + xml.tag! 'soap12:Body' do |x| + x.tag! "#{action}", {'xmlns' => 'https://www.eway.com.au/gateway/managedpayment'} do |y| + post.each do |key, value| + y.tag! "#{key}", "#{value}" + end + end + end + end + xml.target! + end + + def default_customer_fields + hash={} + %w( CustomerRef Title FirstName LastName Company JobDesc Email Address Suburb State PostCode Country Phone Mobile Fax URL Comments CCNumber CCNameOnCard CCExpiryMonth CCExpiryYear ).each do |field| + hash[field.to_sym]='' + end + return hash + end + + def default_payment_fields + hash={} + %w( managedCustomerID amount invoiceReference invoiceDescription ).each do |field| + hash[field.to_sym]='' + end + return hash + end + + class EwayResponse < Response + # add a method to response so we can easily get the eway token "ManagedCustomerID" + def token + @params['CreateCustomerResult'] + end + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_rapid.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_rapid.rb new file mode 100644 index 000000000..628f91889 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/eway_rapid.rb @@ -0,0 +1,300 @@ +require "nokogiri" +require "cgi" + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class EwayRapidGateway < Gateway + self.test_url = "https://api.sandbox.ewaypayments.com/" + self.live_url = "https://api.ewaypayments.com/" + + self.money_format = :cents + self.supported_countries = ["AU"] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club] + self.homepage_url = "http://www.eway.com.au/" + self.display_name = "eWAY Rapid 3.0" + self.default_currency = "AUD" + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Public: Run a purchase transaction. Treats the Rapid 3.0 transparent + # redirect as an API endpoint in order to conform to the standard + # ActiveMerchant #purchase API. + # + # amount - The monetary amount of the transaction in cents. + # options - A standard ActiveMerchant options hash: + # :order_id - A merchant-supplied identifier for the + # transaction (optional). + # :description - A merchant-supplied description of the + # transaction (optional). + # :currency - Three letter currency code for the + # transaction (default: "AUD") + # :billing_address - Standard ActiveMerchant address hash + # (optional). + # :shipping_address - Standard ActiveMerchant address hash + # (optional). + # :ip - The ip of the consumer initiating the + # transaction (optional). + # :application_id - A string identifying the application + # submitting the transaction + # (default: "https://github.com/Shopify/active_merchant") + # + # Returns an ActiveMerchant::Billing::Response object + def purchase(amount, payment_method, options={}) + MultiResponse.new.tap do |r| + # Rather than follow the redirect, we detect the 302 and capture the + # token out of the Location header in the run_purchase step. But we + # still need a placeholder url to pass to eWay, and that is what + # example.com is used for here. + r.process{setup_purchase(amount, options.merge(:redirect_url => "http://example.com/"))} + r.process{run_purchase(r.authorization, payment_method, r.params["formactionurl"])} + r.process{status(r.authorization)} + end + end + + # Public: Acquire the token necessary to run a transparent redirect. + # + # amount - The monetary amount of the transaction in cents. + # options - A supplemented ActiveMerchant options hash: + # :redirect_url - The url to return the customer to after + # the transparent redirect is completed + # (required). + # :order_id - A merchant-supplied identifier for the + # transaction (optional). + # :description - A merchant-supplied description of the + # transaction (optional). + # :currency - Three letter currency code for the + # transaction (default: "AUD") + # :billing_address - Standard ActiveMerchant address hash + # (optional). + # :shipping_address - Standard ActiveMerchant address hash + # (optional). + # :ip - The ip of the consumer initiating the + # transaction (optional). + # :application_id - A string identifying the application + # submitting the transaction + # (default: "https://github.com/Shopify/active_merchant") + # + # Returns an EwayRapidResponse object, which conforms to the + # ActiveMerchant::Billing::Response API, but also exposes #form_url. + def setup_purchase(amount, options={}) + requires!(options, :redirect_url) + request = build_xml_request("CreateAccessCodeRequest") do |doc| + add_metadata(doc, options) + add_invoice(doc, amount, options) + add_customer_data(doc, options) + end + + commit(url_for("CreateAccessCode"), request) + end + + # Public: Retrieve the status of a transaction. + # + # identification - The Eway Rapid 3.0 access code for the transaction + # (returned as the response.authorization by + # #setup_purchase). + # + # Returns an EwayRapidResponse object. + def status(identification) + request = build_xml_request("GetAccessCodeResultRequest") do |doc| + doc.AccessCode identification + end + commit(url_for("GetAccessCodeResult"), request) + end + + private + + def run_purchase(identification, payment_method, endpoint) + post = { + "accesscode" => identification + } + add_credit_card(post, payment_method) + + commit_form(endpoint, build_form_request(post)) + end + + def add_metadata(doc, options) + doc.RedirectUrl(options[:redirect_url]) + doc.CustomerIP options[:ip] if options[:ip] + doc.Method "ProcessPayment" + doc.DeviceID(options[:application_id] || application_id) + end + + def add_invoice(doc, money, options) + doc.Payment do + doc.TotalAmount amount(money) + doc.InvoiceReference options[:order_id] + doc.InvoiceDescription options[:description] + currency_code = (options[:currency] || currency(money) || default_currency) + doc.CurrencyCode currency_code + end + end + + def add_customer_data(doc, options) + doc.Customer do + add_address(doc, (options[:billing_address] || options[:address]), {:email => options[:email]}) + end + doc.ShippingAddress do + add_address(doc, options[:shipping_address], {:skip_company => true}) + end + end + + def add_address(doc, address, options={}) + return unless address + if name = address[:name] + parts = name.split(/\s+/) + doc.FirstName parts.shift if parts.size > 1 + doc.LastName parts.join(" ") + end + doc.CompanyName address[:company] unless options[:skip_company] + doc.Street1 address[:address1] + doc.Street2 address[:address2] + doc.City address[:city] + doc.State address[:state] + doc.PostalCode address[:zip] + doc.Country address[:country] + doc.Phone address[:phone] + doc.Fax address[:fax] + doc.Email options[:email] + end + + def add_credit_card(post, credit_card) + post["cardname"] = credit_card.name + post["cardnumber"] = credit_card.number + post["cardexpirymonth"] = credit_card.month + post["cardexpiryyear"] = credit_card.year + post["cardcvn"] = credit_card.verification_value + end + + def build_xml_request(root) + builder = Nokogiri::XML::Builder.new + builder.__send__(root) do |doc| + yield(doc) + end + builder.to_xml + end + + def build_form_request(post) + request = [] + post.each do |key, value| + request << "EWAY_#{key.upcase}=#{CGI.escape(value.to_s)}" + end + request.join("&") + end + + def url_for(action) + (test? ? test_url : live_url) + action + ".xml" + end + + def commit(url, request, form_post=false) + headers = { + "Authorization" => ("Basic " + Base64.strict_encode64(@options[:login].to_s + ":" + @options[:password].to_s).chomp), + "Content-Type" => "text/xml" + } + + raw = parse(ssl_post(url, request, headers)) + + succeeded = success?(raw) + EwayRapidResponse.new( + succeeded, + message_from(succeeded, raw), + raw, + :authorization => authorization_from(raw), + :test => test?, + :avs_result => avs_result_from(raw), + :cvv_result => cvv_result_from(raw) + ) + rescue ActiveMerchant::ResponseError => e + return EwayRapidResponse.new(false, e.response.message, {:status_code => e.response.code}, :test => test?) + end + + def commit_form(url, request) + http_response = raw_ssl_request(:post, url, request) + + success = (http_response.code.to_s == "302") + message = (success ? "Succeeded" : http_response.body) + if success + authorization = CGI.unescape(http_response["Location"].split("=").last) + end + Response.new(success, message, {:location => http_response["Location"]}, :authorization => authorization, :test => test?) + end + + def parse(xml) + response = {} + + doc = Nokogiri::XML(xml) + doc.root.xpath("*").each do |node| + if (node.elements.size == 0) + response[node.name.downcase.to_sym] = node.text + else + node.elements.each do |childnode| + name = "#{node.name.downcase}_#{childnode.name.downcase}" + response[name.to_sym] = childnode.text + end + end + end unless doc.root.nil? + + response + end + + def success?(response) + if response[:errors] + false + elsif response[:transactionstatus] + (response[:transactionstatus] == "true") + else + true + end + end + + def message_from(succeeded, response) + if response[:errors] + response[:errors] + elsif response[:responsecode] + ActiveMerchant::Billing::EwayGateway::MESSAGES[response[:responsecode]] + elsif response[:responsemessage] + response[:responsemessage] + elsif succeeded + "Succeeded" + else + "Failed" + end + end + + def authorization_from(response) + response[:accesscode] + end + + def avs_result_from(response) + code = case response[:verification_address] + when "Valid" + "M" + when "Invalid" + "N" + else + "I" + end + {:code => code} + end + + def cvv_result_from(response) + case response[:verification_cvn] + when "Valid" + "M" + when "Invalid" + "N" + else + "P" + end + end + + class EwayRapidResponse < ActiveMerchant::Billing::Response + def form_url + params["formactionurl"] + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/exact.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/exact.rb new file mode 100644 index 000000000..8b6f04ec2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/exact.rb @@ -0,0 +1,218 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class ExactGateway < Gateway + self.live_url = self.test_url = 'https://secure2.e-xact.com/vplug-in/transaction/rpc-enc/service.asmx' + + API_VERSION = "8.5" + + TEST_LOGINS = [ {:login => "A00049-01", :password => "test1"}, + {:login => "A00427-01", :password => "testus"} ] + + TRANSACTIONS = { :sale => "00", + :authorization => "01", + :capture => "32", + :credit => "34" } + + + ENVELOPE_NAMESPACES = { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', + 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' + } + + SEND_AND_COMMIT_ATTRIBUTES = { 'xmlns:n1' => "http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/Request", + 'env:encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/' + } + + SEND_AND_COMMIT_SOURCE_ATTRIBUTES = { 'xmlns:n2' => 'http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/encodedTypes', + 'xsi:type' => 'n2:Transaction' + } + + POST_HEADERS = { 'soapAction' => "http://secure2.e-xact.com/vplug-in/transaction/rpc-enc/SendAndCommit", + 'Content-Type' => 'text/xml' + } + + SUCCESS = "true" + + SENSITIVE_FIELDS = [ :verification_str2, :expiry_date, :card_number ] + + self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover] + self.supported_countries = ['CA', 'US'] + self.homepage_url = 'http://www.e-xact.com' + self.display_name = 'E-xact' + + def initialize(options = {}) + requires!(options, :login, :password) + + super + end + + def authorize(money, credit_card, options = {}) + commit(:authorization, build_sale_or_authorization_request(money, credit_card, options)) + end + + def purchase(money, credit_card, options = {}) + commit(:sale, build_sale_or_authorization_request(money, credit_card, options)) + end + + def capture(money, authorization, options = {}) + commit(:capture, build_capture_or_credit_request(money, authorization, options)) + end + + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + def refund(money, authorization, options = {}) + commit(:credit, build_capture_or_credit_request(money, authorization, options)) + end + + private + def build_request(action, body) + xml = Builder::XmlMarkup.new + + xml.instruct! + xml.tag! 'env:Envelope', ENVELOPE_NAMESPACES do + xml.tag! 'env:Body' do + xml.tag! 'n1:SendAndCommit', SEND_AND_COMMIT_ATTRIBUTES do + xml.tag! 'SendAndCommitSource', SEND_AND_COMMIT_SOURCE_ATTRIBUTES do + add_credentials(xml) + add_transaction_type(xml, action) + xml << body + end + end + end + end + xml.target! + end + + def build_sale_or_authorization_request(money, credit_card, options) + xml = Builder::XmlMarkup.new + + add_amount(xml, money) + add_credit_card(xml, credit_card) + add_customer_data(xml, options) + add_invoice(xml, options) + + xml.target! + end + + def build_capture_or_credit_request(money, identification, options) + xml = Builder::XmlMarkup.new + + add_identification(xml, identification) + add_amount(xml, money) + add_customer_data(xml, options) + + xml.target! + end + + def add_credentials(xml) + xml.tag! 'ExactID', @options[:login] + xml.tag! 'Password', @options[:password] + end + + def add_transaction_type(xml, action) + xml.tag! 'Transaction_Type', TRANSACTIONS[action] + end + + def add_identification(xml, identification) + authorization_num, transaction_tag = identification.split(';') + + xml.tag! 'Authorization_Num', authorization_num + xml.tag! 'Transaction_Tag', transaction_tag + end + + def add_amount(xml, money) + xml.tag! 'DollarAmount', amount(money) + end + + def add_credit_card(xml, credit_card) + xml.tag! 'Card_Number', credit_card.number + xml.tag! 'Expiry_Date', expdate(credit_card) + xml.tag! 'CardHoldersName', credit_card.name + + if credit_card.verification_value? + xml.tag! 'CVD_Presence_Ind', '1' + xml.tag! 'VerificationStr2', credit_card.verification_value + end + end + + def add_customer_data(xml, options) + xml.tag! 'Customer_Ref', options[:customer] + xml.tag! 'Client_IP', options[:ip] + xml.tag! 'Client_Email', options[:email] + end + + def add_address(xml, options) + if address = options[:billing_address] || options[:address] + xml.tag! 'ZipCode', address[:zip] + end + end + + def add_invoice(xml, options) + xml.tag! 'Reference_No', options[:order_id] + xml.tag! 'Reference_3', options[:description] + end + + def expdate(credit_card) + "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}" + end + + def commit(action, request) + response = parse(ssl_post(self.live_url, build_request(action, request), POST_HEADERS)) + + Response.new(successful?(response), message_from(response), response, + :test => test?, + :authorization => authorization_from(response), + :avs_result => { :code => response[:avs] }, + :cvv_result => response[:cvv2] + ) + end + + def successful?(response) + response[:transaction_approved] == SUCCESS + end + + def authorization_from(response) + if response[:authorization_num] && response[:transaction_tag] + "#{response[:authorization_num]};#{response[:transaction_tag]}" + else + '' + end + end + + def message_from(response) + if response[:faultcode] && response[:faultstring] + response[:faultstring] + elsif response[:error_number] != '0' + response[:error_description] + else + result = response[:exact_message] || '' + result << " - #{response[:bank_message]}" unless response[:bank_message].blank? + result + end + end + + def parse(xml) + response = {} + xml = REXML::Document.new(xml) + + if root = REXML::XPath.first(xml, "//types:TransactionResult") + parse_elements(response, root) + elsif root = REXML::XPath.first(xml, "//soap:Fault") + parse_elements(response, root) + end + + response.delete_if{ |k,v| SENSITIVE_FIELDS.include?(k) } + end + + def parse_elements(response, root) + root.elements.to_a.each do |node| + response[node.name.gsub(/EXact/, 'Exact').underscore.to_sym] = (node.text || '').strip + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/fat_zebra.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/fat_zebra.rb new file mode 100644 index 000000000..735f93153 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/fat_zebra.rb @@ -0,0 +1,152 @@ +require 'json' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class FatZebraGateway < Gateway + self.live_url = "https://gateway.fatzebra.com.au/v1.0" + self.test_url = "https://gateway.sandbox.fatzebra.com.au/v1.0" + + self.supported_countries = ['AU'] + self.default_currency = 'AUD' + self.money_format = :cents + self.supported_cardtypes = [:visa, :master, :american_express, :jcb] + + self.homepage_url = 'https://www.fatzebra.com.au/' + self.display_name = 'Fat Zebra' + + # Setup a new instance of the gateway. + # + # The options hash should include :username and :token + # You can find your username and token at https://dashboard.fatzebra.com.au + # Under the Your Account section + def initialize(options = {}) + requires!(options, :username) + requires!(options, :token) + @username = options[:username] + @token = options[:token] + super + end + + # To create a purchase on a credit card use: + # + # purchase(money, creditcard , { ... }) + # + # To charge a tokenized card + # + # purchase(money, {:token => "abzy87u", :cvv => "123"}, { ... }}) + def purchase(money, creditcard, options = {}) + post = {} + + add_amount(post, money, options) + add_creditcard(post, creditcard, options) + post[:reference] = options[:order_id] + post[:customer_ip] = options[:ip] + + commit(:post, 'purchases', post) + end + + # Refund a transaction + # + # amount - Integer - the amount to refund + # txn_id - String - the original transaction to be refunded + # reference - String - your transaction reference + def refund(money, txn_id, reference) + post = {} + + post[:amount] = money + post[:transaction_id] = txn_id + post[:reference] = reference + + commit(:post, "refunds", post) + end + + # Tokenize a credit card + def store(creditcard) + post = {} + add_creditcard(post, creditcard) + + commit(:post, "credit_cards", post) + end + + private + # Add the money details to the request + def add_amount(post, money, options) + post[:amount] = money + end + + # Add the credit card details to the request + def add_creditcard(post, creditcard, options = {}) + if creditcard.respond_to?(:number) + post[:card_number] = creditcard.number + post[:card_expiry] = "#{creditcard.month}/#{creditcard.year}" + post[:cvv] = creditcard.verification_value if creditcard.verification_value? + post[:card_holder] = creditcard.name if creditcard.name + else + post[:card_token] = creditcard[:token] + post[:cvv] = creditcard[:cvv] + end + end + + # Post the data to the gateway + def commit(method, uri, parameters=nil) + raw_response = response = nil + success = false + begin + raw_response = ssl_request(method, get_url(uri), parameters.to_json, headers) + response = parse(raw_response) + success = response["successful"] && (response["response"]["successful"] || response["response"]["token"]) + rescue ResponseError => e + if e.response.code == "401" + return Response.new(false, "Invalid Login") + end + + raw_response = e.response.body + response = parse(raw_response) + rescue JSON::ParserError + response = json_error(raw_response) + end + + message = response["response"]["message"] + unless response["successful"] + # There is an error, so we will show that instead + message = response["errors"].empty? ? "Unknown Error" : response["errors"].join(", ") + end + + Response.new(success, + message, + response, + :test => response.has_key?("test") ? response["test"] : false, + :authorization => response["response"]["id"] || response["response"]["token"]) + end + + # Parse the returned JSON, if parse errors are raised then return a detailed error. + def parse(response) + begin + JSON.parse(response) + rescue JSON::ParserError + msg = 'Invalid JSON response received from Fat Zebra. Please contact support@fatzebra.com.au if you continue to receive this message.' + msg += " (The raw response returned by the API was #{response.inspect})" + { + "successful" => false, + "response" => {}, + "errors" => [msg] + } + end + end + + # Build the URL based on the AM mode and the URI + def get_url(uri) + base = test? ? self.test_url : self.live_url + base + "/" + uri + end + + # Builds the auth and U-A headers for the request + def headers + { + "Authorization" => "Basic " + Base64.strict_encode64(@username.to_s + ":" + @token.to_s).strip, + "User-Agent" => "Fat Zebra v1.0/ActiveMerchant #{ActiveMerchant::VERSION}" + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/federated_canada.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/federated_canada.rb new file mode 100644 index 000000000..d08e87a44 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/federated_canada.rb @@ -0,0 +1,167 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class FederatedCanadaGateway < Gateway + # Same URL for both test and live, testing is done by using the test username (demo) and password (password). + self.live_url = self.test_url = 'https://secure.federatedgateway.com/api/transact.php' + + APPROVED, DECLINED, ERROR = 1, 2, 3 + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['CA'] + + self.default_currency = 'CAD' + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.federatedcanada.com/' + + # The name of the gateway + self.display_name = 'Federated Canada' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + commit('sale', money, post) + end + + def authorize(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + commit('auth', money, post) + end + + def capture(money, authorization, options = {}) + options[:transactionid] = authorization + commit('capture', money, options) + end + + def void(authorization, options = {}) + options[:transactionid] = authorization + commit('void', nil, options) + end + + def refund(money, authorization, options = {}) + commit('refund', money, options.merge(:transactionid => authorization)) + end + + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + private + + def add_customer_data(post, options) + post[:firstname] = options[:first_name] + post[:lastname] = options[:last_name] + + post[:email] = options[:email] + end + + def add_address(post, options) + if address = (options[:billing_address] || options[:address]) + post[:company] = address[:company] + post[:address1] = address[:address1] + post[:address2] = address[:address2] + post[:city] = address[:city] + post[:state] = address[:state] + post[:zip] = address[:zip] + post[:country] = address[:country] + post[:phone] = address[:phone] + end + if address = options[:shipping_address] + post[:shipping_firstname] = address[:first_name] + post[:shipping_lastname] = address[:last_name] + post[:shipping_company] = address[:company] + post[:shipping_address1] = address[:address1] + post[:shipping_address2] = address[:address2] + post[:shipping_city] = address[:city] + post[:shipping_state] = address[:state] + post[:shipping_zip] = address[:zip] + post[:shipping_country] = address[:country] + post[:shipping_email] = address[:email] + end + end + + def add_invoice(post, options) + post[:orderid] = options[:order_id] + post[:orderdescription] = options[:description] + end + + def add_creditcard(post, creditcard) + post[:ccnumber] = creditcard.number + post[:ccexp] = expdate(creditcard) + post[:cvv] = creditcard.verification_value + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + "#{month}#{year[-2..-1]}" + end + + def parse(body) + body.split('&').inject({}) do |memo, x| + k, v = x.split('=') + memo[k] = v + memo + end + end + + def commit(action, money, parameters) + parameters[:amount] = amount(money) + data = ssl_post(self.live_url, post_data(action, parameters)) + response = parse(data) + message = message_from(response) + test_mode = test? + + Response.new(success?(response), message, response, + :test => test?, + :authorization => response['transactionid'], + :avs_result => {:code => response['avsresponse']}, + :cvv_result => response['cvvresponse'] + ) + end + + def success?(response) + response['response'] == '1' + end + + def test? + (@options[:login].eql?('demo')) && (@options[:password].eql?('password')) + end + + def message_from(response) + case response['response'].to_i + when APPROVED + "Transaction Approved" + when DECLINED + "Transaction Declined" + else + "Error in transaction data or system error" + end + end + + def post_data(action, parameters = {}) + parameters[:type] = action + parameters[:username] = @options[:login] + parameters[:password] = @options[:password] + parameters.map{|k, v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&') + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/finansbank.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/finansbank.rb new file mode 100644 index 000000000..a81cecd54 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/finansbank.rb @@ -0,0 +1,22 @@ +require File.dirname(__FILE__) + '/cc5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class FinansbankGateway < CC5Gateway + self.live_url = self.test_url = 'https://www.fbwebpos.com/servlet/cc5ApiServer' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US', 'TR'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master] + + # The homepage URL of the gateway + self.homepage_url = 'https://www.fbwebpos.com/' + + # The name of the gateway + self.display_name = 'Finansbank WebPOS' + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/first_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/first_pay.rb new file mode 100644 index 000000000..b356dddb7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/first_pay.rb @@ -0,0 +1,176 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class FirstPayGateway < Gateway + class FirstPayPostData < PostData + # Fields that will be sent even if they are blank + self.required_fields = [ :action, :amount, :trackid ] + end + + # both URLs are IP restricted + self.test_url = 'https://apgcert.first-pay.com/AcqENGIN/SecureCapture' + self.live_url = 'https://acqengin.first-pay.com/AcqENGIN/SecureCapture' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.first-pay.com' + + # The name of the gateway + self.display_name = 'First Pay' + + # all transactions are in cents + self.money_format = :cents + + ACTIONS = { + 'sale' => 1, + 'credit' => 2, + 'void' => 3 + } + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, creditcard, options = {}) + post = FirstPayPostData.new + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + + commit('sale', money, post) + end + + def refund(money, reference, options = {}) + requires!(options, :credit_card) + + post = FirstPayPostData.new + add_invoice(post, options) + add_creditcard(post, options[:credit_card]) + add_address(post, options) + add_customer_data(post, options) + add_credit_data(post, reference) + + commit('credit', money, post) + end + + def credit(money, reference, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, reference, options) + end + + def void(money, creditcard, options = {}) + post = FirstPayPostData.new + add_creditcard(post, creditcard) + add_void_data(post, options) + add_invoice(post, options) + add_customer_data(post, options) + + commit('void', money, post) + end + + + private + + def add_customer_data(post, options) + post[:cardip] = options[:ip] + post[:email] = options[:email] + end + + def add_address(post, options) + if billing_address = options[:billing_address] || options[:address] + post[:addr] = billing_address[:address1].to_s + ' ' + billing_address[:address2].to_s + post[:city] = billing_address[:city] + post[:state] = billing_address[:state] + post[:zip] = billing_address[:zip] + post[:country] = billing_address[:country] + end + end + + def add_invoice(post, options) + post[:trackid] = rand(Time.now.to_i) + end + + def add_creditcard(post, creditcard) + post[:member] = creditcard.first_name.to_s + " " + creditcard.last_name.to_s + post[:card] = creditcard.number + post[:exp] = expdate(creditcard) + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + def add_credit_data(post, transaction_id) + post[:transid] = transaction_id + end + + def add_void_data(post, options) + post[:transid] = options[:transactionid] + end + + def commit(action, money, post) + response = parse( ssl_post(test? ? self.test_url : self.live_url, post_data(action, post, money)) ) + + Response.new(response[:response] == 'CAPTURED', response[:message], response, + :test => test?, + :authorization => response[:authorization], + :avs_result => { :code => response[:avsresponse] }, + :cvv_result => response[:cvvresponse]) + end + + def parse(body) + response = {} + + # check for an error first + if body.include?('!ERROR!') + response[:response] = 'ERROR' + response[:message] = error_message_from(body) + else + # a capture / not captured response will be : delimited + split = body.split(':') + response[:response] = split[0] + + # FirstPay docs are worthless. turns out the transactionid is required for credits + # so we need to store that in authorization, not the actual auth. + if response[:response] == 'CAPTURED' + response[:message] = 'CAPTURED' + response[:authorization] = split[9] # actually the transactionid + response[:auth] = split[1] + response[:avsresponse] = split[3] + response[:cvvresponse] = split[17] + else + # NOT CAPTURED response + response[:message] = split[1] + response[:transactionid] = split[9] + end + end + + return response + end + + def error_message_from(response) + # error messages use this format - '!ERROR! 704-MISSING BASIC DATA TYPE:card, exp, zip, addr, member, amount\n' + response.split("! ")[1].chomp + end + + def post_data(action, post, money) + post[:vid] = @options[:login] + post[:password] = @options[:password] + post[:action] = ACTIONS[action] + post[:amount] = amount(money) + + return post.to_post_data + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/firstdata_e4.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/firstdata_e4.rb new file mode 100644 index 000000000..ee9f6b4b4 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/firstdata_e4.rb @@ -0,0 +1,314 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class FirstdataE4Gateway < Gateway + # TransArmor support requires v11 or lower + self.test_url = "https://api.demo.globalgatewaye4.firstdata.com/transaction/v11" + self.live_url = "https://api.globalgatewaye4.firstdata.com/transaction/v11" + + TRANSACTIONS = { + :sale => "00", + :authorization => "01", + :capture => "32", + :void => "33", + :credit => "34", + :store => "05" + } + + POST_HEADERS = { + "Accepts" => "application/xml", + "Content-Type" => "application/xml" + } + + SUCCESS = "true" + + SENSITIVE_FIELDS = [:verification_str2, :expiry_date, :card_number] + + self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover] + self.supported_countries = ["CA", "US"] + self.default_currency = "USD" + self.homepage_url = "http://www.firstdata.com" + self.display_name = "FirstData Global Gateway e4" + + # Create a new FirstdataE4Gateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The EXACT ID. Also known as the Gateway ID. + # (Found in your administration terminal settings) + # * :password -- The terminal password (not your account password) + def initialize(options = {}) + requires!(options, :login, :password) + @options = options + + super + end + + def authorize(money, credit_card_or_store_authorization, options = {}) + commit(:authorization, build_sale_or_authorization_request(money, credit_card_or_store_authorization, options)) + end + + def purchase(money, credit_card_or_store_authorization, options = {}) + commit(:sale, build_sale_or_authorization_request(money, credit_card_or_store_authorization, options)) + end + + def capture(money, authorization, options = {}) + commit(:capture, build_capture_or_credit_request(money, authorization, options)) + end + + def void(authorization, options = {}) + commit(:void, build_capture_or_credit_request(money_from_authorization(authorization), authorization, options)) + end + + def refund(money, authorization, options = {}) + commit(:credit, build_capture_or_credit_request(money, authorization, options)) + end + + # Tokenize a credit card with TransArmor + # + # The TransArmor token and other card data necessary for subsequent + # transactions is stored in the response's +authorization+ attribute. + # The authorization string may be passed to +authorize+ and +purchase+ + # instead of a +ActiveMerchant::Billing::CreditCard+ instance. + # + # TransArmor support must be explicitly activated on your gateway + # account by FirstData. If your authorization string is empty, contact + # FirstData support for account setup assistance. + # + # === Example + # + # # Generate token + # result = gateway.store(credit_card) + # if result.success? + # my_record.update_attributes(:authorization => result.authorization) + # end + # + # # Use token + # result = gateway.purchase(1000, my_record.authorization) + # + # https://firstdata.zendesk.com/entries/21303361-transarmor-tokenization + def store(credit_card, options = {}) + commit(:store, build_store_request(credit_card, options), credit_card) + end + + private + + def build_request(action, body) + xml = Builder::XmlMarkup.new + + xml.instruct! + xml.tag! "Transaction" do + add_credentials(xml) + add_transaction_type(xml, action) + xml << body + end + + xml.target! + end + + def build_sale_or_authorization_request(money, credit_card_or_store_authorization, options) + xml = Builder::XmlMarkup.new + + add_amount(xml, money) + + if credit_card_or_store_authorization.is_a? String + add_credit_card_token(xml, credit_card_or_store_authorization) + else + add_credit_card(xml, credit_card_or_store_authorization) + end + + add_customer_data(xml, options) + add_invoice(xml, options) + + xml.target! + end + + def build_capture_or_credit_request(money, identification, options) + xml = Builder::XmlMarkup.new + + add_identification(xml, identification) + add_amount(xml, money) + add_customer_data(xml, options) + + xml.target! + end + + def build_store_request(credit_card, options) + xml = Builder::XmlMarkup.new + + add_credit_card(xml, credit_card) + add_customer_data(xml, options) + + xml.target! + end + + def add_credentials(xml) + xml.tag! "ExactID", @options[:login] + xml.tag! "Password", @options[:password] + end + + def add_transaction_type(xml, action) + xml.tag! "Transaction_Type", TRANSACTIONS[action] + end + + def add_identification(xml, identification) + authorization_num, transaction_tag, _ = identification.split(";") + + xml.tag! "Authorization_Num", authorization_num + xml.tag! "Transaction_Tag", transaction_tag + end + + def add_amount(xml, money) + xml.tag! "DollarAmount", amount(money) + end + + def add_credit_card(xml, credit_card) + xml.tag! "Card_Number", credit_card.number + xml.tag! "Expiry_Date", expdate(credit_card) + xml.tag! "CardHoldersName", credit_card.name + xml.tag! "CardType", credit_card.brand + + if credit_card.verification_value? + xml.tag! "CVD_Presence_Ind", "1" + xml.tag! "VerificationStr2", credit_card.verification_value + end + end + + def add_credit_card_token(xml, store_authorization) + params = store_authorization.split(";") + credit_card = CreditCard.new( + :brand => params[1], + :first_name => params[2], + :last_name => params[3], + :month => params[4], + :year => params[5]) + + xml.tag! "TransarmorToken", params[0] + xml.tag! "Expiry_Date", expdate(credit_card) + xml.tag! "CardHoldersName", credit_card.name + xml.tag! "CardType", credit_card.brand + end + + def add_customer_data(xml, options) + xml.tag! "Customer_Ref", options[:customer] if options[:customer] + xml.tag! "Client_IP", options[:ip] if options[:ip] + xml.tag! "Client_Email", options[:email] if options[:email] + end + + def add_address(xml, options) + if address = (options[:billing_address] || options[:address]) + xml.tag! "ZipCode", address[:zip] + end + end + + def add_invoice(xml, options) + xml.tag! "Reference_No", options[:order_id] + xml.tag! "Reference_3", options[:description] if options[:description] + end + + def expdate(credit_card) + "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}" + end + + def commit(action, request, credit_card = nil) + url = (test? ? self.test_url : self.live_url) + begin + response = parse(ssl_post(url, build_request(action, request), POST_HEADERS)) + rescue ResponseError => e + response = parse_error(e.response) + end + + Response.new(successful?(response), message_from(response), response, + :test => test?, + :authorization => response_authorization(action, response, credit_card), + :avs_result => {:code => response[:avs]}, + :cvv_result => response[:cvv2] + ) + end + + def successful?(response) + response[:transaction_approved] == SUCCESS + end + + def response_authorization(action, response, credit_card) + if action == :store + store_authorization_from(response, credit_card) + else + authorization_from(response) + end + end + + def authorization_from(response) + if response[:authorization_num] && response[:transaction_tag] + [ + response[:authorization_num], + response[:transaction_tag], + (response[:dollar_amount].to_f * 100).to_i + ].join(";") + else + "" + end + end + + def store_authorization_from(response, credit_card) + if response[:transarmor_token].present? + [ + response[:transarmor_token], + credit_card.brand, + credit_card.first_name, + credit_card.last_name, + credit_card.month, + credit_card.year + ].map { |value| value.to_s.gsub(/;/, "") }.join(";") + else + raise StandardError, "TransArmor support is not enabled on your #{display_name} account" + end + end + + def money_from_authorization(auth) + _, _, amount = auth.split(/;/, 3) + amount.to_i # return the # of cents, no need to divide + end + + def message_from(response) + if(response[:faultcode] && response[:faultstring]) + response[:faultstring] + elsif(response[:error_number] && response[:error_number] != "0") + response[:error_description] + else + result = (response[:exact_message] || "") + result << " - #{response[:bank_message]}" if response[:bank_message].present? + result + end + end + + def parse_error(error) + { + :transaction_approved => "false", + :error_number => error.code, + :error_description => error.body + } + end + + def parse(xml) + response = {} + xml = REXML::Document.new(xml) + + if root = REXML::XPath.first(xml, "//TransactionResult") + parse_elements(response, root) + end + + response.delete_if{ |k,v| SENSITIVE_FIELDS.include?(k) } + end + + def parse_elements(response, root) + root.elements.to_a.each do |node| + response[node.name.gsub(/EXact/, "Exact").underscore.to_sym] = (node.text || "").strip + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/garanti.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/garanti.rb new file mode 100644 index 000000000..c6de668a1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/garanti.rb @@ -0,0 +1,257 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class GarantiGateway < Gateway + self.live_url = self.test_url = 'https://sanalposprov.garanti.com.tr/VPServlet' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US','TR'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # The homepage URL of the gateway + self.homepage_url = 'https://sanalposweb.garanti.com.tr' + + # The name of the gateway + self.display_name = 'Garanti Sanal POS' + + self.default_currency = 'TRL' + + self.money_format = :cents + + CURRENCY_CODES = { + 'YTL' => 949, + 'TRL' => 949, + 'TL' => 949, + 'USD' => 840, + 'EUR' => 978, + 'GBP' => 826, + 'JPY' => 392 + } + + + def initialize(options = {}) + requires!(options, :login, :password, :terminal_id, :merchant_id) + super + end + + def purchase(money, credit_card, options = {}) + options = options.merge(:gvp_order_type => "sales") + commit(money, build_sale_request(money, credit_card, options)) + end + + def authorize(money, credit_card, options = {}) + options = options.merge(:gvp_order_type => "preauth") + commit(money, build_authorize_request(money, credit_card, options)) + end + + def capture(money, ref_id, options = {}) + options = options.merge(:gvp_order_type => "postauth") + commit(money, build_capture_request(money, ref_id, options)) + end + + private + + def security_data + rjusted_terminal_id = @options[:terminal_id].to_s.rjust(9, "0") + Digest::SHA1.hexdigest(@options[:password].to_s + rjusted_terminal_id).upcase + end + + def generate_hash_data(order_id, terminal_id, credit_card_number, amount, security_data) + data = [order_id, terminal_id, credit_card_number, amount, security_data].join + Digest::SHA1.hexdigest(data).upcase + end + + def build_xml_request(money, credit_card, options, &block) + card_number = credit_card.respond_to?(:number) ? credit_card.number : '' + hash_data = generate_hash_data(format_order_id(options[:order_id]), @options[:terminal_id], card_number, amount(money), security_data) + + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8" + + xml.tag! 'GVPSRequest' do + xml.tag! 'Mode', test? ? 'TEST' : 'PROD' + xml.tag! 'Version', 'V0.01' + xml.tag! 'Terminal' do + xml.tag! 'ProvUserID', 'PROVAUT' + xml.tag! 'HashData', hash_data + xml.tag! 'UserID', @options[:login] + xml.tag! 'ID', @options[:terminal_id] + xml.tag! 'MerchantID', @options[:merchant_id] + end + + if block_given? + yield xml + else + xml.target! + end + end + end + + def build_sale_request(money, credit_card, options) + build_xml_request(money, credit_card, options) do |xml| + add_customer_data(xml, options) + add_order_data(xml, options) do |xml| + add_addresses(xml, options) + end + add_credit_card(xml, credit_card) + add_transaction_data(xml, money, options) + + xml.target! + end + end + + def build_authorize_request(money, credit_card, options) + build_xml_request(money, credit_card, options) do |xml| + add_customer_data(xml, options) + add_order_data(xml, options) do |xml| + add_addresses(xml, options) + end + add_credit_card(xml, credit_card) + add_transaction_data(xml, money, options) + + xml.target! + end + end + + def build_capture_request(money, ref_id, options) + options = options.merge(:order_id => ref_id) + build_xml_request(money, ref_id, options) do |xml| + add_customer_data(xml, options) + add_order_data(xml, options) + add_transaction_data(xml, money, options) + + xml.target! + end + end + + def add_customer_data(xml, options) + xml.tag! 'Customer' do + xml.tag! 'IPAddress', options[:ip] || '1.1.1.1' + xml.tag! 'EmailAddress', options[:email] + end + end + + def add_order_data(xml, options, &block) + xml.tag! 'Order' do + xml.tag! 'OrderID', format_order_id(options[:order_id]) + xml.tag! 'GroupID' + + if block_given? + yield xml + end + end + end + + def add_credit_card(xml, credit_card) + xml.tag! 'Card' do + xml.tag! 'Number', credit_card.number + xml.tag! 'ExpireDate', [format_exp(credit_card.month), format_exp(credit_card.year)].join + xml.tag! 'CVV2', credit_card.verification_value + end + end + + def format_exp(value) + format(value, :two_digits) + end + + # OrderId field must be A-Za-z0-9_ format and max 36 char + def format_order_id(order_id) + order_id.to_s.gsub(/[^A-Za-z0-9_]/, '')[0...36] + end + + def add_addresses(xml, options) + xml.tag! 'AddressList' do + if billing_address = options[:billing_address] || options[:address] + xml.tag! 'Address' do + xml.tag! 'Type', 'B' + add_address(xml, billing_address) + end + end + + if options[:shipping_address] + xml.tag! 'Address' do + xml.tag! 'Type', 'S' + add_address(xml, options[:shipping_address]) + end + end + end + end + + def add_address(xml, address) + xml.tag! 'Name', normalize(address[:name]) + address_text = address[:address1] + address_text << " #{ address[:address2]}" if address[:address2] + xml.tag! 'Text', normalize(address_text) + xml.tag! 'City', normalize(address[:city]) + xml.tag! 'District', normalize(address[:state]) + xml.tag! 'PostalCode', address[:zip] + xml.tag! 'Country', normalize(address[:country]) + xml.tag! 'Company', normalize(address[:company]) + xml.tag! 'PhoneNumber', address[:phone].to_s.gsub(/[^0-9]/, '') if address[:phone] + end + + def normalize(text) + return unless text + + if ActiveSupport::Inflector.method(:transliterate).arity == -2 + ActiveSupport::Inflector.transliterate(text,'') + elsif RUBY_VERSION >= '1.9' + text.gsub(/[^\x00-\x7F]+/, '') + else + ActiveSupport::Inflector.transliterate(text).to_s + end + end + + def add_transaction_data(xml, money, options) + xml.tag! 'Transaction' do + xml.tag! 'Type', options[:gvp_order_type] + xml.tag! 'Amount', amount(money) + xml.tag! 'CurrencyCode', currency_code(options[:currency] || currency(money)) + xml.tag! 'CardholderPresentCode', 0 + end + end + + def currency_code(currency) + CURRENCY_CODES[currency] || CURRENCY_CODES[default_currency] + end + + def commit(money,request) + raw_response = ssl_post(self.live_url, "data=" + request) + response = parse(raw_response) + + success = success?(response) + + Response.new(success, + success ? 'Approved' : "Declined (Reason: #{response[:reason_code]} - #{response[:error_msg]} - #{response[:sys_err_msg]})", + response, + :test => test?, + :authorization => response[:order_id]) + end + + def parse(body) + xml = REXML::Document.new(body) + + response = {} + xml.root.elements.to_a.each do |node| + parse_element(response, node) + end + response + end + + def parse_element(response, node) + if node.has_elements? + node.elements.each{|element| parse_element(response, element) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + def success?(response) + response[:message] == "Approved" + end + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/hdfc.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/hdfc.rb new file mode 100644 index 000000000..be9738577 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/hdfc.rb @@ -0,0 +1,207 @@ +require "nokogiri" + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class HdfcGateway < Gateway + self.display_name = "HDFC" + self.homepage_url = "http://www.hdfcbank.com/sme/sme-details/merchant-services/guzh6m0i" + + self.test_url = "https://securepgtest.fssnet.co.in/pgway/servlet/" + self.live_url = "https://securepg.fssnet.co.in/pgway/servlet/" + + self.supported_countries = ["IN"] + self.default_currency = "INR" + self.money_format = :dollars + self.supported_cardtypes = [:visa, :master, :discover, :diners_club] + + def initialize(options={}) + requires!(options, :login, :password) + super + end + + def purchase(amount, payment_method, options={}) + post = {} + add_invoice(post, amount, options) + add_payment_method(post, payment_method) + add_customer_data(post, options) + + commit("purchase", post) + end + + def authorize(amount, payment_method, options={}) + post = {} + add_invoice(post, amount, options) + add_payment_method(post, payment_method) + add_customer_data(post, options) + + commit("authorize", post) + end + + def capture(amount, authorization, options={}) + post = {} + add_invoice(post, amount, options) + add_reference(post, authorization) + add_customer_data(post, options) + + commit("capture", post) + end + + def refund(amount, authorization, options={}) + post = {} + add_invoice(post, amount, options) + add_reference(post, authorization) + add_customer_data(post, options) + + commit("refund", post) + end + + private + + CURRENCY_CODES = Hash.new{|h,k| raise ArgumentError.new("Unsupported currency for HDFC: #{k}")} + CURRENCY_CODES["AED"] = "784" + CURRENCY_CODES["AUD"] = "036" + CURRENCY_CODES["CAD"] = "124" + CURRENCY_CODES["EUR"] = "978" + CURRENCY_CODES["GBP"] = "826" + CURRENCY_CODES["INR"] = "356" + CURRENCY_CODES["OMR"] = "512" + CURRENCY_CODES["QAR"] = "634" + CURRENCY_CODES["SGD"] = "702" + CURRENCY_CODES["USD"] = "840" + + def add_invoice(post, amount, options) + post[:amt] = amount(amount) + post[:currencycode] = CURRENCY_CODES[options[:currency] || currency(amount)] + post[:trackid] = escape(options[:order_id], 40) if options[:order_id] + post[:udf1] = escape(options[:description]) if options[:description] + post[:eci] = options[:eci] if options[:eci] + end + + def add_customer_data(post, options) + post[:udf2] = escape(options[:email]) if options[:email] + if address = (options[:billing_address] || options[:address]) + post[:udf3] = escape(address[:phone]) if address[:phone] + post[:udf4] = escape(< "1", + "refund" => "2", + "authorize" => "4", + "capture" => "5", + } + + def commit(action, post) + post[:id] = @options[:login] + post[:password] = @options[:password] + post[:action] = ACTIONS[action] if ACTIONS[action] + + raw = parse(ssl_post(url(action), build_request(post))) + + succeeded = success_from(raw[:result]) + Response.new( + succeeded, + message_from(succeeded, raw), + raw, + :authorization => authorization_from(post, raw), + :test => test? + ) + end + + def build_request(post) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + post.each do |field, value| + xml.tag!(field, value) + end + xml.target! + end + + def url(action) + endpoint = "TranPortalXMLServlet" + (test? ? test_url : live_url) + endpoint + end + + def success_from(result) + case result + when "CAPTURED", "APPROVED", "NOT ENROLLED", "ENROLLED" + true + else + false + end + end + + def message_from(succeeded, response) + if succeeded + "Succeeded" + else + (response[:error_text] || response[:result] || "Unable to read error message").split("-").last + end + end + + def authorization_from(request, response) + [response[:tranid], request[:member]].join("|") + end + + def split_authorization(authorization) + tranid, member = authorization.split("|") + [tranid, member] + end + + def escape(string, max_length=250) + return "" unless string + if max_length + string = string[0...max_length] + end + string.gsub(/[^A-Za-z0-9 \-_@\.\n]/, '') + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_base.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_base.rb new file mode 100644 index 000000000..360f0ad5e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_base.rb @@ -0,0 +1,249 @@ +require File.dirname(__FILE__) + '/ideal_response' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # Implementation contains some simplifications + # - does not support multiple subID per merchant + # - language is fixed to 'nl' + class IdealBaseGateway < Gateway + class_attribute :server_pem, :pem_password, :default_expiration_period + self.default_expiration_period = 'PT10M' + self.default_currency = 'EUR' + self.pem_password = true + + self.abstract_class = true + + # These constants will never change for most users + AUTHENTICATION_TYPE = 'SHA1_RSA' + LANGUAGE = 'nl' + SUB_ID = '0' + API_VERSION = '1.1.0' + + def initialize(options = {}) + requires!(options, :login, :password, :pem) + + options[:pem_password] = options[:password] + super + end + + # Setup transaction. Get redirect_url from response.service_url + def setup_purchase(money, options = {}) + requires!(options, :issuer_id, :return_url, :order_id, :currency, :description, :entrance_code) + + commit(build_transaction_request(money, options)) + end + + # Check status of transaction and confirm payment + # transaction_id must be a valid transaction_id from a prior setup. + def capture(transaction, options = {}) + options[:transaction_id] = transaction + commit(build_status_request(options)) + end + + # Get list of issuers from response.issuer_list + def issuers + commit(build_directory_request) + end + + private + + def url + (test? ? test_url : live_url) + end + + def token + if @token.nil? + @token = create_fingerprint(@options[:pem]) + end + @token + end + + # + # + # 2001-12-17T09:30:47.0Z + # + # 1003 + # + # + # 000123456 + # 0 + # passkey + # 1 + # 3823ad872eff23 + # https://www.mijnwinkel.nl/betaalafhandeling + # + # + # + # iDEAL-aankoop 21 + # 5999 + # EUR + # PT3M30S + # nl + # Documentensuite + # D67tyx6rw9IhY71 + # + # + def build_transaction_request(money, options) + date_time_stamp = create_time_stamp + message = date_time_stamp + + options[:issuer_id] + + @options[:login] + + SUB_ID + + options[:return_url] + + options[:order_id] + + money.to_s + + (options[:currency] || currency(money)) + + LANGUAGE + + options[:description] + + options[:entrance_code] + token_code = sign_message(@options[:pem], @options[:password], message) + + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct! + xml.tag! 'AcquirerTrxReq', 'xmlns' => 'http://www.idealdesk.com/Message', 'version' => API_VERSION do + xml.tag! 'createDateTimeStamp', date_time_stamp + xml.tag! 'Issuer' do + xml.tag! 'issuerID', options[:issuer_id] + end + xml.tag! 'Merchant' do + xml.tag! 'merchantID', @options[:login] + xml.tag! 'subID', SUB_ID + xml.tag! 'authentication', AUTHENTICATION_TYPE + xml.tag! 'token', token + xml.tag! 'tokenCode', token_code + xml.tag! 'merchantReturnURL', options[:return_url] + end + xml.tag! 'Transaction' do + xml.tag! 'purchaseID', options[:order_id] + xml.tag! 'amount', money + xml.tag! 'currency', options[:currency] + xml.tag! 'expirationPeriod', options[:expiration_period] || default_expiration_period + xml.tag! 'language', LANGUAGE + xml.tag! 'description', options[:description] + xml.tag! 'entranceCode', options[:entrance_code] + end + xml.target! + end + end + + # + # + # 2001-12-17T09:30:47.0Z + # + # 000123456 + # 0 + # keyed hash + # 1 + # 3823ad872eff23 + # + # + # 0001023456789112 + # + # + def build_status_request(options) + datetimestamp = create_time_stamp + message = datetimestamp + @options[:login] + SUB_ID + options[:transaction_id] + tokenCode = sign_message(@options[:pem], @options[:password], message) + + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct! + xml.tag! 'AcquirerStatusReq', 'xmlns' => 'http://www.idealdesk.com/Message', 'version' => API_VERSION do + xml.tag! 'createDateTimeStamp', datetimestamp + xml.tag! 'Merchant' do + xml.tag! 'merchantID', @options[:login] + xml.tag! 'subID', SUB_ID + xml.tag! 'authentication' , AUTHENTICATION_TYPE + xml.tag! 'token', token + xml.tag! 'tokenCode', tokenCode + end + xml.tag! 'Transaction' do + xml.tag! 'transactionID', options[:transaction_id] + end + end + xml.target! + end + + # + # + # 2001-12-17T09:30:47.0Z + # + # 000000001 + # 0 + # 1 + # hashkey + # WajqV1a3nDen0be2r196g9FGFF= + # + # + def build_directory_request + datetimestamp = create_time_stamp + message = datetimestamp + @options[:login] + SUB_ID + tokenCode = sign_message(@options[:pem], @options[:password], message) + + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct! + xml.tag! 'DirectoryReq', 'xmlns' => 'http://www.idealdesk.com/Message', 'version' => API_VERSION do + xml.tag! 'createDateTimeStamp', datetimestamp + xml.tag! 'Merchant' do + xml.tag! 'merchantID', @options[:login] + xml.tag! 'subID', SUB_ID + xml.tag! 'authentication', AUTHENTICATION_TYPE + xml.tag! 'token', token + xml.tag! 'tokenCode', tokenCode + end + end + xml.target! + end + + def commit(request) + raw_response = ssl_post(url, request) + response = Hash.from_xml(raw_response.to_s) + response_type = response.keys[0] + + case response_type + when 'AcquirerTrxRes', 'DirectoryRes' + success = true + when 'ErrorRes' + success = false + when 'AcquirerStatusRes' + raise SecurityError, "Message verification failed.", caller unless status_response_verified?(response) + success = (response['AcquirerStatusRes']['Transaction']['status'] == 'Success') + else + raise ArgumentError, "Unknown response type.", caller + end + + return IdealResponse.new(success, response.keys[0], response, :test => test?) + end + + def create_fingerprint(cert_file) + cert_data = OpenSSL::X509::Certificate.new(cert_file).to_s + cert_data = cert_data.sub(/-----BEGIN CERTIFICATE-----/, '') + cert_data = cert_data.sub(/-----END CERTIFICATE-----/, '') + fingerprint = Base64.decode64(cert_data) + fingerprint = Digest::SHA1.hexdigest(fingerprint) + return fingerprint.upcase + end + + def sign_message(private_key_data, password, data) + private_key = OpenSSL::PKey::RSA.new(private_key_data, password) + signature = private_key.sign(OpenSSL::Digest::SHA1.new, data.gsub('\s', '')) + return Base64.encode64(signature).gsub(/\n/, '') + end + + def verify_message(cert_file, data, signature) + public_key = OpenSSL::X509::Certificate.new(cert_file).public_key + return public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(signature), data) + end + + def status_response_verified?(response) + transaction = response['AcquirerStatusRes']['Transaction'] + message = response['AcquirerStatusRes']['createDateTimeStamp'] + transaction['transactionID' ] + transaction['status'] + message << transaction['consumerAccountNumber'].to_s + verify_message(server_pem, message, response['AcquirerStatusRes']['Signature']['signatureValue']) + end + + def create_time_stamp + Time.now.gmtime.strftime('%Y-%m-%dT%H:%M:%S.000Z') + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem new file mode 100755 index 000000000..3259cfa33 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICQDCCAakCBELvbPYwDQYJKoZIhvcNAQEEBQAwZzELMAkGA1UEBhMCREUxDzANBgNVBAgTBkhl +c3NlbjESMBAGA1UEBxMJRnJhbmtmdXJ0MQ4wDAYDVQQKEwVpREVBTDEOMAwGA1UECxMFaURFQUwx +EzARBgNVBAMTCmlERUFMIFJhYm8wHhcNMDUwODAyMTI1NDE0WhcNMTUwNzMxMTI1NDE0WjBnMQsw +CQYDVQQGEwJERTEPMA0GA1UECBMGSGVzc2VuMRIwEAYDVQQHEwlGcmFua2Z1cnQxDjAMBgNVBAoT +BWlERUFMMQ4wDAYDVQQLEwVpREVBTDETMBEGA1UEAxMKaURFQUwgUmFibzCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEA486iIKVhr8RNjxH+PZ3yTWx/8k2fqDFm8XU8I1Z5esRmPFnXmlgA8cG7 +e9AaBPaLoP7Dc8dRQoUO66KMakzGI/WAVdHIJiiKrz8xOcioIgrzPSqec7aqse3J28UraEHkGESJ +7dAW7Pw/shrmpmkzKsunLt6AkXss4W3JUndZUN0CAwEAATANBgkqhkiG9w0BAQQFAAOBgQCGy/FK +Lotp2ZOTtuLMgvDy74eicq/Znv4bLfpglzAPHycRHcHsXuer/lNHyvpKf2gdYe+IFalUW3OJZWIM +jpm4UniJ16RPdgwWVRJEdPr/P7JXMIqD2IEOgujuuTQ7x0VgCf9XrsPsP9ZR5DIPcDDhbrpSE0yF +Do77nwG61xMaGA== +-----END CERTIFICATE----- diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_response.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_response.rb new file mode 100644 index 000000000..e050964ae --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal/ideal_response.rb @@ -0,0 +1,29 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class IdealResponse < Response + + def issuer_list + list = @params.values[0]['Directory']['Issuer'] + case list + when Hash + return [list] + when Array + return list + end + end + + def service_url + @params.values[0]['Issuer']['issuerAuthenticationURL'] + end + + def transaction + @params.values[0]['Transaction'] + end + + def error + @params.values[0]['Error'] + end + + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal_rabobank.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal_rabobank.rb new file mode 100644 index 000000000..1edf7bfbc --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ideal_rabobank.rb @@ -0,0 +1,66 @@ +require File.dirname(__FILE__) + '/ideal/ideal_base' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # First, make sure you have everything setup correctly and all of your dependencies in place with: + # + # require 'rubygems' + # require 'active_merchant' + # + # ActiveMerchant expects the amounts to be given as an Integer in cents. In this case, 10 EUR becomes 1000. + # + # Create certificates for authentication: + # + # The PEM file expected should contain both the certificate and the generated PEM file. + # Some sample shell commands to generate the certificates: + # + # openssl genrsa -aes128 -out priv.pem -passout pass:[YOUR PASSWORD] 1024 + # openssl req -x509 -new -key priv.pem -passin pass:[YOUR PASSWORD] -days 3000 -out cert.cer + # cat cert.cer priv.pem > ideal.pem + # + # Following the steps above, upload cert.cer to the ideal web interface and pass the path of ideal.pem to the :pem option. + # + # Configure the gateway using your iDEAL bank account info and security settings: + # + # Create gateway: + # gateway = ActiveMerchant::Billing::IdealRabobankGateway.new( + # :login => '123456789', # 9 digit merchant number + # :pem => File.read(Rails.root + 'config/ideal.pem'), + # :password => 'password' # password for the PEM key + # ) + # + # Get list of issuers to fill selection list on your payment form: + # response = gateway.issuers + # list = response.issuer_list + # + # Request transaction: + # + # options = { + # :issuer_id => '0001', + # :expiration_period => 'PT10M', + # :return_url => 'http://www.return.url', + # :order_id => '1234567890123456', + # :currency => 'EUR', + # :description => 'Een omschrijving', + # :entrance_code => '1234' + # } + # + # response = gateway.setup_purchase(amount, options) + # transaction_id = response.transaction['transactionID'] + # redirect_url = response.service_url + # + # Mandatory status request will confirm transaction: + # response = gateway.capture(transaction_id) + # + # Implementation contains some simplifications + # - does not support multiple subID per merchant + # - language is fixed to 'nl' + class IdealRabobankGateway < IdealBaseGateway + class_attribute :test_url, :live_url + + self.test_url = 'https://idealtest.rabobank.nl/ideal/iDeal' + self.live_url = 'https://ideal.rabobank.nl/ideal/iDeal' + self.server_pem = File.read(File.dirname(__FILE__) + '/ideal/ideal_rabobank.pem') + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/inspire.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/inspire.rb new file mode 100644 index 000000000..a3646b7ff --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/inspire.rb @@ -0,0 +1,221 @@ +require File.join(File.dirname(__FILE__), '..', 'check.rb') +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class InspireGateway < Gateway + self.live_url = self.test_url = 'https://secure.inspiregateway.net/api/transact.php' + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express] + self.homepage_url = 'http://www.inspiregateway.com' + self.display_name = 'Inspire Commerce' + + # Creates a new InspireGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The Inspire Username. + # * :password -- The Inspire Passowrd. + # See the Inspire Integration Guide for details. (default: +false+) + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Pass :store => true in the options to store the + # payment info at Inspire Gateway and get a generated + # customer_vault_id in the response. + # Pass :store => some_number_or_string to specify the + # customer_vault_id InspireGateway should use (make sure it's + # unique). + def authorize(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_payment_source(post, creditcard,options) + add_address(post, creditcard, options) + add_customer_data(post, options) + + commit('auth', money, post) + end + + def purchase(money, payment_source, options = {}) + post = {} + add_invoice(post, options) + add_payment_source(post, payment_source, options) + add_address(post, payment_source, options) + add_customer_data(post, options) + + commit('sale', money, post) + end + + def capture(money, authorization, options = {}) + post ={} + post[:transactionid] = authorization + commit('capture', money, post) + end + + def void(authorization, options = {}) + post ={} + post[:transactionid] = authorization + commit('void', nil, post) + end + + # Update the values (such as CC expiration) stored at + # InspireGateway. The CC number must be supplied in the + # CreditCard object. + def update(vault_id, creditcard, options = {}) + post = {} + post[:customer_vault] = "update_customer" + add_customer_vault_id(post, vault_id) + add_creditcard(post, creditcard, options) + add_address(post, creditcard, options) + add_customer_data(post, options) + + commit(nil, nil, post) + end + + def delete(vault_id) + post = {} + post[:customer_vault] = "delete_customer" + add_customer_vault_id(post, vault_id) + commit(nil, nil, post) + end + + # To match the other stored-value gateways, like TrustCommerce, + # store and unstore need to be defined + def store(creditcard, options = {}) + billing_id = options.delete(:billing_id).to_s || true + authorize(100, creditcard, options.merge(:store => billing_id)) + end + + alias_method :unstore, :delete + + private + def add_customer_data(post, options) + if options.has_key? :email + post[:email] = options[:email] + end + + if options.has_key? :ip + post[:ipaddress] = options[:ip] + end + end + + def add_address(post, creditcard, options) + if address = options[:billing_address] || options[:address] + post[:address1] = address[:address1].to_s + post[:address2] = address[:address2].to_s unless address[:address2].blank? + post[:company] = address[:company].to_s + post[:phone] = address[:phone].to_s + post[:zip] = address[:zip].to_s + post[:city] = address[:city].to_s + post[:country] = address[:country].to_s + post[:state] = address[:state].blank? ? 'n/a' : address[:state] + end + end + + def add_invoice(post, options) + post[:orderid] = options[:order_id].to_s.gsub(/[^\w.]/, '') + post[:orderdescription] = options[:description] + end + + def add_payment_source(params, source, options={}) + case determine_funding_source(source) + when :vault then add_customer_vault_id(params, source) + when :credit_card then add_creditcard(params, source, options) + when :check then add_check(params, source) + end + end + + def add_customer_vault_id(params,vault_id) + params[:customer_vault_id] = vault_id + end + + def add_creditcard(post, creditcard,options) + if options[:store] + post[:customer_vault] = "add_customer" + post[:customer_vault_id] = options[:store] unless options[:store] == true + end + post[:ccnumber] = creditcard.number + post[:cvv] = creditcard.verification_value if creditcard.verification_value? + post[:ccexp] = expdate(creditcard) + post[:firstname] = creditcard.first_name + post[:lastname] = creditcard.last_name + end + + def add_check(post, check) + post[:payment] = 'check' # Set transaction to ACH + post[:checkname] = check.name # The name on the customer's Checking Account + post[:checkaba] = check.routing_number # The customer's bank routing number + post[:checkaccount] = check.account_number # The customer's account number + post[:account_holder_type] = check.account_holder_type # The customer's type of ACH account + post[:account_type] = check.account_type # The customer's type of ACH account + end + + def parse(body) + results = {} + body.split(/&/).each do |pair| + key,val = pair.split(/=/) + results[key] = val + end + + results + end + + def commit(action, money, parameters) + parameters[:amount] = amount(money) if money + + response = parse( ssl_post(self.live_url, post_data(action,parameters)) ) + + Response.new(response["response"] == "1", message_from(response), response, + :authorization => response["transactionid"], + :test => test?, + :cvv_result => response["cvvresponse"], + :avs_result => { :code => response["avsresponse"] } + ) + + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + + "#{month}#{year[-2..-1]}" + end + + + def message_from(response) + case response["responsetext"] + when "SUCCESS","Approved" + "This transaction has been approved" + when "DECLINE" + "This transaction has been declined" + else + response["responsetext"] + end + end + + def post_data(action, parameters = {}) + post = {} + post[:username] = @options[:login] + post[:password] = @options[:password] + post[:type] = action if action + + request = post.merge(parameters).map {|key,value| "#{key}=#{CGI.escape(value.to_s)}"}.join("&") + request + end + + def determine_funding_source(source) + case + when source.is_a?(String) then :vault + when CreditCard.card_companies.keys.include?(card_brand(source)) then :credit_card + when card_brand(source) == 'check' then :check + else raise ArgumentError, "Unsupported funding source provided" + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/instapay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/instapay.rb new file mode 100755 index 000000000..ee4ddc550 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/instapay.rb @@ -0,0 +1,163 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class InstapayGateway < Gateway + self.live_url = 'https://trans.instapaygateway.com/cgi-bin/process.cgi' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + self.money_format = :dollars + self.default_currency = 'USD' + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.instapayllc.com' + + # The name of the gateway + self.display_name = 'InstaPay' + + SUCCESS = "Accepted" + SUCCESS_MESSAGE = "The transaction has been approved" + + def initialize(options = {}) + requires!(options, :login) + super + end + + def authorize(money, creditcard, options = {}) + post = {} + post[:authonly] = 1 + add_amount(post, money) + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + + commit('ns_quicksale_cc', post) + end + + def purchase(money, creditcard, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + + commit('ns_quicksale_cc', post) + end + + def capture(money, authorization, options = {}) + post = {} + add_amount(post, money) + add_reference(post, authorization) + commit('ns_quicksale_cc', post) + end + + private + + def add_amount(post, money) + post[:amount] = amount(money) + end + + def add_reference(post, reference) + post[:postonly] = reference + end + + def add_customer_data(post, options) + post[:ci_email] = options[:email] + post["ci_IP Address"] = options[:ip] + end + + def add_address(post, options) + if address = options[:billing_address] || options[:address] + post[:ci_billaddr1] = address[:address1] + post[:ci_billaddr2] = address[:address2] + post[:ci_billcity] = address[:city] + post[:ci_billstate] = address[:state] + post[:ci_billzip] = address[:zip] + post[:ci_billcountry] = address[:country] + post[:ci_phone] = address[:phone] + end + + if address = options[:shipping_address] + post[:ci_shipaddr1] = address[:address1] + post[:ci_shipaddr2] = address[:address2] + post[:ci_shipcity] = address[:city] + post[:ci_shipstate] = address[:state] + post[:ci_shipzip] = address[:zip] + post[:ci_shipcountry] = address[:country] + end + end + + def add_invoice(post, options) + post[:merchantordernumber] = options[:order_id] + post[:ci_memo] = options[:description] + post[:pocustomerrefid] = options[:invoice] + end + + def add_creditcard(post, creditcard) + post[:ccnum] = creditcard.number + post[:expmon] = format(creditcard.month, :two_digits) + post[:cvv2] = creditcard.verification_value if creditcard.verification_value? + post[:expyear] = creditcard.year + post[:ccname] = creditcard.name + end + + def parse(body) + results = {} + fields = body.split("\r\n") + + response = fields[1].split('=') + response_data = response[1].split(':') + + if response[0] == SUCCESS + results[:success] = true + results[:message] = SUCCESS_MESSAGE + results[:transaction_type] = response_data[0] + results[:authorization_code] = response_data[1] + results[:reference_number] = response_data[2] + results[:batch_number] = response_data[3] + results[:transaction_id] = response_data[4] + results[:avs_result] = response_data[5] + results[:authorize_net] = response_data[6] + results[:cvv_result] = response_data[7] + else + results[:success] = false + results[:result] = response_data[0] + results[:response_code] = response_data[1] + results[:message] = response_data[2] + end + + fields[1..-1].each do |pair| + key, value = pair.split('=') + results[key] = value + end + results + end + + def commit(action, parameters) + data = ssl_post self.live_url, post_data(action, parameters) + response = parse(data) + + Response.new(response[:success] , response[:message], response, + :authorization => response[:transaction_id], + :avs_result => { :code => response[:avs_result] }, + :cvv_result => response[:cvv_result] + ) + end + + def post_data(action, parameters = {}) + post = {} + post[:acctid] = @options[:login] + if(@options[:password]) + post[:merchantpin] = @options[:password] + end + post[:action] = action + request = post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + request + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/iridium.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/iridium.rb new file mode 100644 index 000000000..f0156b3d5 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/iridium.rb @@ -0,0 +1,262 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # For more information on the Iridium Gateway please download the + # documentation from their Merchant Management System. + # + # The login and password are not the username and password you use to + # login to the Iridium Merchant Management System. Instead, you will + # use the API username and password you were issued separately. + class IridiumGateway < Gateway + self.live_url = self.test_url = 'https://gw1.iridiumcorp.net/' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['GB', 'ES'] + self.default_currency = 'EUR' + self.money_format = :cents + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :maestro, :jcb, :solo, :diners_club] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.iridiumcorp.co.uk/' + + # The name of the gateway + self.display_name = 'Iridium' + + CURRENCY_CODES = { + "AUD" => '036', + "CAD" => '124', + "EUR" => '978', + "GBP" => '826', + "MXN" => '484', + "NZD" => '554', + "USD" => '840', + } + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, payment_source, options = {}) + setup_address_hash(options) + + if payment_source.respond_to?(:number) + commit(build_purchase_request('PREAUTH', money, payment_source, options), options) + else + commit(build_reference_request('PREAUTH', money, payment_source, options), options) + end + end + + def purchase(money, payment_source, options = {}) + setup_address_hash(options) + + if payment_source.respond_to?(:number) + commit(build_purchase_request('SALE', money, payment_source, options), options) + else + commit(build_reference_request('SALE', money, payment_source, options), options) + end + end + + def capture(money, authorization, options = {}) + commit(build_reference_request('COLLECTION', money, authorization, options), options) + end + + def credit(money, authorization, options={}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + def refund(money, authorization, options={}) + commit(build_reference_request('REFUND', money, authorization, options), options) + end + + def void(authorization, options={}) + commit(build_reference_request('VOID', nil, authorization, options), options) + end + + private + + def build_purchase_request(type, money, creditcard, options) + options.merge!(:action => 'CardDetailsTransaction') + build_request(options) do |xml| + add_purchase_data(xml, type, money, options) + add_creditcard(xml, creditcard) + add_customerdetails(xml, creditcard, options[:billing_address], options) + end + end + + def build_reference_request(type, money, authorization, options) + options.merge!(:action => 'CrossReferenceTransaction') + order_id, cross_reference, auth_id = authorization.split(";") + build_request(options) do |xml| + if money + details = {'CurrencyCode' => currency_code(options[:currency] || default_currency), 'Amount' => amount(money)} + else + details = {'CurrencyCode' => currency_code(default_currency), 'Amount' => '0'} + end + xml.tag! 'TransactionDetails', details do + xml.tag! 'MessageDetails', {'TransactionType' => type, 'CrossReference' => cross_reference} + xml.tag! 'OrderID', (options[:order_id] || order_id) + end + end + end + + def build_request(options) + requires!(options, :action) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct!(:xml, :version => '1.0', :encoding => 'utf-8') + xml.tag! 'soap:Envelope', { 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do + xml.tag! 'soap:Body' do + xml.tag! options[:action], {'xmlns' => "https://www.thepaymentgateway.net/"} do + xml.tag! 'PaymentMessage' do + add_merchant_data(xml, options) + yield(xml) + end + end + end + end + xml.target! + end + + def setup_address_hash(options) + options[:billing_address] = options[:billing_address] || options[:address] || {} + options[:shipping_address] = options[:shipping_address] || {} + end + + def add_purchase_data(xml, type, money, options) + requires!(options, :order_id) + xml.tag! 'TransactionDetails', {'Amount' => amount(money), 'CurrencyCode' => currency_code(options[:currency] || currency(money))} do + xml.tag! 'MessageDetails', {'TransactionType' => type} + xml.tag! 'OrderID', options[:order_id] + xml.tag! 'TransactionControl' do + xml.tag! 'ThreeDSecureOverridePolicy', 'FALSE' + xml.tag! 'EchoAVSCheckResult', 'TRUE' + xml.tag! 'EchoCV2CheckResult', 'TRUE' + end + end + end + + def add_customerdetails(xml, creditcard, address, options, shipTo = false) + xml.tag! 'CustomerDetails' do + if address + unless address[:country].blank? + country_code = Country.find(address[:country]).code(:numeric) + end + xml.tag! 'BillingAddress' do + xml.tag! 'Address1', address[:address1] + xml.tag! 'Address2', address[:address2] + xml.tag! 'City', address[:city] + xml.tag! 'State', address[:state] + xml.tag! 'PostCode', address[:zip] + xml.tag! 'CountryCode', country_code if country_code + end + xml.tag! 'PhoneNumber', address[:phone] + end + + xml.tag! 'EmailAddress', options[:email] + xml.tag! 'CustomerIPAddress', options[:ip] || "127.0.0.1" + end + end + + def add_creditcard(xml, creditcard) + xml.tag! 'CardDetails' do + xml.tag! 'CardName', creditcard.name + xml.tag! 'CV2', creditcard.verification_value if creditcard.verification_value + xml.tag! 'CardNumber', creditcard.number + xml.tag! 'ExpiryDate', { 'Month' => creditcard.month.to_s.rjust(2, "0"), 'Year' => creditcard.year.to_s[/\d\d$/] } + end + end + + def add_merchant_data(xml, options) + xml.tag! 'MerchantAuthentication', {"MerchantID" => @options[:login], "Password" => @options[:password]} + end + + def commit(request, options) + requires!(options, :action) + response = parse(ssl_post(test? ? self.test_url : self.live_url, request, + {"SOAPAction" => "https://www.thepaymentgateway.net/#{options[:action]}", + "Content-Type" => "text/xml; charset=utf-8" })) + + success = response[:transaction_result][:status_code] == "0" + message = response[:transaction_result][:message] + authorization = success ? [ options[:order_id], response[:transaction_output_data][:cross_reference], response[:transaction_output_data][:auth_code] ].compact.join(";") : nil + + Response.new(success, message, response, + :test => test?, + :authorization => authorization) + end + + def parse(xml) + reply = {} + xml = REXML::Document.new(xml) + if (root = REXML::XPath.first(xml, "//CardDetailsTransactionResponse")) or + (root = REXML::XPath.first(xml, "//CrossReferenceTransactionResponse")) + root.elements.to_a.each do |node| + case node.name + when 'Message' + reply[:message] = reply(node.text) + else + parse_element(reply, node) + end + end + elsif root = REXML::XPath.first(xml, "//soap:Fault") + parse_element(reply, root) + reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}" + end + reply + end + + def parse_element(reply, node) + case node.name + when "CrossReferenceTransactionResult" + reply[:transaction_result] = {} + node.attributes.each do |a,b| + reply[:transaction_result][a.underscore.to_sym] = b + end + node.elements.each{|e| parse_element(reply[:transaction_result], e) } if node.has_elements? + + when "CardDetailsTransactionResult" + reply[:transaction_result] = {} + node.attributes.each do |a,b| + reply[:transaction_result][a.underscore.to_sym] = b + end + node.elements.each{|e| parse_element(reply[:transaction_result], e) } if node.has_elements? + + when "TransactionOutputData" + reply[:transaction_output_data] = {} + node.attributes.each{|a,b| reply[:transaction_output_data][a.underscore.to_sym] = b } + node.elements.each{|e| parse_element(reply[:transaction_output_data], e) } if node.has_elements? + when "CustomVariables" + reply[:custom_variables] = {} + node.attributes.each{|a,b| reply[:custom_variables][a.underscore.to_sym] = b } + node.elements.each{|e| parse_element(reply[:custom_variables], e) } if node.has_elements? + when "GatewayEntryPoints" + reply[:gateway_entry_points] = {} + node.attributes.each{|a,b| reply[:gateway_entry_points][a.underscore.to_sym] = b } + node.elements.each{|e| parse_element(reply[:gateway_entry_points], e) } if node.has_elements? + else + k = node.name.underscore.to_sym + if node.has_elements? + reply[k] = {} + node.elements.each{|e| parse_element(reply[k], e) } + else + if node.has_attributes? + reply[k] = {} + node.attributes.each{|a,b| reply[k][a.underscore.to_sym] = b } + else + reply[k] = node.text + end + end + end + reply + end + + def currency_code(currency) + CURRENCY_CODES[currency] + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/itransact.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/itransact.rb new file mode 100644 index 000000000..0d96f7556 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/itransact.rb @@ -0,0 +1,448 @@ +require 'nokogiri' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # iTransact, Inc. is an authorized reseller of the PaymentClearing gateway. If your merchant service provider uses PaymentClearing.com to process payments, you can use this module. + # + # + # Please note, the username and API Access Key are not what you use to log into the Merchant Control Panel. + # + # ==== How to get your GatewayID and API Access Key + # + # 1. If you don't already have a Gateway Account, go to http://www.itransact.com/merchant/test.html to sign up. + # 2. Go to http://support.paymentclearing.com and login or register, if necessary. + # 3. Click on "Submit a Ticket." + # 4. Select "Merchant Support" as the department and click "Next" + # 5. Enter *both* your company name and GatewayID. Put "API Access Key" in the subject. In the body, you can request a username, but it may already be in use. + # + # ==== Initialization + # + # Once you have the username, API Access Key, and your GatewayId, you're ready + # to begin. You initialize the Gateway like so: + # + # gateway = ActiveMerchant::Billing::ItransactGateway.new( + # :login => "#{THE_USERNAME}", + # :password => "#{THE_API_ACCESS_KEY}", + # :gateway_id => "#{THE_GATEWAY_ID}" + # ) + # + # ==== Important Notes + # 1. Recurring is not implemented + # 1. CreditTransactions are not implemented (these are credits not related to a previously run transaction). + # 1. TransactionStatus is not implemented + # + class ItransactGateway < Gateway + self.live_url = self.test_url = 'https://secure.paymentclearing.com/cgi-bin/rc/xmltrans2.cgi' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.itransact.com/' + + # The name of the gateway + self.display_name = 'iTransact' + + # + # Creates a new instance of the iTransact Gateway. + # + # ==== Parameters + # * options - A Hash of options + # + # ==== Options Hash + # * :login - A String containing your PaymentClearing assigned API Access Username + # * :password - A String containing your PaymentClearing assigned API Access Key + # * :gateway_id - A String containing your PaymentClearing assigned GatewayID + # * :test_mode - true or false. Run *all* transactions with the 'TestMode' element set to 'TRUE'. + # + def initialize(options = {}) + requires!(options, :login, :password, :gateway_id) + super + end + + # Performs an authorize transaction. In PaymentClearing's documentation + # this is known as a "PreAuth" transaction. + # + # ==== Parameters + # * money - The amount to be captured. Should be an Integer amount in cents. + # * creditcard - The CreditCard details for the transaction + # * options - A Hash of options + # + # ==== Options Hash + # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as: + # * :order_items - An Array of Hash objects with the keys :description, :cost (in cents!), and :quantity. If this is provided, :description and money will be ignored. + # * :vendor_data - An Array of Hash objects with the keys being the name of the VendorData element and value being the value. + # * :send_customer_email - true or false. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'. + # * :send_merchant_email - true or false. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'. + # * :email_text - An Array of (up to ten (10)) String objects to be included in emails + # * :test_mode - true or false. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'. + # + # ==== Examples + # response = gateway.authorize(1000, creditcard, + # :order_id => '1212', :address => {...}, :email => 'test@test.com', + # :order_items => [ + # {:description => 'Line Item 1', :cost => '8.98', :quantity => '6'}, + # {:description => 'Line Item 2', :cost => '6.99', :quantity => '4'} + # ], + # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}], + # :send_customer_email => true, + # :send_merchant_email => true, + # :email_text => ['line1', 'line2', 'line3'], + # :test_mode => true + # ) + # + def authorize(money, payment_source, options = {}) + payload = Nokogiri::XML::Builder.new do |xml| + xml.AuthTransaction { + xml.Preauth + add_customer_data(xml, payment_source, options) + add_invoice(xml, money, options) + add_payment_source(xml, payment_source) + add_transaction_control(xml, options) + add_vendor_data(xml, options) + } + end.doc + + commit(payload) + end + + # Performs an authorize and capture in single transaction. In PaymentClearing's + # documentation this is known as an "Auth" or a "Sale" transaction + # + # ==== Parameters + # * money - The amount to be captured. Should be nil or an Integer amount in cents. + # * creditcard - The CreditCard details for the transaction + # * options - A Hash of options + # + # ==== Options Hash + # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as: + # * :order_items - An Array of Hash objects with the keys :description, :cost (in cents!), and :quantity. If this is provided, :description and money will be ignored. + # * :vendor_data - An Array of Hash objects with the keys being the name of the VendorData element and value being the value. + # * :send_customer_email - true or false. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'. + # * :send_merchant_email - true or false. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'. + # * :email_text - An Array of (up to ten (10)) String objects to be included in emails + # * :test_mode - true or false. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'. + # + # ==== Examples + # response = gateway.purchase(1000, creditcard, + # :order_id => '1212', :address => {...}, :email => 'test@test.com', + # :order_items => [ + # {:description => 'Line Item 1', :cost => '8.98', :quantity => '6'}, + # {:description => 'Line Item 2', :cost => '6.99', :quantity => '4'} + # ], + # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}], + # :send_customer_email => true, + # :send_merchant_email => true, + # :email_text => ['line1', 'line2', 'line3'], + # :test_mode => true + # ) + # + def purchase(money, payment_source, options = {}) + payload = Nokogiri::XML::Builder.new do |xml| + xml.AuthTransaction { + add_customer_data(xml, payment_source, options) + add_invoice(xml, money, options) + add_payment_source(xml, payment_source) + add_transaction_control(xml, options) + add_vendor_data(xml, options) + } + end.doc + + commit(payload) + end + + # Captures the funds from an authorize transaction. In PaymentClearing's + # documentation this is known as a "PostAuth" transaction. + # + # ==== Parameters + # * money - The amount to be captured. Should be an Integer amount in cents + # * authorization - The authorization returned from the previous capture or purchase request + # * options - A Hash of options, all are optional. + # + # ==== Options Hash + # The standard options apply here (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address), as well as: + # * :vendor_data - An Array of Hash objects with the keys being the name of the VendorData element and value being the value. + # * :send_customer_email - true or false. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'. + # * :send_merchant_email - true or false. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'. + # * :email_text - An Array of (up to ten (10)) String objects to be included in emails + # * :test_mode - true or false. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'. + # + # ==== Examples + # response = gateway.capture(1000, creditcard, + # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}], + # :send_customer_email => true, + # :send_merchant_email => true, + # :email_text => ['line1', 'line2', 'line3'], + # :test_mode => true + # ) + # + def capture(money, authorization, options = {}) + payload = Nokogiri::XML::Builder.new do |xml| + xml.PostAuthTransaction { + xml.OperationXID(authorization) + add_invoice(xml, money, options) + add_transaction_control(xml, options) + add_vendor_data(xml, options) + } + end.doc + + commit(payload) + end + + # This will reverse a previously run transaction which *has* *not* settled. + # + # ==== Parameters + # * authorization - The authorization returned from the previous capture or purchase request + # * options - A Hash of options, all are optional + # + # ==== Options Hash + # The standard options (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address) are ignored. + # * :vendor_data - An Array of Hash objects with the keys being the name of the VendorData element and value being the value. + # * :send_customer_email - true or false. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'. + # * :send_merchant_email - true or false. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'. + # * :email_text - An Array of (up to ten (10)) String objects to be included in emails + # * :test_mode - true or false. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'. + # + # ==== Examples + # response = gateway.void('9999999999', + # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}], + # :send_customer_email => true, + # :send_merchant_email => true, + # :email_text => ['line1', 'line2', 'line3'], + # :test_mode => true + # ) + # + def void(authorization, options = {}) + payload = Nokogiri::XML::Builder.new do |xml| + xml.VoidTransaction { + xml.OperationXID(authorization) + add_transaction_control(xml, options) + add_vendor_data(xml, options) + } + end.doc + + commit(payload) + end + + # This will reverse a previously run transaction which *has* settled. + # + # ==== Parameters + # * money - The amount to be credited. Should be an Integer amount in cents + # * authorization - The authorization returned from the previous capture or purchase request + # * options - A Hash of options, all are optional + # + # ==== Options Hash + # The standard options (:order_id, :ip, :customer, :invoice, :merchant, :description, :email, :currency, :address, :billing_address, :shipping_address) are ignored. + # * :vendor_data - An Array of Hash objects with the keys being the name of the VendorData element and value being the value. + # * :send_customer_email - true or false. Runs the transaction with the 'SendCustomerEmail' element set to 'TRUE' or 'FALSE'. + # * :send_merchant_email - true or false. Runs the transaction with the 'SendMerchantEmail' element set to 'TRUE' or 'FALSE'. + # * :email_text - An Array of (up to ten (10)) String objects to be included in emails + # * :test_mode - true or false. Runs the transaction with the 'TestMode' element set to 'TRUE' or 'FALSE'. + # + # ==== Examples + # response = gateway.refund(555, '9999999999', + # :vendor_data => [{'repId' => '1234567'}, {'customerId' => '9886'}], + # :send_customer_email => true, + # :send_merchant_email => true, + # :email_text => ['line1', 'line2', 'line3'], + # :test_mode => true + # ) + # + def refund(money, authorization, options = {}) + payload = Nokogiri::XML::Builder.new do |xml| + xml.TranCredTransaction { + xml.OperationXID(authorization) + add_invoice(xml, money, options) + add_transaction_control(xml, options) + add_vendor_data(xml, options) + } + end.doc + + commit(payload) + end + + private + + def add_customer_data(xml, payment_source, options) + billing_address = options[:billing_address] || options[:address] + shipping_address = options[:shipping_address] || options[:address] + + xml.CustomerData { + xml.Email(options[:email]) unless options[:email].blank? + xml.CustId(options[:order_id]) unless options[:order_id].blank? + xml.BillingAddress { + xml.FirstName(payment_source.first_name || parse_first_name(billing_address[:name])) + xml.LastName(payment_source.last_name || parse_last_name(billing_address[:name])) + xml.Address1(billing_address[:address1]) + xml.Address2(billing_address[:address2]) unless billing_address[:address2].blank? + xml.City(billing_address[:city]) + xml.State(billing_address[:state]) + xml.Zip(billing_address[:zip]) + xml.Country(billing_address[:country]) + xml.Phone(billing_address[:phone]) + } + xml.ShippingAddress { + xml.FirstName(payment_source.first_name || parse_first_name(shipping_address[:name])) + xml.LastName(payment_source.last_name || parse_last_name(shipping_address[:name])) + xml.Address1(shipping_address[:address1]) + xml.Address2(shipping_address[:address2]) unless shipping_address[:address2].blank? + xml.City(shipping_address[:city]) + xml.State(shipping_address[:state]) + xml.Zip(shipping_address[:zip]) + xml.Country(shipping_address[:country]) + xml.Phone(shipping_address[:phone]) + } unless shipping_address.blank? + } + end + + def add_invoice(xml, money, options) + xml.AuthCode options[:force] if options[:force] + if options[:order_items].blank? + xml.Total(amount(money)) unless(money.nil? || money < 0.01) + xml.Description(options[:description]) unless( options[:description].blank?) + else + xml.OrderItems { + options[:order_items].each do |item| + xml.Item { + xml.Description(item[:description]) + xml.Cost(amount(item[:cost])) + xml.Qty(item[:quantity].to_s) + } + end + } + end + end + + def add_payment_source(xml, source) + case determine_funding_source(source) + when :credit_card then add_creditcard(xml, source) + when :check then add_check(xml, source) + end + end + + def determine_funding_source(payment_source) + case payment_source + when ActiveMerchant::Billing::CreditCard + :credit_card + when ActiveMerchant::Billing::Check + :check + end + end + + def add_creditcard(xml, creditcard) + xml.AccountInfo { + xml.CardAccount { + xml.AccountNumber(creditcard.number.to_s) + xml.ExpirationMonth(creditcard.month.to_s.rjust(2,'0')) + xml.ExpirationYear(creditcard.year.to_s) + xml.CVVNumber(creditcard.verification_value.to_s) unless creditcard.verification_value.blank? + } + } + end + + def add_check(xml, check) + xml.AccountInfo { + xml.ABA(check.routing_number.to_s) + xml.AccountNumber(check.account_number.to_s) + xml.AccountSource(check.account_type.to_s) + xml.AccountType(check.account_holder_type.to_s) + xml.CheckNumber(check.number.to_s) + } + end + + def add_transaction_control(xml, options) + xml.TransactionControl { + # if there was a 'global' option set... + xml.TestMode(@options[:test_mode].upcase) if !@options[:test_mode].blank? + # allow the global option to be overridden... + xml.TestMode(options[:test_mode].upcase) if !options[:test_mode].blank? + xml.SendCustomerEmail(options[:send_customer_email].upcase) unless options[:send_customer_email].blank? + xml.SendMerchantEmail(options[:send_merchant_email].upcase) unless options[:send_merchant_email].blank? + xml.EmailText { + options[:email_text].each do |item| + xml.EmailTextItem(item) + end + } if options[:email_text] + } + end + + def add_vendor_data(xml, options) + return if options[:vendor_data].blank? + xml.VendorData { + options[:vendor_data].each do |k,v| + xml.Element { + xml.Name(k) + xml.Key(v) + } + end + } + end + + def commit(payload) + # Set the Content-Type header -- otherwise the URL decoding messes up + # the Base64 encoded payload signature! + response = parse(ssl_post(self.live_url, post_data(payload), 'Content-Type' => 'text/xml')) + + Response.new(successful?(response), response[:error_message], response, + :test => test?, + :authorization => response[:xid], + :avs_result => { :code => response[:avs_response] }, + :cvv_result => response[:cvv_response]) + end + + def post_data(payload) + payload_xml = payload.root.to_xml(:indent => 0) + + payload_signature = sign_payload(payload_xml) + + request = Nokogiri::XML::Builder.new do |xml| + xml.GatewayInterface { + xml.APICredentials { + xml.Username(@options[:login]) + xml.PayloadSignature(payload_signature) + xml.TargetGateway(@options[:gateway_id]) + } + } + end.doc + + request.root.children.first.after payload.root + request.to_xml(:indent => 0) + end + + def parse(raw_xml) + doc = REXML::Document.new(raw_xml) + response = Hash.new + transaction_result = doc.root.get_elements('TransactionResponse/TransactionResult/*') + transaction_result.each do |e| + response[e.name.to_s.underscore.to_sym] = e.text unless e.text.blank? + end + response + end + + def successful?(response) + # Turns out the PaymentClearing gateway is not consistent... + response[:status].downcase =='ok' + end + + def test_mode?(response) + # The '1' is a legacy thing; most of the time it should be 'TRUE'... + response[:test_mode] == 'TRUE' || response[:test_mode] == '1' + end + + def message_from(response) + response[:error_message] + end + + def sign_payload(payload) + key = @options[:password].to_s + digest=OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new(key), key, payload) + signature = Base64.encode64(digest) + signature.chomp! + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/jetpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/jetpay.rb new file mode 100644 index 000000000..7a7002d0b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/jetpay.rb @@ -0,0 +1,275 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class JetpayGateway < Gateway + self.test_url = 'https://test1.jetpay.com/jetpay' + self.live_url = 'https://gateway17.jetpay.com/jetpay' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.jetpay.com/' + + # The name of the gateway + self.display_name = 'JetPay' + + # all transactions are in cents + self.money_format = :cents + + ACTION_CODE_MESSAGES = { + "001" => "Refer to card issuer.", + "002" => "Refer to card issuer, special condition.", + "003" => "Pick up card.", + "200" => "Deny - Pick up card.", + "005" => "Do not honor.", + "100" => "Deny.", + "006" => "Error.", + "181" => "Format error.", + "007" => "Pickup card, special condition.", + "104" => "Deny - New card issued.", + "110" => "Invalid amount.", + "014" => "Invalid account number (no such number).", + "111" => "Invalid account.", + "015" => "No such issuer.", + "103" => "Deny - Invalid manual Entry 4DBC.", + "182" => "Please wait.", + "109" => "Invalid merchant.", + "041" => "Pick up card (lost card).", + "043" => "Pick up card (stolen card).", + "051" => "Insufficient funds.", + "052" => "No checking account.", + "105" => "Deny - Account Cancelled.", + "054" => "Expired Card.", + "101" => "Expired Card.", + "183" => "Invalid currency code.", + "057" => "Transaction not permitted to cardholder.", + "115" => "Service not permitted.", + "062" => "Restricted card.", + "189" => "Deny - Cancelled or Closed Merchant/SE.", + "188" => "Deny - Expiration date required.", + "125" => "Invalid effective date.", + "122" => "Invalid card (CID) security code.", + "400" => "Reversal accepted.", + "992" => "DECLINE/TIMEOUT.", + "107" => "Please Call Issuer.", + "025" => "Transaction Not Found.", + "981" => "AVS Error.", + "913" => "Invalid Card Type.", + "996" => "Terminal ID Not Found.", + nil => "No response returned (missing credentials?)." + } + + def initialize(options = {}) + requires!(options, :login) + super + end + + def purchase(money, credit_card, options = {}) + commit(money, build_sale_request(money, credit_card, options)) + end + + def authorize(money, credit_card, options = {}) + commit(money, build_authonly_request(money, credit_card, options)) + end + + def capture(money, reference, options = {}) + commit(money, build_capture_request('CAPT', reference.split(";").first)) + end + + def void(reference, options = {}) + transaction_id, approval, amount = reference.split(";") + commit(amount.to_i, build_void_request(amount.to_i, transaction_id, approval)) + end + + def credit(money, transaction_id_or_card, options = {}) + if transaction_id_or_card.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, transaction_id_or_card, options) + else + commit(money, build_credit_request('CREDIT', money, nil, transaction_id_or_card)) + end + end + + def refund(money, reference, options = {}) + transaction_id = reference.split(";").first + credit_card = options[:credit_card] + commit(money, build_credit_request('CREDIT', money, transaction_id, credit_card)) + end + + + private + + def build_xml_request(transaction_type, transaction_id = nil, &block) + xml = Builder::XmlMarkup.new + xml.tag! 'JetPay' do + # The basic values needed for any request + xml.tag! 'TerminalID', @options[:login] + xml.tag! 'TransactionType', transaction_type + xml.tag! 'TransactionID', transaction_id.nil? ? generate_unique_id.slice(0, 18) : transaction_id + + if block_given? + yield xml + else + xml.target! + end + end + end + + def build_sale_request(money, credit_card, options) + build_xml_request('SALE') do |xml| + add_credit_card(xml, credit_card) + add_addresses(xml, options) + add_customer_data(xml, options) + add_invoice_data(xml, options) + xml.tag! 'TotalAmount', amount(money) + + xml.target! + end + end + + def build_authonly_request(money, credit_card, options) + build_xml_request('AUTHONLY') do |xml| + add_credit_card(xml, credit_card) + add_addresses(xml, options) + add_customer_data(xml, options) + add_invoice_data(xml, options) + xml.tag! 'TotalAmount', amount(money) + + xml.target! + end + end + + def build_capture_request(transaction_type, transaction_id) + build_xml_request(transaction_type, transaction_id) + end + + def build_void_request(money, transaction_id, approval) + build_xml_request('VOID', transaction_id) do |xml| + xml.tag! 'Approval', approval + xml.tag! 'TotalAmount', amount(money) + + xml.target! + end + end + + # `transaction_id` may be nil for unlinked credit transactions. + def build_credit_request(transaction_type, money, transaction_id, card) + build_xml_request(transaction_type, transaction_id) do |xml| + add_credit_card(xml, card) if card + xml.tag! 'TotalAmount', amount(money) + + xml.target! + end + end + + def commit(money, request) + response = parse(ssl_post(test? ? self.test_url : self.live_url, request)) + + success = success?(response) + Response.new(success, + success ? 'APPROVED' : message_from(response), + response, + :test => test?, + :authorization => authorization_from(response, money), + :avs_result => { :code => response[:avs] }, + :cvv_result => response[:cvv2] + ) + end + + def parse(body) + return {} if body.blank? + + xml = REXML::Document.new(body) + + response = {} + xml.root.elements.to_a.each do |node| + parse_element(response, node) + end + response + end + + def parse_element(response, node) + if node.has_elements? + node.elements.each{|element| parse_element(response, element) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + def format_exp(value) + format(value, :two_digits) + end + + def success?(response) + response[:action_code] == "000" + end + + def message_from(response) + ACTION_CODE_MESSAGES[response[:action_code]] + end + + def authorization_from(response, money) + original_amount = amount(money) if money + [ response[:transaction_id], response[:approval], original_amount ].join(";") + end + + def add_credit_card(xml, credit_card) + xml.tag! 'CardNum', credit_card.number + xml.tag! 'CardExpMonth', format_exp(credit_card.month) + xml.tag! 'CardExpYear', format_exp(credit_card.year) + + if credit_card.first_name || credit_card.last_name + xml.tag! 'CardName', [credit_card.first_name,credit_card.last_name].compact.join(' ') + end + + unless credit_card.verification_value.nil? || (credit_card.verification_value.length == 0) + xml.tag! 'CVV2', credit_card.verification_value + end + end + + def add_addresses(xml, options) + if billing_address = options[:billing_address] || options[:address] + xml.tag! 'BillingAddress', [billing_address[:address1], billing_address[:address2]].compact.join(" ") + xml.tag! 'BillingCity', billing_address[:city] + xml.tag! 'BillingStateProv', billing_address[:state] + xml.tag! 'BillingPostalCode', billing_address[:zip] + xml.tag! 'BillingCountry', lookup_country_code(billing_address[:country]) + xml.tag! 'BillingPhone', billing_address[:phone] + end + + if shipping_address = options[:shipping_address] + xml.tag! 'ShippingInfo' do + xml.tag! 'ShippingName', shipping_address[:name] + + xml.tag! 'ShippingAddr' do + xml.tag! 'Address', [shipping_address[:address1], shipping_address[:address2]].compact.join(" ") + xml.tag! 'City', shipping_address[:city] + xml.tag! 'StateProv', shipping_address[:state] + xml.tag! 'PostalCode', shipping_address[:zip] + xml.tag! 'Country', lookup_country_code(shipping_address[:country]) + end + end + end + end + + def add_customer_data(xml, options) + xml.tag! 'Email', options[:email] if options[:email] + xml.tag! 'UserIPAddress', options[:ip] if options[:ip] + end + + def add_invoice_data(xml, options) + xml.tag! 'OrderNumber', options[:order_id] if options[:order_id] + xml.tag! 'TaxAmount', amount(options[:tax]) if options[:tax] + end + + def lookup_country_code(code) + country = Country.find(code) rescue nil + country && country.code(:alpha3) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/linkpoint.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/linkpoint.rb new file mode 100644 index 000000000..10917c875 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/linkpoint.rb @@ -0,0 +1,447 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + # Initialization Options + # :login Your store number + # :pem The text of your linkpoint PEM file. Note + # this is not the path to file, but its + # contents. If you are only using one PEM + # file on your site you can declare it + # globally and then you won't need to + # include this option + # + # + # A valid store number is required. Unfortunately, with LinkPoint + # YOU CAN'T JUST USE ANY OLD STORE NUMBER. Also, you can't just + # generate your own PEM file. You'll need to use a special PEM file + # provided by LinkPoint. + # + # Go to http://www.linkpoint.com/support/sup_teststore.asp to set up + # a test account and obtain your PEM file. + # + # Declaring PEM file Globally + # ActiveMerchant::Billing::LinkpointGateway.pem_file = File.read( File.dirname(__FILE__) + '/../mycert.pem' ) + # + # + # Valid Order Options + # :result => + # LIVE Production mode + # GOOD Approved response in test mode + # DECLINE Declined response in test mode + # DUPLICATE Duplicate response in test mode + # + # :ponumber Order number + # + # :transactionorigin => Source of the transaction + # ECI Email or Internet + # MAIL Mail order + # MOTO Mail order/Telephone + # TELEPHONE Telephone + # RETAIL Face-to-face + # + # :ordertype => + # SALE Real live sale + # PREAUTH Authorize only + # POSTAUTH Forced Ticket or Ticket Only transaction + # VOID + # CREDIT + # CALCSHIPPING For shipping charges calculations + # CALCTAX For sales tax calculations + # + # Recurring Options + # :action => + # SUBMIT + # MODIFY + # CANCEL + # + # :installments Identifies how many recurring payments to charge the customer + # :startdate Date to begin charging the recurring payments. Format: YYYYMMDD or "immediate" + # :periodicity => + # MONTHLY + # BIMONTHLY + # WEEKLY + # BIWEEKLY + # YEARLY + # DAILY + # :threshold Tells how many times to retry the transaction (if it fails) before contacting the merchant. + # :comments Uh... comments + # + # + # For reference: + # + # https://www.linkpointcentral.com/lpc/docs/Help/APIHelp/lpintguide.htm + # + # Entities = { + # :payment => [:subtotal, :tax, :vattax, :shipping, :chargetotal], + # :billing => [:name, :address1, :address2, :city, :state, :zip, :country, :email, :phone, :fax, :addrnum], + # :shipping => [:name, :address1, :address2, :city, :state, :zip, :country, :weight, :items, :carrier, :total], + # :creditcard => [:cardnumber, :cardexpmonth, :cardexpyear, :cvmvalue, :track], + # :telecheck => [:routing, :account, :checknumber, :bankname, :bankstate, :dl, :dlstate, :void, :accounttype, :ssn], + # :transactiondetails => [:transactionorigin, :oid, :ponumber, :taxexempt, :terminaltype, :ip, :reference_number, :recurring, :tdate], + # :periodic => [:action, :installments, :threshold, :startdate, :periodicity, :comments], + # :notes => [:comments, :referred] + # :items => [:item => [:price, :quantity, :description, :id, :options => [:option => [:name, :value]]]] + # } + # + # + # LinkPoint's Items entity is an optional entity that can be attached to orders. + # It is entered as :line_items to be consistent with the CyberSource implementation + # + # The line_item hash goes in the options hash and should look like + # + # :line_items => [ + # { + # :id => '123456', + # :description => 'Logo T-Shirt', + # :price => '12.00', + # :quantity => '1', + # :options => [ + # { + # :name => 'Color', + # :value => 'Red' + # }, + # { + # :name => 'Size', + # :value => 'XL' + # } + # ] + # }, + # { + # :id => '111', + # :description => 'keychain', + # :price => '3.00', + # :quantity => '1' + # } + # ] + # This functionality is only supported by this particular gateway may + # be changed at any time + # + class LinkpointGateway < Gateway + # Your global PEM file. This will be assigned to you by linkpoint + # + # Example: + # + # ActiveMerchant::Billing::LinkpointGateway.pem_file = File.read( File.dirname(__FILE__) + '/../mycert.pem' ) + # + cattr_accessor :pem_file + + self.test_url = 'https://staging.linkpt.net:1129/' + self.live_url = 'https://secure.linkpt.net:1129/' + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club] + self.homepage_url = 'http://www.linkpoint.com/' + self.display_name = 'LinkPoint' + + def initialize(options = {}) + requires!(options, :login) + + @options = { + :result => 'LIVE', + :pem => LinkpointGateway.pem_file + }.update(options) + + raise ArgumentError, "You need to pass in your pem file using the :pem parameter or set it globally using ActiveMerchant::Billing::LinkpointGateway.pem_file = File.read( File.dirname(__FILE__) + '/../mycert.pem' ) or similar" if @options[:pem].blank? + end + + # Send a purchase request with periodic options + # Recurring Options + # :action => + # SUBMIT + # MODIFY + # CANCEL + # + # :installments Identifies how many recurring payments to charge the customer + # :startdate Date to begin charging the recurring payments. Format: YYYYMMDD or "immediate" + # :periodicity => + # :monthly + # :bimonthly + # :weekly + # :biweekly + # :yearly + # :daily + # :threshold Tells how many times to retry the transaction (if it fails) before contacting the merchant. + # :comments Uh... comments + # + def recurring(money, creditcard, options={}) + requires!(options, [:periodicity, :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily], :installments, :order_id ) + + options.update( + :ordertype => "SALE", + :action => options[:action] || "SUBMIT", + :installments => options[:installments] || 12, + :startdate => options[:startdate] || "immediate", + :periodicity => options[:periodicity].to_s || "monthly", + :comments => options[:comments] || nil, + :threshold => options[:threshold] || 3 + ) + commit(money, creditcard, options) + end + + # Buy the thing + def purchase(money, creditcard, options={}) + requires!(options, :order_id) + options.update( + :ordertype => "SALE" + ) + commit(money, creditcard, options) + end + + # + # Authorize the transaction + # + # Reserves the funds on the customer's credit card, but does not charge the card. + # + def authorize(money, creditcard, options = {}) + requires!(options, :order_id) + options.update( + :ordertype => "PREAUTH" + ) + commit(money, creditcard, options) + end + + # + # Post an authorization. + # + # Captures the funds from an authorized transaction. + # Order_id must be a valid order id from a prior authorized transaction. + # + def capture(money, authorization, options = {}) + options.update( + :order_id => authorization, + :ordertype => "POSTAUTH" + ) + commit(money, nil, options) + end + + # Void a previous transaction + def void(identification, options = {}) + options.update( + :order_id => identification, + :ordertype => "VOID" + ) + commit(nil, nil, options) + end + + # + # Refund an order + # + # identification must be a valid order id previously submitted by SALE + # + def refund(money, identification, options = {}) + options.update( + :ordertype => "CREDIT", + :order_id => identification + ) + commit(money, nil, options) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + private + # Commit the transaction by posting the XML file to the LinkPoint server + def commit(money, creditcard, options = {}) + response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(money, creditcard, options))) + + Response.new(successful?(response), response[:message], response, + :test => test?, + :authorization => response[:ordernum], + :avs_result => { :code => response[:avs].to_s[2,1] }, + :cvv_result => response[:avs].to_s[3,1] + ) + end + + def successful?(response) + response[:approved] == "APPROVED" + end + + # Build the XML file + def post_data(money, creditcard, options) + params = parameters(money, creditcard, options) + + xml = REXML::Document.new + order = xml.add_element("order") + + # Merchant Info + merchantinfo = order.add_element("merchantinfo") + merchantinfo.add_element("configfile").text = @options[:login] + + # Loop over the params hash to construct the XML string + for key, value in params + elem = order.add_element(key.to_s) + if key == :items + build_items(elem, value) + else + for k, v in params[key] + elem.add_element(k.to_s).text = params[key][k].to_s if params[key][k] + end + end + # Linkpoint doesn't understand empty elements: + order.delete(elem) if elem.size == 0 + end + return xml.to_s + end + + # adds LinkPoint's Items entity to the XML. Called from post_data + def build_items(element, items) + for item in items + item_element = element.add_element("item") + for key, value in item + if key == :options + options_element = item_element.add_element("options") + for option in value + opt_element = options_element.add_element("option") + opt_element.add_element("name").text = option[:name] unless option[:name].blank? + opt_element.add_element("value").text = option[:value] unless option[:value].blank? + end + else + item_element.add_element(key.to_s).text = item[key].to_s unless item[key].blank? + end + end + end + end + + # Set up the parameters hash just once so we don't have to do it + # for every action. + def parameters(money, creditcard, options = {}) + + params = { + :payment => { + :subtotal => amount(options[:subtotal]), + :tax => amount(options[:tax]), + :vattax => amount(options[:vattax]), + :shipping => amount(options[:shipping]), + :chargetotal => amount(money) + }, + :transactiondetails => { + :transactionorigin => options[:transactionorigin] || "ECI", + :oid => options[:order_id], + :ponumber => options[:ponumber], + :taxexempt => options[:taxexempt], + :terminaltype => options[:terminaltype], + :ip => options[:ip], + :reference_number => options[:reference_number], + :recurring => options[:recurring] || "NO", #DO NOT USE if you are using the periodic billing option. + :tdate => options[:tdate] + }, + :orderoptions => { + :ordertype => options[:ordertype], + :result => @options[:result] + }, + :periodic => { + :action => options[:action], + :installments => options[:installments], + :threshold => options[:threshold], + :startdate => options[:startdate], + :periodicity => options[:periodicity], + :comments => options[:comments] + }, + :telecheck => { + :routing => options[:telecheck_routing], + :account => options[:telecheck_account], + :checknumber => options[:telecheck_checknumber], + :bankname => options[:telecheck_bankname], + :dl => options[:telecheck_dl], + :dlstate => options[:telecheck_dlstate], + :void => options[:telecheck_void], + :accounttype => options[:telecheck_accounttype], + :ssn => options[:telecheck_ssn], + } + } + + if creditcard + params[:creditcard] = { + :cardnumber => creditcard.number, + :cardexpmonth => creditcard.month, + :cardexpyear => format_creditcard_expiry_year(creditcard.year), + :track => nil + } + + if creditcard.verification_value? + params[:creditcard][:cvmvalue] = creditcard.verification_value + params[:creditcard][:cvmindicator] = 'provided' + else + params[:creditcard][:cvmindicator] = 'not_provided' + end + end + + if billing_address = options[:billing_address] || options[:address] + + params[:billing] = {} + params[:billing][:name] = billing_address[:name] || (creditcard ? creditcard.name : nil) + params[:billing][:address1] = billing_address[:address1] unless billing_address[:address1].blank? + params[:billing][:address2] = billing_address[:address2] unless billing_address[:address2].blank? + params[:billing][:city] = billing_address[:city] unless billing_address[:city].blank? + params[:billing][:state] = billing_address[:state] unless billing_address[:state].blank? + params[:billing][:zip] = billing_address[:zip] unless billing_address[:zip].blank? + params[:billing][:country] = billing_address[:country] unless billing_address[:country].blank? + params[:billing][:company] = billing_address[:company] unless billing_address[:company].blank? + params[:billing][:phone] = billing_address[:phone] unless billing_address[:phone].blank? + params[:billing][:email] = options[:email] unless options[:email].blank? + end + + if shipping_address = options[:shipping_address] + + params[:shipping] = {} + params[:shipping][:name] = shipping_address[:name] || (creditcard ? creditcard.name : nil) + params[:shipping][:address1] = shipping_address[:address1] unless shipping_address[:address1].blank? + params[:shipping][:address2] = shipping_address[:address2] unless shipping_address[:address2].blank? + params[:shipping][:city] = shipping_address[:city] unless shipping_address[:city].blank? + params[:shipping][:state] = shipping_address[:state] unless shipping_address[:state].blank? + params[:shipping][:zip] = shipping_address[:zip] unless shipping_address[:zip].blank? + params[:shipping][:country] = shipping_address[:country] unless shipping_address[:country].blank? + end + + params[:items] = options[:line_items] if options[:line_items] + + return params + end + + def parse(xml) + + # For reference, a typical response... + # + # + # + # + # + # This is a test transaction and will not show up in the Reports + # + # Thu Feb 2 15:40:21 2006 + # + # + # APPROVED + # + + response = {:message => "Global Error Receipt", :complete => false} + + xml = REXML::Document.new("#{xml}") + xml.root.elements.each do |node| + response[node.name.downcase.sub(/^r_/, '').to_sym] = normalize(node.text) + end unless xml.root.nil? + + response + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def format_creditcard_expiry_year(year) + sprintf("%.4i", year)[-2..-1] + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/litle.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/litle.rb new file mode 100755 index 000000000..fcc8b740f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/litle.rb @@ -0,0 +1,540 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class LitleGateway < Gateway + # Specific to Litle options: + # * :merchant_id - Merchant Id assigned by Litle + # * :user - Username assigned by Litle + # * :password - Password assigned by Litle + # * :version - The version of the api you are using (eg, '8.10') + # * :proxy_addr - Proxy address - nil if not needed + # * :proxy_port - Proxy port - nil if not needed + # * :url - URL assigned by Litle (for testing, use the sandbox) + # + # Standard Active Merchant options + # * :order_id - The order number + # * :ip - The IP address of the customer making the purchase + # * :customer - The name, customer number, or other information that identifies the customer + # * :invoice - The invoice number + # * :merchant - The name or description of the merchant offering the product + # * :description - A description of the transaction + # * :email - The email address of the customer + # * :currency - The currency of the transaction. Only important when you are using a currency that is not the default with a gateway that supports multiple currencies. + # * :billing_address - A hash containing the billing address of the customer. + # * :shipping_address - A hash containing the shipping address of the customer. + # + # The :billing_address, and :shipping_address hashes can have the following keys: + # + # * :name - The full name of the customer. + # * :company - The company name of the customer. + # * :address1 - The primary street address of the customer. + # * :address2 - Additional line of address information. + # * :city - The city of the customer. + # * :state - The state of the customer. The 2 digit code for US and Canadian addresses. The full name of the state or province for foreign addresses. + # * :country - The [ISO 3166-1-alpha-2 code](http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm) for the customer. + # * :zip - The zip or postal code of the customer. + # * :phone - The phone number of the customer. + + self.test_url = 'https://www.testlitle.com/sandbox/communicator/online' + self.live_url = 'https://payments.litle.com/vap/communicator/online' + + LITLE_SCHEMA_VERSION = '8.13' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.litle.com/' + + # The name of the gateway + self.display_name = 'Litle & Co.' + + self.default_currency = 'USD' + + def initialize(options = {}) + begin + require 'LitleOnline' + rescue LoadError + raise "Could not load the LitleOnline gem (>= 08.13.2). Use `gem install LitleOnline` to install it." + end + + @litle = LitleOnline::LitleOnlineRequest.new + + options[:version] ||= LITLE_SCHEMA_VERSION + options[:merchant] ||= 'Default Report Group' + options[:user] ||= options[:login] + + requires!(options, :merchant_id, :user, :password, :merchant, :version) + + super + end + + def authorize(money, creditcard_or_token, options = {}) + to_pass = build_authorize_request(money, creditcard_or_token, options) + build_response(:authorization, @litle.authorization(to_pass)) + end + + def purchase(money, creditcard_or_token, options = {}) + to_pass = build_purchase_request(money, creditcard_or_token, options) + build_response(:sale, @litle.sale(to_pass)) + end + + def capture(money, authorization, options = {}) + transaction_id, kind = split_authorization(authorization) + to_pass = create_capture_hash(money, transaction_id, options) + build_response(:capture, @litle.capture(to_pass)) + end + + # Note: Litle requires that authorization requests be voided via auth_reversal + # and other requests via void. To maintain the same interface as the other + # gateways the transaction_id and the kind of transaction are concatenated + # together with a ; separator (e.g. 1234;authorization) + # + # A partial auth_reversal can be accomplished by passing :amount as an option + def void(identification, options = {}) + transaction_id, kind = split_authorization(identification) + if(kind == 'authorization') + to_pass = create_auth_reversal_hash(transaction_id, options[:amount], options) + build_response(:authReversal, @litle.auth_reversal(to_pass)) + else + to_pass = create_void_hash(transaction_id, options) + build_response(:void, @litle.void(to_pass)) + end + end + + def credit(money, identification_or_token, options = {}) + to_pass = build_credit_request(money, identification_or_token, options) + build_response(:credit, @litle.credit(to_pass)) + end + + def store(creditcard, options = {}) + to_pass = create_token_hash(creditcard, options) + build_response(:registerToken, @litle.register_token_request(to_pass), %w(000 801 802)) + end + + private + + CARD_TYPE = { + 'visa' => 'VI', + 'master' => 'MC', + 'american_express' => 'AX', + 'discover' => 'DI', + 'jcb' => 'DI', + 'diners_club' => 'DI' + } + + AVS_RESPONSE_CODE = { + '00' => 'Y', + '01' => 'X', + '02' => 'D', + '10' => 'Z', + '11' => 'W', + '12' => 'A', + '13' => 'A', + '14' => 'P', + '20' => 'N', + '30' => 'S', + '31' => 'R', + '32' => 'U', + '33' => 'R', + '34' => 'I', + '40' => 'E' + } + + def url + return @options[:url] if @options[:url].present? + + test? ? self.test_url : self.live_url + end + + def build_response(kind, litle_response, valid_responses=%w(000)) + response = Hash.from_xml(litle_response.raw_xml.to_s)['litleOnlineResponse'] + + if response['response'] == "0" + detail = response["#{kind}Response"] + fraud = fraud_result(detail) + Response.new( + valid_responses.include?(detail['response']), + detail['message'], + { :litleOnlineResponse => response }, + :authorization => authorization_from(detail, kind), + :avs_result => { :code => fraud['avs'] }, + :cvv_result => fraud['cvv'], + :test => test? + ) + else + Response.new(false, response['message'], :litleOnlineResponse => response, :test => test?) + end + end + + # Generates an authorization string of the appropriate id and the kind of transaction + # See #void for how the kind is used + def authorization_from(litle_response, kind) + case kind + when :registerToken + authorization = litle_response['litleToken'] + else + authorization = [litle_response['litleTxnId'], kind.to_s].join(";") + end + end + + def split_authorization(authorization) + transaction_id, kind = authorization.to_s.split(';') + [transaction_id, kind] + end + + def build_authorize_request(money, creditcard_or_token, options) + payment_method = build_payment_method(creditcard_or_token, options) + + hash = create_hash(money, options) + + add_creditcard_or_cardtoken_hash(hash, payment_method) + + hash + end + + def build_purchase_request(money, creditcard_or_token, options) + payment_method = build_payment_method(creditcard_or_token, options) + + hash = create_hash(money, options) + + add_creditcard_or_cardtoken_hash(hash, payment_method) + + hash + end + + def build_credit_request(money, identification_or_token, options) + payment_method = build_payment_method(identification_or_token, options) + + hash = create_hash(money, options) + + add_identification_or_cardtoken_hash(hash, payment_method) + + unless payment_method.is_a?(LitleCardToken) + hash['orderSource'] = nil + hash['orderId'] = nil + end + + hash + end + + def build_payment_method(payment_method, options) + result = payment_method + + # Build instance of the LitleCardToken class for internal use if this is a token request. + if payment_method.is_a?(String) && options.has_key?(:token) + result = LitleCardToken.new(:token => payment_method) + result.month = options[:token][:month] + result.year = options[:token][:year] + result.verification_value = options[:token][:verification_value] + result.brand = options[:token][:brand] + end + + result + end + + def add_creditcard_or_cardtoken_hash(hash, creditcard_or_cardtoken) + if creditcard_or_cardtoken.is_a?(LitleCardToken) + add_cardtoken_hash(hash, creditcard_or_cardtoken) + else + add_creditcard_hash(hash, creditcard_or_cardtoken) + end + end + + def add_identification_or_cardtoken_hash(hash, identification_or_cardtoken) + if identification_or_cardtoken.is_a?(LitleCardToken) + add_cardtoken_hash(hash, identification_or_cardtoken) + else + transaction_id, kind = split_authorization(identification_or_cardtoken) + hash['litleTxnId'] = transaction_id + end + end + + def add_cardtoken_hash(hash, cardtoken) + token_info = {} + token_info['litleToken'] = cardtoken.token + token_info['expDate'] = cardtoken.exp_date if cardtoken.exp_date? + token_info['cardValidationNum'] = cardtoken.verification_value unless cardtoken.verification_value.blank? + token_info['type'] = cardtoken.type unless cardtoken.type.blank? + + hash['token'] = token_info + hash + end + + def add_creditcard_hash(hash, creditcard) + cc_type = CARD_TYPE[creditcard.brand] + exp_date_yr = creditcard.year.to_s[2..3] + exp_date_mo = '%02d' % creditcard.month.to_i + exp_date = exp_date_mo + exp_date_yr + + card_info = { + 'type' => cc_type, + 'number' => creditcard.number, + 'expDate' => exp_date, + 'cardValidationNum' => creditcard.verification_value + } + + hash['card'] = card_info + hash + end + + def create_capture_hash(money, authorization, options) + hash = create_hash(money, options) + hash['litleTxnId'] = authorization + hash + end + + def create_token_hash(creditcard, options) + hash = create_hash(0, options) + hash['accountNumber'] = creditcard.number + hash + end + + def create_void_hash(identification, options) + hash = create_hash(nil, options) + hash['litleTxnId'] = identification + hash + end + + def create_auth_reversal_hash(identification, money, options) + hash = create_hash(money, options) + hash['litleTxnId'] = identification + hash + end + + def create_hash(money, options) + fraud_check_type = {} + if options[:ip] + fraud_check_type['customerIpAddress'] = options[:ip] + end + + enhanced_data = {} + if options[:invoice] + enhanced_data['invoiceReferenceNumber'] = options[:invoice] + end + + if options[:description] + enhanced_data['customerReference'] = options[:description] + end + + if options[:billing_address] + bill_to_address = { + 'name' => options[:billing_address][:name], + 'companyName' => options[:billing_address][:company], + 'addressLine1' => options[:billing_address][:address1], + 'addressLine2' => options[:billing_address][:address2], + 'city' => options[:billing_address][:city], + 'state' => options[:billing_address][:state], + 'zip' => options[:billing_address][:zip], + 'country' => options[:billing_address][:country], + 'email' => options[:email], + 'phone' => options[:billing_address][:phone] + } + end + if options[:shipping_address] + ship_to_address = { + 'name' => options[:shipping_address][:name], + 'companyName' => options[:shipping_address][:company], + 'addressLine1' => options[:shipping_address][:address1], + 'addressLine2' => options[:shipping_address][:address2], + 'city' => options[:shipping_address][:city], + 'state' => options[:shipping_address][:state], + 'zip' => options[:shipping_address][:zip], + 'country' => options[:shipping_address][:country], + 'email' => options[:email], + 'phone' => options[:shipping_address][:phone] + } + end + + hash = { + 'billToAddress' => bill_to_address, + 'shipToAddress' => ship_to_address, + 'orderId' => (options[:order_id] || @options[:order_id]), + 'customerId' => options[:customer], + 'reportGroup' => (options[:merchant] || @options[:merchant]), + 'merchantId' => (options[:merchant_id] || @options[:merchant_id]), + 'orderSource' => (options[:order_source] || 'ecommerce'), + 'enhancedData' => enhanced_data, + 'fraudCheckType' => fraud_check_type, + 'user' => (options[:user] || @options[:user]), + 'password' => (options[:password] || @options[:password]), + 'version' => (options[:version] || @options[:version]), + 'url' => (options[:url] || url), + 'proxy_addr' => (options[:proxy_addr] || @options[:proxy_addr]), + 'proxy_port' => (options[:proxy_port] || @options[:proxy_port]), + 'id' => (options[:id] || options[:order_id] || @options[:order_id]) + } + + if (!money.nil? && money.to_s.length > 0) + hash.merge!({ 'amount' => money }) + end + hash + end + + def fraud_result(authorization_response) + if result = authorization_response['fraudResult'] + if result.key?('cardValidationResult') + cvv_to_pass = result['cardValidationResult'].blank? ? "P" : result['cardValidationResult'] + end + + avs_to_pass = AVS_RESPONSE_CODE[result['avsResult']] unless result['avsResult'].blank? + end + { 'cvv' => cvv_to_pass, 'avs' => avs_to_pass } + end + + # A +LitleCardToken+ object represents a tokenized credit card, and is capable of validating the various + # data associated with these. + # + # == Example Usage + # token = LitleCardToken.new( + # :token => '1234567890123456', + # :month => '9', + # :year => '2010', + # :brand => 'visa', + # :verification_value => '123' + # ) + # + # token.valid? # => true + # cc.exp_date # => 0910 + # + class LitleCardToken + include Validateable + + # Returns or sets the token. (required) + # + # @return [String] + attr_accessor :token + + # Returns or sets the expiry month for the card associated with token. (optional) + # + # @return [Integer] + attr_accessor :month + + # Returns or sets the expiry year for the card associated with token. (optional) + # + # @return [Integer] + attr_accessor :year + + # Returns or sets the card verification value. (optional) + # + # @return [String] the verification value + attr_accessor :verification_value + + # Returns or sets the credit card brand. (optional) + # + # Valid card types are + # + # * +'visa'+ + # * +'master'+ + # * +'discover'+ + # * +'american_express'+ + # * +'diners_club'+ + # * +'jcb'+ + # * +'switch'+ + # * +'solo'+ + # * +'dankort'+ + # * +'maestro'+ + # * +'forbrugsforeningen'+ + # * +'laser'+ + # + # @return (String) the credit card brand + attr_accessor :brand + + # Returns the Litle credit card type identifier. + # + # @return (String) the credit card type identifier + def type + CARD_TYPE[brand] unless brand.blank? + end + + # Returns true if the expiration date is set. + # + # @return (Boolean) + def exp_date? + !month.to_i.zero? && !year.to_i.zero? + end + + # Returns the card token expiration date in MMYY format. + # + # @return (String) the expiration date in MMYY format + def exp_date + result = '' + if exp_date? + exp_date_yr = year.to_s[2..3] + exp_date_mo = '%02d' % month.to_i + + result = exp_date_mo + exp_date_yr + end + result + end + + # Validates the card token details. + # + # Any validation errors are added to the {#errors} attribute. + def validate + validate_card_token + validate_expiration_date + validate_card_brand + end + + def check? + false + end + + private + + CARD_TYPE = { + 'visa' => 'VI', + 'master' => 'MC', + 'american_express' => 'AX', + 'discover' => 'DI', + 'jcb' => 'DI', + 'diners_club' => 'DI' + } + + def before_validate #:nodoc: + self.month = month.to_i + self.year = year.to_i + end + + # Litle XML Reference Guide 1.8.2 + # + # The length of the original card number is reflected in the token, so a + # submitted 16-digit number results in a 16-digit token. Also, all tokens + # use only numeric characters, so you do not have to change your + # systems to accept alpha-numeric characters. + # + # The credit card token numbers themselves have two parts. + # The last four digits match the last four digits of the card number. + # The remaining digits (length can vary based upon original card number + # length) are a randomly generated. + def validate_card_token #:nodoc: + if token.to_s.length < 12 || token.to_s.match(/\A\d+\Z/).nil? + errors.add :token, "is not a valid card token" + end + end + + def validate_expiration_date #:nodoc: + if !month.to_i.zero? || !year.to_i.zero? + errors.add :month, "is not a valid month" unless valid_month?(month) + errors.add :year, "is not a valid year" unless valid_expiry_year?(year) + end + end + + def validate_card_brand #:nodoc: + errors.add :brand, "is invalid" unless brand.blank? || CreditCard.card_companies.keys.include?(brand) + end + + def valid_month?(month) + (1..12).include?(month.to_i) + end + + def valid_expiry_year?(year) + year.to_s =~ /\A\d{4}\Z/ && year.to_i > 1987 + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_e_solutions.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_e_solutions.rb new file mode 100644 index 000000000..c1ae20084 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_e_solutions.rb @@ -0,0 +1,176 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class MerchantESolutionsGateway < Gateway + self.test_url = 'https://cert.merchante-solutions.com/mes-api/tridentApi' + self.live_url = 'https://api.merchante-solutions.com/mes-api/tridentApi' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.merchante-solutions.com/' + + # The name of the gateway + self.display_name = 'Merchant e-Solutions' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, creditcard_or_card_id, options = {}) + post = {} + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + post[:moto_ecommerce_ind] = options[:moto_ecommerce_ind] if options.has_key?(:moto_ecommerce_ind) + add_invoice(post, options) + add_payment_source(post, creditcard_or_card_id, options) + add_address(post, options) + commit('P', money, post) + end + + def purchase(money, creditcard_or_card_id, options = {}) + post = {} + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + post[:moto_ecommerce_ind] = options[:moto_ecommerce_ind] if options.has_key?(:moto_ecommerce_ind) + add_invoice(post, options) + add_payment_source(post, creditcard_or_card_id, options) + add_address(post, options) + commit('D', money, post) + end + + def capture(money, transaction_id, options = {}) + post ={} + post[:transaction_id] = transaction_id + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + commit('S', money, post) + end + + def store(creditcard, options = {}) + post = {} + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + add_creditcard(post, creditcard, options) + commit('T', nil, post) + end + + def unstore(card_id) + post = {} + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + post[:card_id] = card_id + commit('X', nil, post) + end + + def refund(money, identification, options = {}) + post = {} + post[:transaction_id] = identification + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + options.delete(:customer) + options.delete(:billing_address) + commit('U', money, options.merge(post)) + end + + def credit(money, creditcard_or_card_id, options = {}) + post = {} + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + add_invoice(post, options) + add_payment_source(post, creditcard_or_card_id, options) + commit('C', money, post) + end + + def void(transaction_id, options = {}) + post = {} + post[:transaction_id] = transaction_id + post[:client_reference_number] = options[:customer] if options.has_key?(:customer) + options.delete(:customer) + options.delete(:billing_address) + commit('V', nil, options.merge(post)) + end + + private + + def add_address(post, options) + if address = options[:billing_address] || options[:address] + post[:cardholder_street_address] = address[:address1].to_s.gsub(/[^\w.]/, '+') + post[:cardholder_zip] = address[:zip].to_s + end + end + + def add_invoice(post, options) + if options.has_key? :order_id + post[:invoice_number] = options[:order_id].to_s.gsub(/[^\w.]/, '') + end + end + + def add_payment_source(post, creditcard_or_card_id, options) + if creditcard_or_card_id.is_a?(String) + # using stored card + post[:card_id] = creditcard_or_card_id + post[:card_exp_date] = options[:expiration_date] if options[:expiration_date] + else + # card info is provided + add_creditcard(post, creditcard_or_card_id, options) + end + end + + def add_creditcard(post, creditcard, options) + post[:card_number] = creditcard.number + post[:cvv2] = creditcard.verification_value if creditcard.verification_value? + post[:card_exp_date] = expdate(creditcard) + end + + def parse(body) + results = {} + body.split(/&/).each do |pair| + key,val = pair.split(/=/) + results[key] = val + end + results + end + + def commit(action, money, parameters) + url = test? ? self.test_url : self.live_url + parameters[:transaction_amount] = amount(money) if money unless action == 'V' + + + response = begin + parse( ssl_post(url, post_data(action,parameters)) ) + rescue ActiveMerchant::ResponseError => e + { "error_code" => "404", "auth_response_text" => e.to_s } + end + + Response.new(response["error_code"] == "000", message_from(response), response, + :authorization => response["transaction_id"], + :test => test?, + :cvv_result => response["cvv2_result"], + :avs_result => { :code => response["avs_result"] } + ) + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + "#{month}#{year[-2..-1]}" + end + + def message_from(response) + if response["error_code"] == "000" + "This transaction has been approved" + else + response["auth_response_text"] + end + end + + def post_data(action, parameters = {}) + post = {} + post[:profile_id] = @options[:login] + post[:profile_key] = @options[:password] + post[:transaction_type] = action if action + + request = post.merge(parameters).map {|key,value| "#{key}=#{CGI.escape(value.to_s)}"}.join("&") + request + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_ware.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_ware.rb new file mode 100644 index 000000000..940432918 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_ware.rb @@ -0,0 +1,323 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class MerchantWareGateway < Gateway + class_attribute :v4_live_url + + self.live_url = self.test_url = 'https://ps1.merchantware.net/MerchantWARE/ws/RetailTransaction/TXRetail.asmx' + self.v4_live_url = 'https://ps1.merchantware.net/Merchantware/ws/RetailTransaction/v4/Credit.asmx' + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://merchantwarehouse.com/merchantware' + self.display_name = 'MerchantWARE' + + ENV_NAMESPACES = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", + "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema", + "xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/" + } + ENV_NAMESPACES_V4 = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", + "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema", + "xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/" + } + + TX_NAMESPACE = "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail" + TX_NAMESPACE_V4 = "http://schemas.merchantwarehouse.com/merchantware/40/Credit/" + + ACTIONS = { + :purchase => "IssueKeyedSale", + :authorize => "IssueKeyedPreAuth", + :capture => "IssuePostAuth", + :void => "VoidPreAuthorization", + :credit => "IssueKeyedRefund", + :reference_credit => "IssueRefundByReference" + } + + # Creates a new MerchantWareGateway + # + # The gateway requires that a valid login, password, and name be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login - The MerchantWARE SiteID. + # * :password - The MerchantWARE Key. + # * :name - The MerchantWARE Name. + def initialize(options = {}) + requires!(options, :login, :password, :name) + super + end + + # Authorize a credit card for a given amount. + # + # ==== Parameters + # * money - The amount to be authorized as an Integer value in cents. + # * credit_card - The CreditCard details for the transaction. + # * options + # * :order_id - A unique reference for this order (required). + # * :billing_address - The billing address for the cardholder. + def authorize(money, credit_card, options = {}) + request = build_purchase_request(:authorize, money, credit_card, options) + commit(:authorize, request) + end + + # Authorize and immediately capture funds from a credit card. + # + # ==== Parameters + # * money - The amount to be authorized as anInteger value in cents. + # * credit_card - The CreditCard details for the transaction. + # * options + # * :order_id - A unique reference for this order (required). + # * :billing_address - The billing address for the cardholder. + def purchase(money, credit_card, options = {}) + request = build_purchase_request(:purchase, money, credit_card, options) + commit(:purchase, request) + end + + # Capture authorized funds from a credit card. + # + # ==== Parameters + # * money - The amount to be captured as anInteger value in cents. + # * authorization - The authorization string returned from the initial authorization. + def capture(money, authorization, options = {}) + request = build_capture_request(:capture, money, authorization, options) + commit(:capture, request) + end + + # Void a transaction. + # + # ==== Parameters + # * authorization - The authorization string returned from the initial authorization or purchase. + def void(authorization, options = {}) + reference, options[:order_id] = split_reference(authorization) + request = v4_soap_request(:void) do |xml| + add_reference_token(xml, reference) + end + commit(:void, request, true) + end + + # Refund an amount back a cardholder + # + # ==== Parameters + # + # * money - The amount to be refunded as an Integer value in cents. + # * identification - The credit card you want to refund or the authorization for the existing transaction you are refunding. + # * options + # * :order_id - A unique reference for this order (required when performing a non-referenced credit) + def credit(money, identification, options = {}) + if identification.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + else + perform_credit(money, identification, options) + end + end + + def refund(money, reference, options = {}) + perform_reference_credit(money, reference, options) + end + + private + + def soap_request(action) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! "env:Envelope", ENV_NAMESPACES do + xml.tag! "env:Body" do + xml.tag! ACTIONS[action], "xmlns" => TX_NAMESPACE do + add_credentials(xml) + yield xml + end + end + end + xml.target! + end + + def v4_soap_request(action) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! "soap:Envelope", ENV_NAMESPACES_V4 do + xml.tag! "soap:Body" do + xml.tag! ACTIONS[:void], "xmlns" => TX_NAMESPACE_V4 do + xml.tag! "merchantName", @options[:name] + xml.tag! "merchantSiteId", @options[:login] + xml.tag! "merchantKey", @options[:password] + yield xml + end + end + end + xml.target! + end + + def build_purchase_request(action, money, credit_card, options) + requires!(options, :order_id) + + request = soap_request(action) do |xml| + add_invoice(xml, options) + add_amount(xml, money) + add_credit_card(xml, credit_card) + add_address(xml, options) + end + end + + def build_capture_request(action, money, identification, options) + reference, options[:order_id] = split_reference(identification) + + request = soap_request(action) do |xml| + add_reference(xml, reference) + add_invoice(xml, options) + add_amount(xml, money) + end + end + + def perform_reference_credit(money, identification, options) + reference, options[:order_id] = split_reference(identification) + + request = soap_request(:reference_credit) do |xml| + add_reference(xml, reference) + add_invoice(xml, options) + add_amount(xml, money, "strOverrideAmount") + end + + commit(:reference_credit, request) + end + + def perform_credit(money, credit_card, options) + requires!(options, :order_id) + + request = soap_request(:credit) do |xml| + add_invoice(xml, options) + add_amount(xml, money) + add_credit_card(xml, credit_card) + end + + commit(:credit, request) + end + + def add_credentials(xml) + xml.tag! "strSiteId", @options[:login] + xml.tag! "strKey", @options[:password] + xml.tag! "strName", @options[:name] + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + def add_invoice(xml, options) + xml.tag! "strOrderNumber", options[:order_id].to_s.gsub(/[^\w]/, '').slice(0, 25) + end + + def add_amount(xml, money, tag = "strAmount") + xml.tag! tag, amount(money) + end + + def add_reference(xml, reference) + xml.tag! "strReferenceCode", reference + end + + def add_reference_token(xml, reference) + xml.tag! "token", reference + end + + def add_address(xml, options) + if address = options[:billing_address] || options[:address] + xml.tag! "strAVSStreetAddress", address[:address1] + xml.tag! "strAVSZipCode", address[:zip] + end + end + + def add_credit_card(xml, credit_card) + xml.tag! "strPAN", credit_card.number + xml.tag! "strExpDate", expdate(credit_card) + xml.tag! "strCardHolder", credit_card.name + xml.tag! "strCVCode", credit_card.verification_value if credit_card.verification_value? + end + + def split_reference(reference) + reference.to_s.split(";") + end + + def parse(action, data) + response = {} + xml = REXML::Document.new(data) + + root = REXML::XPath.first(xml, "//#{ACTIONS[action]}Response/#{ACTIONS[action]}Result") + + root.elements.each do |element| + response[element.name] = element.text + end + + status, code, message = response["ApprovalStatus"].split(";") + response[:status] = status + + if response[:success] = status == "APPROVED" + response[:message] = status + else + response[:message] = message + response[:failure_code] = code + end + + response + end + + def parse_error(http_response) + response = {} + response[:http_code] = http_response.code + response[:http_message] = http_response.message + response[:success] = false + + document = REXML::Document.new(http_response.body) + + node = REXML::XPath.first(document, "//soap:Fault") + + node.elements.each do |element| + response[element.name] = element.text + end + + response[:message] = response["faultstring"].to_s.gsub("\n", " ") + response + rescue REXML::ParseException => e + response[:http_body] = http_response.body + response[:message] = "Failed to parse the failed response" + response + end + + def soap_action(action, v4 = false) + v4 ? "#{TX_NAMESPACE_V4}#{ACTIONS[action]}" : "#{TX_NAMESPACE}/#{ACTIONS[action]}" + end + + def url(v4 = false) + v4 ? v4_live_url : live_url + end + + def commit(action, request, v4 = false) + begin + data = ssl_post(url(v4), request, + "Content-Type" => 'text/xml; charset=utf-8', + "SOAPAction" => soap_action(action, v4) + ) + response = parse(action, data) + rescue ActiveMerchant::ResponseError => e + response = parse_error(e.response) + end + + Response.new(response[:success], response[:message], response, + :test => test?, + :authorization => authorization_from(response), + :avs_result => { :code => response["AVSResponse"] }, + :cvv_result => response["CVResponse"] + ) + end + + def authorization_from(response) + if response[:success] + [ response["ReferenceID"], response["OrderNumber"] ].join(";") + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_warrior.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_warrior.rb new file mode 100644 index 000000000..be58bd0bf --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/merchant_warrior.rb @@ -0,0 +1,190 @@ +require 'digest/md5' +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class MerchantWarriorGateway < Gateway + TOKEN_TEST_URL = 'https://base.merchantwarrior.com/token/' + TOKEN_LIVE_URL = 'https://api.merchantwarrior.com/token/' + + POST_TEST_URL = 'https://base.merchantwarrior.com/post/' + POST_LIVE_URL = 'https://api.merchantwarrior.com/post/' + + self.supported_countries = ['AU'] + self.supported_cardtypes = [:visa, :master, :american_express, + :diners_club, :discover] + self.homepage_url = 'http://www.merchantwarrior.com/' + self.display_name = 'MerchantWarrior' + + self.money_format = :dollars + self.default_currency = 'AUD' + + def initialize(options = {}) + requires!(options, :merchant_uuid, :api_key, :api_passphrase) + super + end + + def authorize(money, payment_method, options = {}) + post = {} + add_amount(post, money, options) + add_product(post, options) + add_address(post, options) + add_payment_method(post, payment_method) + commit('processAuth', post) + end + + def purchase(money, payment_method, options = {}) + post = {} + add_amount(post, money, options) + add_product(post, options) + add_address(post, options) + add_payment_method(post, payment_method) + commit('processCard', post) + end + + def capture(money, identification) + post = {} + add_amount(post, money, options) + add_transaction(post, identification) + post.merge!('captureAmount' => money.to_s) + commit('processCapture', post) + end + + def refund(money, identification) + post = {} + add_amount(post, money, options) + add_transaction(post, identification) + post['refundAmount'] = money + commit('refundCard', post) + end + + def store(creditcard, options = {}) + post = { + 'cardName' => creditcard.name, + 'cardNumber' => creditcard.number, + 'cardExpiryMonth' => format(creditcard.month, :two_digits), + 'cardExpiryYear' => format(creditcard.year, :two_digits) + } + commit('addCard', post) + end + + private + + def add_transaction(post, identification) + post['transactionID'] = identification + end + + def add_address(post, options) + return unless(address = options[:address]) + + post['customerName'] = address[:name] + post['customerCountry'] = address[:country] + post['customerState'] = address[:state] + post['customerCity'] = address[:city] + post['customerAddress'] = address[:address1] + post['customerPostCode'] = address[:zip] + end + + def add_product(post, options) + post['transactionProduct'] = options[:transaction_product] + end + + def add_payment_method(post, payment_method) + if payment_method.respond_to?(:number) + add_creditcard(post, payment_method) + else + add_token(post, payment_method) + end + end + + def add_token(post, token) + post['cardID'] = token + end + + def add_creditcard(post, creditcard) + post['paymentCardNumber'] = creditcard.number + post['paymentCardName'] = creditcard.name + post['paymentCardExpiry'] = creditcard.expiry_date.expiration.strftime("%m%y") + end + + def add_amount(post, money, options) + currency = (options[:currency] || currency(money)) + + post['transactionAmount'] = money.to_s + post['transactionCurrency'] = currency + post['hash'] = verification_hash(money, currency) + end + + def verification_hash(money, currency) + Digest::MD5.hexdigest( + ( + @options[:api_passphrase].to_s + + @options[:merchant_uuid].to_s + + money.to_s + + currency + ).downcase + ) + end + + def parse(body) + xml = REXML::Document.new(body) + + response = {} + xml.root.elements.to_a.each do |node| + parse_element(response, node) + end + response + end + + def parse_element(response, node) + if node.has_elements? + node.elements.each{|element| parse_element(response, element)} + else + response[node.name.underscore.to_sym] = node.text + end + end + + def commit(action, post) + add_auth(action, post) + + response = parse(ssl_post(url_for(action, post), post_data(post))) + + Response.new( + success?(response), + response[:response_message], + response, + :test => test?, + :authorization => (response[:card_id] || response[:transaction_id]) + ) + end + + def add_auth(action, post) + post['merchantUUID'] = @options[:merchant_uuid] + post['apiKey'] = @options[:api_key] + unless token?(post) + post['method'] = action + end + end + + def url_for(action, post) + if token?(post) + [(test? ? TOKEN_TEST_URL : TOKEN_LIVE_URL), action].join("/") + else + (test? ? POST_TEST_URL : POST_LIVE_URL) + end + end + + def token?(post) + (post["cardID"] || post["cardName"]) + end + + def success?(response) + (response[:response_code] == '0') + end + + def post_data(post) + post.collect{|k,v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&") + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/mercury.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/mercury.rb new file mode 100644 index 000000000..2819cc488 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/mercury.rb @@ -0,0 +1,272 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class MercuryGateway < Gateway + URLS = { + :test => 'https://w1.mercurydev.net/ws/ws.asmx', + :live => 'https://w1.mercurypay.com/ws/ws.asmx' + } + + self.homepage_url = 'http://www.mercurypay.com' + self.display_name = 'Mercury' + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + self.default_currency = 'USD' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card, options = {}) + requires!(options, :order_id) + + request = build_non_authorized_request('Sale', money, credit_card, options) + commit('Sale', request) + end + + def credit(money, credit_card, options = {}) + requires!(options, :order_id) + + request = build_non_authorized_request('Return', money, credit_card, options) + commit('Return', request) + end + + def authorize(money, credit_card, options = {}) + requires!(options, :order_id) + + options[:authorized] ||= money + request = build_non_authorized_request('PreAuth', money, credit_card, options) + commit('PreAuth', request) + end + + def capture(money, authorization, options = {}) + requires!(options, :credit_card) + options[:authorized] ||= money + request = build_authorized_request('PreAuthCapture', money, authorization, options[:credit_card], options) + commit('PreAuthCapture', request) + end + + def refund(money, authorization, options = {}) + requires!(options, :credit_card) + + request = build_authorized_request('VoidSale', money, authorization, options[:credit_card], options) + commit(options[:void], request) + end + + private + + def build_non_authorized_request(action, money, credit_card, options) + xml = Builder::XmlMarkup.new + + xml.tag! "TStream" do + xml.tag! "Transaction" do + xml.tag! 'TranType', 'Credit' + xml.tag! 'TranCode', action + if action == 'PreAuth' || action == 'Sale' + xml.tag! "PartialAuth", "Allow" + end + add_invoice(xml, options[:order_id], nil, options) + add_customer_data(xml, options) + add_amount(xml, money, options) + add_credit_card(xml, credit_card, action) + add_address(xml, options) + end + end + xml = xml.target! + end + + def build_authorized_request(action, money, authorization, credit_card, options) + xml = Builder::XmlMarkup.new + + invoice_no, ref_no, auth_code, acq_ref_data, process_data = split_authorization(authorization) + + xml.tag! "TStream" do + xml.tag! "Transaction" do + xml.tag! 'TranType', 'Credit' + xml.tag! 'TranCode', action + if action == 'PreAuthCapture' + xml.tag! "PartialAuth", "Allow" + end + add_invoice(xml, invoice_no, ref_no, options) + add_customer_data(xml, options) + add_amount(xml, money, options) + add_credit_card(xml, credit_card, action) + add_address(xml, options) + xml.tag! 'TranInfo' do + xml.tag! "AuthCode", auth_code + xml.tag! "AcqRefData", acq_ref_data + xml.tag! "ProcessData", process_data + end + end + end + xml = xml.target! + end + + def add_invoice(xml, invoice_no, ref_no, options) + if /^\d+$/ !~ invoice_no.to_s + raise ArgumentError.new("#{invoice_no} is not numeric as required by Mercury") + end + + xml.tag! 'InvoiceNo', invoice_no + xml.tag! 'RefNo', ref_no || invoice_no + xml.tag! 'OperatorID', options[:merchant] if options[:merchant] + xml.tag! 'Memo', options[:description] if options[:description] + end + + def add_customer_data(xml, options) + xml.tag! 'IpAddress', options[:ip] if options[:ip] + if options[:customer] + xml.tag! "TranInfo" do + xml.tag! 'CustomerCode', options[:customer] + end + end + xml.tag! 'MerchantID', @options[:login] + end + + def add_amount(xml, money, options = {}) + xml.tag! 'Amount' do + xml.tag! 'Purchase', amount(money) + xml.tag! 'Tax', options[:tax] if options[:tax] + xml.tag! 'Authorize', amount(options[:authorized]) if options[:authorized] + xml.tag! 'Gratuity', amount(options[:tip]) if options[:tip] + end + end + + CARD_CODES = { + 'visa' => 'VISA', + 'master' => 'M/C', + 'american_express' => 'AMEX', + 'discover' => 'DCVR', + 'diners_club' => 'DCLB', + 'jcb' => 'JCB' + } + + def add_credit_card(xml, credit_card, action) + xml.tag! 'Account' do + xml.tag! 'AcctNo', credit_card.number + xml.tag! 'ExpDate', expdate(credit_card) + end + xml.tag! 'CardType', CARD_CODES[credit_card.brand] if credit_card.brand + + include_cvv = !%w(Return PreAuthCapture).include?(action) + xml.tag! 'CVVData', credit_card.verification_value if(include_cvv && credit_card.verification_value) + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + def add_address(xml, options) + if billing_address = options[:billing_address] || options[:address] + xml.tag! 'AVS' do + xml.tag! 'Address', billing_address[:address1] + xml.tag! 'Zip', billing_address[:zip] + end + end + end + + def parse(action, body) + response = {} + hashify_xml!(unescape_xml(body), response) + response + end + + def hashify_xml!(xml, response) + xml = REXML::Document.new(xml) + + xml.elements.each("//CmdResponse/*") do |node| + response[node.name.underscore.to_sym] = node.text + end + + xml.elements.each("//TranResponse/*") do |node| + if node.name.to_s == "Amount" + node.elements.each do |amt| + response[amt.name.underscore.to_sym] = amt.text + end + else + response[node.name.underscore.to_sym] = node.text + end + end + end + + def endpoint_url + URLS[test? ? :test : :live] + end + + def build_soap_request(body) + xml = Builder::XmlMarkup.new + + xml.instruct! + xml.tag! 'soap:Envelope', ENVELOPE_NAMESPACES do + xml.tag! 'soap:Body' do + xml.tag! 'CreditTransaction', 'xmlns' => homepage_url do + xml.tag! 'tran' do + xml << escape_xml(body) + end + xml.tag! 'pw', @options[:password] + end + end + end + xml.target! + end + + def build_header + { + "SOAPAction" => "http://www.mercurypay.com/CreditTransaction", + "Content-Type" => "text/xml; charset=utf-8" + } + end + + SUCCESS_CODES = [ 'Approved', 'Success' ] + + def commit(action, request) + response = parse(action, ssl_post(endpoint_url, build_soap_request(request), build_header)) + + success = SUCCESS_CODES.include?(response[:cmd_status]) + message = success ? 'Success' : message_from(response) + + Response.new(success, message, response, + :test => test?, + :authorization => authorization_from(response), + :avs_result => { :code => response[:avs_result] }, + :cvv_result => response[:cvv_result]) + end + + def message_from(response) + response[:text_response] + end + + def authorization_from(response) + [ + response[:invoice_no], + response[:ref_no], + response[:auth_code], + response[:acq_ref_data], + response[:process_data] + ].join(";") + end + + def split_authorization(authorization) + invoice_no, ref_no, auth_code, acq_ref_data, process_data = authorization.split(";") + [invoice_no, ref_no, auth_code, acq_ref_data, process_data] + end + + ENVELOPE_NAMESPACES = { + 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', + 'xmlns:soap' => "http://schemas.xmlsoap.org/soap/envelope/", + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' + } + + def escape_xml(xml) + "\n\n" + end + + def unescape_xml(escaped_xml) + escaped_xml.gsub(/\>/,'>').gsub(/\</,'<') + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/metrics_global.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/metrics_global.rb new file mode 100644 index 000000000..fd7bf7643 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/metrics_global.rb @@ -0,0 +1,322 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # For more information on the Metrics Global Payment Gateway, visit the {Metrics Global website}[www.metricsglobal.com]. + # Further documentation on AVS and CVV response codes are available under the support section of the Metrics Global + # control panel. + # + # === Metrics Global Payment Gateway Authentication + # + # The login and password for the gateway are the same as the username and password used to log in to the Metrics Global + # control panel. Contact Metrics Global support to receive credentials for the control panel. + # + # === Demo Account + # + # There is a public demo account available with the following credentials: + # + # Login: demo + # Password: password + class MetricsGlobalGateway < Gateway + API_VERSION = '3.1' + + class_attribute :test_url, :live_url + + self.test_url = "https://secure.metricsglobalgateway.com/gateway/transact.dll?testing=true" + self.live_url = "https://secure.metricsglobalgateway.com/gateway/transact.dll" + + class_attribute :duplicate_window + + APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4 + + RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3 + AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE = 5, 6, 38 + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + self.homepage_url = 'http://www.metricsglobal.com' + self.display_name = 'Metrics Global' + + CARD_CODE_ERRORS = %w( N S ) + AVS_ERRORS = %w( A E N R W Z ) + AVS_REASON_CODES = %w(27 45) + + # Creates a new MetricsGlobalGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The username required to access the Metrics Global control panel. (REQUIRED) + # * :password -- The password required to access the Metrics Global control panel. (REQUIRED) + # * :test -- +true+ or +false+. If true, perform transactions against the test server. + # Otherwise, perform transactions against the production server. + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Performs an authorization, which reserves the funds on the customer's credit card, but does not + # charge the card. + # + # ==== Parameters + # + # * money -- The amount to be authorized as an Integer value in cents. + # * creditcard -- The CreditCard details for the transaction. + # * options -- A hash of optional parameters. + def authorize(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + add_duplicate_window(post) + + commit('AUTH_ONLY', money, post) + end + + # Perform a purchase, which is essentially an authorization and capture in a single operation. + # + # ==== Parameters + # + # * money -- The amount to be purchased as an Integer value in cents. + # * creditcard -- The CreditCard details for the transaction. + # * options -- A hash of optional parameters. + def purchase(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + add_duplicate_window(post) + + commit('AUTH_CAPTURE', money, post) + end + + # Captures the funds from an authorized transaction. + # + # ==== Parameters + # + # * money -- The amount to be captured as an Integer value in cents. + # * authorization -- The authorization returned from the previous authorize request. + def capture(money, authorization, options = {}) + post = {:trans_id => authorization} + add_customer_data(post, options) + commit('PRIOR_AUTH_CAPTURE', money, post) + end + + # Void a previous transaction + # + # ==== Parameters + # + # * authorization - The authorization returned from the previous authorize request. + def void(authorization, options = {}) + post = {:trans_id => authorization} + add_duplicate_window(post) + commit('VOID', nil, post) + end + + # Refund a transaction. + # + # This transaction indicates to the gateway that + # money should flow from the merchant to the customer. + # + # ==== Parameters + # + # * money -- The amount to be credited to the customer as an Integer value in cents. + # * identification -- The ID of the original transaction against which the refund is being issued. + # * options -- A hash of parameters. + # + # ==== Options + # + # * :card_number -- The credit card number the refund is being issued to. (REQUIRED) + # * :first_name -- The first name of the account being refunded. + # * :last_name -- The last name of the account being refunded. + # * :zip -- The postal code of the account being refunded. + def refund(money, identification, options = {}) + requires!(options, :card_number) + + post = { :trans_id => identification, + :card_num => options[:card_number] + } + + post[:first_name] = options[:first_name] if options[:first_name] + post[:last_name] = options[:last_name] if options[:last_name] + post[:zip] = options[:zip] if options[:zip] + + add_invoice(post, options) + add_duplicate_window(post) + + commit('CREDIT', money, post) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + private + + def commit(action, money, parameters) + parameters[:amount] = amount(money) unless action == 'VOID' + + # Only activate the test_request when the :test option is passed in + parameters[:test_request] = @options[:test] ? 'TRUE' : 'FALSE' + + url = test? ? self.test_url : self.live_url + data = ssl_post url, post_data(action, parameters) + + response = parse(data) + + message = message_from(response) + + # Return the response. The authorization can be taken out of the transaction_id + # Test Mode on/off is something we have to parse from the response text. + # It usually looks something like this + # + # (TESTMODE) Successful Sale + test_mode = test? || message =~ /TESTMODE/ + + Response.new(success?(response), message, response, + :test => test_mode, + :authorization => response[:transaction_id], + :fraud_review => fraud_review?(response), + :avs_result => { :code => response[:avs_result_code] }, + :cvv_result => response[:card_code] + ) + end + + def success?(response) + response[:response_code] == APPROVED + end + + def fraud_review?(response) + response[:response_code] == FRAUD_REVIEW + end + + def parse(body) + fields = split(body) + + results = { + :response_code => fields[RESPONSE_CODE].to_i, + :response_reason_code => fields[RESPONSE_REASON_CODE], + :response_reason_text => fields[RESPONSE_REASON_TEXT], + :avs_result_code => fields[AVS_RESULT_CODE], + :transaction_id => fields[TRANSACTION_ID], + :card_code => fields[CARD_CODE_RESPONSE_CODE] + } + results + end + + def post_data(action, parameters = {}) + post = {} + + post[:version] = API_VERSION + post[:login] = @options[:login] + post[:tran_key] = @options[:password] + post[:relay_response] = "FALSE" + post[:type] = action + post[:delim_data] = "TRUE" + post[:delim_char] = "," + post[:encap_char] = "$" + post[:solution_ID] = application_id if application_id.present? && application_id != "ActiveMerchant" + + request = post.merge(parameters).collect { |key, value| "x_#{key}=#{CGI.escape(value.to_s)}" }.join("&") + request + end + + def add_invoice(post, options) + post[:invoice_num] = options[:order_id] + post[:description] = options[:description] + end + + def add_creditcard(post, creditcard) + post[:card_num] = creditcard.number + post[:card_code] = creditcard.verification_value if creditcard.verification_value? + post[:exp_date] = expdate(creditcard) + post[:first_name] = creditcard.first_name + post[:last_name] = creditcard.last_name + end + + def add_customer_data(post, options) + if options.has_key? :email + post[:email] = options[:email] + post[:email_customer] = false + end + + if options.has_key? :customer + post[:cust_id] = options[:customer] + end + + if options.has_key? :ip + post[:customer_ip] = options[:ip] + end + end + + # x_duplicate_window won't be sent by default, because sending it changes the response. + # "If this field is present in the request with or without a value, an enhanced duplicate transaction response will be sent." + def add_duplicate_window(post) + unless duplicate_window.nil? + post[:duplicate_window] = duplicate_window + end + end + + def add_address(post, options) + if address = options[:billing_address] || options[:address] + post[:address] = address[:address1].to_s + post[:company] = address[:company].to_s + post[:phone] = address[:phone].to_s + post[:zip] = address[:zip].to_s + post[:city] = address[:city].to_s + post[:country] = address[:country].to_s + post[:state] = address[:state].blank? ? 'n/a' : address[:state] + end + + if address = options[:shipping_address] + post[:ship_to_first_name] = address[:first_name].to_s + post[:ship_to_last_name] = address[:last_name].to_s + post[:ship_to_address] = address[:address1].to_s + post[:ship_to_company] = address[:company].to_s + post[:ship_to_phone] = address[:phone].to_s + post[:ship_to_zip] = address[:zip].to_s + post[:ship_to_city] = address[:city].to_s + post[:ship_to_country] = address[:country].to_s + post[:ship_to_state] = address[:state].blank? ? 'n/a' : address[:state] + end + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def message_from(results) + if results[:response_code] == DECLINED + return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code]) + if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code]) + return AVSResult.messages[ results[:avs_result_code] ] + end + end + + (results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '') + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + + "#{month}#{year[-2..-1]}" + end + + def split(response) + response[1..-2].split(/\$,\$/) + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs.rb new file mode 100644 index 000000000..7eabdfdfa --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs.rb @@ -0,0 +1,265 @@ +require File.dirname(__FILE__) + '/migs/migs_codes' + +require 'digest/md5' # Used in add_secure_hash + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class MigsGateway < Gateway + include MigsCodes + + API_VERSION = 1 + + class_attribute :server_hosted_url, :merchant_hosted_url + + self.server_hosted_url = 'https://migs.mastercard.com.au/vpcpay' + self.merchant_hosted_url = 'https://migs.mastercard.com.au/vpcdps' + + self.live_url = self.server_hosted_url + + # MiGS is supported throughout Asia Pacific, Middle East and Africa + # MiGS is used in Australia (AU) by ANZ (eGate), CBA (CommWeb) and more + # Source of Country List: http://www.scribd.com/doc/17811923 + 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) + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb] + + self.money_format = :cents + + # The homepage URL of the gateway + self.homepage_url = 'http://mastercard.com/mastercardsps' + + # The name of the gateway + self.display_name = 'MasterCard Internet Gateway Service (MiGS)' + + # Creates a new MigsGateway + # The advanced_login/advanced_password fields are needed for + # advanced methods such as the capture, refund and status methods + # + # ==== Options + # + # * :login -- The MiGS Merchant ID (REQUIRED) + # * :password -- The MiGS Access Code (REQUIRED) + # * :secure_hash -- The MiGS Secure Hash + # (Required for Server Hosted payments) + # * :advanced_login -- The MiGS AMA User + # * :advanced_password -- The MiGS AMA User's password + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # ==== Options + # + # * :order_id -- A reference for tracking the order (REQUIRED) + # * :unique_id -- A unique id for this request (Max 40 chars). + # If not supplied one will be generated. + def purchase(money, creditcard, options = {}) + requires!(options, :order_id) + + post = {} + post[:Amount] = amount(money) + add_invoice(post, options) + add_creditcard(post, creditcard) + add_standard_parameters('pay', post, options[:unique_id]) + + commit(post) + end + + # MiGS works by merchants being either purchase only or authorize/capture + # So authorize is the same as purchase when in authorize mode + alias_method :authorize, :purchase + + # ==== Options + # + # * :unique_id -- A unique id for this request (Max 40 chars). + # If not supplied one will be generated. + def capture(money, authorization, options = {}) + requires!(@options, :advanced_login, :advanced_password) + + post = options.merge(:TransNo => authorization) + post[:Amount] = amount(money) + add_advanced_user(post) + add_standard_parameters('capture', post, options[:unique_id]) + + commit(post) + end + + # ==== Options + # + # * :unique_id -- A unique id for this request (Max 40 chars). + # If not supplied one will be generated. + def refund(money, authorization, options = {}) + requires!(@options, :advanced_login, :advanced_password) + + post = options.merge(:TransNo => authorization) + post[:Amount] = amount(money) + add_advanced_user(post) + add_standard_parameters('refund', post, options[:unique_id]) + + commit(post) + end + + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + # Checks the status of a previous transaction + # This can be useful when a response is not received due to network issues + # + # ==== Parameters + # + # * unique_id -- Unique id of transaction to find. + # This is the value of the option supplied in other methods or + # if not supplied is returned with key :MerchTxnRef + def status(unique_id) + requires!(@options, :advanced_login, :advanced_password) + + post = {} + add_advanced_user(post) + add_standard_parameters('queryDR', post, unique_id) + + commit(post) + end + + # Generates a URL to redirect user to MiGS to process payment + # Once user is finished MiGS will redirect back to specified URL + # With a response hash which can be turned into a Response object + # with purchase_offsite_response + # + # ==== Options + # + # * :order_id -- A reference for tracking the order (REQUIRED) + # * :locale -- Change the language of the redirected page + # Values are 2 digit locale, e.g. en, es + # * :return_url -- the URL to return to once the payment is complete + # * :card_type -- Providing this skips the card type step. + # Values are ActiveMerchant formats: e.g. master, visa, american_express, diners_club + # * :unique_id -- Unique id of transaction to find. + # If not supplied one will be generated. + def purchase_offsite_url(money, options = {}) + requires!(options, :order_id, :return_url) + requires!(@options, :secure_hash) + + post = {} + post[:Amount] = amount(money) + add_invoice(post, options) + add_creditcard_type(post, options[:card_type]) if options[:card_type] + + post.merge!( + :Locale => options[:locale] || 'en', + :ReturnURL => options[:return_url] + ) + + add_standard_parameters('pay', post, options[:unique_id]) + + add_secure_hash(post) + + self.server_hosted_url + '?' + post_data(post) + end + + # Parses a response from purchase_offsite_url once user is redirected back + # + # ==== Parameters + # + # * data -- All params when offsite payment returns + # e.g. returns to http://company.com/return?a=1&b=2, then input "a=1&b=2" + def purchase_offsite_response(data) + requires!(@options, :secure_hash) + + response_hash = parse(data) + + expected_secure_hash = calculate_secure_hash(response_hash.reject{|k, v| k == :SecureHash}, @options[:secure_hash]) + unless response_hash[:SecureHash] == expected_secure_hash + raise SecurityError, "Secure Hash mismatch, response may be tampered with" + end + + response_object(response_hash) + end + + def test? + @options[:login].start_with?('TEST') + end + + private + + def add_advanced_user(post) + post[:User] = @options[:advanced_login] + post[:Password] = @options[:advanced_password] + end + + def add_invoice(post, options) + post[:OrderInfo] = options[:order_id] + end + + def add_creditcard(post, creditcard) + post[:CardNum] = creditcard.number + post[:CardSecurityCode] = creditcard.verification_value if creditcard.verification_value? + post[:CardExp] = format(creditcard.year, :two_digits) + format(creditcard.month, :two_digits) + end + + def add_creditcard_type(post, card_type) + post[:Gateway] = 'ssl' + post[:card] = CARD_TYPES.detect{|ct| ct.am_code == card_type}.migs_long_code + end + + def parse(body) + params = CGI::parse(body) + hash = {} + params.each do |key, value| + hash[key.gsub('vpc_', '').to_sym] = value[0] + end + hash + end + + def commit(post) + data = ssl_post self.merchant_hosted_url, post_data(post) + response_hash = parse(data) + response_object(response_hash) + end + + def response_object(response) + Response.new(success?(response), response[:Message], response, + :test => test?, + :authorization => response[:TransactionNo], + :fraud_review => fraud_review?(response), + :avs_result => { :code => response[:AVSResultCode] }, + :cvv_result => response[:CSCResultCode] + ) + end + + def success?(response) + response[:TxnResponseCode] == '0' + end + + def fraud_review?(response) + ISSUER_RESPONSE_CODES[response[:AcqResponseCode]] == 'Suspected Fraud' + end + + def add_standard_parameters(action, post, unique_id = nil) + post.merge!( + :Version => API_VERSION, + :Merchant => @options[:login], + :AccessCode => @options[:password], + :Command => action, + :MerchTxnRef => unique_id || generate_unique_id.slice(0, 40) + ) + end + + def post_data(post) + post.collect { |key, value| "vpc_#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def add_secure_hash(post) + post[:SecureHash] = calculate_secure_hash(post, @options[:secure_hash]) + end + + def calculate_secure_hash(post, secure_hash) + sorted_values = post.sort_by(&:to_s).map(&:last) + input = secure_hash + sorted_values.join + Digest::MD5.hexdigest(input).upcase + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs/migs_codes.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs/migs_codes.rb new file mode 100644 index 000000000..9eae5f4bd --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/migs/migs_codes.rb @@ -0,0 +1,100 @@ +module ActiveMerchant + module Billing + module MigsCodes + TXN_RESPONSE_CODES = { + '?' => 'Response Unknown', + '0' => 'Transaction Successful', + '1' => 'Transaction Declined - Bank Error', + '2' => 'Bank Declined Transaction', + '3' => 'Transaction Declined - No Reply from Bank', + '4' => 'Transaction Declined - Expired Card', + '5' => 'Transaction Declined - Insufficient funds', + '6' => 'Transaction Declined - Error Communicating with Bank', + '7' => 'Payment Server Processing Error - Typically caused by invalid input data such as an invalid credit card number. Processing errors can also occur', + '8' => 'Transaction Declined - Transaction Type Not Supported', + '9' => 'Bank Declined Transaction (Do not contact Bank)', + 'A' => 'Transaction Aborted', + 'C' => 'Transaction Cancelled', + 'D' => 'Deferred Transaction', + 'E' => 'Issuer Returned a Referral Response', + 'F' => '3D Secure Authentication Failed', + 'I' => 'Card Security Code Failed', + 'L' => 'Shopping Transaction Locked (This indicates that there is another transaction taking place using the same shopping transaction number)', + 'N' => 'Cardholder is not enrolled in 3D Secure (Authentication Only)', + 'P' => 'Transaction is Pending', + 'R' => 'Retry Limits Exceeded, Transaction Not Processed', + 'S' => 'Duplicate OrderInfo used. (This is only relevant for Payment Servers that enforce the uniqueness of this field)', + 'U' => 'Card Security Code Failed' + } + + ISSUER_RESPONSE_CODES = { + '00' => 'Approved', + '01' => 'Refer to Card Issuer', + '02' => 'Refer to Card Issuer', + '03' => 'Invalid Merchant', + '04' => 'Pick Up Card', + '05' => 'Do Not Honor', + '07' => 'Pick Up Card', + '12' => 'Invalid Transaction', + '14' => 'Invalid Card Number (No such Number)', + '15' => 'No Such Issuer', + '33' => 'Expired Card', + '34' => 'Suspected Fraud', + '36' => 'Restricted Card', + '39' => 'No Credit Account', + '41' => 'Card Reported Lost', + '43' => 'Stolen Card', + '51' => 'Insufficient Funds', + '54' => 'Expired Card', + '57' => 'Transaction Not Permitted', + '59' => 'Suspected Fraud', + '62' => 'Restricted Card', + '65' => 'Exceeds withdrawal frequency limit', + '91' => 'Cannot Contact Issuer' + } + + VERIFIED_3D_CODES = { + 'Y' => 'The cardholder was successfully authenticated.', + 'E' => 'The cardholder is not enrolled.', + 'N' => 'The cardholder was not verified.', + 'U' => 'The cardholder\'s Issuer was unable to authenticate due to a system error at the Issuer.', + '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.', + '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).', + '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.', + 'C' => 'The card type is not supported for authentication.', + '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.', + 'S' => 'The signature on the response received from the Issuer could not be validated. This should be considered a failure.', + 'T' => 'ACS timed out. The Issuer\'s ACS did not respond to the Authentication request within the time out period.', + 'P' => 'Error parsing input from Issuer.', + '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.' + } + + class CreditCardType + attr_accessor :am_code, :migs_code, :migs_long_code, :name + def initialize(am_code, migs_code, migs_long_code, name) + @am_code = am_code + @migs_code = migs_code + @migs_long_code = migs_long_code + @name = name + end + end + + CARD_TYPES = [ + # The following are 4 different representations of credit card types + # am_code: The active merchant code + # migs_code: Used in response for purchase/authorize/status + # migs_long_code: Used to pre-select card for server_purchase_url + # name: The nice display name + %w(american_express AE Amex American\ Express), + %w(diners_club DC Dinersclub Diners\ Club), + %w(jcb JC JCB JCB\ Card), + %w(maestro MS Maestro Maestro\ Card), + %w(master MC Mastercard MasterCard), + %w(na PL PrivateLabelCard Private\ Label\ Card), + %w(visa VC Visa Visa\ Card') + ].map do |am_code, migs_code, migs_long_code, name| + CreditCardType.new(am_code, migs_code, migs_long_code, name) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments.rb new file mode 100644 index 000000000..91f059017 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments.rb @@ -0,0 +1,37 @@ +require File.dirname(__FILE__) + '/modern_payments_cim' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class ModernPaymentsGateway < Gateway + self.supported_countries = ModernPaymentsCimGateway.supported_countries + self.supported_cardtypes = ModernPaymentsCimGateway.supported_cardtypes + self.homepage_url = ModernPaymentsCimGateway.homepage_url + self.display_name = ModernPaymentsCimGateway.display_name + + self.abstract_class = true + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card, options = {}) + customer_response = cim.create_customer(options) + return customer_response unless customer_response.success? + + customer_id = customer_response.params["create_customer_result"] + + card_response = cim.modify_customer_credit_card(customer_id, credit_card) + return card_response unless card_response.success? + + cim.authorize_credit_card_payment(customer_id, money) + end + + private + def cim + @cim ||= ModernPaymentsCimGateway.new(@options) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments_cim.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments_cim.rb new file mode 100644 index 000000000..756055ad7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/modern_payments_cim.rb @@ -0,0 +1,219 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class ModernPaymentsCimGateway < Gateway #:nodoc: + self.test_url = "https://secure.modpay.com/netservices/test/ModpayTest.asmx" + self.live_url = 'https://secure.modpay.com/ws/modpay.asmx' + + LIVE_XMLNS = "https://secure.modpay.com/ws/" + TEST_XMLNS = "https://secure.modpay.com/netservices/test/" + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.modpay.com' + self.display_name = 'Modern Payments' + + SUCCESS_MESSAGE = "Transaction accepted" + FAILURE_MESSAGE = "Transaction failed" + ERROR_MESSAGE = "Transaction error" + + PAYMENT_METHOD = { + :check => 1, + :credit_card => 2 + } + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def create_customer(options = {}) + post = {} + add_customer_data(post, options) + add_address(post, options) + + commit('CreateCustomer', post) + end + + def modify_customer_credit_card(customer_id, credit_card) + raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank? + + post = {} + add_customer_id(post, customer_id) + add_credit_card(post, credit_card) + + commit('ModifyCustomerCreditCard', post) + end + + def authorize_credit_card_payment(customer_id, amount) + raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank? + + post = {} + add_customer_id(post, customer_id) + add_amount(post, amount) + + commit('AuthorizeCreditCardPayment', post) + end + + def create_payment(customer_id, amount, options = {}) + raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank? + + post = {} + add_customer_id(post, customer_id) + add_amount(post, amount) + add_payment_details(post, options) + + commit('CreatePayment', post) + end + + private + def add_payment_details(post, options) + post[:pmtDate] = (options[:payment_date] || Time.now.utc).strftime("%Y-%m-%dT%H:%M:%SZ") + post[:pmtType] = PAYMENT_METHOD[options[:payment_method] || :credit_card] + end + + def add_amount(post, money) + post[:pmtAmount] = amount(money) + end + + def add_customer_id(post, customer_id) + post[:custId] = customer_id + end + + def add_customer_data(post, options) + post[:acctNum] = options[:customer] + end + + def add_address(post, options) + address = options[:billing_address] || options[:address] || {} + + if name = address[:name] + segments = name.split(' ') + post[:lastName] = segments.pop + post[:firstName] = segments.join(' ') + else + post[:firstName] = address[:first_name] + post[:lastName] = address[:last_name] + end + + post[:address] = address[:address1] + post[:city] = address[:city] + post[:state] = address[:state] + post[:zip] = address[:zip] + post[:phone] = address[:phone] + post[:fax] = address[:fax] + post[:email] = options[:email] + end + + def add_credit_card(post, credit_card) + post[:ccName] = credit_card.name + post[:ccNum] = credit_card.number + post[:expMonth] = credit_card.month + post[:expYear] = credit_card.year + end + + def build_request(action, params) + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! 'env:Envelope', + { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', + 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' } do + + xml.tag! 'env:Body' do + xml.tag! action, { "xmlns" => xmlns(action) } do + xml.tag! "clientId", @options[:login] + xml.tag! "clientCode", @options[:password] + params.each {|key, value| xml.tag! key, value } + end + end + end + xml.target! + end + + def xmlns(action) + if test? && action == 'AuthorizeCreditCardPayment' + TEST_XMLNS + else + LIVE_XMLNS + end + end + + def url(action) + if test? && action == 'AuthorizeCreditCardPayment' + self.test_url + else + self.live_url + end + end + + def commit(action, params) + data = ssl_post(url(action), build_request(action, params), + { 'Content-Type' =>'text/xml; charset=utf-8', + 'SOAPAction' => "#{xmlns(action)}#{action}" } + ) + + response = parse(action, data) + Response.new(successful?(action, response), message_from(action, response), response, + :test => test?, + :authorization => authorization_from(action, response), + :avs_result => { :code => response[:avs_code] } + ) + end + + def authorization_from(action, response) + response[authorization_key(action)] + end + + def authorization_key(action) + action == "AuthorizeCreditCardPayment" ? :trans_id : "#{action.underscore}_result".to_sym + end + + def successful?(action, response) + key = authorization_key(action) + + if key == :trans_id + response[:approved] == "true" + else + response[key].to_i > 0 + end + end + + def message_from(action, response) + if response[:faultcode] + ERROR_MESSAGE + elsif successful?(action, response) + SUCCESS_MESSAGE + else + FAILURE_MESSAGE + end + end + + def parse(action, xml) + response = {} + response[:action] = action + + xml = REXML::Document.new(xml) + if root = REXML::XPath.first(xml, "//#{action}Response") + root.elements.to_a.each do |node| + parse_element(response, node) + end + elsif root = REXML::XPath.first(xml, "//soap:Fault") + root.elements.to_a.each do |node| + response[node.name.underscore.to_sym] = node.text + end + end + + response + end + + def parse_element(response, node) + if node.has_elements? + node.elements.each{|e| parse_element(response, e) } + else + response[node.name.underscore.to_sym] = node.text.to_s.strip + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris.rb new file mode 100644 index 000000000..e254b9489 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris.rb @@ -0,0 +1,244 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + # To learn more about the Moneris gateway, please contact + # eselectplus@moneris.com for a copy of their integration guide. For + # information on remote testing, please see "Test Environment Penny Value + # Response Table", and "Test Environment eFraud (AVS and CVD) Penny + # Response Values", available at Moneris' {eSelect Plus Documentation + # Centre}[https://www3.moneris.com/connect/en/documents/index.html]. + class MonerisGateway < Gateway + self.test_url = 'https://esqa.moneris.com/gateway2/servlet/MpgRequest' + self.live_url = 'https://www3.moneris.com/gateway2/servlet/MpgRequest' + + self.supported_countries = ['CA'] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover] + self.homepage_url = 'http://www.moneris.com/' + self.display_name = 'Moneris' + + # login is your Store ID + # password is your API Token + def initialize(options = {}) + requires!(options, :login, :password) + options = { :crypt_type => 7 }.merge(options) + super + end + + # Referred to as "PreAuth" in the Moneris integration guide, this action + # verifies and locks funds on a customer's card, which then must be + # captured at a later date. + # + # Pass in +order_id+ and optionally a +customer+ parameter. + def authorize(money, creditcard_or_datakey, options = {}) + requires!(options, :order_id) + post = {} + add_payment_source(post, creditcard_or_datakey) + post[:amount] = amount(money) + post[:order_id] = options[:order_id] + post[:cust_id] = options[:customer] + post[:crypt_type] = options[:crypt_type] || @options[:crypt_type] + action = (post[:data_key].blank?) ? 'preauth' : 'res_preauth_cc' + commit(action, post) + end + + # This action verifies funding on a customer's card and readies them for + # deposit in a merchant's account. + # + # Pass in order_id and optionally a customer parameter + def purchase(money, creditcard_or_datakey, options = {}) + requires!(options, :order_id) + post = {} + add_payment_source(post, creditcard_or_datakey) + post[:amount] = amount(money) + post[:order_id] = options[:order_id] + post[:cust_id] = options[:customer] + post[:crypt_type] = options[:crypt_type] || @options[:crypt_type] + action = (post[:data_key].blank?) ? 'purchase' : 'res_purchase_cc' + commit(action, post) + end + + # This method retrieves locked funds from a customer's account (from a + # PreAuth) and prepares them for deposit in a merchant's account. + # + # Note: Moneris requires both the order_id and the transaction number of + # the original authorization. To maintain the same interface as the other + # gateways the two numbers are concatenated together with a ; separator as + # the authorization number returned by authorization + def capture(money, authorization, options = {}) + commit 'completion', crediting_params(authorization, :comp_amount => amount(money)) + end + + # Voiding cancels an open authorization. + # + # Concatenate your transaction number and order_id by using a semicolon + # (';'). This is to keep the Moneris interface consistent with other + # gateways. (See +capture+ for details.) + def void(authorization, options = {}) + capture(0, authorization, options) + end + + # Performs a refund. This method requires that the original transaction + # number and order number be included. Concatenate your transaction + # number and order_id by using a semicolon (';'). This is to keep the + # Moneris interface consistent with other gateways. (See +capture+ for + # details.) + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + def refund(money, authorization, options = {}) + commit 'refund', crediting_params(authorization, :amount => amount(money)) + end + + def store(credit_card, options = {}) + post = {} + post[:pan] = credit_card.number + post[:expdate] = expdate(credit_card) + post[:crypt_type] = options[:crypt_type] || @options[:crypt_type] + commit('res_add_cc', post) + end + + def unstore(data_key) + post = {} + post[:data_key] = data_key + commit('res_delete', post) + end + + def update(data_key, credit_card, options = {}) + post = {} + post[:pan] = credit_card.number + post[:expdate] = expdate(credit_card) + post[:data_key] = data_key + post[:crypt_type] = options[:crypt_type] || @options[:crypt_type] + commit('res_update_cc', post) + end + + private # :nodoc: all + + def expdate(creditcard) + sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month) + end + + def add_payment_source(post, source) + if source.is_a?(String) + post[:data_key] = source + else + post[:pan] = source.number + post[:expdate] = expdate(source) + end + end + + # Common params used amongst the +credit+, +void+ and +capture+ methods + def crediting_params(authorization, options = {}) + { + :txn_number => split_authorization(authorization).first, + :order_id => split_authorization(authorization).last, + :crypt_type => options[:crypt_type] || @options[:crypt_type] + }.merge(options) + end + + # Splits an +authorization+ param and retrives the order id and + # transaction number in that order. + def split_authorization(authorization) + if authorization.nil? || authorization.empty? || authorization !~ /;/ + raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")' + else + authorization.split(';') + end + end + + def commit(action, parameters = {}) + response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(action, parameters))) + + Response.new(successful?(response), message_from(response[:message]), response, + :test => test?, + :authorization => authorization_from(response) + ) + end + + # Generates a Moneris authorization string of the form 'trans_id;receipt_id'. + def authorization_from(response = {}) + if response[:trans_id] && response[:receipt_id] + "#{response[:trans_id]};#{response[:receipt_id]}" + end + end + + # Tests for a successful response from Moneris' servers + def successful?(response) + response[:response_code] && + response[:complete] && + (0..49).include?(response[:response_code].to_i) + end + + def parse(xml) + response = { :message => "Global Error Receipt", :complete => false } + hashify_xml!(xml, response) + response + end + + def hashify_xml!(xml, response) + xml = REXML::Document.new(xml) + return if xml.root.nil? + xml.elements.each('//receipt/*') do |node| + response[node.name.underscore.to_sym] = normalize(node.text) + end + end + + def post_data(action, parameters = {}) + xml = REXML::Document.new + root = xml.add_element("request") + root.add_element("store_id").text = options[:login] + root.add_element("api_token").text = options[:password] + transaction = root.add_element(action) + + # Must add the elements in the correct order + actions[action].each do |key| + transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank? + end + + xml.to_s + end + + def message_from(message) + return 'Unspecified error' if message.blank? + message.gsub(/[^\w]/, ' ').split.join(" ").capitalize + end + + # Make a Ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when '', "null" then nil + else field + end + end + + def actions + { + "purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type], + "preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type], + "command" => [:order_id], + "refund" => [:order_id, :amount, :txn_number, :crypt_type], + "indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type], + "completion" => [:order_id, :comp_amount, :txn_number, :crypt_type], + "purchasecorrection" => [:order_id, :txn_number, :crypt_type], + "cavvpurcha" => [:order_id, :cust_id, :amount, :pan, :expdate, :cav], + "cavvpreaut" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv], + "transact" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type], + "Batchcloseall" => [], + "opentotals" => [:ecr_number], + "batchclose" => [:ecr_number], + "res_add_cc" => [:pan, :expdate, :crypt_type], + "res_delete" => [:data_key], + "res_update_cc" => [:data_key, :pan, :expdate, :crypt_type], + "res_purchase_cc" => [:data_key, :order_id, :cust_id, :amount, :crypt_type], + "res_preauth_cc" => [:data_key, :order_id, :cust_id, :amount, :crypt_type] + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris_us.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris_us.rb new file mode 100644 index 000000000..92feec273 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/moneris_us.rb @@ -0,0 +1,208 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + # To learn more about the Moneris (US) gateway, please contact + # ussales@moneris.com for a copy of their integration guide. For + # information on remote testing, please see "Test Environment Penny Value + # Response Table", and "Test Environment eFraud (AVS and CVD) Penny + # Response Values", available at Moneris' {eSelect Plus Documentation + # Centre}[https://www3.moneris.com/connect/en/documents/index.html]. + class MonerisUsGateway < Gateway + self.test_url = 'https://esplusqa.moneris.com/gateway_us/servlet/MpgRequest' + self.live_url = 'https://esplus.moneris.com/gateway_us/servlet/MpgRequest' + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover] + self.homepage_url = 'http://www.monerisusa.com/' + self.display_name = 'Moneris (US)' + + # login is your Store ID + # password is your API Token + def initialize(options = {}) + requires!(options, :login, :password) + options = { :crypt_type => 7 }.merge(options) + super + end + + # Referred to as "PreAuth" in the Moneris integration guide, this action + # verifies and locks funds on a customer's card, which then must be + # captured at a later date. + # + # Pass in +order_id+ and optionally a +customer+ parameter. + def authorize(money, creditcard, options = {}) + debit_commit 'us_preauth', money, creditcard, options + end + + # This action verifies funding on a customer's card, and readies them for + # deposit in a merchant's account. + # + # Pass in order_id and optionally a customer parameter + def purchase(money, creditcard, options = {}) + debit_commit 'us_purchase', money, creditcard, options + end + + # This method retrieves locked funds from a customer's account (from a + # PreAuth) and prepares them for deposit in a merchant's account. + # + # Note: Moneris requires both the order_id and the transaction number of + # the original authorization. To maintain the same interface as the other + # gateways the two numbers are concatenated together with a ; separator as + # the authorization number returned by authorization + def capture(money, authorization, options = {}) + commit 'us_completion', crediting_params(authorization, :comp_amount => amount(money)) + end + + # Voiding requires the original transaction ID and order ID of some open + # transaction. Closed transactions must be refunded. Note that the only + # methods which may be voided are +capture+ and +purchase+. + # + # Concatenate your transaction number and order_id by using a semicolon + # (';'). This is to keep the Moneris interface consistent with other + # gateways. (See +capture+ for details.) + def void(authorization, options = {}) + commit 'us_purchasecorrection', crediting_params(authorization) + end + + # Performs a refund. This method requires that the original transaction + # number and order number be included. Concatenate your transaction + # number and order_id by using a semicolon (';'). This is to keep the + # Moneris interface consistent with other gateways. (See +capture+ for + # details.) + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + def refund(money, authorization, options = {}) + commit 'us_refund', crediting_params(authorization, :amount => amount(money)) + end + + private # :nodoc: all + + def expdate(creditcard) + sprintf("%.4i", creditcard.year)[-2..-1] + sprintf("%.2i", creditcard.month) + end + + def debit_commit(commit_type, money, creditcard, options) + requires!(options, :order_id) + commit(commit_type, debit_params(money, creditcard, options)) + end + + # Common params used amongst the +purchase+ and +authorization+ methods + def debit_params(money, creditcard, options = {}) + { + :order_id => options[:order_id], + :cust_id => options[:customer], + :amount => amount(money), + :pan => creditcard.number, + :expdate => expdate(creditcard), + :crypt_type => options[:crypt_type] || @options[:crypt_type] + } + end + + # Common params used amongst the +credit+, +void+ and +capture+ methods + def crediting_params(authorization, options = {}) + { + :txn_number => split_authorization(authorization).first, + :order_id => split_authorization(authorization).last, + :crypt_type => options[:crypt_type] || @options[:crypt_type] + }.merge(options) + end + + # Splits an +authorization+ param and retrives the order id and + # transaction number in that order. + def split_authorization(authorization) + if authorization.nil? || authorization.empty? || authorization !~ /;/ + raise ArgumentError, 'You must include a valid authorization code (e.g. "1234;567")' + else + authorization.split(';') + end + end + + def commit(action, parameters = {}) + response = parse(ssl_post(test? ? self.test_url : self.live_url, post_data(action, parameters))) + + Response.new(successful?(response), message_from(response[:message]), response, + :test => test?, + :authorization => authorization_from(response) + ) + end + + # Generates a Moneris authorization string of the form 'trans_id;receipt_id'. + def authorization_from(response = {}) + if response[:trans_id] && response[:receipt_id] + "#{response[:trans_id]};#{response[:receipt_id]}" + end + end + + # Tests for a successful response from Moneris' servers + def successful?(response) + response[:response_code] && + response[:complete] && + (0..49).include?(response[:response_code].to_i) + end + + def parse(xml) + response = { :message => "Global Error Receipt", :complete => false } + hashify_xml!(xml, response) + response + end + + def hashify_xml!(xml, response) + xml = REXML::Document.new(xml) + return if xml.root.nil? + xml.elements.each('//receipt/*') do |node| + response[node.name.underscore.to_sym] = normalize(node.text) + end + end + + def post_data(action, parameters = {}) + xml = REXML::Document.new + root = xml.add_element("request") + root.add_element("store_id").text = options[:login] + root.add_element("api_token").text = options[:password] + transaction = root.add_element(action) + + # Must add the elements in the correct order + actions[action].each do |key| + transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank? + end + + xml.to_s + end + + def message_from(message) + return 'Unspecified error' if message.blank? + message.gsub(/[^\w]/, ' ').split.join(" ").capitalize + end + + # Make a Ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when '', "null" then nil + else field + end + end + + def actions + { + "us_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type], + "us_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type], + "us_refund" => [:order_id, :amount, :txn_number, :crypt_type], + "us_ind_refund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type], + "us_completion" => [:order_id, :comp_amount, :txn_number, :crypt_type], + "us_purchasecorrection" => [:order_id, :txn_number, :crypt_type], + "us_cavv_purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv], + "us_cavv_preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :cavv], + "us_batchcloseall" => [], + "us_opentotals" => [:ecr_number], + "us_batchclose" => [:ecr_number] + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nab_transact.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nab_transact.rb new file mode 100644 index 000000000..39e324f40 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nab_transact.rb @@ -0,0 +1,269 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # The National Australia Bank provide a payment gateway that seems to + # be a rebadged Securepay Australia service, though some differences exist. + class NabTransactGateway < Gateway + API_VERSION = 'xml-4.2' + PERIODIC_API_VERSION = "spxml-4.2" + + class_attribute :test_periodic_url, :live_periodic_url + + self.test_url = 'https://transact.nab.com.au/test/xmlapi/payment' + self.live_url = 'https://transact.nab.com.au/live/xmlapi/payment' + self.test_periodic_url = 'https://transact.nab.com.au/xmlapidemo/periodic' + self.live_periodic_url = 'https://transact.nab.com.au/xmlapi/periodic' + + self.supported_countries = ['AU'] + + # The card types supported by the payment gateway + # Note that support for Diners, Amex, and JCB require extra + # steps in setting up your account, as detailed in the NAB Transact API + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb] + + self.homepage_url = 'http://transact.nab.com.au' + self.display_name = 'NAB Transact' + + cattr_accessor :request_timeout + self.request_timeout = 60 + + self.money_format = :cents + self.default_currency = 'AUD' + + #Transactions currently accepted by NAB Transact XML API + TRANSACTIONS = { + :purchase => 0, #Standard Payment + :refund => 4, #Refund + :void => 6, #Client Reversal (Void) + :authorization => 10, #Preauthorise + :capture => 11 #Preauthorise Complete (Advice) + } + + PERIODIC_TYPES = { + :addcrn => 5, + :editcrn => 5, + :deletecrn => 5, + :trigger => 8 + } + + SUCCESS_CODES = [ '00', '08', '11', '16', '77' ] + + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card_or_stored_id, options = {}) + if credit_card_or_stored_id.respond_to?(:number) + #Credit card for instant payment + commit :purchase, build_purchase_request(money, credit_card_or_stored_id, options) + else + #Triggered payment for an existing stored credit card + options[:billing_id] = credit_card_or_stored_id.to_s + commit_periodic build_periodic_item(:trigger, money, nil, options) + end + end + + def refund(money, authorization, options = {}) + commit :refund, build_reference_request(money, authorization) + end + + def store(creditcard, options = {}) + requires!(options, :billing_id, :amount) + commit_periodic(build_periodic_item(:addcrn, options[:amount], creditcard, options)) + end + + def unstore(identification, options = {}) + options[:billing_id] = identification + commit_periodic(build_periodic_item(:deletecrn, options[:amount], nil, options)) + end + + private + + def add_metadata(xml, options) + if options[:merchant_name] || options[:merchant_location] + xml.tag! 'metadata' do + xml.tag! 'meta', :name => 'ca_name', :value => options[:merchant_name] if options[:merchant_name] + xml.tag! 'meta', :name => 'ca_location', :value => options[:merchant_location] if options[:merchant_location] + end + end + end + + def build_purchase_request(money, credit_card, options) + xml = Builder::XmlMarkup.new + xml.tag! 'amount', amount(money) + xml.tag! 'currency', options[:currency] || currency(money) + xml.tag! 'purchaseOrderNo', options[:order_id].to_s.gsub(/[ ']/, '') + + xml.tag! 'CreditCardInfo' do + xml.tag! 'cardNumber', credit_card.number + xml.tag! 'expiryDate', expdate(credit_card) + xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value? + end + + add_metadata(xml, options) + + xml.target! + end + + def build_reference_request(money, reference) + xml = Builder::XmlMarkup.new + + transaction_id, order_id, preauth_id, original_amount = reference.split('*') + + xml.tag! 'amount', (money ? amount(money) : original_amount) + xml.tag! 'currency', options[:currency] || currency(money) + xml.tag! 'txnID', transaction_id + xml.tag! 'purchaseOrderNo', order_id + xml.tag! 'preauthID', preauth_id + + xml.target! + end + + #Generate payment request XML + # - API is set to allow multiple Txn's but currentlu only allows one + # - txnSource = 23 - (XML) + def build_request(action, body) + xml = Builder::XmlMarkup.new + xml.instruct! + xml.tag! 'NABTransactMessage' do + xml.tag! 'MessageInfo' do + xml.tag! 'messageID', Utils.generate_unique_id.slice(0, 30) + xml.tag! 'messageTimestamp', generate_timestamp + xml.tag! 'timeoutValue', request_timeout + xml.tag! 'apiVersion', API_VERSION + end + + xml.tag! 'MerchantInfo' do + xml.tag! 'merchantID', @options[:login] + xml.tag! 'password', @options[:password] + end + + xml.tag! 'RequestType', 'Payment' + xml.tag! 'Payment' do + xml.tag! 'TxnList', "count" => 1 do + xml.tag! 'Txn', "ID" => 1 do + xml.tag! 'txnType', TRANSACTIONS[action] + xml.tag! 'txnSource', 23 + xml << body + end + end + end + end + + xml.target! + end + + def build_periodic_item(action, money, credit_card, options) + xml = Builder::XmlMarkup.new + + xml.tag! 'actionType', action.to_s + xml.tag! 'periodicType', PERIODIC_TYPES[action] if PERIODIC_TYPES[action] + xml.tag! 'currency', options[:currency] || currency(money) + xml.tag! 'crn', options[:billing_id] + + if credit_card + xml.tag! 'CreditCardInfo' do + xml.tag! 'cardNumber', credit_card.number + xml.tag! 'expiryDate', expdate(credit_card) + xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value? + end + end + xml.tag! 'amount', amount(money) + + xml.target! + end + + def build_periodic_request(body) + xml = Builder::XmlMarkup.new + xml.instruct! + xml.tag! 'NABTransactMessage' do + xml.tag! 'MessageInfo' do + xml.tag! 'messageID', ActiveMerchant::Utils.generate_unique_id.slice(0, 30) + xml.tag! 'messageTimestamp', generate_timestamp + xml.tag! 'timeoutValue', request_timeout + xml.tag! 'apiVersion', PERIODIC_API_VERSION + end + + xml.tag! 'MerchantInfo' do + xml.tag! 'merchantID', @options[:login] + xml.tag! 'password', @options[:password] + end + + xml.tag! 'RequestType', 'Periodic' + xml.tag! 'Periodic' do + xml.tag! 'PeriodicList', "count" => 1 do + xml.tag! 'PeriodicItem', "ID" => 1 do + xml << body + end + end + end + end + + xml.target! + end + + def commit(action, request) + response = parse(ssl_post(test? ? self.test_url : self.live_url, build_request(action, request))) + + Response.new(success?(response), message_from(response), response, + :test => test?, + :authorization => authorization_from(response) + ) + end + + def commit_periodic(request) + response = parse(ssl_post(test? ? self.test_periodic_url : self.live_periodic_url, build_periodic_request(request))) + Response.new(success?(response), message_from(response), response, + :test => test?, + :authorization => authorization_from(response) + ) + end + + def success?(response) + SUCCESS_CODES.include?(response[:response_code]) + end + + def authorization_from(response) + [response[:txn_id], response[:purchase_order_no], response[:preauth_id], response[:amount]].join('*') + end + + def message_from(response) + response[:response_text] || response[:status_description] + end + + def expdate(credit_card) + "#{format(credit_card.month, :two_digits)}/#{format(credit_card.year, :two_digits)}" + end + + def parse(body) + xml = REXML::Document.new(body) + + response = {} + + xml.root.elements.to_a.each do |node| + parse_element(response, node) + end + + response + end + + def parse_element(response, node) + if node.has_elements? + node.elements.each{|element| parse_element(response, element) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + # YYYYDDMMHHNNSSKKK000sOOO + def generate_timestamp + time = Time.now.utc + time.strftime("%Y%d%m%H%M%S#{time.usec}+000") + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/net_registry.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/net_registry.rb new file mode 100644 index 000000000..fddad0d16 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/net_registry.rb @@ -0,0 +1,193 @@ +module ActiveMerchant + module Billing + # Gateway for netregistry.com.au. + # + # Note that NetRegistry itself uses gateway service providers. At the + # time of this writing, there are at least two (Quest and Ingenico). + # This module has only been tested with Quest. + # + # Also note that NetRegistry does not offer a test mode, nor does it + # have support for the authorize/capture/void functionality by default + # (you may arrange for this as described in "Programming for + # NetRegistry's E-commerce Gateway." [http://rubyurl.com/hNG]), and no + # #void functionality is documented. As a result, the #authorize and + # #capture have not yet been tested through a live gateway, and #void + # will raise an error. + # + # If you have this functionality enabled, please consider contributing + # to ActiveMerchant by writing tests/code for these methods, and + # submitting a patch. + # + # In addition to the standard ActiveMerchant functionality, the + # response will contain a 'receipt' parameter + # (response.params['receipt']) if a receipt was issued by the gateway. + class NetRegistryGateway < Gateway + self.live_url = self.test_url = 'https://4tknox.au.com/cgi-bin/themerchant.au.com/ecom/external2.pl' + + FILTERED_PARAMS = [ 'card_no', 'card_expiry', 'receipt_array' ] + + self.supported_countries = ['AU'] + + # Note that support for Diners, Amex, and JCB require extra + # steps in setting up your account, as detailed in + # "Programming for NetRegistry's E-commerce Gateway." + # [http://rubyurl.com/hNG] + self.supported_cardtypes = [:visa, :master, :diners_club, :american_express, :jcb] + self.display_name = 'NetRegistry' + self.homepage_url = 'http://www.netregistry.com.au' + + TRANSACTIONS = { + :authorization => 'preauth', + :purchase => 'purchase', + :capture => 'completion', + :status => 'status', + :refund => 'refund' + } + + # Create a new NetRegistry gateway. + # + # Options :login and :password must be given. + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Note that #authorize and #capture only work if your account + # vendor is St George, and if your account has been setup as + # described in "Programming for NetRegistry's E-commerce + # Gateway." [http://rubyurl.com/hNG] + def authorize(money, credit_card, options = {}) + params = { + 'AMOUNT' => amount(money), + 'CCNUM' => credit_card.number, + 'CCEXP' => expiry(credit_card) + } + add_request_details(params, options) + commit(:authorization, params) + end + + # Note that #authorize and #capture only work if your account + # vendor is St George, and if your account has been setup as + # described in "Programming for NetRegistry's E-commerce + # Gateway." [http://rubyurl.com/hNG] + def capture(money, authorization, options = {}) + requires!(options, :credit_card) + credit_card = options[:credit_card] + + params = { + 'PREAUTHNUM' => authorization, + 'AMOUNT' => amount(money), + 'CCNUM' => credit_card.number, + 'CCEXP' => expiry(credit_card) + } + add_request_details(params, options) + commit(:capture, params) + end + + def purchase(money, credit_card, options = {}) + params = { + 'AMOUNT' => amount(money), + 'CCNUM' => credit_card.number, + 'CCEXP' => expiry(credit_card) + } + add_request_details(params, options) + commit(:purchase, params) + end + + def refund(money, identification, options = {}) + params = { + 'AMOUNT' => amount(money), + 'TXNREF' => identification + } + add_request_details(params, options) + commit(:refund, params) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + # Specific to NetRegistry. + # + # Run a 'status' command. This lets you view the status of a + # completed transaction. + # + def status(identification) + params = { + 'TXNREF' => identification + } + + commit(:status, params) + end + + private + def add_request_details(params, options) + params['COMMENT'] = options[:description] unless options[:description].blank? + end + + # Return the expiry for the given creditcard in the required + # format for a command. + def expiry(credit_card) + month = format(credit_card.month, :two_digits) + year = format(credit_card.year , :two_digits) + "#{month}/#{year}" + end + + # Post the a request with the given parameters and return the + # response object. + # + # Login and password are added automatically, and the comment is + # omitted if nil. + def commit(action, params) + # get gateway response + response = parse( ssl_post(self.live_url, post_data(action, params)) ) + + Response.new(response['status'] == 'approved', message_from(response), response, + :authorization => authorization_from(response, action) + ) + end + + def post_data(action, params) + params['COMMAND'] = TRANSACTIONS[action] + params['LOGIN'] = "#{@options[:login]}/#{@options[:password]}" + URI.encode(params.map{|k,v| "#{k}=#{v}"}.join('&')) + end + + def parse(response) + params = {} + + lines = response.split("\n") + + # Just incase there is no real response returned + params['status'] = lines[0] + params['response_text'] = lines[1] + + started = false + lines.each do |line| + if started + key, val = line.chomp.split(/=/, 2) + params[key] = val unless FILTERED_PARAMS.include?(key) + end + + started = line.chomp =~ /^\.$/ unless started + end + + params + end + + def message_from(response) + response['response_text'] + end + + def authorization_from(response, command) + case command + when :purchase + response['txn_ref'] + when :authorization + response['transaction_no'] + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netaxept.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netaxept.rb new file mode 100644 index 000000000..3ee6443f5 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netaxept.rb @@ -0,0 +1,181 @@ +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class NetaxeptGateway < Gateway + self.test_url = 'https://epayment-test.bbs.no/' + self.live_url = 'https://epayment.bbs.no/' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['NO', 'DK', 'SE', 'FI'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.betalingsterminal.no/Netthandel-forside/' + + # The name of the gateway + self.display_name = 'BBS Netaxept' + + self.money_format = :cents + + self.default_currency = 'NOK' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, creditcard, options = {}) + requires!(options, :order_id) + + MultiResponse.run do |r| + r.process{authorize(money, creditcard, options)} + r.process{capture(money, r.authorization, options)} + end + end + + def authorize(money, creditcard, options = {}) + requires!(options, :order_id) + + MultiResponse.run do |r| + r.process{setup_transaction(money, options)} + r.process{add_and_auth_credit_card(r.authorization, creditcard, options)} + r.process{query_transaction(r.authorization, options)} + end + end + + def capture(money, authorization, options = {}) + post = {} + add_credentials(post, options) + add_authorization(post, authorization, money) + post[:operation] = "Capture" + commit("Netaxept/process.aspx", post) + end + + def refund(money, authorization, options = {}) + post = {} + add_credentials(post, options) + add_authorization(post, authorization, money) + post[:operation] = "Credit" + commit("Netaxept/process.aspx", post) + end + + def void(authorization, options = {}) + post = {} + add_credentials(post, options) + add_authorization(post, authorization) + post[:operation] = "Annul" + commit("Netaxept/process.aspx", post) + end + + private + + def setup_transaction(money, options) + post = {} + add_credentials(post, options) + add_order(post, money, options) + commit("Netaxept/Register.aspx", post) + end + + def add_and_auth_credit_card(authorization, creditcard, options) + post = {} + add_credentials(post, options, false) + add_authorization(post, authorization) + add_creditcard(post, creditcard) + commit("terminal/default.aspx", post, false) + end + + def query_transaction(authorization, options) + post = {} + add_credentials(post, options) + add_authorization(post, authorization) + commit("Netaxept/query.aspx", post) + end + + def add_credentials(post, options, secure=true) + post[:merchantId] = @options[:login] + post[:token] = @options[:password] if secure + end + + def add_authorization(post, authorization, money=nil) + post[:transactionId] = authorization + post[:transactionAmount] = amount(money) if money + end + + def add_order(post, money, options) + post[:serviceType] = 'M' + post[:orderNumber] = options[:order_id] + post[:amount] = amount(money) + post[:currencyCode] = (options[:currency] || currency(money)) + post[:autoAuth] = "true" + end + + def add_creditcard(post, options) + post[:pan] = options.number + post[:expiryDate] = format(options.month, :two_digits) + format(options.year, :two_digits) + post[:securityCode] = options.verification_value + end + + def commit(path, parameters, xml=true) + raw = parse(ssl_get(build_url(path, parameters)), xml) + + success = false + authorization = (raw["TransactionId"] || parameters[:transactionId]) + if raw[:container] =~ /Exception|Error/ + message = (raw["Message"] || raw["Error"]["Message"]) + elsif raw["Error"] && !raw["Error"].empty? + message = (raw["Error"]["ResponseText"] || raw["Error"]["ResponseCode"]) + else + message = (raw["ResponseText"] || raw["ResponseCode"] || "OK") + success = true + end + + Response.new( + success, + message, + raw, + :test => test?, + :authorization => authorization + ) + end + + def parse(result, expects_xml=true) + if expects_xml + doc = REXML::Document.new(result) + extract_xml(doc.root).merge(:container => doc.root.name) + else + {:result => result} + end + end + + def extract_xml(element) + if element.has_elements? + hash = {} + element.elements.each do |e| + hash[e.name] = extract_xml(e) + end + hash + else + element.text + end + end + + def build_url(base, parameters=nil) + url = (test? ? self.test_url : self.live_url).dup + url << base + if parameters + url << '?' + url << encode(parameters) + end + url + end + + def encode(hash) + hash.collect{|(k,v)| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"}.join('&') + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netbilling.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netbilling.rb new file mode 100644 index 000000000..6488d54d1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netbilling.rb @@ -0,0 +1,197 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class NetbillingGateway < Gateway + self.live_url = self.test_url = 'https://secure.netbilling.com:1402/gw/sas/direct3.1' + + TRANSACTIONS = { + :authorization => 'A', + :purchase => 'S', + :refund => 'R', + :credit => 'C', + :capture => 'D', + :void => 'U' + } + + SUCCESS_CODES = [ '1', 'T' ] + SUCCESS_MESSAGE = 'The transaction was approved' + FAILURE_MESSAGE = 'The transaction failed' + TEST_LOGIN = '104901072025' + + self.display_name = 'NETbilling' + self.homepage_url = 'http://www.netbilling.com' + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club] + + def initialize(options = {}) + requires!(options, :login) + super + end + + def authorize(money, credit_card, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, credit_card, options) + add_customer_data(post, options) + + commit(:authorization, post) + end + + def purchase(money, credit_card, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, credit_card, options) + add_customer_data(post, options) + + commit(:purchase, post) + end + + def capture(money, authorization, options = {}) + post = {} + add_reference(post, authorization) + commit(:capture, post) + end + + def refund(money, source, options = {}) + post = {} + add_amount(post, money) + add_reference(post, source) + commit(:refund, post) + end + + def credit(money, credit_card, options = {}) + post = {} + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, credit_card, options) + add_customer_data(post, options) + + commit(:credit, post) + end + + def void(source, options = {}) + post = {} + add_reference(post, source) + commit(:void, post) + end + + def test? + (@options[:login] == TEST_LOGIN || super) + end + + private + + def add_amount(post, money) + post[:amount] = amount(money) + end + + def add_reference(post, reference) + post[:orig_id] = reference + end + + def add_customer_data(post, options) + post[:cust_email] = options[:email] + post[:cust_ip] = options[:ip] + end + + def add_address(post, credit_card, options) + if billing_address = options[:billing_address] || options[:address] + post[:bill_street] = billing_address[:address1] + post[:cust_phone] = billing_address[:phone] + post[:bill_zip] = billing_address[:zip] + post[:bill_city] = billing_address[:city] + post[:bill_country] = billing_address[:country] + post[:bill_state] = billing_address[:state] + end + + if shipping_address = options[:shipping_address] + first_name, last_name = parse_first_and_last_name(shipping_address[:name]) + + post[:ship_name1] = first_name + post[:ship_name2] = last_name + post[:ship_street] = shipping_address[:address1] + post[:ship_zip] = shipping_address[:zip] + post[:ship_city] = shipping_address[:city] + post[:ship_country] = shipping_address[:country] + post[:ship_state] = shipping_address[:state] + end + end + + def add_invoice(post, options) + post[:description] = options[:description] + end + + def add_credit_card(post, credit_card) + post[:bill_name1] = credit_card.first_name + post[:bill_name2] = credit_card.last_name + post[:card_number] = credit_card.number + post[:card_expire] = expdate(credit_card) + post[:card_cvv2] = credit_card.verification_value + end + + def parse(body) + results = {} + body.split(/&/).each do |pair| + key,val = pair.split(/\=/) + results[key.to_sym] = CGI.unescape(val) + end + results + end + + def commit(action, parameters) + response = parse(ssl_post(self.live_url, post_data(action, parameters))) + + Response.new(success?(response), message_from(response), response, + :test => test_response?(response), + :authorization => response[:trans_id], + :avs_result => { :code => response[:avs_code]}, + :cvv_result => response[:cvv2_code] + ) + rescue ActiveMerchant::ResponseError => e + raise unless(e.response.code =~ /^[67]\d\d$/) + return Response.new(false, e.response.message, {:status_code => e.response.code}, :test => test?) + end + + def test_response?(response) + !!(test? || response[:auth_msg] =~ /TEST/) + end + + def success?(response) + SUCCESS_CODES.include?(response[:status_code]) + end + + def message_from(response) + success?(response) ? SUCCESS_MESSAGE : (response[:auth_msg] || FAILURE_MESSAGE) + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + def post_data(action, parameters = {}) + parameters[:account_id] = @options[:login] + parameters[:site_tag] = @options[:site_tag] if @options[:site_tag].present? + parameters[:pay_type] = 'C' + parameters[:tran_type] = TRANSACTIONS[action] + + parameters.reject{|k,v| v.blank?}.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def parse_first_and_last_name(value) + name = value.to_s.split(' ') + + last_name = name.pop || '' + first_name = name.join(' ') + [ first_name, last_name ] + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netpay.rb new file mode 100644 index 000000000..babf95425 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/netpay.rb @@ -0,0 +1,223 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # + # NETPAY Gateway + # + # Support for NETPAY's HTTP Connector payment gateway in Mexico. + # + # The gateway sends requests as HTTP POST and receives the response details + # in the HTTP header, making the process really rather simple. + # + # Support for calls to the authorize and capture methods have been included + # as per the Netpay manuals, however, your millage may vary with these + # methods. At the time of writing (January 2013) they were not fully + # supported by the production or test gateways. This situation is + # expected to change within a few weeks/months. + # + # Purchases can be cancelled (`#void`) only within 24 hours of the + # transaction. After this, a refund should be performed instead. + # + # In addition to the regular ActiveMerchant transaction options, NETPAY + # also supports a `:mode` parameter. This allows testing to be peformed + # in production and force specific results. + # + # * 'P' - Production + # * 'A' - Approved + # * 'D' - Declined + # * 'R' - Random (Approved or Declined) + # * 'T' - Test + # + # For example: + # + # response = @gateway.purchase(1000, card, :mode => 'D') + # response.success # false + # + class NetpayGateway < Gateway + self.test_url = 'http://200.57.87.243:8855' + self.live_url = 'https://suite.netpay.com.mx/acquirerprd' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['MX'] + + self.default_currency = 'MXN' + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.netpay.com.mx' + + # The name of the gateway + self.display_name = 'NETPAY Gateway' + + CURRENCY_CODES = { + "MXN" => '484' + } + + # The header keys that we will provide in the response params hash + RESPONSE_KEYS = ['ResponseMsg', 'ResponseText', 'ResponseCode', 'TimeIn', 'TimeOut', 'AuthCode', 'OrderId', 'CardTypeName', 'MerchantId', 'IssuerAuthDate'] + + def initialize(options = {}) + requires!(options, :store_id, :login, :password) + super + end + + # Send an authorization request + def authorize(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + add_customer_data(post, options) + add_amount(post, money, options) + + commit('PreAuth', post, options) + end + + # Capture an authorization + def capture(money, authorization, options = {}) + post = {} + add_order_id(post, order_id_from(authorization)) + add_amount(post, money, options) + + commit('PostAuth', post, options) + end + + # Cancel an auth/purchase within first 24 hours + def void(authorization, options = {}) + post = {} + order_id, amount, currency = split_authorization(authorization) + add_order_id(post, order_id) + post['Total'] = (options[:amount] || amount) + post['CurrencyCode'] = currency + + commit('Refund', post, options) + end + + # Make a purchase. + def purchase(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + add_customer_data(post, options) + add_amount(post, money, options) + + commit('Auth', post, options) + end + + # Perform a Credit transaction. + def refund(money, authorization, options = {}) + post = {} + add_order_id(post, order_id_from(authorization)) + add_amount(post, money, options) + + #commit('Refund', post, options) + commit('Credit', post, options) + end + + private + + def add_login_data(post) + post['StoreId'] = @options[:store_id] + post['UserName'] = @options[:login] + post['Password'] = @options[:password] + end + + def add_action(post, action, options) + post['ResourceName'] = action + post['ContentType'] = 'Transaction' + post['Mode'] = options[:mode] || 'P' + end + + def add_order_id(post, order_id) + post['OrderId'] = order_id + end + + def add_amount(post, money, options) + post['Total'] = amount(money) + post['CurrencyCode'] = currency_code(options[:currency] || currency(money)) + end + + def add_customer_data(post, options) + post['IPAddress'] = options[:ip] unless options[:ip].blank? + end + + def add_invoice(post, options) + post['Comments'] = options[:description] if options[:description] + end + + def add_creditcard(post, creditcard) + post['CardNumber'] = creditcard.number + post['ExpDate'] = expdate(creditcard) + post['CustomerName'] = creditcard.name + post['CVV2'] = creditcard.verification_value unless creditcard.verification_value.nil? + end + + def build_authorization(request_params, response_params) + [response_params['OrderId'], request_params['Total'], request_params['CurrencyCode']].join('|') + end + + def split_authorization(authorization) + order_id, amount, currency = authorization.split("|") + [order_id, amount, currency] + end + + def order_id_from(authorization) + split_authorization(authorization).first + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}/#{year[-2..-1]}" + end + + def url + test? ? test_url : live_url + end + + def parse(response, request_params) + response_params = params_from_response(response) + + success = (response_params['ResponseCode'] == '00') + message = response_params['ResponseText'] || response_params['ResponseMsg'] + options = @options.merge(:test => test?, + :authorization => build_authorization(request_params, response_params)) + + Response.new(success, message, response_params, options) + end + + def commit(action, parameters, options) + add_login_data(parameters) + add_action(parameters, action, options) + + post = parameters.collect{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + parse(ssl_post(url, post), parameters) + end + + # Override the regular handle response so we can access the headers + def handle_response(response) + case response.code.to_i + when 200...300 + response + else + raise ResponseError.new(response) + end + end + + # Return a hash containing all the useful, or informative values from netpay + def params_from_response(response) + params = {} + RESPONSE_KEYS.each do |k| + params[k] = response[k] unless response[k].to_s.empty? + end + params + end + + def currency_code(currency) + return currency if currency =~ /^\d+$/ + CURRENCY_CODES[currency] + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nmi.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nmi.rb new file mode 100644 index 000000000..12c62afdb --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/nmi.rb @@ -0,0 +1,13 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class NmiGateway < AuthorizeNetGateway + self.test_url = 'https://secure.networkmerchants.com/gateway/transact.dll' + self.live_url = 'https://secure.networkmerchants.com/gateway/transact.dll' + self.homepage_url = 'http://nmi.com/' + self.display_name = 'NMI' + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ogone.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ogone.rb new file mode 100644 index 000000000..92a38d1ca --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/ogone.rb @@ -0,0 +1,424 @@ +# coding: utf-8 +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # = Ogone DirectLink Gateway + # + # DirectLink is the API version of the Ogone Payment Platform. It allows server to server + # communication between Ogone systems and your e-commerce website. + # + # This implementation follows the specification provided in the DirectLink integration + # guide version 4.3.0 (25 April 2012), available here: + # https://secure.ogone.com/ncol/Ogone_DirectLink_EN.pdf + # + # It also features aliases, which allow to store/unstore credit cards, as specified in + # the Alias Manager Option guide version 3.2.1 (25 April 2012) available here: + # https://secure.ogone.com/ncol/Ogone_Alias_EN.pdf + # + # It also implements the 3-D Secure feature, as specified in the DirectLink with + # 3-D Secure guide version 3.0 (25 April 2012) available here: + # https://secure.ogone.com/ncol/Ogone_DirectLink-3-D_EN.pdf + # + # It was last tested on Release 4.92 of Ogone DirectLink + AliasManager + Direct Link 3D + # (25 April 2012). + # + # For any questions or comments, please contact one of the following: + # - Joel Cogen (joel.cogen@belighted.com) + # - Nicolas Jacobeus (nicolas.jacobeus@belighted.com), + # - Sébastien Grosjean (public@zencocoon.com), + # - Rémy Coutable (remy@jilion.com). + # + # == Usage + # + # gateway = ActiveMerchant::Billing::OgoneGateway.new( + # :login => "my_ogone_psp_id", + # :user => "my_ogone_user_id", + # :password => "my_ogone_pswd", + # :signature => "my_ogone_sha_signature", # Only if you configured your Ogone environment so. + # :signature_encryptor => "sha512", # Can be "none" (default), "sha1", "sha256" or "sha512". + # # Must be the same as the one configured in your Ogone account. + # ) + # + # # set up credit card object as in main ActiveMerchant example + # creditcard = ActiveMerchant::Billing::CreditCard.new( + # :type => 'visa', + # :number => '4242424242424242', + # :month => 8, + # :year => 2009, + # :first_name => 'Bob', + # :last_name => 'Bobsen' + # ) + # + # # run request + # response = gateway.purchase(1000, creditcard, :order_id => "1") # charge 10 EUR + # + # If you don't provide an :order_id, the gateway will generate a random one for you. + # + # puts response.success? # Check whether the transaction was successful + # puts response.message # Retrieve the message returned by Ogone + # puts response.authorization # Retrieve the unique transaction ID returned by Ogone + # puts response.order_id # Retrieve the order ID + # + # == Alias feature + # + # To use the alias feature, simply add :billing_id in the options hash: + # + # # Associate the alias to that credit card + # gateway.purchase(1000, creditcard, :order_id => "1", :billing_id => "myawesomecustomer") + # + # # You can use the alias instead of the credit card for subsequent orders + # gateway.purchase(2000, "myawesomecustomer", :order_id => "2") + # + # # You can also create an alias without making a purchase using store + # gateway.store(creditcard, :billing_id => "myawesomecustomer") + # + # # When using store, you can also let Ogone generate the alias for you + # response = gateway.store(creditcard) + # puts response.billing_id # Retrieve the generated alias + # + # == 3-D Secure feature + # + # To use the 3-D Secure feature, simply add :d3d => true in the options hash: + # gateway.purchase(2000, "myawesomecustomer", :order_id => "2", :d3d => true) + # + # Specific 3-D Secure request options are (please refer to the documentation for more infos about these options): + # :win_3ds => :main_window (default), :pop_up or :pop_ix. + # :http_accept => "*/*" (default), or any other HTTP_ACCEPT header value. + # :http_user_agent => The cardholder's User-Agent string + # :accept_url => URL of the web page to show the customer when the payment is authorized. + # (or waiting to be authorized). + # :decline_url => URL of the web page to show the customer when the acquirer rejects the authorization + # more than the maximum permitted number of authorization attempts (10 by default, but can + # be changed in the "Global transaction parameters" tab, "Payment retry" section of the + # Technical Information page). + # :exception_url => URL of the web page to show the customer when the payment result is uncertain. + # :paramplus => Field to submit the miscellaneous parameters and their values that you wish to be + # returned in the post sale request or final redirection. + # :complus => Field to submit a value you wish to be returned in the post sale request or output. + # :language => Customer's language, for example: "en_EN" + # + class OgoneGateway < Gateway + + URLS = { + :order => 'https://secure.ogone.com/ncol/%s/orderdirect.asp', + :maintenance => 'https://secure.ogone.com/ncol/%s/maintenancedirect.asp' + } + + CVV_MAPPING = { 'OK' => 'M', + 'KO' => 'N', + 'NO' => 'P' } + + AVS_MAPPING = { 'OK' => 'M', + 'KO' => 'N', + 'NO' => 'R' } + + SUCCESS_MESSAGE = "The transaction was successful" + + THREE_D_SECURE_DISPLAY_WAYS = { :main_window => 'MAINW', # display the identification page in the main window + # (default value). + :pop_up => 'POPUP', # display the identification page in a pop-up window + # and return to the main window at the end. + :pop_ix => 'POPIX' } # display the identification page in a pop-up window + # and remain in the pop-up window. + + OGONE_NO_SIGNATURE_DEPRECATION_MESSAGE = "Signature usage will be the default for a future release of ActiveMerchant. You should either begin using it, or update your configuration to explicitly disable it (signature_encryptor: none)" + OGONE_STORE_OPTION_DEPRECATION_MESSAGE = "The 'store' option has been renamed to 'billing_id', and its usage is deprecated." + + self.test_url = URLS[:order] % "test" + self.live_url = URLS[:order] % "prod" + + self.supported_countries = ['BE', 'DE', 'FR', 'NL', 'AT', 'CH'] + # also supports Airplus and UATP + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover, :jcb, :maestro] + self.homepage_url = 'http://www.ogone.com/' + self.display_name = 'Ogone' + self.default_currency = 'EUR' + self.money_format = :cents + + def initialize(options = {}) + requires!(options, :login, :user, :password) + super + end + + # Verify and reserve the specified amount on the account, without actually doing the transaction. + def authorize(money, payment_source, options = {}) + post = {} + add_invoice(post, options) + add_payment_source(post, payment_source, options) + add_address(post, payment_source, options) + add_customer_data(post, options) + add_money(post, money, options) + commit('RES', post) + end + + # Verify and transfer the specified amount. + def purchase(money, payment_source, options = {}) + post = {} + action = options[:action] || 'SAL' + add_invoice(post, options) + add_payment_source(post, payment_source, options) + add_address(post, payment_source, options) + add_customer_data(post, options) + add_money(post, money, options) + commit(action, post) + end + + # Complete a previously authorized transaction. + def capture(money, authorization, options = {}) + post = {} + action = options[:action] || 'SAL' + add_authorization(post, reference_from(authorization)) + add_invoice(post, options) + add_customer_data(post, options) + add_money(post, money, options) + commit(action, post) + end + + # Cancels a previously authorized transaction. + def void(identification, options = {}) + post = {} + add_authorization(post, reference_from(identification)) + commit('DES', post) + end + + # Credit the specified account by a specific amount. + def credit(money, identification_or_credit_card, options = {}) + if reference_transaction?(identification_or_credit_card) + deprecated CREDIT_DEPRECATION_MESSAGE + # Referenced credit: refund of a settled transaction + refund(money, identification_or_credit_card, options) + else # must be a credit card or card reference + perform_non_referenced_credit(money, identification_or_credit_card, options) + end + end + + # Refund of a settled transaction + def refund(money, reference, options = {}) + perform_reference_credit(money, reference, options) + end + + # Store a credit card by creating an Ogone Alias + def store(payment_source, options = {}) + options.merge!(:alias_operation => 'BYPSP') unless(options.has_key?(:billing_id) || options.has_key?(:store)) + response = authorize(1, payment_source, options) + void(response.authorization) if response.success? + response + end + + private + + def reference_from(authorization) + authorization.split(";").first + end + + def reference_transaction?(identifier) + return false unless identifier.is_a?(String) + _, action = identifier.split(";") + !action.nil? + end + + def perform_reference_credit(money, payment_target, options = {}) + post = {} + add_authorization(post, reference_from(payment_target)) + add_money(post, money, options) + commit('RFD', post) + end + + def perform_non_referenced_credit(money, payment_target, options = {}) + # Non-referenced credit: acts like a reverse purchase + post = {} + add_invoice(post, options) + add_payment_source(post, payment_target, options) + add_address(post, payment_target, options) + add_customer_data(post, options) + add_money(post, money, options) + commit('RFD', post) + end + + def add_payment_source(post, payment_source, options) + if payment_source.is_a?(String) + add_alias(post, payment_source, options[:alias_operation]) + add_eci(post, options[:eci] || '9') + else + if options.has_key?(:store) + deprecated OGONE_STORE_OPTION_DEPRECATION_MESSAGE + options[:billing_id] ||= options[:store] + end + add_alias(post, options[:billing_id], options[:alias_operation]) + add_eci(post, options[:eci] || '7') + add_d3d(post, options) if options[:d3d] + add_creditcard(post, payment_source) + end + end + + def add_d3d(post, options) + add_pair post, 'FLAG3D', 'Y' + win_3ds = THREE_D_SECURE_DISPLAY_WAYS.key?(options[:win_3ds]) ? + THREE_D_SECURE_DISPLAY_WAYS[options[:win_3ds]] : + THREE_D_SECURE_DISPLAY_WAYS[:main_window] + add_pair post, 'WIN3DS', win_3ds + + add_pair post, 'HTTP_ACCEPT', options[:http_accept] || "*/*" + add_pair post, 'HTTP_USER_AGENT', options[:http_user_agent] if options[:http_user_agent] + add_pair post, 'ACCEPTURL', options[:accept_url] if options[:accept_url] + add_pair post, 'DECLINEURL', options[:decline_url] if options[:decline_url] + add_pair post, 'EXCEPTIONURL', options[:exception_url] if options[:exception_url] + add_pair post, 'PARAMPLUS', options[:paramplus] if options[:paramplus] + add_pair post, 'COMPLUS', options[:complus] if options[:complus] + add_pair post, 'LANGUAGE', options[:language] if options[:language] + end + + def add_eci(post, eci) + add_pair post, 'ECI', eci.to_s + end + + def add_alias(post, _alias, alias_operation = nil) + add_pair post, 'ALIAS', _alias + add_pair post, 'ALIASOPERATION', alias_operation unless alias_operation.nil? + end + + def add_authorization(post, authorization) + add_pair post, 'PAYID', authorization + end + + def add_money(post, money, options) + add_pair post, 'currency', options[:currency] || @options[:currency] || currency(money) + add_pair post, 'amount', amount(money) + end + + def add_customer_data(post, options) + add_pair post, 'EMAIL', options[:email] + add_pair post, 'REMOTE_ADDR', options[:ip] + end + + def add_address(post, creditcard, options) + return unless options[:billing_address] + add_pair post, 'Owneraddress', options[:billing_address][:address1] + add_pair post, 'OwnerZip', options[:billing_address][:zip] + add_pair post, 'ownertown', options[:billing_address][:city] + add_pair post, 'ownercty', options[:billing_address][:country] + add_pair post, 'ownertelno', options[:billing_address][:phone] + end + + def add_invoice(post, options) + add_pair post, 'orderID', options[:order_id] || generate_unique_id[0...30] + add_pair post, 'COM', options[:description] + end + + def add_creditcard(post, creditcard) + add_pair post, 'CN', creditcard.name + add_pair post, 'CARDNO', creditcard.number + add_pair post, 'ED', "%02d%02s" % [creditcard.month, creditcard.year.to_s[-2..-1]] + add_pair post, 'CVC', creditcard.verification_value + end + + def parse(body) + xml_root = REXML::Document.new(body).root + response = convert_attributes_to_hash(xml_root.attributes) + + # Add HTML_ANSWER element (3-D Secure specific to the response's params) + # Note: HTML_ANSWER is not an attribute so we add it "by hand" to the response + if html_answer = REXML::XPath.first(xml_root, "//HTML_ANSWER") + response["HTML_ANSWER"] = html_answer.text + end + + response + end + + def commit(action, parameters) + add_pair parameters, 'PSPID', @options[:login] + add_pair parameters, 'USERID', @options[:user] + add_pair parameters, 'PSWD', @options[:password] + + url = URLS[parameters['PAYID'] ? :maintenance : :order] % [test? ? "test" : "prod"] + response = parse(ssl_post(url, post_data(action, parameters))) + + options = { + :authorization => [response["PAYID"], action].join(";"), + :test => test?, + :avs_result => { :code => AVS_MAPPING[response["AAVCheck"]] }, + :cvv_result => CVV_MAPPING[response["CVCCheck"]] + } + OgoneResponse.new(successful?(response), message_from(response), response, options) + end + + def successful?(response) + response["NCERROR"] == "0" + end + + def message_from(response) + if successful?(response) + SUCCESS_MESSAGE + else + format_error_message(response["NCERRORPLUS"]) + end + end + + def format_error_message(message) + raw_message = message.to_s.strip + case raw_message + when /\|/ + raw_message.split("|").join(", ").capitalize + when /\// + raw_message.split("/").first.to_s.capitalize + else + raw_message.to_s.capitalize + end + end + + def post_data(action, parameters = {}) + add_pair parameters, 'Operation', action + add_signature(parameters) + parameters.to_query + end + + def add_signature(parameters) + if @options[:signature].blank? + deprecated(OGONE_NO_SIGNATURE_DEPRECATION_MESSAGE) unless(@options[:signature_encryptor] == "none") + return + end + + sha_encryptor = case @options[:signature_encryptor] + when 'sha256' + Digest::SHA256 + when 'sha512' + Digest::SHA512 + else + Digest::SHA1 + end + + string_to_digest = if @options[:signature_encryptor] + parameters.sort { |a, b| a[0].upcase <=> b[0].upcase }.map { |k, v| "#{k.upcase}=#{v}" }.join(@options[:signature]) + else + %w[orderID amount currency CARDNO PSPID Operation ALIAS].map { |key| parameters[key] }.join + end + string_to_digest << @options[:signature] + + add_pair parameters, 'SHASign', sha_encryptor.hexdigest(string_to_digest).upcase + end + + def add_pair(post, key, value) + post[key] = value if !value.blank? + end + + def convert_attributes_to_hash(rexml_attributes) + response_hash = {} + rexml_attributes.each do |key, value| + response_hash[key] = value + end + response_hash + end + end + + class OgoneResponse < Response + def order_id + @params['orderID'] + end + + def billing_id + @params['ALIAS'] + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/optimal_payment.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/optimal_payment.rb new file mode 100644 index 000000000..604eefa18 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/optimal_payment.rb @@ -0,0 +1,297 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class OptimalPaymentGateway < Gateway + self.test_url = 'https://webservices.test.optimalpayments.com/creditcardWS/CreditCardServlet/v1' + self.live_url = 'https://webservices.optimalpayments.com/creditcardWS/CreditCardServlet/v1' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['CA', 'US', 'GB'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :solo] # :switch? + + # The homepage URL of the gateway + self.homepage_url = 'http://www.optimalpayments.com/' + + # The name of the gateway + self.display_name = 'Optimal Payments' + + def initialize(options = {}) + #requires!(options, :login, :password) + super + end + + def authorize(money, card_or_auth, options = {}) + parse_card_or_auth(card_or_auth, options) + commit("cc#{@stored_data}Authorize", money, options) + end + alias stored_authorize authorize # back-compat + + def purchase(money, card_or_auth, options = {}) + parse_card_or_auth(card_or_auth, options) + commit("cc#{@stored_data}Purchase", money, options) + end + alias stored_purchase purchase # back-compat + + def refund(money, authorization, options = {}) + options[:confirmationNumber] = authorization + commit('ccCredit', money, options) + end + + def void(authorization, options = {}) + options[:confirmationNumber] = authorization + commit('ccAuthorizeReversal', nil, options) + end + + def capture(money, authorization, options = {}) + options[:confirmationNumber] = authorization + commit('ccSettlement', money, options) + end + + private + + def parse_card_or_auth(card_or_auth, options) + if card_or_auth.respond_to?(:number) + @credit_card = card_or_auth + @stored_data = "" + else + options[:confirmationNumber] = card_or_auth + @stored_data = "StoredData" + end + end + + def parse(body) + REXML::Document.new(body || '') + end + + def commit(action, money, post) + post[:order_id] ||= 'order_id' + + xml = case action + when 'ccAuthorize', 'ccPurchase', 'ccVerification' + cc_auth_request(money, post) + when 'ccCredit', 'ccSettlement' + cc_post_auth_request(money, post) + when 'ccStoredDataAuthorize', 'ccStoredDataPurchase' + cc_stored_data_request(money, post) + when 'ccAuthorizeReversal' + cc_auth_reversal_request(post) + #when 'ccCancelSettle', 'ccCancelCredit', 'ccCancelPayment' + # cc_cancel_request(money, post) + #when 'ccPayment' + # cc_payment_request(money, post) + #when 'ccAuthenticate' + # cc_authenticate_request(money, post) + else + raise 'Unknown Action' + end + txnRequest = URI.encode(xml) + response = parse(ssl_post(test? ? self.test_url : self.live_url, "txnMode=#{action}&txnRequest=#{txnRequest}")) + + Response.new(successful?(response), message_from(response), hash_from_xml(response), + :test => test?, + :authorization => authorization_from(response), + :avs_result => { :code => avs_result_from(response) }, + :cvv_result => cvv_result_from(response) + ) + end + + def successful?(response) + REXML::XPath.first(response, '//decision').text == 'ACCEPTED' rescue false + end + + def message_from(response) + REXML::XPath.each(response, '//detail') do |detail| + if detail.is_a?(REXML::Element) && detail.elements['tag'].text == 'InternalResponseDescription' + return detail.elements['value'].text + end + end + nil + end + + def authorization_from(response) + get_text_from_document(response, '//confirmationNumber') + end + + def avs_result_from(response) + get_text_from_document(response, '//avsResponse') + end + + def cvv_result_from(response) + get_text_from_document(response, '//cvdResponse') + end + + def hash_from_xml(response) + hsh = {} + %w(confirmationNumber authCode + decision code description + actionCode avsResponse cvdResponse + txnTime duplicateFound + ).each do |tag| + node = REXML::XPath.first(response, "//#{tag}") + hsh[tag] = node.text if node + end + REXML::XPath.each(response, '//detail') do |detail| + next unless detail.is_a?(REXML::Element) + tag = detail.elements['tag'].text + value = detail.elements['value'].text + hsh[tag] = value + end + hsh + end + + def xml_document(root_tag) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag!(root_tag, schema) do + yield xml + end + xml.target! + end + + def get_text_from_document(document, node) + node = REXML::XPath.first(document, node) + node && node.text + end + + def cc_auth_request(money, opts) + xml_document('ccAuthRequestV1') do |xml| + build_merchant_account(xml, @options) + xml.merchantRefNum opts[:order_id] + xml.amount(money/100.0) + build_card(xml, opts) + build_billing_details(xml, opts) + build_shipping_details(xml, opts) + end + end + + def cc_auth_reversal_request(opts) + xml_document('ccAuthReversalRequestV1') do |xml| + build_merchant_account(xml, @options) + xml.confirmationNumber opts[:confirmationNumber] + xml.merchantRefNum opts[:order_id] + end + end + + def cc_post_auth_request(money, opts) + xml_document('ccPostAuthRequestV1') do |xml| + build_merchant_account(xml, @options) + xml.confirmationNumber opts[:confirmationNumber] + xml.merchantRefNum opts[:order_id] + xml.amount(money/100.0) + end + end + + def cc_stored_data_request(money, opts) + xml_document('ccStoredDataRequestV1') do |xml| + build_merchant_account(xml, @options) + xml.merchantRefNum opts[:order_id] + xml.confirmationNumber opts[:confirmationNumber] + xml.amount(money/100.0) + end + end + + # untested + # + # def cc_cancel_request(opts) + # xml_document('ccCancelRequestV1') do |xml| + # build_merchant_account(xml, @options) + # xml.confirmationNumber opts[:confirmationNumber] + # end + # end + # + # def cc_payment_request(money, opts) + # xml_document('ccPaymentRequestV1') do |xml| + # build_merchant_account(xml, @options) + # xml.merchantRefNum opts[:order_id] + # xml.amount(money/100.0) + # build_card(xml, opts) + # build_billing_details(xml, opts) + # end + # end + # + # def cc_authenticate_request(opts) + # xml_document('ccAuthenticateRequestV1') do |xml| + # build_merchant_account(xml, @options) + # xml.confirmationNumber opts[:confirmationNumber] + # xml.paymentResponse 'myPaymentResponse' + # end + # end + + def schema + { 'xmlns' => 'http://www.optimalpayments.com/creditcard/xmlschema/v1', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation' => 'http://www.optimalpayments.com/creditcard/xmlschema/v1' + } + end + + def build_merchant_account(xml, opts) + xml.tag! 'merchantAccount' do + xml.tag! 'accountNum' , opts[:account] + xml.tag! 'storeID' , opts[:login] + xml.tag! 'storePwd' , opts[:password] + end + end + + def build_card(xml, opts) + xml.tag! 'card' do + xml.tag! 'cardNum' , @credit_card.number + xml.tag! 'cardExpiry' do + xml.tag! 'month' , @credit_card.month + xml.tag! 'year' , @credit_card.year + end + if brand = card_type(@credit_card.brand) + xml.tag! 'cardType' , brand + end + if @credit_card.verification_value + xml.tag! 'cvdIndicator' , '1' # Value Provided + xml.tag! 'cvd' , @credit_card.verification_value + end + end + end + + def build_billing_details(xml, opts) + xml.tag! 'billingDetails' do + xml.tag! 'cardPayMethod', 'WEB' + build_address(xml, opts[:billing_address], opts[:email]) + end + end + + def build_shipping_details(xml, opts) + xml.tag! 'shippingDetails' do + build_address(xml, opts[:shipping_address], opts[:email]) + end if opts[:shipping_address].present? + end + + def build_address(xml, addr, email=nil) + if addr[:name] + xml.tag! 'firstName', CGI.escape(addr[:name].split(' ').first) # TODO: parse properly + xml.tag! 'lastName' , CGI.escape(addr[:name].split(' ').last ) + end + xml.tag! 'street' , CGI.escape(addr[:address1]) if addr[:address1].present? + xml.tag! 'street2', CGI.escape(addr[:address2]) if addr[:address2].present? + xml.tag! 'city' , CGI.escape(addr[:city] ) if addr[:city].present? + if addr[:state].present? + state_tag = %w(US CA).include?(addr[:country]) ? 'state' : 'region' + xml.tag! state_tag, CGI.escape(addr[:state]) + end + xml.tag! 'country', CGI.escape(addr[:country] ) if addr[:country].present? + xml.tag! 'zip' , CGI.escape(addr[:zip] ) if addr[:zip].present? + xml.tag! 'phone' , CGI.escape(addr[:phone] ) if addr[:phone].present? + xml.tag! 'email', CGI.escape(email) if email + end + + def card_type(key) + { 'visa' => 'VI', + 'master' => 'MC', + 'american_express'=> 'AM', + 'discover' => 'DI', + 'diners_club' => 'DC', + #'switch' => '', + 'solo' => 'SO' + }[key] + end + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital.rb new file mode 100644 index 000000000..c26ebbac4 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital.rb @@ -0,0 +1,633 @@ +require File.dirname(__FILE__) + '/orbital/orbital_soft_descriptors' +require File.dirname(__FILE__) + '/orbital/avs_result' +require "rexml/document" + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # For more information on Orbital, visit the {integration center}[http://download.chasepaymentech.com] + # + # ==== Authentication Options + # + # The Orbital Gateway supports two methods of authenticating incoming requests: + # Source IP authentication and Connection Username/Password authentication + # + # In addition, these IP addresses/Connection Usernames must be affiliated with the Merchant IDs + # for which the client should be submitting transactions. + # + # This does allow Third Party Hosting service organizations presenting on behalf of other + # merchants to submit transactions. However, each time a new customer is added, the + # merchant or Third-Party hosting organization needs to ensure that the new Merchant IDs + # or Chain IDs are affiliated with the hosting companies IPs or Connection Usernames. + # + # If the merchant expects to have more than one merchant account with the Orbital + # Gateway, it should have its IP addresses/Connection Usernames affiliated at the Chain + # level hierarchy within the Orbital Gateway. Each time a new merchant ID is added, as + # long as it is placed within the same Chain, it will simply work. Otherwise, the additional + # MIDs will need to be affiliated with the merchant IPs or Connection Usernames respectively. + # For example, we generally affiliate all Salem accounts [BIN 000001] with + # their Company Number [formerly called MA #] number so all MIDs or Divisions under that + # Company will automatically be affiliated. + + class OrbitalGateway < Gateway + API_VERSION = "5.6" + + POST_HEADERS = { + "MIME-Version" => "1.1", + "Content-Type" => "application/PTI56", + "Content-transfer-encoding" => "text", + "Request-number" => '1', + "Document-type" => "Request", + "Interface-Version" => "Ruby|ActiveMerchant|Proprietary Gateway" + } + + SUCCESS, APPROVED = '0', '00' + + class_attribute :secondary_test_url, :secondary_live_url + + self.test_url = "https://orbitalvar1.paymentech.net/authorize" + self.secondary_test_url = "https://orbitalvar2.paymentech.net/authorize" + + self.live_url = "https://orbital1.paymentech.net/authorize" + self.secondary_live_url = "https://orbital2.paymentech.net/authorize" + + self.supported_countries = ["US", "CA"] + self.default_currency = "CAD" + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + + self.display_name = 'Orbital Paymentech' + self.homepage_url = 'http://chasepaymentech.com/' + + self.money_format = :cents + + AVS_SUPPORTED_COUNTRIES = ['US', 'CA', 'UK', 'GB'] + + CURRENCY_CODES = { + "AUD" => '036', + "CAD" => '124', + "CZK" => '203', + "DKK" => '208', + "HKD" => '344', + "ICK" => '352', + "JPY" => '392', + "MXN" => '484', + "NZD" => '554', + "NOK" => '578', + "SGD" => '702', + "SEK" => '752', + "CHF" => '756', + "GBP" => '826', + "USD" => '840', + "EUR" => '978' + } + + # INDUSTRY TYPES + ECOMMERCE_TRANSACTION = 'EC' + RECURRING_PAYMENT_TRANSACTION = 'RC' + MAIL_ORDER_TELEPHONE_ORDER_TRANSACTION = 'MO' + INTERACTIVE_VOICE_RESPONSE = 'IV' + # INTERACTIVE_VOICE_RESPONSE = 'IN' + + # Auth Only No Capture + AUTH_ONLY = 'A' + # AC - Auth and Capture = 'AC' + AUTH_AND_CAPTURE = 'AC' + # F - Force Auth No Capture and no online authorization = 'F' + FORCE_AUTH_ONLY = 'F' + # FR - Force Auth No Capture and no online authorization = 'FR' + # FC - Force Auth and Capture no online authorization = 'FC' + FORCE_AUTH_AND_CAPTURE = 'FC' + # Refund and Capture no online authorization + REFUND = 'R' + + # Tax Inds + TAX_NOT_PROVIDED = 0 + TAX_INCLUDED = 1 + NON_TAXABLE_TRANSACTION = 2 + + # Customer Profile Actions + CREATE = 'C' + RETRIEVE = 'R' + UPDATE = 'U' + DELETE = 'D' + + RECURRING = 'R' + DEFERRED = 'D' + + # Status + # Profile Status Flag + # This field is used to set the status of a Customer Profile. + ACTIVE = 'A' + INACTIVE = 'I' + MANUAL_SUSPEND = 'MS' + + # CustomerProfileOrderOverrideInd + # Defines if any Order Data can be pre-populated from + # the Customer Reference Number (CustomerRefNum) + NO_MAPPING_TO_ORDER_DATA = 'NO' + USE_CRN_FOR_ORDER_ID = 'OI' + USE_CRN_FOR_COMMENTS = 'OD' + USE_CRN_FOR_ORDER_ID_AND_COMMENTS = 'OA' + + # CustomerProfileFromOrderInd + # Method to use to Generate the Customer Profile Number + # When Customer Profile Action Type = Create, defines + # what the Customer Profile Number will be: + AUTO_GENERATE = 'A' # Auto-Generate the CustomerRefNum + USE_CUSTOMER_REF_NUM = 'S' # Use CustomerRefNum field + USE_ORDER_ID = 'O' # Use OrderID field + USE_COMMENTS = 'D' # Use Comments field + + def initialize(options = {}) + requires!(options, :merchant_id) + requires!(options, :login, :password) unless options[:ip_authentication] + super + end + + # A – Authorization request + def authorize(money, creditcard, options = {}) + order = build_new_order_xml(AUTH_ONLY, money, options) do |xml| + add_creditcard(xml, creditcard, options[:currency]) unless creditcard.nil? && options[:profile_txn] + add_address(xml, creditcard, options) + if @options[:customer_profiles] + add_customer_data(xml, options) + add_managed_billing(xml, options) + end + end + commit(order, :authorize, options[:trace_number]) + end + + # AC – Authorization and Capture + def purchase(money, creditcard, options = {}) + order = build_new_order_xml(AUTH_AND_CAPTURE, money, options) do |xml| + add_creditcard(xml, creditcard, options[:currency]) unless creditcard.nil? && options[:profile_txn] + add_address(xml, creditcard, options) + if @options[:customer_profiles] + add_customer_data(xml, options) + add_managed_billing(xml, options) + end + end + commit(order, :purchase, options[:trace_number]) + end + + # MFC - Mark For Capture + def capture(money, authorization, options = {}) + commit(build_mark_for_capture_xml(money, authorization, options), :capture) + end + + # R – Refund request + def refund(money, authorization, options = {}) + order = build_new_order_xml(REFUND, money, options.merge(:authorization => authorization)) do |xml| + add_refund(xml, options[:currency]) + xml.tag! :CustomerRefNum, options[:customer_ref_num] if @options[:customer_profiles] && options[:profile_txn] + end + commit(order, :refund, options[:trace_number]) + end + + def credit(money, authorization, options= {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + def void(authorization, options = {}, deprecated = {}) + if(!options.kind_of?(Hash)) + deprecated("Calling the void method with an amount parameter is deprecated and will be removed in a future version.") + return void(options, deprecated.merge(:amount => authorization)) + end + + order = build_void_request_xml(authorization, options) + commit(order, :void, options[:trace_number]) + end + + + # ==== Customer Profiles + # :customer_ref_num should be set unless your happy with Orbital providing one + # + # :customer_profile_order_override_ind can be set to map + # the CustomerRefNum to OrderID or Comments. Defaults to 'NO' - no mapping + # + # 'NO' - No mapping to order data + # 'OI' - Use for + # 'OD' - Use for + # 'OA' - Use for and + # + # :order_default_description can be set optionally. 64 char max. + # + # :order_default_amount can be set optionally. integer as cents. + # + # :status defaults to Active + # + # 'A' - Active + # 'I' - Inactive + # 'MS' - Manual Suspend + + def add_customer_profile(creditcard, options = {}) + options.merge!(:customer_profile_action => CREATE) + order = build_customer_request_xml(creditcard, options) + commit(order, :add_customer_profile) + end + + def update_customer_profile(creditcard, options = {}) + options.merge!(:customer_profile_action => UPDATE) + order = build_customer_request_xml(creditcard, options) + commit(order, :update_customer_profile) + end + + def retrieve_customer_profile(customer_ref_num) + options = {:customer_profile_action => RETRIEVE, :customer_ref_num => customer_ref_num} + order = build_customer_request_xml(nil, options) + commit(order, :retrieve_customer_profile) + end + + def delete_customer_profile(customer_ref_num) + options = {:customer_profile_action => DELETE, :customer_ref_num => customer_ref_num} + order = build_customer_request_xml(nil, options) + commit(order, :delete_customer_profile) + end + + private + + def authorization_string(*args) + args.compact.join(";") + end + + def split_authorization(authorization) + authorization.split(';') + end + + def add_customer_data(xml, options) + if options[:profile_txn] + xml.tag! :CustomerRefNum, options[:customer_ref_num] + else + if options[:customer_ref_num] + xml.tag! :CustomerProfileFromOrderInd, USE_CUSTOMER_REF_NUM + xml.tag! :CustomerRefNum, options[:customer_ref_num] + else + xml.tag! :CustomerProfileFromOrderInd, AUTO_GENERATE + end + xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA + end + end + + def add_soft_descriptors(xml, soft_desc) + xml.tag! :SDMerchantName, soft_desc.merchant_name if soft_desc.merchant_name + xml.tag! :SDProductDescription, soft_desc.product_description if soft_desc.product_description + xml.tag! :SDMerchantCity, soft_desc.merchant_city if soft_desc.merchant_city + xml.tag! :SDMerchantPhone, soft_desc.merchant_phone if soft_desc.merchant_phone + xml.tag! :SDMerchantURL, soft_desc.merchant_url if soft_desc.merchant_url + xml.tag! :SDMerchantEmail, soft_desc.merchant_email if soft_desc.merchant_email + end + + def add_address(xml, creditcard, options) + if(address = (options[:billing_address] || options[:address])) + avs_supported = AVS_SUPPORTED_COUNTRIES.include?(address[:country].to_s) + + if avs_supported + xml.tag! :AVSzip, (address[:zip] ? address[:zip].to_s[0..9] : nil) + xml.tag! :AVSaddress1, (address[:address1] ? address[:address1][0..29] : nil) + xml.tag! :AVSaddress2, (address[:address2] ? address[:address2][0..29] : nil) + xml.tag! :AVScity, (address[:city] ? address[:city][0..19] : nil) + xml.tag! :AVSstate, address[:state] + xml.tag! :AVSphoneNum, (address[:phone] ? address[:phone].scan(/\d/).join.to_s[0..13] : nil) + end + # can't look in billing address? + xml.tag! :AVSname, ((creditcard && creditcard.name) ? creditcard.name[0..29] : nil) + xml.tag! :AVScountryCode, (avs_supported ? address[:country] : '') + + # Needs to come after AVScountryCode + add_destination_address(xml, address) if avs_supported + end + end + + def add_destination_address(xml, address) + if address[:dest_zip] + xml.tag! :AVSDestzip, (address[:dest_zip] ? address[:dest_zip].to_s[0..9] : nil) + xml.tag! :AVSDestaddress1, (address[:dest_address1] ? address[:dest_address1][0..29] : nil) + xml.tag! :AVSDestaddress2, (address[:dest_address2] ? address[:dest_address2][0..29] : nil) + xml.tag! :AVSDestcity, (address[:dest_city] ? address[:dest_city][0..19] : nil) + xml.tag! :AVSDeststate, address[:dest_state] + xml.tag! :AVSDestphoneNum, (address[:dest_phone] ? address[:dest_phone].scan(/\d/).join.to_s[0..13] : nil) + + xml.tag! :AVSDestname, (address[:dest_name] ? address[:dest_name][0..29] : nil) + xml.tag! :AVSDestcountryCode, address[:dest_country] + end + end + + # For Profile requests + def add_customer_address(xml, options) + if(address = (options[:billing_address] || options[:address])) + xml.tag! :CustomerAddress1, (address[:address1] ? address[:address1][0..29] : nil) + xml.tag! :CustomerAddress2, (address[:address2] ? address[:address2][0..29] : nil) + xml.tag! :CustomerCity, (address[:city] ? address[:city][0..19] : nil) + xml.tag! :CustomerState, address[:state] + xml.tag! :CustomerZIP, (address[:zip] ? address[:zip].to_s[0..9] : nil) + xml.tag! :CustomerEmail, address[:email].to_s[0..49] if address[:email] + xml.tag! :CustomerPhone, (address[:phone] ? address[:phone].scan(/\d/).join.to_s : nil) + xml.tag! :CustomerCountryCode, (address[:country] ? address[:country][0..1] : nil) + end + end + + def add_creditcard(xml, creditcard, currency=nil) + xml.tag! :AccountNum, creditcard.number + xml.tag! :Exp, expiry_date(creditcard) + + xml.tag! :CurrencyCode, currency_code(currency) + xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen. + + # If you are trying to collect a Card Verification Number + # (CardSecVal) for a Visa or Discover transaction, pass one of these values: + # 1 Value is Present + # 2 Value on card but illegible + # 9 Cardholder states data not available + # If the transaction is not a Visa or Discover transaction: + # Null-fill this attribute OR + # Do not submit the attribute at all. + # - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf + if %w( visa discover ).include?(creditcard.brand) + xml.tag! :CardSecValInd, (creditcard.verification_value? ? '1' : '9') + end + xml.tag! :CardSecVal, creditcard.verification_value if creditcard.verification_value? + end + + def add_refund(xml, currency=nil) + xml.tag! :AccountNum, nil + + xml.tag! :CurrencyCode, currency_code(currency) + xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen. + end + + def add_managed_billing(xml, options) + if mb = options[:managed_billing] + # default to recurring (R). Other option is deferred (D). + xml.tag! :MBType, mb[:type] || RECURRING + # default to Customer Reference Number + xml.tag! :MBOrderIdGenerationMethod, mb[:order_id_generation_method] || 'IO' + # By default use MBRecurringEndDate, set to N. + # MMDDYYYY + xml.tag! :MBRecurringStartDate, mb[:start_date].scan(/\d/).join.to_s if mb[:start_date] + # MMDDYYYY + xml.tag! :MBRecurringEndDate, mb[:end_date].scan(/\d/).join.to_s if mb[:end_date] + # By default listen to any value set in MBRecurringEndDate. + xml.tag! :MBRecurringNoEndDateFlag, mb[:no_end_date_flag] || 'N' # 'Y' || 'N' (Yes or No). + xml.tag! :MBRecurringMaxBillings, mb[:max_billings] if mb[:max_billings] + xml.tag! :MBRecurringFrequency, mb[:frequency] if mb[:frequency] + xml.tag! :MBDeferredBillDate, mb[:deferred_bill_date] if mb[:deferred_bill_date] + xml.tag! :MBMicroPaymentMaxDollarValue, mb[:max_dollar_value] if mb[:max_dollar_value] + xml.tag! :MBMicroPaymentMaxBillingDays, mb[:max_billing_days] if mb[:max_billing_days] + xml.tag! :MBMicroPaymentMaxTransactions, mb[:max_transactions] if mb[:max_transactions] + end + end + + def parse(body) + response = {} + xml = REXML::Document.new(body) + root = REXML::XPath.first(xml, "//Response") || + REXML::XPath.first(xml, "//ErrorResponse") + if root + root.elements.to_a.each do |node| + recurring_parse_element(response, node) + end + end + response + end + + def recurring_parse_element(response, node) + if node.has_elements? + node.elements.each{|e| recurring_parse_element(response, e) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + def commit(order, message_type, trace_number=nil) + headers = POST_HEADERS.merge("Content-length" => order.size.to_s) + headers.merge!( "Trace-number" => trace_number.to_s, + "Merchant-Id" => @options[:merchant_id] ) if @options[:retry_logic] && trace_number + request = lambda{|url| parse(ssl_post(url, order, headers))} + + # Failover URL will be attempted in the event of a connection error + response = begin + request.call(remote_url) + rescue ConnectionError + request.call(remote_url(:secondary)) + end + + Response.new(success?(response, message_type), message_from(response), response, + { + :authorization => authorization_string(response[:tx_ref_num], response[:order_id]), + :test => self.test?, + :avs_result => OrbitalGateway::AVSResult.new(response[:avs_resp_code]), + :cvv_result => response[:cvv2_resp_code] + } + ) + end + + def remote_url(url=:primary) + if url == :primary + (self.test? ? self.test_url : self.live_url) + else + (self.test? ? self.secondary_test_url : self.secondary_live_url) + end + end + + def success?(response, message_type) + if [:refund, :void].include?(message_type) + response[:proc_status] == SUCCESS + elsif response[:customer_profile_action] + response[:profile_proc_status] == SUCCESS + else + response[:proc_status] == SUCCESS && + response[:resp_code] == APPROVED + end + end + + def message_from(response) + response[:resp_msg] || response[:status_msg] || response[:customer_profile_message] + end + + def ip_authentication? + @options[:ip_authentication] == true + end + + def build_new_order_xml(action, money, parameters = {}) + requires!(parameters, :order_id) + xml = xml_envelope + xml.tag! :Request do + xml.tag! :NewOrder do + add_xml_credentials(xml) + # EC - Ecommerce transaction + # RC - Recurring Payment transaction + # MO - Mail Order Telephone Order transaction + # IV - Interactive Voice Response + # IN - Interactive Voice Response + xml.tag! :IndustryType, parameters[:industry_type] || ECOMMERCE_TRANSACTION + # A - Auth Only No Capture + # AC - Auth and Capture + # F - Force Auth No Capture and no online authorization + # FR - Force Auth No Capture and no online authorization + # FC - Force Auth and Capture no online authorization + # R - Refund and Capture no online authorization + xml.tag! :MessageType, action + add_bin_merchant_and_terminal(xml, parameters) + + yield xml if block_given? + + xml.tag! :OrderID, format_order_id(parameters[:order_id]) + xml.tag! :Amount, amount(money) + xml.tag! :Comments, parameters[:comments] if parameters[:comments] + + # CustomerAni, AVSPhoneType and AVSDestPhoneType could be added here. + + if parameters[:soft_descriptors].is_a?(OrbitalSoftDescriptors) + add_soft_descriptors(xml, parameters[:soft_descriptors]) + end + + set_recurring_ind(xml, parameters) + + # Append Transaction Reference Number at the end for Refund transactions + if action == REFUND + tx_ref_num, _ = split_authorization(parameters[:authorization]) + xml.tag! :TxRefNum, tx_ref_num + end + end + end + xml.target! + end + + # For Canadian transactions on PNS Tampa on New Order + # RF - First Recurring Transaction + # RS - Subsequent Recurring Transactions + def set_recurring_ind(xml, parameters) + if parameters[:recurring_ind] + raise "RecurringInd must be set to either \"RF\" or \"RS\"" unless %w(RF RS).include?(parameters[:recurring_ind]) + xml.tag! :RecurringInd, parameters[:recurring_ind] + end + end + + def build_mark_for_capture_xml(money, authorization, parameters = {}) + tx_ref_num, order_id = split_authorization(authorization) + xml = xml_envelope + xml.tag! :Request do + xml.tag! :MarkForCapture do + add_xml_credentials(xml) + xml.tag! :OrderID, format_order_id(order_id) + xml.tag! :Amount, amount(money) + add_bin_merchant_and_terminal(xml, parameters) + xml.tag! :TxRefNum, tx_ref_num + end + end + xml.target! + end + + def build_void_request_xml(authorization, parameters = {}) + tx_ref_num, order_id = split_authorization(authorization) + xml = xml_envelope + xml.tag! :Request do + xml.tag! :Reversal do + add_xml_credentials(xml) + xml.tag! :TxRefNum, tx_ref_num + xml.tag! :TxRefIdx, parameters[:transaction_index] + xml.tag! :AdjustedAmt, parameters[:amount] # setting adjusted amount to nil will void entire amount + xml.tag! :OrderID, format_order_id(order_id || parameters[:order_id]) + add_bin_merchant_and_terminal(xml, parameters) + xml.tag! :ReversalRetryNumber, parameters[:reversal_retry_number] if parameters[:reversal_retry_number] + xml.tag! :OnlineReversalInd, parameters[:online_reversal_ind] if parameters[:online_reversal_ind] + end + end + xml.target! + end + + def currency_code(currency) + CURRENCY_CODES[(currency || self.default_currency)].to_s + end + + def expiry_date(credit_card) + "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}" + end + + def bin + @options[:bin] || (salem_mid? ? '000001' : '000002') + end + + def xml_envelope + xml = Builder::XmlMarkup.new(:indent => 2) + xml.instruct!(:xml, :version => '1.0', :encoding => 'UTF-8') + xml + end + + def add_xml_credentials(xml) + unless ip_authentication? + xml.tag! :OrbitalConnectionUsername, @options[:login] + xml.tag! :OrbitalConnectionPassword, @options[:password] + end + end + + def add_bin_merchant_and_terminal(xml, parameters) + xml.tag! :BIN, bin + xml.tag! :MerchantID, @options[:merchant_id] + xml.tag! :TerminalID, parameters[:terminal_id] || '001' + end + + def salem_mid? + @options[:merchant_id].length == 6 + end + + # The valid characters include: + # + # 1. all letters and digits + # 2. - , $ @ & and a space character, though the space character cannot be the leading character + # 3. PINless Debit transactions can only use uppercase and lowercase alpha (A-Z, a-z) and numeric (0-9) + def format_order_id(order_id) + illegal_characters = /[^,$@\- \w]/ + order_id = order_id.to_s.gsub(/\./, '-') + order_id.gsub!(illegal_characters, '') + order_id[0...22] + end + + def build_customer_request_xml(creditcard, options = {}) + xml = xml_envelope + xml.tag! :Request do + xml.tag! :Profile do + xml.tag! :OrbitalConnectionUsername, @options[:login] unless ip_authentication? + xml.tag! :OrbitalConnectionPassword, @options[:password] unless ip_authentication? + xml.tag! :CustomerBin, bin + xml.tag! :CustomerMerchantID, @options[:merchant_id] + xml.tag! :CustomerName, creditcard.name if creditcard + xml.tag! :CustomerRefNum, options[:customer_ref_num] if options[:customer_ref_num] + + add_customer_address(xml, options) + + xml.tag! :CustomerProfileAction, options[:customer_profile_action] # C, R, U, D + # NO No mapping to order data + # OI Use for + # OD Use for + # OA Use for and + xml.tag! :CustomerProfileOrderOverrideInd, options[:customer_profile_order_override_ind] || NO_MAPPING_TO_ORDER_DATA + + if options[:customer_profile_action] == CREATE + # A Auto-Generate the CustomerRefNum + # S Use CustomerRefNum field + # O Use OrderID field + # D Use Comments field + xml.tag! :CustomerProfileFromOrderInd, (options[:customer_ref_num] ? USE_CUSTOMER_REF_NUM : AUTO_GENERATE) + end + + xml.tag! :OrderDefaultDescription, options[:order_default_description][0..63] if options[:order_default_description] + xml.tag! :OrderDefaultAmount, options[:order_default_amount] if options[:order_default_amount] + + if [CREATE, UPDATE].include? options[:customer_profile_action] + xml.tag! :CustomerAccountType, 'CC' # Only credit card supported + xml.tag! :Status, options[:status] || ACTIVE # Active + end + + xml.tag! :CCAccountNum, creditcard.number if creditcard + xml.tag! :CCExpireDate, creditcard.expiry_date.expiration.strftime("%m%y") if creditcard + + # This has to come after CCExpireDate. + add_managed_billing(xml, options) + end + end + xml.target! + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/avs_result.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/avs_result.rb new file mode 100644 index 000000000..264030a23 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/avs_result.rb @@ -0,0 +1,93 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class OrbitalGateway < Gateway + # Unfortunately, Orbital uses their own special codes for AVS responses + # that are different than the standard codes defined in + # ActiveMerchant::Billing::AVSResult. + # + # This class encapsulates the response codes shown on page 240 of their spec: + # http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf + # + class AVSResult < ActiveMerchant::Billing::AVSResult + CODES = { + '1' => 'No address supplied', + '2' => 'Bill-to address did not pass Auth Host edit checks', + '3' => 'AVS not performed', + '4' => 'Issuer does not participate in AVS', + '5' => 'Edit-error - AVS data is invalid', + '6' => 'System unavailable or time-out', + '7' => 'Address information unavailable', + '8' => 'Transaction Ineligible for AVS', + '9' => 'Zip Match/Zip 4 Match/Locale match', + 'A' => 'Zip Match/Zip 4 Match/Locale no match', + 'B' => 'Zip Match/Zip 4 no Match/Locale match', + 'C' => 'Zip Match/Zip 4 no Match/Locale no match', + 'D' => 'Zip No Match/Zip 4 Match/Locale match', + 'E' => 'Zip No Match/Zip 4 Match/Locale no match', + 'F' => 'Zip No Match/Zip 4 No Match/Locale match', + 'G' => 'No match at all', + 'H' => 'Zip Match/Locale match', + 'J' => 'Issuer does not participate in Global AVS', + 'JA' => 'International street address and postal match', + 'JB' => 'International street address match. Postal code not verified', + 'JC' => 'International street address and postal code not verified', + 'JD' => 'International postal code match. Street address not verified', + 'M1' => 'Merchant Override Decline', + 'M2' => 'Cardholder name, billing address, and postal code matches', + 'M3' => 'Cardholder name and billing code matches', + 'M4' => 'Cardholder name and billing address matches', + 'M5' => 'Cardholder name incorrect, billing address and postal code match', + 'M6' => 'Cardholder name incorrect, billing address matches', + 'M7' => 'Cardholder name incorrect, billing address matches', + 'M8' => 'Cardholder name, billing address and postal code are all incorrect', + 'N3' => 'Address matches, ZIP not verified', + 'N4' => 'Address and ZIP code not verified due to incompatible formats', + 'N5' => 'Address and ZIP code match (International only)', + 'N6' => 'Address not verified (International only)', + 'N7' => 'ZIP matches, address not verified', + 'N8' => 'Address and ZIP code match (International only)', + 'N9' => 'Address and ZIP code match (UK only)', + 'R' => 'Issuer does not participate in AVS', + 'UX' => 'Unknown', + 'X' => 'Zip Match/Zip 4 Match/Address Match', + 'Z' => 'Zip Match/Locale no match', + } + + # Map vendor's AVS result code to a postal match code + ORBITAL_POSTAL_MATCH_CODE = { + 'Y' => %w( 9 A B C H JA JD M2 M3 M5 N5 N8 N9 X Z ), + 'N' => %w( D E F G M8 ), + 'X' => %w( 4 J R ), + nil => %w( 1 2 3 5 6 7 8 JB JC M1 M4 M6 M7 N3 N4 N6 N7 UX ) + }.inject({}) do |map, (type, codes)| + codes.each { |code| map[code] = type } + map + end + + # Map vendor's AVS result code to a street match code + ORBITAL_STREET_MATCH_CODE = { + 'Y' => %w( 9 B D F H JA JB M2 M4 M5 M6 M7 N3 N5 N7 N8 N9 X ), + 'N' => %w( A C E G M8 Z ), + 'X' => %w( 4 J R ), + nil => %w( 1 2 3 5 6 7 8 JC JD M1 M3 N4 N6 UX ) + }.inject({}) do |map, (type, codes)| + codes.each { |code| map[code] = type } + map + end + + def self.messages + CODES + end + + def initialize(code) + @code = code.to_s.strip.upcase unless code.blank? + if @code + @message = CODES[@code] + @postal_match = ORBITAL_POSTAL_MATCH_CODE[@code] + @street_match = ORBITAL_STREET_MATCH_CODE[@code] + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb new file mode 100644 index 000000000..010af3911 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb @@ -0,0 +1,46 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class OrbitalSoftDescriptors + include Validateable + + PHONE_FORMAT_1 = /\A\d{3}-\d{3}-\d{4}\z/ + PHONE_FORMAT_2 = /\A\d{3}-\w{7}\z/ + + # ==== Tampa PNS Soft Descriptors + # The support for Soft Descriptors via the PNS Host is only for customers processing through Chase + # Paymentech Canada. + + # Unlike Salem, the only value that gets passed on the cardholder statement is the Merchant Name field. + # And for these customers, it is a maximum of 25 bytes of data. + # + # All other Soft Descriptor fields can optionally be sent, but will not be submitted to the settlement host + # and will not display on the cardholder statement. + + attr_accessor :merchant_name, :product_description, :merchant_city, :merchant_phone, :merchant_url, :merchant_email + + def initialize(options = {}) + self.merchant_name = options[:merchant_name] + self.merchant_city = options[:merchant_city] + self.merchant_phone = options[:merchant_phone] + self.merchant_url = options[:merchant_url] + self.merchant_email = options[:merchant_email] + end + + def validate + errors.add(:merchant_name, "is required") if self.merchant_name.blank? + errors.add(:merchant_name, "is required to be 25 bytes or less") if self.merchant_name.bytesize > 25 + + unless self.merchant_phone.blank? || self.merchant_phone.match(PHONE_FORMAT_1) || self.merchant_phone.match(PHONE_FORMAT_2) + errors.add(:merchant_phone, "is required to follow \"NNN-NNN-NNNN\" or \"NNN-AAAAAAA\" format") + end + + [:merchant_email, :merchant_url].each do |attr| + unless self.send(attr).blank? + errors.add(attr, "is required to be 13 bytes or less") if self.send(attr).bytesize > 13 + end + end + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_gate_xml.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_gate_xml.rb new file mode 100644 index 000000000..5f84e9f6d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_gate_xml.rb @@ -0,0 +1,261 @@ +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # This gateway accepts the following arguments: + # :login => your PayJunction username + # :password => your PayJunction pass + # Example use: + # + # gateway = ActiveMerchant::Billing::Base.gateway(:pay_gate_xml).new( + # :login => "my_account", + # :password => "my_pass" + # ) + # + # # set up credit card obj as in main ActiveMerchant example + # creditcard = ActiveMerchant::Billing::CreditCard.new( + # :type => 'visa', + # :number => '4242424242424242', + # :month => 8, + # :year => 2009, + # :first_name => 'Bob', + # :last_name => 'Bobsen' + # ) + # + # # run request + # response = gateway.purchase(1000, creditcard) # charge 10 dollars + # + # 1) Check whether the transaction was successful + # + # response.success? + # + # 2) Retrieve the message returned by PayJunction + # + # response.message + # + # 3) Retrieve the unique transaction ID returned by PayGateXML + # + # response.authorization + # + # This gateway has many other features which are not implemented here yet + # The basic setup here only supports auth/capture transactions. + # + # Test Transactions + # + # PayGateXML has a global test user/pass, but you can also sign up for your own. + # The class and the test come equipped with the global test creds + # + # Usage Details + # + # Below is a map of only SOME of the values accepted by PayGateXML and how you should submit + # each to ActiveMerchant + # + # PayGateXML Field ActiveMerchant Use + # + # pgid use :login value to gateway instantation + # pwd use :password value to gateway instantiation + # + # cname credit_card.name + # cc credit_card.number + # exp credit_card values formatted to YYYYMMDD + # budp South Africa only - set to 0 if purchase is not on budget + # amt include as argument to method for your transaction type + # ver do nothing, always set to current API version + # + # cref provide as :invoice in options, varchar(80) + # cur 3 char field, currently only ZAR + # cvv credit_card.verification + # bno batch processing number, i.e. you supply this + # + # others -- not used in this implementation + # nurl, rurl - must remain blank or absent or they will use an alternative authentication mechanism + # email, ip - must remain blank or absent or they will use a PayGate extra service call PayProtector + # threed - must remain blank unless you are using your own 3D Secure server + # + class PayGateXmlGateway < Gateway + self.live_url = 'https://www.paygate.co.za/payxml/process.trans' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US', 'ZA'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club] + + # The homepage URL of the gateway + self.homepage_url = 'http://paygate.co.za/' + + # The name of the gateway + self.display_name = 'PayGate PayXML' + + # PayGate only supports Rands + self.default_currency = 'ZAR' + + # PayGate accepts only lowest denomination + self.money_format = :cents + + # PayGateXML public test account - you can get a private one too + TEST_ID_3DSECURE = '10011013800' + TEST_ID = '10011021600' + TEST_PWD = 'test' + + API_VERSION = '4.0' + + DECLINE_CODES = { + # Credit Card Errors - These RESULT_CODEs are returned if the transaction cannot be authorized due to a problem with the card. The TRANSACTION_STATUS will be 2 + 900001 => "Call for Approval", + 900002 => "Card Expired", + 900003 => "Insufficient Funds", + 900004 => "Invalid Card Number", + 900005 => "Bank Interface Timeout", # indicates a communications failure between the banks systems + 900006 => "Invalid Card", + 900007 => "Declined", + 900009 => "Lost Card", + 900010 => "Invalid Card Length", + 900011 => "Suspected Fraud", + 900012 => "Card Reported As Stolen", + 900013 => "Restricted Card", + 900014 => "Excessive Card Usage", + 900015 => "Card Blacklisted", + + 900207 => "Declined; authentication failed", # indicates the cardholder did not enter their MasterCard SecureCode / Verified by Visa password correctly + + 990020 => "Auth Declined", + + 991001 => "Invalid expiry date", + 991002 => "Invalid amount", + + # Communication Errors - These RESULT_CODEs are returned if the transaction cannot be completed due to an unexpected error. TRANSACTION_STATUS will be 0. + 900205 => "Unexpected authentication result (phase 1)", + 900206 => "Unexpected authentication result (phase 1)", + + 990001 => "Could not insert into Database", + + 990022 => "Bank not available", + + 990053 => "Error processing transaction", + + # Miscellaneous - Unless otherwise noted, the TRANSACTION_STATUS will be 0. + 900209 => "Transaction verification failed (phase 2)", # Indicates the verification data returned from MasterCard SecureCode / Verified by Visa has been altered + 900210 => "Authentication complete; transaction must be restarted", # Indicates that the MasterCard SecuerCode / Verified by Visa transaction has already been completed. Most likely caused by the customer clicking the refresh button + + 990024 => "Duplicate Transaction Detected. Please check before submitting", + + 990028 => "Transaction cancelled" # Customer clicks the 'Cancel' button on the payment page + } + + SUCCESS_CODES = %w( 990004 990005 990017 990012 990018 990031 ) + + TRANSACTION_CODES = { + 0 => 'Not Done', + 1 => 'Approved', + 2 => 'Declined', + 3 => 'Paid', + 4 => 'Refunded', + 5 => 'Received by PayGate', + 6 => 'Replied to Client' + } + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, creditcard, options = {}) + MultiResponse.run do |r| + r.process{authorize(money, creditcard, options)} + r.process{capture(money, r.authorization, options)} + end + end + + def authorize(money, creditcard, options = {}) + action = 'authtx' + + options.merge!(:money => money, :creditcard => creditcard) + commit(action, build_request(action, options)) + end + + def capture(money, authorization, options = {}) + action = 'settletx' + + options.merge!(:money => money, :authorization => authorization) + commit(action, build_request(action, options)) + end + + private + + def successful?(response) + SUCCESS_CODES.include?(response[:res]) + end + + def build_request(action, options={}) + xml = Builder::XmlMarkup.new + xml.instruct! + + xml.tag! 'protocol', :ver => API_VERSION, :pgid => (test? ? TEST_ID : @options[:login]), :pwd => @options[:password] do |protocol| + case action + when 'authtx' + money = options.delete(:money) + creditcard = options.delete(:creditcard) + build_authorization(protocol, money, creditcard, options) + when 'settletx' + money = options.delete(:money) + authorization = options.delete(:authorization) + build_capture(protocol, money, authorization, options) + else + raise "no action specified for build_request" + end + end + + xml.target! + end + + def build_authorization(xml, money, creditcard, options={}) + xml.tag! 'authtx', { + :cref => options[:order_id], + :cname => creditcard.name, + :cc => creditcard.number, + :exp => "#{format(creditcard.month, :two_digits)}#{format(creditcard.year, :four_digits)}", + :budp => 0, + :amt => amount(money), + :cur => (options[:currency] || currency(money)), + :cvv => creditcard.verification_value + } + end + + def build_capture(xml, money, authorization, options={}) + xml.tag! 'settletx', { + :tid => authorization + } + end + + def parse(action, body) + hash = {} + xml = REXML::Document.new(body) + + response_action = action.gsub(/tx/, 'rx') + root = REXML::XPath.first(xml.root, response_action) + # we might have gotten an error + if root.nil? + root = REXML::XPath.first(xml.root, 'errorrx') + end + root.attributes.each do |name, value| + hash[name.to_sym] = value + end + hash + end + + def commit(action, request) + response = parse(action, ssl_post(self.live_url, request)) + Response.new(successful?(response), message_from(response), response, + :test => test?, + :authorization => response[:tid] + ) + end + + def message_from(response) + (response[:rdesc] || response[:edesc]) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_junction.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_junction.rb new file mode 100644 index 000000000..ceb2e184d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_junction.rb @@ -0,0 +1,396 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # PayJunction Gateway + # + # This gateway accepts the following arguments: + # :login => your PayJunction username + # :password => your PayJunction pass + # + # Example use: + # + # gateway = ActiveMerchant::Billing::Base.gateway(:pay_junction).new( + # :login => "my_account", + # :password => "my_pass" + # ) + # + # # set up credit card obj as in main ActiveMerchant example + # creditcard = ActiveMerchant::Billing::CreditCard.new( + # :type => 'visa', + # :number => '4242424242424242', + # :month => 8, + # :year => 2009, + # :first_name => 'Bob', + # :last_name => 'Bobsen' + # ) + # + # # optionally specify address if using AVS + # address = { :address1 => '101 Test Ave', :city => 'Test', :state => 'TS', + # :zip => '10101', :country => 'US' } + # + # # run request + # response = gateway.purchase(1000, creditcard, :address => address) # charge 10 dollars + # + # 1) Check whether the transaction was successful + # + # response.success? + # + # 2) Retrieve the message returned by PayJunction + # + # response.message + # + # 3) Retrieve the unique transaction ID returned by PayJunction + # + # response.authorization + # + # This gateway supports "instant" transactions. These transactions allow you + # to execute an operation on a previously run card without card information + # provided you have the transaction id from a previous transaction with the + # same card. All functions that take a credit card object for this gateway + # can take a transaction id string instead. + # + # Test Transactions + # + # See the source for initialize() for test account information. Note that + # PayJunction does not allow test transactions on your account, so if the + # gateway is running in :test mode your transaction will be run against + # PayJunction's global test account and will not show up in your account. + # + # Transactions ran on this account go through a test processor, so there is no + # need to void or otherwise cancel transactions. However, for further safety, + # please use the special card numbers 4433221111223344 or 4444333322221111 and + # keep transaction amounts below $4.00 when testing. + # + # Also note, transactions ran for an amount between $0.00 and $1.99 will likely + # result in denial. To demonstrate approvals, use amounts between $2.00 and $4.00. + # + # Test transactions can be checked by logging into + # PayJunction Web Login with username 'pj-cm-01' and password 'pj-cm-01p' + # + # Usage Details + # + # Below is a map of values accepted by PayJunction and how you should submit + # each to ActiveMerchant + # + # PayJunction Field ActiveMerchant Use + # + # dc_logon provide as :login value to gateway instantation + # dc_password provide as :password value to gateway instantiation + # + # dc_name will be retrieved from credit_card.name + # dc_first_name :first_name on CreditCard object instantation + # dc_last_name :last_name on CreditCard object instantation + # dc_number :number on CreditCard object instantation + # dc_expiration_month :month on CreditCard object instantation + # dc_expiration_year :year on CreditCard object instantation + # dc_verification_number :verification_value on CC object instantation + # + # dc_transaction_amount include as argument to method for your transaction type + # dc_transaction_type do nothing, set by your transaction type + # dc_version do nothing, always "1.2" + # + # dc_transaction_id submit as a string in place of CreditCard obj for + # "instant" transactions. + # + # dc_invoice :order_id in options for transaction method + # dc_notes :description in options for transaction method + # + # See example use above for address AVS fields + # See #recurring for periodic transaction fields + class PayJunctionGateway < Gateway + API_VERSION = '1.2' + + class_attribute :test_url, :live_url + + self.test_url = "https://www.payjunctionlabs.com/quick_link" + self.live_url = "https://payjunction.com/quick_link" + + TEST_LOGIN = 'pj-ql-01' + TEST_PASSWORD = 'pj-ql-01p' + + SUCCESS_CODES = ["00", "85"] + SUCCESS_MESSAGE = 'The transaction was approved.' + + FAILURE_MESSAGE = 'The transaction was declined.' + + DECLINE_CODES = { + "AE" => 'Address verification failed because address did not match.', + 'ZE' => 'Address verification failed because zip did not match.', + 'XE' => 'Address verification failed because zip and address did not match.', + 'YE' => 'Address verification failed because zip and address did not match.', + 'OE' => 'Address verification failed because address or zip did not match.', + 'UE' => 'Address verification failed because cardholder address unavailable.', + 'RE' => 'Address verification failed because address verification system is not working.', + 'SE' => 'Address verification failed because address verification system is unavailable.', + 'EE' => 'Address verification failed because transaction is not a mail or phone order.', + 'GE' => 'Address verification failed because international support is unavailable.', + 'CE' => 'Declined because CVV2/CVC2 code did not match.', + '04' => 'Declined. Pick up card.', + '07' => 'Declined. Pick up card (Special Condition).', + '41' => 'Declined. Pick up card (Lost).', + '43' => 'Declined. Pick up card (Stolen).', + '13' => 'Declined because of the amount is invalid.', + '14' => 'Declined because the card number is invalid.', + '80' => 'Declined because of an invalid date.', + '05' => 'Declined. Do not honor.', + '51' => 'Declined because of insufficient funds.', + 'N4' => 'Declined because the amount exceeds issuer withdrawal limit.', + '61' => 'Declined because the amount exceeds withdrawal limit.', + '62' => 'Declined because of an invalid service code (restricted).', + '65' => 'Declined because the card activity limit exceeded.', + '93' => 'Declined because there a violation (the transaction could not be completed).', + '06' => 'Declined because address verification failed.', + '54' => 'Declined because the card has expired.', + '15' => 'Declined because there is no such issuer.', + '96' => 'Declined because of a system error.', + 'N7' => 'Declined because of a CVV2/CVC2 mismatch.', + 'M4' => 'Declined.', + "FE" => "There was a format error with your Trinity Gateway Service (API) request.", + "LE" => "Could not log you in (problem with dc_logon and/or dc_password).", + 'NL' => 'Aborted because of a system error, please try again later. ', + 'AB' => 'Aborted because of an upstream system error, please try again later.' + } + + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.supported_countries = ['US'] + self.homepage_url = 'http://www.payjunction.com/' + self.display_name = 'PayJunction' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # The first half of the preauth(authorize)/postauth(capture) model. + # Checks to make sure funds are available for a transaction, and returns a + # transaction_id that can be used later to postauthorize (capture) the funds. + def authorize(money, payment_source, options = {}) + parameters = { + :transaction_amount => amount(money), + } + + add_payment_source(parameters, payment_source) + add_address(parameters, options) + add_optional_fields(parameters, options) + commit('AUTHORIZATION', parameters) + end + + # A simple sale, capturing funds immediately. + # Execute authorization and capture in a single step. + def purchase(money, payment_source, options = {}) + parameters = { + :transaction_amount => amount(money), + } + + add_payment_source(parameters, payment_source) + add_address(parameters, options) + add_optional_fields(parameters, options) + commit('AUTHORIZATION_CAPTURE', parameters) + end + + # The second half of the preauth(authorize)/postauth(capture) model. + # Retrieve funds that have been previously authorized with _authorization_ + def capture(money, authorization, options = {}) + parameters = { + :transaction_id => authorization, + :posture => 'capture' + } + + add_optional_fields(parameters, options) + commit('update', parameters) + end + + # Return money to a card that was previously billed. + # _authorization_ should be the transaction id of the transaction we are returning. + def refund(money, authorization, options = {}) + parameters = { + :transaction_amount => amount(money), + :transaction_id => authorization + } + + commit('CREDIT', parameters) + end + + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + # Cancel a transaction that has been charged but has not yet made it + # through the batch process. + def void(authorization, options = {}) + parameters = { + :transaction_id => authorization, + :posture => 'void' + } + + add_optional_fields(parameters, options) + commit('update', parameters) + end + + # Set up a sale that will be made on a regular basis for the same amount + # (ex. $20 a month for 12 months) + # + # The parameter :periodicity should be specified as either :monthly, :weekly, or :daily + # The parameter :payments should be the number of payments to be made + # + # gateway.recurring('2000', creditcard, :periodicity => :monthly, :payments => 12) + # + # The optional parameter :starting_at takes a date or time argument or a string in + # YYYYMMDD format and can be used to specify when the first charge will be made. + # If omitted the first charge will be immediate. + def recurring(money, payment_source, options = {}) + requires!(options, [:periodicity, :monthly, :weekly, :daily], :payments) + + periodic_type = case options[:periodicity] + when :monthly + 'month' + when :weekly + 'week' + when :daily + 'day' + end + + if options[:starting_at].nil? + start_date = Time.now.strftime('%Y-%m-%d') + elsif options[:starting_at].is_a?(String) + sa = options[:starting_at] + start_date = "#{sa[0..3]}-#{sa[4..5]}-#{sa[6..7]}" + else + start_date = options[:starting_at].strftime('%Y-%m-%d') + end + + parameters = { + :transaction_amount => amount(money), + :schedule_periodic_type => periodic_type, + :schedule_create => 'true', + :schedule_limit => options[:payments].to_i > 1 ? options[:payments] : 1, + :schedule_periodic_number => 1, + :schedule_start => start_date + } + + add_payment_source(parameters, payment_source) + add_optional_fields(parameters, options) + add_address(parameters, options) + commit('AUTHORIZATION_CAPTURE', parameters) + end + + def test? + (test_login? || super) + end + + private + + def test_login? + @options[:login] == TEST_LOGIN && @options[:password] == TEST_PASSWORD + end + + # add fields depending on payment source selected (cc or transaction id) + def add_payment_source(params, source) + if source.is_a?(String) + add_billing_id(params, source) + else + add_creditcard(params, source) + end + end + + # add fields for credit card + def add_creditcard(params, creditcard) + params[:name] = creditcard.name + params[:number] = creditcard.number + params[:expiration_month] = creditcard.month + params[:expiration_year] = creditcard.year + params[:verification_number] = creditcard.verification_value if creditcard.verification_value? + end + + # add field for "instant" transaction, using previous transaction id + def add_billing_id(params, billingid) + params[:transaction_id] = billingid + end + + # add address fields if present + def add_address(params, options) + address = options[:billing_address] || options[:address] + + if address + params[:address] = address[:address1] unless address[:address1].blank? + params[:city] = address[:city] unless address[:city].blank? + params[:state] = address[:state] unless address[:state].blank? + params[:zipcode] = address[:zip] unless address[:zip].blank? + params[:country] = address[:country] unless address[:country].blank? + end + end + + def add_optional_fields(params, options) + params[:notes] = options[:description] unless options[:description].blank? + params[:invoice] = options[:order_id].to_s.gsub(/[^-\/\w.,']/, '') unless options[:order_id].blank? + end + + def commit(action, parameters) + url = test? ? self.test_url : self.live_url + + response = parse( ssl_post(url, post_data(action, parameters)) ) + + Response.new(successful?(response), message_from(response), response, + :test => test?, + :authorization => response[:transaction_id] || parameters[:transaction_id] + ) + end + + def successful?(response) + SUCCESS_CODES.include?(response[:response_code]) || response[:query_status] == true + end + + def message_from(response) + if successful?(response) + SUCCESS_MESSAGE + else + DECLINE_CODES[response[:response_code]] || FAILURE_MESSAGE + end + end + + def post_data(action, params) + if test? + # test requests must use global test account + params[:logon] = TEST_LOGIN + params[:password] = TEST_PASSWORD + else + params[:logon] = @options[:login] + params[:password] = @options[:password] + end + params[:version] = API_VERSION + params[:transaction_type] = action + + params.reject{|k,v| v.blank?}.collect{ |k, v| "dc_#{k.to_s}=#{CGI.escape(v.to_s)}" }.join("&") + end + + def parse(body) + # PayJunction uses the Field Separator ASCII character to separate key/val + # pairs in the response. The character's octal value is 034. + # + # Sample response: + # + # transaction_id=44752response_code=M4response_message=Declined (INV TEST CARD). + + pairs = body.chomp.split("\034") + response = {} + pairs.each do |pair| + key, val = pair.split('=') + response[key[3..-1].to_sym] = val ? normalize(val) : nil + end + response + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_secure.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_secure.rb new file mode 100644 index 000000000..16df1f9fa --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pay_secure.rb @@ -0,0 +1,119 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaySecureGateway < Gateway + self.live_url = self.test_url = 'https://clearance.commsecure.com.au/cgi-bin/PSDirect' + + self.money_format = :cents + + # Currently Authorization and Capture is not implemented because + # capturing requires the original credit card information + TRANSACTIONS = { + :purchase => 'PURCHASE', + :authorization => 'AUTHORISE', + :capture => 'ADVICE', + :credit => 'REFUND' + } + + SUCCESS = 'Accepted' + SUCCESS_MESSAGE = 'The transaction was approved' + + self.supported_countries = ['AU'] + self.homepage_url = 'http://www.commsecure.com.au/paysecure.shtml' + self.display_name = 'PaySecure' + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club] + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card, options = {}) + requires!(options, :order_id) + + post = {} + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, credit_card) + + commit(:purchase, money, post) + end + + private + # Used for capturing, which is currently not supported. + def add_reference(post, identification) + auth, trans_id = identification.split(";") + post[:authnum] = auth + post[:transid] = trans_id + end + + def add_amount(post, money) + post[:amount] = amount(money) + end + + def add_invoice(post, options) + post[:merchant_transid] = options[:order_id].to_s.slice(0,21) + post[:memnum] = options[:invoice] + post[:custnum] = options[:customer] + post[:clientdata] = options[:description] + end + + def add_credit_card(post, credit_card) + post[:cardnum] = credit_card.number + post[:cardname] = credit_card.name + post[:expiry] = expdate(credit_card) + post[:cvv2] = credit_card.verification_value + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + def commit(action, money, parameters) + response = parse( ssl_post(self.live_url, post_data(action, parameters)) ) + + Response.new(successful?(response), message_from(response), response, + :test => test_response?(response), + :authorization => authorization_from(response) + ) + + end + + def successful?(response) + response[:status] == SUCCESS + end + + def authorization_from(response) + [ response[:authnum], response[:transid] ].compact.join(";") + end + + def test_response?(response) + !!(response[:transid] =~ /SimProxy/) + end + + def message_from(response) + successful?(response) ? SUCCESS_MESSAGE : response[:errorstring] + end + + def parse(body) + response = {} + body.to_s.each_line do |l| + key, value = l.split(":", 2) + response[key.to_s.downcase.to_sym] = value.strip + end + response + end + + def post_data(action, parameters = {}) + parameters[:request_type] = TRANSACTIONS[action] + parameters[:merchant_id] = @options[:login] + parameters[:password] = @options[:password] + + parameters.reject{|k,v| v.blank?}.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&") + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paybox_direct.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paybox_direct.rb new file mode 100644 index 000000000..a3e3d70ae --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paybox_direct.rb @@ -0,0 +1,196 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PayboxDirectGateway < Gateway + class_attribute :live_url_backup + + self.test_url = 'https://preprod-ppps.paybox.com/PPPS.php' + self.live_url = 'https://ppps.paybox.com/PPPS.php' + self.live_url_backup = 'https://ppps1.paybox.com/PPPS.php' + + # Payment API Version + API_VERSION = '00103' + + # Transactions hash + TRANSACTIONS = { + :authorization => '00001', + :capture => '00002', + :purchase => '00003', + :unreferenced_credit => '00004', + :void => '00005', + :refund => '00014' + } + + CURRENCY_CODES = { + "AUD"=> '036', + "CAD"=> '124', + "CZK"=> '203', + "DKK"=> '208', + "HKD"=> '344', + "ICK"=> '352', + "JPY"=> '392', + "NOK"=> '578', + "SGD"=> '702', + "SEK"=> '752', + "CHF"=> '756', + "GBP"=> '826', + "USD"=> '840', + "EUR"=> '978' + } + + SUCCESS_CODES = ['00000'] + UNAVAILABILITY_CODES = ['00001', '00097', '00098'] + SUCCESS_MESSAGE = 'The transaction was approved' + FAILURE_MESSAGE = 'The transaction failed' + + # Money is referenced in cents + self.money_format = :cents + self.default_currency = 'EUR' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['FR'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.paybox.com/' + + # The name of the gateway + self.display_name = 'Paybox Direct' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + commit('authorization', money, post) + end + + def purchase(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + commit('purchase', money, post) + end + + def capture(money, authorization, options = {}) + requires!(options, :order_id) + post = {} + add_invoice(post, options) + post[:numappel] = authorization[0,10] + post[:numtrans] = authorization[10,10] + commit('capture', money, post) + end + + def void(identification, options = {}) + requires!(options, :order_id, :amount) + post ={} + add_invoice(post, options) + add_reference(post, identification) + post[:porteur] = '000000000000000' + post[:dateval] = '0000' + commit('void', options[:amount], post) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + def refund(money, identification, options = {}) + post = {} + add_invoice(post, options) + add_reference(post, identification) + commit('refund', money, post) + end + + private + + def add_invoice(post, options) + post[:reference] = options[:order_id] + end + + def add_creditcard(post, creditcard) + post[:porteur] = creditcard.number + post[:dateval] = expdate(creditcard) + post[:cvv] = creditcard.verification_value if creditcard.verification_value? + end + + def add_reference(post, identification) + post[:numappel] = identification[0,10] + post[:numtrans] = identification[10,10] + end + + def parse(body) + results = {} + body.split(/&/).each do |pair| + key,val = pair.split(/\=/) + results[key.downcase.to_sym] = CGI.unescape(val) if val + end + results + end + + def commit(action, money = nil, parameters = nil) + parameters[:montant] = ('0000000000' + (money ? amount(money) : ''))[-10..-1] + parameters[:devise] = CURRENCY_CODES[options[:currency] || currency(money)] + request_data = post_data(action,parameters) + response = parse(ssl_post(test? ? self.test_url : self.live_url, request_data)) + response = parse(ssl_post(self.live_url_backup, request_data)) if service_unavailable?(response) && !test? + Response.new(success?(response), message_from(response), response.merge( + :timestamp => parameters[:dateq]), + :test => test?, + :authorization => response[:numappel].to_s + response[:numtrans].to_s, + :fraud_review => false, + :sent_params => parameters.delete_if{|key,value| ['porteur','dateval','cvv'].include?(key.to_s)} + ) + end + + def success?(response) + SUCCESS_CODES.include?(response[:codereponse]) + end + + def service_unavailable?(response) + UNAVAILABILITY_CODES.include?(response[:codereponse]) + end + + def message_from(response) + success?(response) ? SUCCESS_MESSAGE : (response[:commentaire] || FAILURE_MESSAGE) + end + + def post_data(action, parameters = {}) + + parameters.update( + :version => API_VERSION, + :type => TRANSACTIONS[action.to_sym], + :dateq => Time.now.strftime('%d%m%Y%H%M%S'), + :numquestion => unique_id(parameters[:order_id]), + :site => @options[:login].to_s[0,7], + :rang => @options[:login].to_s[7..-1], + :cle => @options[:password], + :pays => '', + :archivage => parameters[:order_id] + ) + + parameters.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def unique_id(seed = 0) + randkey = "#{seed}#{Time.now.usec}".to_i % 2147483647 # Max paybox value for the question number + + "0000000000#{randkey}"[-10..-1] + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow.rb new file mode 100644 index 000000000..770c426d8 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow.rb @@ -0,0 +1,268 @@ +require File.dirname(__FILE__) + '/payflow/payflow_common_api' +require File.dirname(__FILE__) + '/payflow/payflow_response' +require File.dirname(__FILE__) + '/payflow_express' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PayflowGateway < Gateway + include PayflowCommonAPI + + RECURRING_ACTIONS = Set.new([:add, :modify, :cancel, :inquiry, :reactivate, :payment]) + + self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover, :diners_club] + self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside' + self.display_name = 'PayPal Payflow Pro' + + def authorize(money, credit_card_or_reference, options = {}) + request = build_sale_or_authorization_request(:authorization, money, credit_card_or_reference, options) + + commit(request, options) + end + + def purchase(money, credit_card_or_reference, options = {}) + request = build_sale_or_authorization_request(:purchase, money, credit_card_or_reference, options) + + commit(request, options) + end + + def credit(money, identification_or_credit_card, options = {}) + if identification_or_credit_card.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + # Perform referenced credit + refund(money, identification_or_credit_card, options) + else + # Perform non-referenced credit + request = build_credit_card_request(:credit, money, identification_or_credit_card, options) + commit(request, options) + end + end + + def refund(money, reference, options = {}) + commit(build_reference_request(:credit, money, reference, options), options) + end + + # Adds or modifies a recurring Payflow profile. See the Payflow Pro Recurring Billing Guide for more details: + # https://www.paypal.com/en_US/pdf/PayflowPro_RecurringBilling_Guide.pdf + # + # Several options are available to customize the recurring profile: + # + # * profile_id - is only required for editing a recurring profile + # * starting_at - takes a Date, Time, or string in mmddyyyy format. The date must be in the future. + # * name - The name of the customer to be billed. If not specified, the name from the credit card is used. + # * periodicity - The frequency that the recurring payments will occur at. Can be one of + # :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly + # * payments - The term, or number of payments that will be made + # * comment - A comment associated with the profile + def recurring(money, credit_card, options = {}) + options[:name] = credit_card.name if options[:name].blank? && credit_card + request = build_recurring_request(options[:profile_id] ? :modify : :add, money, options) do |xml| + add_credit_card(xml, credit_card) if credit_card + end + commit(request, options.merge(:request_type => :recurring)) + end + + def cancel_recurring(profile_id) + request = build_recurring_request(:cancel, 0, :profile_id => profile_id) + commit(request, options.merge(:request_type => :recurring)) + end + + def recurring_inquiry(profile_id, options = {}) + request = build_recurring_request(:inquiry, nil, options.update( :profile_id => profile_id )) + commit(request, options.merge(:request_type => :recurring)) + end + + def express + @express ||= PayflowExpressGateway.new(@options) + end + + private + def build_sale_or_authorization_request(action, money, credit_card_or_reference, options) + if credit_card_or_reference.is_a?(String) + build_reference_sale_or_authorization_request(action, money, credit_card_or_reference, options) + else + build_credit_card_request(action, money, credit_card_or_reference, options) + end + end + + def build_reference_sale_or_authorization_request(action, money, reference, options) + xml = Builder::XmlMarkup.new + xml.tag! TRANSACTIONS[action] do + xml.tag! 'PayData' do + xml.tag! 'Invoice' do + # Fields accepted by PayFlow and recommended to be provided even for Reference Transaction, per Payflow docs. + xml.tag! 'CustIP', options[:ip] unless options[:ip].blank? + xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank? + xml.tag! 'Description', options[:description] unless options[:description].blank? + xml.tag! 'Comment', options[:comment] unless options[:comment].blank? + xml.tag!('ExtData', 'Name'=> 'COMMENT2', 'Value'=> options[:comment2]) unless options[:comment2].blank? + xml.tag! 'TaxAmt', options[:taxamt] unless options[:taxamt].blank? + xml.tag! 'FreightAmt', options[:freightamt] unless options[:freightamt].blank? + xml.tag! 'DutyAmt', options[:dutyamt] unless options[:dutyamt].blank? + xml.tag! 'DiscountAmt', options[:discountamt] unless options[:discountamt].blank? + + billing_address = options[:billing_address] || options[:address] + add_address(xml, 'BillTo', billing_address, options) if billing_address + add_address(xml, 'ShipTo', options[:shipping_address],options) if options[:shipping_address] + + xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money) + end + xml.tag! 'Tender' do + xml.tag! 'Card' do + xml.tag! 'ExtData', 'Name' => 'ORIGID', 'Value' => reference + end + end + end + end + xml.target! + end + + def build_credit_card_request(action, money, credit_card, options) + xml = Builder::XmlMarkup.new + xml.tag! TRANSACTIONS[action] do + xml.tag! 'PayData' do + xml.tag! 'Invoice' do + xml.tag! 'CustIP', options[:ip] unless options[:ip].blank? + xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank? + xml.tag! 'Description', options[:description] unless options[:description].blank? + # Comment and Comment2 will show up in manager.paypal.com as Comment1 and Comment2 + xml.tag! 'Comment', options[:comment] unless options[:comment].blank? + xml.tag!('ExtData', 'Name'=> 'COMMENT2', 'Value'=> options[:comment2]) unless options[:comment2].blank? + xml.tag! 'TaxAmt', options[:taxamt] unless options[:taxamt].blank? + xml.tag! 'FreightAmt', options[:freightamt] unless options[:freightamt].blank? + xml.tag! 'DutyAmt', options[:dutyamt] unless options[:dutyamt].blank? + xml.tag! 'DiscountAmt', options[:discountamt] unless options[:discountamt].blank? + + billing_address = options[:billing_address] || options[:address] + add_address(xml, 'BillTo', billing_address, options) if billing_address + add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address] + + xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money) + end + + xml.tag! 'Tender' do + add_credit_card(xml, credit_card) + end + end + end + xml.target! + end + + def add_credit_card(xml, credit_card) + xml.tag! 'Card' do + xml.tag! 'CardType', credit_card_type(credit_card) + xml.tag! 'CardNum', credit_card.number + xml.tag! 'ExpDate', expdate(credit_card) + xml.tag! 'NameOnCard', credit_card.first_name + xml.tag! 'CVNum', credit_card.verification_value if credit_card.verification_value? + + if requires_start_date_or_issue_number?(credit_card) + xml.tag!('ExtData', 'Name' => 'CardStart', 'Value' => startdate(credit_card)) unless credit_card.start_month.blank? || credit_card.start_year.blank? + xml.tag!('ExtData', 'Name' => 'CardIssue', 'Value' => format(credit_card.issue_number, :two_digits)) unless credit_card.issue_number.blank? + end + xml.tag! 'ExtData', 'Name' => 'LASTNAME', 'Value' => credit_card.last_name + end + end + + def credit_card_type(credit_card) + return '' if card_brand(credit_card).blank? + + CARD_MAPPING[card_brand(credit_card).to_sym] + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year.to_s.sub(/^0+/, '')) + month = sprintf("%.2i", creditcard.month.to_s.sub(/^0+/, '')) + + "#{year}#{month}" + end + + def startdate(creditcard) + year = format(creditcard.start_year, :two_digits) + month = format(creditcard.start_month, :two_digits) + + "#{month}#{year}" + end + + def build_recurring_request(action, money, options) + unless RECURRING_ACTIONS.include?(action) + raise StandardError, "Invalid Recurring Profile Action: #{action}" + end + + xml = Builder::XmlMarkup.new + xml.tag! 'RecurringProfiles' do + xml.tag! 'RecurringProfile' do + xml.tag! action.to_s.capitalize do + unless [:cancel, :inquiry].include?(action) + xml.tag! 'RPData' do + xml.tag! 'Name', options[:name] unless options[:name].nil? + xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money) + xml.tag! 'PayPeriod', get_pay_period(options) + xml.tag! 'Term', options[:payments] unless options[:payments].nil? + xml.tag! 'Comment', options[:comment] unless options[:comment].nil? + xml.tag! 'RetryNumDays', options[:retry_num_days] unless options[:retry_num_days].nil? + xml.tag! 'MaxFailPayments', options[:max_fail_payments] unless options[:max_fail_payments].nil? + + if initial_tx = options[:initial_transaction] + requires!(initial_tx, [:type, :authorization, :purchase]) + requires!(initial_tx, :amount) if initial_tx[:type] == :purchase + + xml.tag! 'OptionalTrans', TRANSACTIONS[initial_tx[:type]] + xml.tag! 'OptionalTransAmt', amount(initial_tx[:amount]) unless initial_tx[:amount].blank? + end + + if action == :add + xml.tag! 'Start', format_rp_date(options[:starting_at] || Date.today + 1 ) + else + xml.tag! 'Start', format_rp_date(options[:starting_at]) unless options[:starting_at].nil? + end + + xml.tag! 'EMail', options[:email] unless options[:email].nil? + + billing_address = options[:billing_address] || options[:address] + add_address(xml, 'BillTo', billing_address, options) if billing_address + add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address] + end + xml.tag! 'Tender' do + yield xml + end + end + if action != :add + xml.tag! "ProfileID", options[:profile_id] + end + if action == :inquiry + xml.tag! "PaymentHistory", ( options[:history] ? 'Y' : 'N' ) + end + end + end + end + end + + def get_pay_period(options) + requires!(options, [:periodicity, :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly]) + case options[:periodicity] + when :weekly then 'Weekly' + when :biweekly then 'Bi-weekly' + when :semimonthly then 'Semi-monthly' + when :quadweekly then 'Every four weeks' + when :monthly then 'Monthly' + when :quarterly then 'Quarterly' + when :semiyearly then 'Semi-yearly' + when :yearly then 'Yearly' + end + end + + def format_rp_date(time) + case time + when Time, Date then time.strftime("%m%d%Y") + else + time.to_s + end + end + + def build_response(success, message, response, options = {}) + PayflowResponse.new(success, message, response, options) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb new file mode 100644 index 000000000..a27684e65 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb @@ -0,0 +1,210 @@ +require 'nokogiri' +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module PayflowCommonAPI + def self.included(base) + base.default_currency = 'USD' + + base.class_attribute :partner + + # Set the default partner to PayPal + base.partner = 'PayPal' + + base.supported_countries = ['US', 'CA', 'SG', 'AU'] + + base.class_attribute :timeout + base.timeout = 60 + + base.test_url = 'https://pilot-payflowpro.paypal.com' + base.live_url = 'https://payflowpro.paypal.com' + + # Enable safe retry of failed connections + # Payflow is safe to retry because retried transactions use the same + # X-VPS-Request-ID header. If a transaction is detected as a duplicate + # only the original transaction data will be used by Payflow, and the + # subsequent Responses will have a :duplicate parameter set in the params + # hash. + base.retry_safe = true + end + + XMLNS = 'http://www.paypal.com/XMLPay' + + CARD_MAPPING = { + :visa => 'Visa', + :master => 'MasterCard', + :discover => 'Discover', + :american_express => 'Amex', + :jcb => 'JCB', + :diners_club => 'DinersClub', + :switch => 'Switch', + :solo => 'Solo' + } + + TRANSACTIONS = { + :purchase => "Sale", + :authorization => "Authorization", + :capture => "Capture", + :void => "Void", + :credit => "Credit" + } + + CVV_CODE = { + 'Match' => 'M', + 'No Match' => 'N', + 'Service Not Available' => 'U', + 'Service not Requested' => 'P' + } + + def initialize(options = {}) + requires!(options, :login, :password) + + options[:partner] = partner if options[:partner].blank? + super + end + + def capture(money, authorization, options = {}) + request = build_reference_request(:capture, money, authorization, options) + commit(request, options) + end + + def void(authorization, options = {}) + request = build_reference_request(:void, nil, authorization, options) + commit(request, options) + end + + private + def build_request(body, options = {}) + xml = Builder::XmlMarkup.new + xml.instruct! + xml.tag! 'XMLPayRequest', 'Timeout' => timeout.to_s, 'version' => "2.1", "xmlns" => XMLNS do + xml.tag! 'RequestData' do + xml.tag! 'Vendor', @options[:login] + xml.tag! 'Partner', @options[:partner] + if options[:request_type] == :recurring + xml << body + else + xml.tag! 'Transactions' do + xml.tag! 'Transaction', 'CustRef' => options[:customer] do + xml.tag! 'Verbosity', 'MEDIUM' + xml << body + end + end + end + end + xml.tag! 'RequestAuth' do + xml.tag! 'UserPass' do + xml.tag! 'User', !@options[:user].blank? ? @options[:user] : @options[:login] + xml.tag! 'Password', @options[:password] + end + end + end + xml.target! + end + + def build_reference_request(action, money, authorization, options) + xml = Builder::XmlMarkup.new + xml.tag! TRANSACTIONS[action] do + xml.tag! 'PNRef', authorization + + unless money.nil? + xml.tag! 'Invoice' do + xml.tag!('TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)) + xml.tag!('Description', options[:description]) unless options[:description].blank? + xml.tag!('Comment', options[:comment]) unless options[:comment].blank? + xml.tag!('ExtData', 'Name'=> 'COMMENT2', 'Value'=> options[:comment2]) unless options[:comment2].blank? + end + end + end + + xml.target! + end + + def add_address(xml, tag, address, options) + return if address.nil? + xml.tag! tag do + xml.tag! 'FirstName', address[:first_name] unless address[:first_name].blank? + xml.tag! 'LastName', address[:last_name] unless address[:last_name].blank? + xml.tag! 'EMail', options[:email] unless options[:email].blank? + xml.tag! 'Phone', address[:phone] unless address[:phone].blank? + xml.tag! 'CustCode', options[:customer] if !options[:customer].blank? && tag == 'BillTo' + xml.tag! 'PONum', options[:po_number] if !options[:po_number].blank? && tag == 'BillTo' + + xml.tag! 'Address' do + xml.tag! 'Street', address[:address1] unless address[:address1].blank? + xml.tag! 'City', address[:city] unless address[:city].blank? + xml.tag! 'State', address[:state].blank? ? "N/A" : address[:state] + xml.tag! 'Country', address[:country] unless address[:country].blank? + xml.tag! 'Zip', address[:zip] unless address[:zip].blank? + end + end + end + + def parse(data) + response = {} + xml = Nokogiri::XML(data) + xml.remove_namespaces! + root = xml.xpath("//ResponseData") + + # REXML::XPath in Ruby 1.8.6 is now unable to match nodes based on their attributes + tx_result = root.xpath(".//TransactionResult").first + + if tx_result && tx_result.attributes['Duplicate'].to_s == "true" + response[:duplicate] = true + end + + root.xpath(".//*").each do |node| + parse_element(response, node) + end + + response + end + + def parse_element(response, node) + node_name = node.name.underscore.to_sym + case + when node_name == :rp_payment_result + # Since we'll have multiple history items, we can't just flatten everything + # down as we do everywhere else. RPPaymentResult elements are not contained + # in an RPPaymentResults element so we'll come here multiple times + response[node_name] ||= [] + response[node_name] << ( payment_result_response = {} ) + node.xpath(".//*").each{ |e| parse_element(payment_result_response, e) } + when node.xpath(".//*").to_a.any? + node.xpath(".//*").each{|e| parse_element(response, e) } + when node_name.to_s =~ /amt$/ + # *Amt elements don't put the value in the #text - instead they use a Currency attribute + response[node_name] = node.attributes['Currency'].to_s + when node_name == :ext_data + response[node.attributes['Name'].to_s.underscore.to_sym] = node.attributes['Value'].to_s + else + response[node_name] = node.text + end + end + + def build_headers(content_length) + { + "Content-Type" => "text/xml", + "Content-Length" => content_length.to_s, + "X-VPS-Client-Timeout" => timeout.to_s, + "X-VPS-VIT-Integration-Product" => "ActiveMerchant", + "X-VPS-VIT-Runtime-Version" => RUBY_VERSION, + "X-VPS-Request-ID" => Utils.generate_unique_id + } + end + + def commit(request_body, options = {}) + request = build_request(request_body, options) + headers = build_headers(request.size) + + response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers)) + + build_response(response[:result] == "0", response[:message], response, + :test => test?, + :authorization => response[:pn_ref] || response[:rp_ref], + :cvv_result => CVV_CODE[response[:cv_result]], + :avs_result => { :code => response[:avs_result] } + ) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb new file mode 100644 index 000000000..7b4068dea --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb @@ -0,0 +1,39 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PayflowExpressResponse < Response + def email + @params['e_mail'] + end + + def full_name + "#{@params['name']} #{@params['lastname']}" + end + + def token + @params['token'] + end + + def payer_id + @params['payer_id'] + end + + # Really the shipping country, but it is all the information provided + def payer_country + address['country'] + end + + def address + { 'name' => full_name, + 'company' => nil, + 'address1' => @params['street'], + 'address2' => @params['shiptostreet2'] || @params['street2'], + 'city' => @params['city'], + 'state' => @params['state'], + 'country' => @params['country'], + 'zip' => @params['zip'], + 'phone' => nil + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_response.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_response.rb new file mode 100644 index 000000000..d2b6e6700 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow/payflow_response.rb @@ -0,0 +1,13 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PayflowResponse < Response + def profile_id + @params['profile_id'] + end + + def payment_history + @payment_history ||= @params['rp_payment_result'].collect{ |result| result.stringify_keys } rescue [] + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express.rb new file mode 100644 index 000000000..f6183218d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express.rb @@ -0,0 +1,224 @@ +require File.dirname(__FILE__) + '/payflow/payflow_common_api' +require File.dirname(__FILE__) + '/payflow/payflow_express_response' +require File.dirname(__FILE__) + '/paypal_express_common' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # ==General Parameters + # The following parameters are supported for #setup_authorization, #setup_purchase, #authorize and #purchase transactions. I've read + # in the docs that they recommend you pass the exact same parameters to both setup and authorize/purchase. + # + # This information was gleaned from a mix of: + # * PayFlow documentation + # * for key value pairs: {Express Checkout for Payflow Pro (PDF)}[https://cms.paypal.com/cms_content/US/en_US/files/developer/PFP_ExpressCheckout_PP.pdf] + # * XMLPay: {Payflow Pro XMLPay Developer's Guide (PDF)}[https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_PayflowPro_XMLPay_Guide.pdf] + # * previous ActiveMerchant code + # * trial & error + # + # The following parameters are currently supported. + # [:ip] (opt) Customer IP Address + # [:order_id] (opt) An order or invoice number. This will be passed through to the Payflow backend at manager.paypal.com, and show up as "Supplier Reference #" + # [:description] (opt) Order description, shown to buyer (after redirected to PayPal). If Order Line Items are used (see below), then the description is suppressed. This will not be passed through to the Payflow backend. + # [:billing_address] (opt) See ActiveMerchant::Billing::Gateway for details + # [:shipping_address] (opt) See ActiveMerchant::Billing::Gateway for details + # [:currency] (req) Currency of transaction, will be set to USD by default for PayFlow Express if not specified + # [:email] (opt) Email of buyer; used to pre-fill PayPal login screen + # [:payer_id] (opt) Unique PayPal buyer account identification number, as returned by details_for request + # [:token] (req for #authorize & #purchase) Token returned by setup transaction + # [:no_shipping] (opt) Boolean for whether or not to display shipping address to buyer + # [:address_override] (opt) Boolean. If true, display shipping address passed by parameters, rather than shipping address on file with PayPal + # [:allow_note] (opt) Boolean for permitting buyer to add note during checkout. Note contents can be retrieved with details_for transaction + # [:return_url] (req) URL to which the buyer’s browser is returned after choosing to pay. + # [:cancel_return_url] (req) URL to which the buyer is returned if the buyer cancels the order. + # [:notify_url] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction. + # [:comment] (opt) Comment field which will be reported to Payflow backend (at manager.paypal.com) as Comment1 + # [:comment2] (opt) Comment field which will be reported to Payflow backend (at manager.paypal.com) as Comment2 + # [:discount] (opt) Total discounts in cents + # + # ==Line Items + # Support for order line items is available, but has to be enabled on the PayFlow backend. This is what I was told by Todd Sieber at Technical Support: + # + # You will need to call Payflow Support at 1-888-883-9770, choose option #2. Request that they update your account in "Pandora" under Product Settings >> PayPal Mark and update the Features Bitmap to 1111111111111112. This is 15 ones and a two. + # + # See here[https://www.x.com/message/206214#206214] for the forum discussion (requires login to {x.com}[https://x.com] + # + # [:items] (opt) Array of Order Line Items hashes. These are shown to the buyer after redirect to PayPal. + # + # + # + # The following keys are supported for line items: + # [:name] Name of line item + # [:description] Description of line item + # [:amount] Line Item Amount in Cents (as Integer) + # [:quantity] Line Item Quantity (default to 1 if left blank) + # + # ====Customization of Payment Page + # [:page_style] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction. + # [:header_image] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction. + # [:background_color] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction. + # ====Additional options for old Checkout Experience, being phased out in 2010 and 2011 + # [:header_background_color] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction. + # [:header_border_color] (opt) Your URL for receiving Instant Payment Notification (IPN) about this transaction. + + + class PayflowExpressGateway < Gateway + include PayflowCommonAPI + include PaypalExpressCommon + + self.test_redirect_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr' + self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside' + self.display_name = 'PayPal Express Checkout' + + def authorize(money, options = {}) + requires!(options, :token, :payer_id) + request = build_sale_or_authorization_request('Authorization', money, options) + commit(request, options) + end + + def purchase(money, options = {}) + requires!(options, :token, :payer_id) + request = build_sale_or_authorization_request('Sale', money, options) + commit(request, options) + end + + def refund(money, identification, options = {}) + request = build_reference_request(:credit, money, identification, options) + commit(request, options) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + def setup_authorization(money, options = {}) + requires!(options, :return_url, :cancel_return_url) + + request = build_setup_express_sale_or_authorization_request('Authorization', money, options) + commit(request, options) + end + + def setup_purchase(money, options = {}) + requires!(options, :return_url, :cancel_return_url) + + request = build_setup_express_sale_or_authorization_request('Sale', money, options) + commit(request, options) + end + + def details_for(token) + request = build_get_express_details_request(token) + commit(request, options) + end + + private + def build_get_express_details_request(token) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'GetExpressCheckout' do + xml.tag! 'Authorization' do + xml.tag! 'PayData' do + xml.tag! 'Tender' do + xml.tag! 'PayPal' do + xml.tag! 'Token', token + end + end + end + end + end + xml.target! + end + + def build_setup_express_sale_or_authorization_request(action, money, options = {}) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'SetExpressCheckout' do + xml.tag! action do + add_pay_data xml, money, options + end + end + xml.target! + end + + def build_sale_or_authorization_request(action, money, options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'DoExpressCheckout' do + xml.tag! action do + add_pay_data xml, money, options + end + end + xml.target! + end + + def add_pay_data(xml, money, options) + xml.tag! 'PayData' do + xml.tag! 'Invoice' do + xml.tag! 'CustIP', options[:ip] unless options[:ip].blank? + xml.tag! 'InvNum', options[:order_id] unless options[:order_id].blank? + # Description field will be shown to buyer, unless line items are also being supplied (then only line items are shown). + xml.tag! 'Description', options[:description] unless options[:description].blank? + # Comment, Comment2 should make it to the backend at manager.paypal.com, as with Payflow credit card transactions + # but that doesn't seem to work (yet?). See: https://www.x.com/thread/51908?tstart=0 + xml.tag! 'Comment', options[:comment] unless options[:comment].nil? + xml.tag!('ExtData', 'Name'=> 'COMMENT2', 'Value'=> options[:comment2]) unless options[:comment2].nil? + + billing_address = options[:billing_address] || options[:address] + add_address(xml, 'BillTo', billing_address, options) if billing_address + add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address] + + # Note: To get order line-items to show up with Payflow Express, this feature has to be enabled on the backend. + # Call Support at 888 883 9770, press 2. Then request that they update your account in "Pandora" under Product Settings >> PayPal + # Mark and update the Features Bitmap to 1111111111111112. This is 15 ones and a two. + # See here for the forum discussion: https://www.x.com/message/206214#206214 + items = options[:items] || [] + items.each_with_index do |item, index| + xml.tag! 'ExtData', 'Name' => "L_DESC#{index}", 'Value' => item[:description] + xml.tag! 'ExtData', 'Name' => "L_COST#{index}", 'Value' => amount(item[:amount]) + xml.tag! 'ExtData', 'Name' => "L_QTY#{index}", 'Value' => item[:quantity] || '1' + xml.tag! 'ExtData', 'Name' => "L_NAME#{index}", 'Value' => item[:name] + # Note: An ItemURL is supported in Paypal Express (different API), but not PayFlow Express, as far as I can tell. + # L_URLn nor L_ITEMURLn seem to work + end + if items.any? + xml.tag! 'ExtData', 'Name' => 'CURRENCY', 'Value' => options[:currency] || currency(money) + xml.tag! 'ExtData', 'Name' => "ITEMAMT", 'Value' => amount(options[:subtotal] || money) + end + xml.tag! 'DiscountAmt', amount(options[:discount]) if options[:discount] + xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money) + + end + + xml.tag! 'Tender' do + add_paypal_details(xml, options) + end + end + end + + def add_paypal_details(xml, options) + xml.tag! 'PayPal' do + xml.tag! 'EMail', options[:email] unless options[:email].blank? + xml.tag! 'ReturnURL', options[:return_url] unless options[:return_url].blank? + xml.tag! 'CancelURL', options[:cancel_return_url] unless options[:cancel_return_url].blank? + xml.tag! 'NotifyURL', options[:notify_url] unless options[:notify_url].blank? + xml.tag! 'PayerID', options[:payer_id] unless options[:payer_id].blank? + xml.tag! 'Token', options[:token] unless options[:token].blank? + xml.tag! 'NoShipping', options[:no_shipping] ? '1' : '0' + xml.tag! 'AddressOverride', options[:address_override] ? '1' : '0' + xml.tag! 'ButtonSource', application_id.to_s.slice(0,32) unless application_id.blank? + + # Customization of the payment page + xml.tag! 'PageStyle', options[:page_style] unless options[:page_style].blank? + xml.tag! 'HeaderImage', options[:header_image] unless options[:header_image].blank? + xml.tag! 'PayflowColor', options[:background_color] unless options[:background_color].blank? + # Note: HeaderImage and PayflowColor apply to both the new (as of 2010) and the old checkout experience + # HeaderBackColor and HeaderBorderColor apply only to the old checkout experience which is being phased out. + xml.tag! 'HeaderBackColor', options[:header_background_color] unless options[:header_background_color].blank? + xml.tag! 'HeaderBorderColor', options[:header_border_color] unless options[:header_border_color].blank? + xml.tag! 'ExtData', 'Name' => 'ALLOWNOTE', 'Value' => options[:allow_note] + end + end + + def build_response(success, message, response, options = {}) + PayflowExpressResponse.new(success, message, response, options) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express_uk.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express_uk.rb new file mode 100644 index 000000000..0469e65e6 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_express_uk.rb @@ -0,0 +1,15 @@ +require File.dirname(__FILE__) + '/payflow_express' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PayflowExpressUkGateway < PayflowExpressGateway + self.default_currency = 'GBP' + self.partner = 'PayPalUk' + + self.supported_countries = ['GB'] + self.homepage_url = 'https://www.paypal.com/uk/cgi-bin/webscr?cmd=_additional-payment-overview-outside' + self.display_name = 'PayPal Express Checkout (UK)' + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_uk.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_uk.rb new file mode 100644 index 000000000..12250c1d5 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payflow_uk.rb @@ -0,0 +1,21 @@ +require File.dirname(__FILE__) + '/payflow' +require File.dirname(__FILE__) + '/payflow_express_uk' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PayflowUkGateway < PayflowGateway + self.default_currency = 'GBP' + self.partner = 'PayPalUk' + + def express + @express ||= PayflowExpressUkGateway.new(@options) + end + + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :solo, :switch] + self.supported_countries = ['GB'] + self.homepage_url = 'https://www.paypal.com/uk/cgi-bin/webscr?cmd=_wp-pro-overview-outside' + self.display_name = 'PayPal Website Payments Pro (UK)' + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payment_express.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payment_express.rb new file mode 100644 index 000000000..7128cd191 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payment_express.rb @@ -0,0 +1,340 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + # In NZ DPS supports ANZ, Westpac, National Bank, ASB and BNZ. + # In Australia DPS supports ANZ, NAB, Westpac, CBA, St George and Bank of South Australia. + # The Maybank in Malaysia is supported and the Citibank for Singapore. + class PaymentExpressGateway < Gateway + self.default_currency = 'NZD' + # PS supports all major credit cards; Visa, Mastercard, Amex, Diners, BankCard & JCB. + # Various white label cards can be accepted as well; Farmers, AirNZCard and Elders etc. + # Please note that not all acquirers and Eftpos networks can support some of these card types. + # VISA, Mastercard, Diners Club and Farmers cards are supported + # + # However, regular accounts with DPS only support VISA and Mastercard + self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :jcb ] + + self.supported_countries = %w[ AU MY NZ SG ZA GB US ] + + self.homepage_url = 'http://www.paymentexpress.com/' + self.display_name = 'PaymentExpress' + + self.live_url = self.test_url = 'https://sec.paymentexpress.com/pxpost.aspx' + + APPROVED = '1' + + TRANSACTIONS = { + :purchase => 'Purchase', + :credit => 'Refund', + :authorization => 'Auth', + :capture => 'Complete', + :validate => 'Validate' + } + + # We require the DPS gateway username and password when the object is created. + # + # The PaymentExpress gateway also supports a :use_custom_payment_token boolean option. + # If set to true the gateway will use BillingId for the Token type. If set to false, + # then the token will be sent as the DPS specified "DpsBillingId". This is per the documentation at + # http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Tokenbilling + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Funds are transferred immediately. + # + # `payment_source` can be a usual ActiveMerchant credit_card object, or can also + # be a string of the `DpsBillingId` or `BillingId` which can be gotten through the + # store method. If you are using a `BillingId` instead of `DpsBillingId` you must + # also set the instance method `#use_billing_id_for_token` to true, see the `#store` + # method for an example of how to do this. + def purchase(money, payment_source, options = {}) + request = build_purchase_or_authorization_request(money, payment_source, options) + commit(:purchase, request) + end + + # NOTE: Perhaps in options we allow a transaction note to be inserted + # Verifies that funds are available for the requested card and amount and reserves the specified amount. + # See: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Authcomplete + # + # `payment_source` can be a usual ActiveMerchant credit_card object or a token, see #purchased method + def authorize(money, payment_source, options = {}) + request = build_purchase_or_authorization_request(money, payment_source, options) + commit(:authorization, request) + end + + # Transfer pre-authorized funds immediately + # See: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Authcomplete + def capture(money, identification, options = {}) + request = build_capture_or_credit_request(money, identification, options) + commit(:capture, request) + end + + # Refund funds to the card holder + def refund(money, identification, options = {}) + requires!(options, :description) + + request = build_capture_or_credit_request(money, identification, options) + commit(:credit, request) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + # Token Based Billing + # + # Instead of storing the credit card details locally, you can store them inside the + # Payment Express system and instead bill future transactions against a token. + # + # This token can either be specified by your code or autogenerated by the PaymentExpress + # system. The default is to let PaymentExpress generate the token for you and so use + # the `DpsBillingId`. If you do not pass in any option of the `billing_id`, then the store + # method will ask PaymentExpress to create a token for you. Additionally, if you are + # using the default `DpsBillingId`, you do not have to do anything extra in the + # initialization of your gateway object. + # + # To specify and use your own token, you need to do two things. + # + # Firstly, pass in a `:billing_id` as an option in the hash of this store method. No + # validation is done on this BillingId by PaymentExpress so you must ensure that it is unique. + # + # gateway.store(credit_card, {:billing_id => 'YourUniqueBillingId'}) + # + # Secondly, you will need to pass in the option `{:use_custom_payment_token => true}` when + # initializing your gateway instance, like so: + # + # gateway = ActiveMerchant::Billing::PaymentExpressGateway.new( + # :login => 'USERNAME', + # :password => 'PASSWORD', + # :use_custom_payment_token => true + # ) + # + # see: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#Tokenbilling + # + # Note, once stored, PaymentExpress does not support unstoring a stored card. + def store(credit_card, options = {}) + request = build_token_request(credit_card, options) + commit(:validate, request) + end + + private + + def use_custom_payment_token? + @options[:use_custom_payment_token] + end + + def build_purchase_or_authorization_request(money, payment_source, options) + result = new_transaction + + if payment_source.is_a?(String) + add_billing_token(result, payment_source) + else + add_credit_card(result, payment_source) + end + + add_amount(result, money, options) + add_invoice(result, options) + add_address_verification_data(result, options) + add_optional_elements(result, options) + result + end + + def build_capture_or_credit_request(money, identification, options) + result = new_transaction + + add_amount(result, money, options) + add_invoice(result, options) + add_reference(result, identification) + add_optional_elements(result, options) + result + end + + def build_token_request(credit_card, options) + result = new_transaction + add_credit_card(result, credit_card) + add_amount(result, 100, options) #need to make an auth request for $1 + add_token_request(result, options) + add_optional_elements(result, options) + result + end + + def add_credentials(xml) + xml.add_element("PostUsername").text = @options[:login] + xml.add_element("PostPassword").text = @options[:password] + end + + def add_reference(xml, identification) + xml.add_element("DpsTxnRef").text = identification + end + + def add_credit_card(xml, credit_card) + xml.add_element("CardHolderName").text = credit_card.name + xml.add_element("CardNumber").text = credit_card.number + xml.add_element("DateExpiry").text = format_date(credit_card.month, credit_card.year) + + if credit_card.verification_value? + xml.add_element("Cvc2").text = credit_card.verification_value + xml.add_element("Cvc2Presence").text = "1" + end + + if requires_start_date_or_issue_number?(credit_card) + xml.add_element("DateStart").text = format_date(credit_card.start_month, credit_card.start_year) unless credit_card.start_month.blank? || credit_card.start_year.blank? + xml.add_element("IssueNumber").text = credit_card.issue_number unless credit_card.issue_number.blank? + end + end + + def add_billing_token(xml, token) + if use_custom_payment_token? + xml.add_element("BillingId").text = token + else + xml.add_element("DpsBillingId").text = token + end + end + + def add_token_request(xml, options) + xml.add_element("BillingId").text = options[:billing_id] if options[:billing_id] + xml.add_element("EnableAddBillCard").text = 1 + end + + def add_amount(xml, money, options) + xml.add_element("Amount").text = amount(money) + xml.add_element("InputCurrency").text = options[:currency] || currency(money) + end + + def add_transaction_type(xml, action) + xml.add_element("TxnType").text = TRANSACTIONS[action] + end + + def add_invoice(xml, options) + xml.add_element("TxnId").text = options[:order_id].to_s.slice(0, 16) unless options[:order_id].blank? + xml.add_element("MerchantReference").text = options[:description].to_s.slice(0, 50) unless options[:description].blank? + end + + def add_address_verification_data(xml, options) + address = options[:billing_address] || options[:address] + return if address.nil? + + xml.add_element("EnableAvsData").text = 1 + xml.add_element("AvsAction").text = 1 + + xml.add_element("AvsStreetAddress").text = address[:address1] + xml.add_element("AvsPostCode").text = address[:zip] + end + + # The options hash may contain optional data which will be passed + # through the the specialized optional fields at PaymentExpress + # as follows: + # + # { + # :client_type => :web, # Possible values are: :web, :ivr, :moto, :unattended, :internet, or :recurring + # :txn_data1 => "String up to 255 characters", + # :txn_data2 => "String up to 255 characters", + # :txn_data3 => "String up to 255 characters" + # } + # + # +:client_type+, while not documented for PxPost, will be sent as + # the +ClientType+ XML element as described in the documentation for + # the PaymentExpress WebService: http://www.paymentexpress.com/Technical_Resources/Ecommerce_NonHosted/WebService#clientType + # (PaymentExpress have confirmed that this value works the same in PxPost). + # The value sent for +:client_type+ will be normalized and sent + # as one of the explicit values allowed by PxPost: + # + # :web => "Web" + # :ivr => "IVR" + # :moto => "MOTO" + # :unattended => "Unattended" + # :internet => "Internet" + # :recurring => "Recurring" + # + # If you set the +:client_type+ to any value not listed above, + # the ClientType element WILL NOT BE INCLUDED at all in the + # POST data. + # + # +:txn_data1+, +:txn_data2+, and +:txn_data3+ will be sent as + # +TxnData1+, +TxnData2+, and +TxnData3+, respectively, and are + # free form fields of the merchant's choosing, as documented here: + # http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#txndata + # + # These optional elements are added to all transaction types: + # +purchase+, +authorize+, +capture+, +refund+, +store+ + def add_optional_elements(xml, options) + if client_type = normalized_client_type(options[:client_type]) + xml.add_element("ClientType").text = client_type + end + + xml.add_element("TxnData1").text = options[:txn_data1].to_s.slice(0,255) unless options[:txn_data1].blank? + xml.add_element("TxnData2").text = options[:txn_data2].to_s.slice(0,255) unless options[:txn_data2].blank? + xml.add_element("TxnData3").text = options[:txn_data3].to_s.slice(0,255) unless options[:txn_data3].blank? + end + + def new_transaction + REXML::Document.new.add_element("Txn") + end + + # Take in the request and post it to DPS + def commit(action, request) + add_credentials(request) + add_transaction_type(request, action) + + # Parse the XML response + response = parse( ssl_post(self.live_url, request.to_s) ) + + # Return a response + PaymentExpressResponse.new(response[:success] == APPROVED, response[:card_holder_help_text], response, + :test => response[:test_mode] == '1', + :authorization => response[:dps_txn_ref] + ) + end + + # Response XML documentation: http://www.paymentexpress.com/technical_resources/ecommerce_nonhosted/pxpost.html#XMLTxnOutput + def parse(xml_string) + response = {} + + xml = REXML::Document.new(xml_string) + + # Gather all root elements such as HelpText + xml.elements.each('Txn/*') do |element| + response[element.name.underscore.to_sym] = element.text unless element.name == 'Transaction' + end + + # Gather all transaction elements and prefix with "account_" + # So we could access the MerchantResponseText by going + # response[account_merchant_response_text] + xml.elements.each('Txn/Transaction/*') do |element| + response[element.name.underscore.to_sym] = element.text + end + + response + end + + def format_date(month, year) + "#{format(month, :two_digits)}#{format(year, :two_digits)}" + end + + def normalized_client_type(client_type_from_options) + case client_type_from_options.to_s.downcase + when 'web' then "Web" + when 'ivr' then "IVR" + when 'moto' then "MOTO" + when 'unattended' then "Unattended" + when 'internet' then "Internet" + when 'recurring' then "Recurring" + else nil + end + end + end + + class PaymentExpressResponse < Response + # add a method to response so we can easily get the token + # for Validate transactions + def token + @params["billing_id"] || @params["dps_billing_id"] + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paymill.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paymill.rb new file mode 100644 index 000000000..05b14bbc9 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paymill.rb @@ -0,0 +1,179 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaymillGateway < Gateway + self.supported_countries = %w(AD AT BE CH CY CZ DE DK EE ES FI FO FR GB GR + HU IE IL IS IT LI LT LU LV MT NL NO PL PT SE + SI SK TR VA) + + self.supported_cardtypes = [:visa, :master] + self.homepage_url = 'https://paymill.com' + self.display_name = 'PAYMILL' + self.money_format = :cents + self.default_currency = 'EUR' + + def initialize(options = {}) + requires!(options, :public_key, :private_key) + super + end + + def purchase(money, payment_method, options = {}) + case payment_method + when String + purchase_with_token(money, payment_method, options) + else + MultiResponse.run do |r| + r.process { save_card(payment_method) } + r.process { purchase_with_token(money, r.authorization, options) } + end + end + end + + def authorize(money, payment_method, options = {}) + case payment_method + when String + authorize_with_token(money, payment_method, options) + else + MultiResponse.run do |r| + r.process { save_card(payment_method) } + r.process { authorize_with_token(money, r.authorization, options) } + end + end + end + + def capture(money, authorization, options = {}) + post = {} + + add_amount(post, money, options) + post[:preauthorization] = preauth(authorization) + post[:description] = options[:description] + commit(:post, 'transactions', post) + end + + def refund(money, authorization, options={}) + post = {} + + post[:amount] = amount(money) + post[:description] = options[:description] + commit(:post, "refunds/#{transaction_id(authorization)}", post) + end + + def store(credit_card, options={}) + save_card(credit_card) + end + + private + + def add_credit_card(post, credit_card) + post['account.number'] = credit_card.number + post['account.expiry.month'] = sprintf("%.2i", credit_card.month) + post['account.expiry.year'] = sprintf("%.4i", credit_card.year) + post['account.verification'] = credit_card.verification_value + end + + def headers + { 'Authorization' => ('Basic ' + Base64.strict_encode64("#{@options[:private_key]}:X").chomp) } + end + + def commit(method, url, parameters=nil) + begin + raw_response = ssl_request(method, "https://api.paymill.com/v2/#{url}", post_data(parameters), headers) + rescue ResponseError => e + parsed = JSON.parse(e.response.body) + return Response.new(false, parsed['error'], parsed, {}) + end + + response_from(raw_response) + end + + def response_from(raw_response) + parsed = JSON.parse(raw_response) + + options = { + :authorization => authorization_from(parsed), + :test => (parsed['mode'] == 'test'), + } + + Response.new(true, 'Transaction approved', parsed, options) + end + + def authorization_from(parsed_response) + [ + parsed_response['data']['id'], + parsed_response['data']['preauthorization'].try(:[], 'id') + ].join(";") + end + + def purchase_with_token(money, card_token, options) + post = {} + + add_amount(post, money, options) + post[:token] = card_token + post[:description] = options[:description] + commit(:post, 'transactions', post) + end + + def authorize_with_token(money, card_token, options) + post = {} + + add_amount(post, money, options) + post[:token] = card_token + commit(:post, 'preauthorizations', post) + end + + def save_card(credit_card) + post = {} + + add_credit_card(post, credit_card) + post['channel.id'] = @options[:public_key] + post['jsonPFunction'] = 'jsonPFunction' + post['transaction.mode'] = (test? ? 'CONNECTOR_TEST' : 'LIVE') + + begin + raw_response = ssl_request(:get, "#{save_card_url}?#{post_data(post)}", nil, {}) + rescue ResponseError => e + return Response.new(false, e.response.body, e.response.body, {}) + end + + response_for_save_from(raw_response) + end + + def response_for_save_from(raw_response) + options = { :test => test? } + + parsed = JSON.parse(raw_response.sub(/jsonPFunction\(/, '').sub(/\)\z/, '')) + if parsed['error'] + succeeded = false + message = parsed['error']['message'] + else + succeeded = parsed['transaction']['processing']['result'] == 'ACK' + message = parsed['transaction']['processing']['return']['message'] + options[:authorization] = parsed['transaction']['identification']['uniqueId'] if succeeded + end + + Response.new(succeeded, message, parsed, options) + end + + def save_card_url + (test? ? 'https://test-token.paymill.com' : 'https://token-v2.paymill.de') + end + + def post_data(params) + no_blanks = params.reject { |key, value| value.blank? } + no_blanks.map { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def add_amount(post, money, options) + post[:amount] = amount(money) + post[:currency] = (options[:currency] || currency(money)) + end + + def preauth(authorization) + authorization.split(";").last + end + + def transaction_id(authorization) + authorization.split(';').first + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal.rb new file mode 100644 index 000000000..49235b852 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal.rb @@ -0,0 +1,106 @@ +require File.dirname(__FILE__) + '/paypal/paypal_common_api' +require File.dirname(__FILE__) + '/paypal/paypal_recurring_api' +require File.dirname(__FILE__) + '/paypal_express' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaypalGateway < Gateway + include PaypalCommonAPI + include PaypalRecurringApi + + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.supported_countries = ['US'] + self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside' + self.display_name = 'PayPal Website Payments Pro (US)' + + def authorize(money, credit_card_or_referenced_id, options = {}) + requires!(options, :ip) + commit define_transaction_type(credit_card_or_referenced_id), build_sale_or_authorization_request('Authorization', money, credit_card_or_referenced_id, options) + end + + def purchase(money, credit_card_or_referenced_id, options = {}) + requires!(options, :ip) + commit define_transaction_type(credit_card_or_referenced_id), build_sale_or_authorization_request('Sale', money, credit_card_or_referenced_id, options) + end + + def express + @express ||= PaypalExpressGateway.new(@options) + end + + private + + def define_transaction_type(transaction_arg) + if transaction_arg.is_a?(String) + return 'DoReferenceTransaction' + else + return 'DoDirectPayment' + end + end + + def build_sale_or_authorization_request(action, money, credit_card_or_referenced_id, options) + transaction_type = define_transaction_type(credit_card_or_referenced_id) + reference_id = credit_card_or_referenced_id if transaction_type == "DoReferenceTransaction" + + billing_address = options[:billing_address] || options[:address] + currency_code = options[:currency] || currency(money) + + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! transaction_type + 'Req', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! transaction_type + 'Request', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:' + transaction_type + 'RequestDetails' do + xml.tag! 'n2:ReferenceID', reference_id if transaction_type == 'DoReferenceTransaction' + xml.tag! 'n2:PaymentAction', action + add_payment_details(xml, money, currency_code, options) + add_credit_card(xml, credit_card_or_referenced_id, billing_address, options) unless transaction_type == 'DoReferenceTransaction' + xml.tag! 'n2:IPAddress', options[:ip] + end + end + end + + xml.target! + end + + def add_credit_card(xml, credit_card, address, options) + xml.tag! 'n2:CreditCard' do + xml.tag! 'n2:CreditCardType', credit_card_type(card_brand(credit_card)) + xml.tag! 'n2:CreditCardNumber', credit_card.number + xml.tag! 'n2:ExpMonth', format(credit_card.month, :two_digits) + xml.tag! 'n2:ExpYear', format(credit_card.year, :four_digits) + xml.tag! 'n2:CVV2', credit_card.verification_value + + if [ 'switch', 'solo' ].include?(card_brand(credit_card).to_s) + xml.tag! 'n2:StartMonth', format(credit_card.start_month, :two_digits) unless credit_card.start_month.blank? + xml.tag! 'n2:StartYear', format(credit_card.start_year, :four_digits) unless credit_card.start_year.blank? + xml.tag! 'n2:IssueNumber', format(credit_card.issue_number, :two_digits) unless credit_card.issue_number.blank? + end + + xml.tag! 'n2:CardOwner' do + xml.tag! 'n2:PayerName' do + xml.tag! 'n2:FirstName', credit_card.first_name + xml.tag! 'n2:LastName', credit_card.last_name + end + + xml.tag! 'n2:Payer', options[:email] + add_address(xml, 'n2:Address', address) + end + end + end + + def credit_card_type(type) + case type + when 'visa' then 'Visa' + when 'master' then 'MasterCard' + when 'discover' then 'Discover' + when 'american_express' then 'Amex' + when 'switch' then 'Switch' + when 'solo' then 'Solo' + end + end + + def build_response(success, message, response, options = {}) + Response.new(success, message, response, options) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb new file mode 100644 index 000000000..4e8697b0d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb @@ -0,0 +1,654 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # This module is included in both PaypalGateway and PaypalExpressGateway + module PaypalCommonAPI + API_VERSION = '72' + + URLS = { + :test => { :certificate => 'https://api.sandbox.paypal.com/2.0/', + :signature => 'https://api-3t.sandbox.paypal.com/2.0/' }, + :live => { :certificate => 'https://api-aa.paypal.com/2.0/', + :signature => 'https://api-3t.paypal.com/2.0/' } + } + + PAYPAL_NAMESPACE = 'urn:ebay:api:PayPalAPI' + EBAY_NAMESPACE = 'urn:ebay:apis:eBLBaseComponents' + + ENVELOPE_NAMESPACES = { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', + 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' + } + CREDENTIALS_NAMESPACES = { 'xmlns' => PAYPAL_NAMESPACE, + 'xmlns:n1' => EBAY_NAMESPACE, + 'env:mustUnderstand' => '0' + } + + AUSTRALIAN_STATES = { + 'ACT' => 'Australian Capital Territory', + 'NSW' => 'New South Wales', + 'NT' => 'Northern Territory', + 'QLD' => 'Queensland', + 'SA' => 'South Australia', + 'TAS' => 'Tasmania', + 'VIC' => 'Victoria', + 'WA' => 'Western Australia' + } + + SUCCESS_CODES = [ 'Success', 'SuccessWithWarning' ] + + FRAUD_REVIEW_CODE = "11610" + + def self.included(base) + base.default_currency = 'USD' + base.cattr_accessor :pem_file + base.cattr_accessor :signature + base.live_url = URLS[:live][:signature] + base.test_url = URLS[:test][:signature] + end + + # The gateway must be configured with either your PayPal PEM file + # or your PayPal API Signature. Only one is required. + # + # :pem The text of your PayPal PEM file. Note + # this is not the path to file, but its + # contents. If you are only using one PEM + # file on your site you can declare it + # globally and then you won't need to + # include this option + # + # :signature The text of your PayPal signature. + # If you are only using one API Signature + # on your site you can declare it + # globally and then you won't need to + # include this option + def initialize(options = {}) + requires!(options, :login, :password) + + headers = {'X-PP-AUTHORIZATION' => options.delete(:auth_signature), 'X-PAYPAL-MESSAGE-PROTOCOL' => 'SOAP11'} if options[:auth_signature] + options = { + :pem => pem_file, + :signature => signature, + :headers => headers || {} + }.update(options) + + + if options[:pem].blank? && options[:signature].blank? + raise ArgumentError, "An API Certificate or API Signature is required to make requests to PayPal" + end + + super(options) + end + + def reauthorize(money, authorization, options = {}) + commit 'DoReauthorization', build_reauthorize_request(money, authorization, options) + end + + def capture(money, authorization, options = {}) + commit 'DoCapture', build_capture_request(money, authorization, options) + end + + # Transfer money to one or more recipients. + # + # gateway.transfer 1000, 'bob@example.com', + # :subject => "The money I owe you", :note => "Sorry it's so late" + # + # gateway.transfer [1000, 'fred@example.com'], + # [2450, 'wilma@example.com', :note => 'You will receive another payment on 3/24'], + # [2000, 'barney@example.com'], + # :subject => "Your Earnings", :note => "Thanks for your business." + # + def transfer(*args) + commit 'MassPay', build_mass_pay_request(*args) + end + + def void(authorization, options = {}) + commit 'DoVoid', build_void_request(authorization, options) + end + + # Refunds a transaction. + # + # For a full refund pass nil for the amount: + # + # gateway.refund nil, 'G39883289DH238' + # + # This will automatically make the :refund_type be "Full". + # + # For a partial refund just pass the amount as usual: + # + # gateway.refund 100, 'UBU83983N920' + # + def refund(money, identification, options = {}) + commit 'RefundTransaction', build_refund_request(money, identification, options) + end + + def credit(money, identification, options = {}) + deprecated Gateway::CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + # ==== For full documentation see {Paypal API Reference:}[https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_soap_r_DoReferenceTransaction] + # ==== Parameter: + # * :money -- (Required) The amount of this new transaction, + # required fo the payment details portion of this request + # + # ==== Options: + # * :reference_id -- (Required) A transaction ID from a previous purchase, such as a credit card charge using the DoDirectPayment API, or a billing agreement ID. + # * :payment_action -- (Optional) How you want to obtain payment. It is one of the following values: + # + # Authorization – This payment is a basic authorization subject to settlement with PayPal Authorization and Capture. + # Sale – This is a final sale for which you are requesting payment. + # + # * :ip_address -- (Optional) IP address of the buyer’s browser. + # Note: PayPal records this IP addresses as a means to detect possible fraud. + # * :req_confirm_shipping -- Whether you require that the buyer’s shipping address on file with PayPal be a confirmed address. You must have permission from PayPal to not require a confirmed address. It is one of the following values: + # + # 0 – You do not require that the buyer’s shipping address be a confirmed address. + # 1 – You require that the buyer’s shipping address be a confirmed address. + # + # * :merchant_session_id -- (Optional) Your buyer session identification token. + # * :return_fmf_details -- (Optional) Flag to indicate whether you want the results returned by Fraud Management Filters. By default, you do not receive this information. It is one of the following values: + # + # 0 – Do not receive FMF details (default) + # 1 – Receive FMF details + # + # * :soft_descriptor -- (Optional) Per transaction description of the payment that is passed to the consumer’s credit card statement. If the API request provides a value for the soft descriptor field, the full descriptor displayed on the buyer’s statement has the following format: + # + # <1 space> + # The soft descriptor can contain only the following characters: + # + # Alphanumeric characters + # - (dash) + # * (asterisk) + # . (period) + # {space} + # + def reference_transaction(money, options = {}) + requires!(options, :reference_id) + commit 'DoReferenceTransaction', build_reference_transaction_request(money, options) + end + + def transaction_details(transaction_id) + commit 'GetTransactionDetails', build_get_transaction_details(transaction_id) + end + + # ==== For full documentation see {PayPal API Reference}[https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_soap_r_TransactionSearch] + # ==== Options: + # * :payer -- (Optional) Search by the buyer’s email address. + # * :receipt_id -- (Optional) Search by the PayPal Account Optional receipt ID. + # * :receiver -- (Optional) Search by the receiver’s email address. If the merchant account has only one email address, this is the primary email. It can also be a non-primary email address. + # * :transaction_id -- (Optional) Search by the transaction ID. The returned results are from the merchant’s transaction records. + # * :invoice_id -- (Optional) Search by invoice identification key, as set by you for the original transaction. This field searches the records for items the merchant sells, not the items purchased. + # * :card_number -- (Optional) Search by credit card number, as set by you for the original transaction. This field searches the records for items the merchant sells, not the items purchased. + # * :auction_item_number -- (Optional) Search by auction item number of the purchased goods. + # * :transaction_class -- (Optional) Search by classification of transaction. Some kinds of possible classes of transactions are not searchable with this field. You cannot search for bank transfer withdrawals, for example. It is one of the following values: + # All – All transaction classifications + # Sent – Only payments sent + # Received – Only payments received + # MassPay – Only mass payments + # MoneyRequest – Only money requests + # FundsAdded – Only funds added to balance + # FundsWithdrawn – Only funds withdrawn from balance + # Referral – Only transactions involving referrals + # Fee – Only transactions involving fees + # Subscription – Only transactions involving subscriptions + # Dividend – Only transactions involving dividends + # Billpay – Only transactions involving BillPay Transactions + # Refund – Only transactions involving funds + # CurrencyConversions – Only transactions involving currency conversions + # BalanceTransfer – Only transactions involving balance transfers + # Reversal – Only transactions involving BillPay reversals + # Shipping – Only transactions involving UPS shipping fees + # BalanceAffecting – Only transactions that affect the account balance + # ECheck – Only transactions involving eCheck + # + # * :currency_code -- (Optional) Search by currency code. + # * :status -- (Optional) Search by transaction status. It is one of the following values: + # One of: + # Pending – The payment is pending. The specific reason the payment is pending is returned by the GetTransactionDetails API PendingReason field. + # Processing – The payment is being processed. + # Success – The payment has been completed and the funds have been added successfully to your account balance. + # Denied – You denied the payment. This happens only if the payment was previously pending. + # Reversed – A payment was reversed due to a chargeback or other type of reversal. The funds have been removed from your account balance and returned to the buyer. + # + def transaction_search(options) + requires!(options, :start_date) + commit 'TransactionSearch', build_transaction_search(options) + end + + # ==== Parameters: + # * :return_all_currencies -- Either '1' or '0' + # 0 – Return only the balance for the primary currency holding. + # 1 – Return the balance for each currency holding. + # + def balance(return_all_currencies = false) + clean_currency_argument = case return_all_currencies + when 1, '1' , true; '1' + else + '0' + end + commit 'GetBalance', build_get_balance(clean_currency_argument) + end + + # DoAuthorization takes the transaction_id returned when you call + # DoExpressCheckoutPayment with a PaymentAction of 'Order'. + # When you did that, you created an order authorization subject to settlement + # with PayPal DoAuthorization and DoCapture + # + # ==== Parameters: + # * :transaction_id -- The ID returned by DoExpressCheckoutPayment with a PaymentAction of 'Order'. + # * :money -- The amount of money to be authorized for this purchase. + # + def authorize_transaction(transaction_id, money, options = {}) + commit 'DoAuthorization', build_do_authorize(transaction_id, money, options) + end + + # The ManagePendingTransactionStatus API operation accepts or denys a + # pending transaction held by Fraud Management Filters. + # + # ==== Parameters: + # * :transaction_id -- The ID of the transaction held by Fraud Management Filters. + # * :action -- Either 'Accept' or 'Deny' + # + def manage_pending_transaction(transaction_id, action) + commit 'ManagePendingTransactionStatus', build_manage_pending_transaction_status(transaction_id, action) + end + + private + def build_request_wrapper(action, options = {}) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! action + 'Req', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! action + 'Request', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + if options[:request_details] + xml.tag! 'n2:' + action + 'RequestDetails' do + yield(xml) + end + else + yield(xml) + end + end + end + xml.target! + end + + def build_do_authorize(transaction_id, money, options = {}) + build_request_wrapper('DoAuthorization') do |xml| + xml.tag! 'TransactionID', transaction_id + xml.tag! 'Amount', amount(money), 'currencyID' => options[:currency] || currency(money) + end + end + + def build_reauthorize_request(money, authorization, options) + xml = Builder::XmlMarkup.new + + xml.tag! 'DoReauthorizationReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'DoReauthorizationRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'AuthorizationID', authorization + xml.tag! 'Amount', amount(money), 'currencyID' => options[:currency] || currency(money) + end + end + + xml.target! + end + + def build_capture_request(money, authorization, options) + xml = Builder::XmlMarkup.new + + xml.tag! 'DoCaptureReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'DoCaptureRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'AuthorizationID', authorization + xml.tag! 'Amount', amount(money), 'currencyID' => options[:currency] || currency(money) + xml.tag! 'CompleteType', options[:complete_type] || 'Complete' + xml.tag! 'InvoiceID', options[:order_id] unless options[:order_id].blank? + xml.tag! 'Note', options[:description] + end + end + + xml.target! + end + + def build_refund_request(money, identification, options) + xml = Builder::XmlMarkup.new + + xml.tag! 'RefundTransactionReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'RefundTransactionRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'TransactionID', identification + xml.tag! 'Amount', amount(money), 'currencyID' => (options[:currency] || currency(money)) if money.present? + xml.tag! 'RefundType', (options[:refund_type] || (money.present? ? 'Partial' : 'Full')) + xml.tag! 'Memo', options[:note] unless options[:note].blank? + end + end + + xml.target! + end + + def build_void_request(authorization, options) + xml = Builder::XmlMarkup.new + + xml.tag! 'DoVoidReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'DoVoidRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'AuthorizationID', authorization + xml.tag! 'Note', options[:description] + end + end + + xml.target! + end + + def build_mass_pay_request(*args) + default_options = args.last.is_a?(Hash) ? args.pop : {} + recipients = args.first.is_a?(Array) ? args : [args] + + xml = Builder::XmlMarkup.new + + xml.tag! 'MassPayReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'MassPayRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'EmailSubject', default_options[:subject] if default_options[:subject] + recipients.each do |money, recipient, options| + options ||= default_options + xml.tag! 'MassPayItem' do + xml.tag! 'ReceiverEmail', recipient + xml.tag! 'Amount', amount(money), 'currencyID' => options[:currency] || currency(money) + xml.tag! 'Note', options[:note] if options[:note] + xml.tag! 'UniqueId', options[:unique_id] if options[:unique_id] + end + end + end + end + + xml.target! + end + + def build_manage_pending_transaction_status(transaction_id, action) + build_request_wrapper('ManagePendingTransactionStatus') do |xml| + xml.tag! 'TransactionID', transaction_id + xml.tag! 'Action', action + end + end + + def build_reference_transaction_request(money, options) + opts = options.dup + opts[:ip_address] ||= opts[:ip] + currency_code = opts[:currency] || currency(money) + reference_transaction_optional_fields = %w{ n2:ReferenceID n2:PaymentAction + n2:PaymentType n2:IPAddress + n2:ReqConfirmShipping n2:MerchantSessionId + n2:ReturnFMFDetails n2:SoftDescriptor } + build_request_wrapper('DoReferenceTransaction', :request_details => true) do |xml| + add_optional_fields(xml, reference_transaction_optional_fields, opts) + add_payment_details(xml, money, currency_code, opts) + end + end + + def build_get_transaction_details(transaction_id) + build_request_wrapper('GetTransactionDetails') do |xml| + xml.tag! 'TransactionID', transaction_id + end + end + + def build_transaction_search(options) + currency_code = options[:currency_code] + currency_code ||= currency(options[:amount]) if options[:amount] + transaction_search_optional_fields = %w{ Payer ReceiptID Receiver + TransactionID InvoiceID CardNumber + AuctionItemNumber TransactionClass + CurrencyCode Status ProfileID } + build_request_wrapper('TransactionSearch') do |xml| + xml.tag! 'StartDate', date_to_iso(options[:start_date]) + xml.tag! 'EndDate', date_to_iso(options[:end_date]) unless options[:end_date].blank? + add_optional_fields(xml, transaction_search_optional_fields, options) + xml.tag! 'Amount', localized_amount(options[:amount], currency_code), 'currencyID' => currency_code unless options[:amount].blank? + end + end + + + def build_get_balance(return_all_currencies) + build_request_wrapper('GetBalance') do |xml| + xml.tag! 'ReturnAllCurrencies', return_all_currencies unless return_all_currencies.nil? + end + end + + def parse(action, xml) + legacy_hash = legacy_parse(action, xml) + xml = strip_attributes(xml) + hash = Hash.from_xml(xml) + hash = hash.fetch('Envelope').fetch('Body').fetch("#{action}Response") + hash = hash["#{action}ResponseDetails"] if hash["#{action}ResponseDetails"] + + legacy_hash.merge(hash) + rescue IndexError + legacy_hash.merge(hash['Envelope']['Body']) + end + + def strip_attributes(xml) + xml = REXML::Document.new(xml) + REXML::XPath.each(xml, '//SOAP-ENV:Envelope//*[@*]') do |el| + el.attributes.each_attribute { |a| a.remove } + end + xml.to_s + end + + def legacy_parse(action, xml) + response = {} + + error_messages = [] + error_codes = [] + + xml = REXML::Document.new(xml) + if root = REXML::XPath.first(xml, "//#{action}Response") + root.elements.each do |node| + case node.name + when 'Errors' + short_message = nil + long_message = nil + + node.elements.each do |child| + case child.name + when "LongMessage" + long_message = child.text unless child.text.blank? + when "ShortMessage" + short_message = child.text unless child.text.blank? + when "ErrorCode" + error_codes << child.text unless child.text.blank? + end + end + + if message = long_message || short_message + error_messages << message + end + else + legacy_parse_element(response, node) + end + end + response[:message] = error_messages.uniq.join(". ") unless error_messages.empty? + response[:error_codes] = error_codes.uniq.join(",") unless error_codes.empty? + elsif root = REXML::XPath.first(xml, "//SOAP-ENV:Fault") + legacy_parse_element(response, root) + response[:message] = "#{response[:faultcode]}: #{response[:faultstring]} - #{response[:detail]}" + end + + response + end + + def legacy_parse_element(response, node) + if node.has_elements? + node.elements.each{|e| legacy_parse_element(response, e) } + else + response[node.name.underscore.to_sym] = node.text + node.attributes.each do |k, v| + response["#{node.name.underscore}_#{k.underscore}".to_sym] = v if k == 'currencyID' + end + end + end + + def build_request(body) + xml = Builder::XmlMarkup.new + + xml.instruct! + xml.tag! 'env:Envelope', ENVELOPE_NAMESPACES do + xml.tag! 'env:Header' do + add_credentials(xml) unless @options[:headers] && @options[:headers]['X-PP-AUTHORIZATION'] + end + + xml.tag! 'env:Body' do + xml << body + end + end + xml.target! + end + + def add_credentials(xml) + xml.tag! 'RequesterCredentials', CREDENTIALS_NAMESPACES do + xml.tag! 'n1:Credentials' do + xml.tag! 'n1:Username', @options[:login] + xml.tag! 'n1:Password', @options[:password] + xml.tag! 'n1:Subject', @options[:subject] + xml.tag! 'n1:Signature', @options[:signature] unless @options[:signature].blank? + end + end + end + + def add_address(xml, element, address) + return if address.nil? + xml.tag! element do + xml.tag! 'n2:Name', address[:name] + xml.tag! 'n2:Street1', address[:address1] + xml.tag! 'n2:Street2', address[:address2] + xml.tag! 'n2:CityName', address[:city] + xml.tag! 'n2:StateOrProvince', address[:state].blank? ? 'N/A' : address[:state] + xml.tag! 'n2:Country', address[:country] + xml.tag! 'n2:Phone', address[:phone] unless address[:phone].blank? + xml.tag! 'n2:PostalCode', address[:zip] + end + end + + def add_payment_details_items_xml(xml, options, currency_code) + options[:items].each do |item| + xml.tag! 'n2:PaymentDetailsItem' do + xml.tag! 'n2:Name', item[:name] + xml.tag! 'n2:Number', item[:number] + xml.tag! 'n2:Quantity', item[:quantity] + if item[:amount] + xml.tag! 'n2:Amount', localized_amount(item[:amount], currency_code), 'currencyID' => currency_code + end + xml.tag! 'n2:Description', item[:description] + xml.tag! 'n2:ItemURL', item[:url] + xml.tag! 'n2:ItemCategory', item[:category] if item[:category] + end + end + end + + def add_payment_details(xml, money, currency_code, options = {}) + xml.tag! 'n2:PaymentDetails' do + xml.tag! 'n2:OrderTotal', localized_amount(money, currency_code), 'currencyID' => currency_code + + # All of the values must be included together and add up to the order total + if [:subtotal, :shipping, :handling, :tax].all?{ |o| options.has_key?(o) } + xml.tag! 'n2:ItemTotal', localized_amount(options[:subtotal], currency_code), 'currencyID' => currency_code + xml.tag! 'n2:ShippingTotal', localized_amount(options[:shipping], currency_code),'currencyID' => currency_code + xml.tag! 'n2:HandlingTotal', localized_amount(options[:handling], currency_code),'currencyID' => currency_code + xml.tag! 'n2:TaxTotal', localized_amount(options[:tax], currency_code), 'currencyID' => currency_code + end + + xml.tag! 'n2:InsuranceTotal', localized_amount(options[:insurance_total], currency_code),'currencyID' => currency_code unless options[:insurance_total].blank? + xml.tag! 'n2:ShippingDiscount', localized_amount(options[:shipping_discount], currency_code),'currencyID' => currency_code unless options[:shipping_discount].blank? + xml.tag! 'n2:InsuranceOptionOffered', options[:insurance_option_offered] if options.has_key?(:insurance_option_offered) + + xml.tag! 'n2:OrderDescription', options[:description] unless options[:description].blank? + + # Custom field Character length and limitations: 256 single-byte alphanumeric characters + xml.tag! 'n2:Custom', options[:custom] unless options[:custom].blank? + + xml.tag! 'n2:InvoiceID', (options[:order_id] || options[:invoice_id]) unless (options[:order_id] || options[:invoice_id]).blank? + xml.tag! 'n2:ButtonSource', application_id.to_s.slice(0,32) unless application_id.blank? + + # The notify URL applies only to DoExpressCheckoutPayment. + # This value is ignored when set in SetExpressCheckout or GetExpressCheckoutDetails + xml.tag! 'n2:NotifyURL', options[:notify_url] unless options[:notify_url].blank? + + add_address(xml, 'n2:ShipToAddress', options[:shipping_address]) unless options[:shipping_address].blank? + + add_payment_details_items_xml(xml, options, currency_code) unless options[:items].blank? + + add_express_only_payment_details(xml, options) if options[:express_request] + + # Any value other than Y – This is not a recurring transaction + # To pass Y in this field, you must have established a billing agreement with + # the buyer specifying the amount, frequency, and duration of the recurring payment. + # requires version 80.0 of the API + xml.tag! 'n2:Recurring', options[:recurring] unless options[:recurring].blank? + end + end + + def add_express_only_payment_details(xml, options = {}) + add_optional_fields(xml, + %w{n2:NoteText n2:SoftDescriptor + n2:TransactionId n2:AllowedPaymentMethodType + n2:PaymentRequestID n2:PaymentAction}, + options) + end + + def add_optional_fields(xml, optional_fields, options = {}) + optional_fields.each do |optional_text_field| + if optional_text_field =~ /(\w+:)(\w+)/ + ns = $1 + field = $2 + field_as_symbol = field.underscore.to_sym + else + ns = '' + field = optional_text_field + field_as_symbol = optional_text_field.underscore.to_sym + end + xml.tag! ns + field, options[field_as_symbol] unless options[field_as_symbol].blank? + end + xml + end + + def endpoint_url + URLS[test? ? :test : :live][@options[:signature].blank? ? :certificate : :signature] + end + + def commit(action, request) + response = parse(action, ssl_post(endpoint_url, build_request(request), @options[:headers])) + + build_response(successful?(response), message_from(response), response, + :test => test?, + :authorization => authorization_from(response), + :fraud_review => fraud_review?(response), + :avs_result => { :code => response[:avs_code] }, + :cvv_result => response[:cvv2_code] + ) + end + + def fraud_review?(response) + response[:error_codes] == FRAUD_REVIEW_CODE + end + + def authorization_from(response) + ( + response[:transaction_id] || + response[:authorization_id] || + response[:refund_transaction_id] || + response[:billing_agreement_id] + ) + end + + def successful?(response) + SUCCESS_CODES.include?(response[:ack]) + end + + def message_from(response) + response[:message] || response[:ack] + end + + def date_to_iso(date) + (date.is_a?(Date) ? date.to_time : date).utc.iso8601 + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb new file mode 100644 index 000000000..7cd7aadbb --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb @@ -0,0 +1,61 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaypalExpressResponse < Response + def email + info['Payer'] + end + + def info + (@params['PayerInfo']||{}) + end + + def details + (@params['PaymentDetails']||{}) + end + + def name + payer = (info['PayerName']||{}) + [payer['FirstName'], payer['MiddleName'], payer['LastName']].compact.join(' ') + end + + def token + @params['Token'] + end + + def payer_id + info['PayerID'] + end + + def payer_country + info['PayerCountry'] + end + + # PayPal returns a contact telephone number only if your Merchant account + # profile settings require that the buyer enter one. + def contact_phone + @params['ContactPhone'] + end + + def address + address = (details['ShipToAddress']||{}) + { 'name' => address['Name'], + 'company' => info['PayerBusiness'], + 'address1' => address['Street1'], + 'address2' => address['Street2'], + 'city' => address['CityName'], + 'state' => address['StateOrProvince'], + 'country' => address['Country'], + 'zip' => address['PostalCode'], + 'phone' => (contact_phone || address['Phone']) + } + end + + def shipping + shipping = (@params['UserSelectedOptions']||{}) + { 'amount' => shipping['ShippingOptionAmount'], + 'name' => shipping['ShippingOptionName'] + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb new file mode 100644 index 000000000..157037cb1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb @@ -0,0 +1,248 @@ +require File.dirname(__FILE__) + '/paypal_common_api' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # This module is included in both PaypalGateway and PaypalExpressGateway + module PaypalRecurringApi + PAYPAL_NAMESPACE = ActiveMerchant::Billing::PaypalCommonAPI::PAYPAL_NAMESPACE + API_VERSION = ActiveMerchant::Billing::PaypalCommonAPI::API_VERSION + EBAY_NAMESPACE = ActiveMerchant::Billing::PaypalCommonAPI::EBAY_NAMESPACE + # Create a recurring payment. + # + # This transaction creates a recurring payment profile + # ==== Parameters + # + # * money -- The amount to be charged to the customer at each interval as an Integer value in cents. + # * credit_card -- The CreditCard details for the transaction. + # * options -- A hash of parameters. + # + # ==== Options + # + # * :period -- [Day, Week, SemiMonth, Month, Year] default: Month + # * :frequency -- a number + # * :cycles -- Limit to certain # of cycles (OPTIONAL) + # * :start_date -- When does the charging starts (REQUIRED) + # * :description -- The description to appear in the profile (REQUIRED) + + def recurring(amount, credit_card, options = {}) + options[:credit_card] = credit_card + options[:amount] = amount + requires!(options, :description, :start_date, :period, :frequency, :amount) + commit 'CreateRecurringPaymentsProfile', build_create_profile_request(options) + end + + # Update a recurring payment's details. + # + # This transaction updates an existing Recurring Billing Profile + # and the subscription must have already been created previously + # by calling +recurring()+. The ability to change certain + # details about a recurring payment is dependent on transaction history + # and the type of plan you're subscribed with paypal. Web Payment Pro + # seems to have the ability to update the most field. + # + # ==== Parameters + # + # * options -- A hash of parameters. + # + # ==== Options + # + # * :profile_id -- A string containing the :profile_id + # of the recurring payment already in place for a given credit card. (REQUIRED) + def update_recurring(options={}) + requires!(options, :profile_id) + opts = options.dup + commit 'UpdateRecurringPaymentsProfile', build_change_profile_request(opts.delete(:profile_id), opts) + end + + # Cancel a recurring payment. + # + # This transaction cancels an existing recurring billing profile. Your account must have recurring billing enabled + # and the subscription must have already been created previously by calling recurring() + # + # ==== Parameters + # + # * profile_id -- A string containing the +profile_id+ of the + # recurring payment already in place for a given credit card. (REQUIRED) + # * options -- A hash with extra info ('note' for ex.) + def cancel_recurring(profile_id, options = {}) + raise_error_if_blank('profile_id', profile_id) + commit 'ManageRecurringPaymentsProfileStatus', build_manage_profile_request(profile_id, 'Cancel', options) + end + + # Get Subscription Status of a recurring payment profile. + # + # ==== Parameters + # + # * profile_id -- A string containing the +profile_id+ of the + # recurring payment already in place for a given credit card. (REQUIRED) + def status_recurring(profile_id) + raise_error_if_blank('profile_id', profile_id) + commit 'GetRecurringPaymentsProfileDetails', build_get_profile_details_request(profile_id) + end + + # Suspends a recurring payment profile. + # + # ==== Parameters + # + # * profile_id -- A string containing the +profile_id+ of the + # recurring payment already in place for a given credit card. (REQUIRED) + def suspend_recurring(profile_id, options = {}) + raise_error_if_blank('profile_id', profile_id) + commit 'ManageRecurringPaymentsProfileStatus', build_manage_profile_request(profile_id, 'Suspend', options) + end + + # Reactivates a suspended recurring payment profile. + # + # ==== Parameters + # + # * profile_id -- A string containing the +profile_id+ of the + # recurring payment already in place for a given credit card. (REQUIRED) + def reactivate_recurring(profile_id, options = {}) + raise_error_if_blank('profile_id', profile_id) +commit 'ManageRecurringPaymentsProfileStatus', build_manage_profile_request(profile_id, 'Reactivate', options) + end + + # Bills outstanding amount to a recurring payment profile. + # + # ==== Parameters + # + # * profile_id -- A string containing the +profile_id+ of the + # recurring payment already in place for a given credit card. (REQUIRED) + def bill_outstanding_amount(profile_id, options = {}) + raise_error_if_blank('profile_id', profile_id) + commit 'BillOutstandingAmount', build_bill_outstanding_amount(profile_id, options) + end + + private + def raise_error_if_blank(field_name, field) + raise ArgumentError.new("Missing required parameter: #{field_name}") if field.blank? + end + def build_create_profile_request(options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'CreateRecurringPaymentsProfileReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'CreateRecurringPaymentsProfileRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:CreateRecurringPaymentsProfileRequestDetails' do + xml.tag! 'Token', options[:token] unless options[:token].blank? + if options[:credit_card] + add_credit_card(xml, options[:credit_card], (options[:billing_address] || options[:address]), options) + end + xml.tag! 'n2:RecurringPaymentsProfileDetails' do + xml.tag! 'n2:BillingStartDate', (options[:start_date].is_a?(Date) ? options[:start_date].to_time : options[:start_date]).utc.iso8601 + xml.tag! 'n2:ProfileReference', options[:profile_reference] unless options[:profile_reference].blank? + end + xml.tag! 'n2:ScheduleDetails' do + xml.tag! 'n2:Description', options[:description] + xml.tag! 'n2:PaymentPeriod' do + xml.tag! 'n2:BillingPeriod', options[:period] || 'Month' + xml.tag! 'n2:BillingFrequency', options[:frequency] + xml.tag! 'n2:TotalBillingCycles', options[:total_billing_cycles] unless options[:total_billing_cycles].blank? + xml.tag! 'n2:Amount', amount(options[:amount]), 'currencyID' => options[:currency] || 'USD' + xml.tag! 'n2:TaxAmount', amount(options[:tax_amount] || 0), 'currencyID' => options[:currency] || 'USD' unless options[:tax_amount].blank? + xml.tag! 'n2:ShippingAmount', amount(options[:shipping_amount] || 0), 'currencyID' => options[:currency] || 'USD' unless options[:shipping_amount].blank? + end + if !options[:trial_amount].blank? + xml.tag! 'n2:TrialPeriod' do + xml.tag! 'n2:BillingPeriod', options[:trial_period] || 'Month' + xml.tag! 'n2:BillingFrequency', options[:trial_frequency] + xml.tag! 'n2:TotalBillingCycles', options[:trial_cycles] || 1 + xml.tag! 'n2:Amount', amount(options[:trial_amount]), 'currencyID' => options[:currency] || 'USD' + xml.tag! 'n2:TaxAmount', amount(options[:trial_tax_amount] || 0), 'currencyID' => options[:currency] || 'USD' unless options[:trial_tax_amount].blank? + xml.tag! 'n2:ShippingAmount', amount(options[:trial_shipping_amount] || 0), 'currencyID' => options[:currency] || 'USD' unless options[:trial_shipping_amount].blank? + end + end + if !options[:initial_amount].blank? + xml.tag! 'n2:ActivationDetails' do + xml.tag! 'n2:InitialAmount', amount(options[:initial_amount]), 'currencyID' => options[:currency] || 'USD' + xml.tag! 'n2:FailedInitialAmountAction', options[:continue_on_failure] ? 'ContinueOnFailure' : 'CancelOnFailure' + end + end + xml.tag! 'n2:MaxFailedPayments', options[:max_failed_payments] unless options[:max_failed_payments].blank? + xml.tag! 'n2:AutoBillOutstandingAmount', options[:auto_bill_outstanding] ? 'AddToNextBilling' : 'NoAutoBill' + end + end + end + end + xml.target! + end + + def build_get_profile_details_request(profile_id) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'GetRecurringPaymentsProfileDetailsReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'GetRecurringPaymentsProfileDetailsRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'ProfileID', profile_id + end + end + xml.target! + end + + def build_change_profile_request(profile_id, options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'UpdateRecurringPaymentsProfileReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'UpdateRecurringPaymentsProfileRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:UpdateRecurringPaymentsProfileRequestDetails' do + xml.tag! 'ProfileID', profile_id + if options[:credit_card] + add_credit_card(xml, options[:credit_card], options[:address], options) + end + xml.tag! 'n2:Note', options[:note] unless options[:note].blank? + xml.tag! 'n2:Description', options[:description] unless options[:description].blank? + xml.tag! 'n2:ProfileReference', options[:reference] unless options[:reference].blank? + xml.tag! 'n2:AdditionalBillingCycles', options[:additional_billing_cycles] unless options[:additional_billing_cycles].blank? + xml.tag! 'n2:MaxFailedPayments', options[:max_failed_payments] unless options[:max_failed_payments].blank? + xml.tag! 'n2:AutoBillOutstandingAmount', options[:auto_bill_outstanding] ? 'AddToNextBilling' : 'NoAutoBill' + if options.has_key?(:amount) + xml.tag! 'n2:Amount', amount(options[:amount]), 'currencyID' => options[:currency] || 'USD' + end + if options.has_key?(:tax_amount) + xml.tag! 'n2:TaxAmount', amount(options[:tax_amount] || 0), 'currencyID' => options[:currency] || 'USD' + end + if options.has_key?(:start_date) + xml.tag! 'n2:BillingStartDate', (options[:start_date].is_a?(Date) ? options[:start_date].to_time : options[:start_date]).utc.iso8601 + end + if options.has_key?(:outstanding_balance) + xml.tag! 'n2:OutstandingBalance', amount(options[:outstanding_balance]), 'currencyID' => options[:currency] || 'USD' + end + end + end + end + xml.target! + end + + def build_manage_profile_request(profile_id, action, options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'ManageRecurringPaymentsProfileStatusReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'ManageRecurringPaymentsProfileStatusRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:ManageRecurringPaymentsProfileStatusRequestDetails' do + xml.tag! 'ProfileID', profile_id + xml.tag! 'n2:Action', action + xml.tag! 'n2:Note', options[:note] unless options[:note].blank? + end + end + end + xml.target! + end + + def build_bill_outstanding_amount(profile_id, options) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'BillOutstandingAmountReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'BillOutstandingAmountRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:BillOutstandingAmountRequestDetails' do + xml.tag! 'ProfileID', profile_id + if options.has_key?(:amount) + xml.tag! 'n2:Amount', amount(options[:amount]), 'currencyID' => options[:currency] || 'USD' + end + xml.tag! 'n2:Note', options[:note] unless options[:note].blank? + end + end + end + xml.target! + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_bogus.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_bogus.rb new file mode 100644 index 000000000..79f7dcefa --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_bogus.rb @@ -0,0 +1,53 @@ +require File.dirname(__FILE__) + '/paypal/paypal_common_api' +require File.dirname(__FILE__) + '/paypal/paypal_express_response' +require File.dirname(__FILE__) + '/paypal_express_common' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaypalBogusGateway < BogusGateway + + REDIRECT_URL = "https://bogus.paypal.com" + + def setup_authorization money, options = {} + requires!(options, :return_url, :cancel_return_url) + + PaypalExpressResponse.new true, SUCCESS_MESSAGE, { Token: AUTHORIZATION }, test: true + end + + def setup_purchase money, options = {} + requires!(options, :return_url, :cancel_return_url) + + PaypalExpressResponse.new true, SUCCESS_MESSAGE, { Token: AUTHORIZATION }, test: true + end + + def authorize money, options = {} + requires!(options, :token, :payer_id) + + case normalize(options[:token]) + when '1' + PaypalExpressResponse.new false, FAILURE_MESSAGE, {:authorized_amount => money}, :test => true + else + PaypalExpressResponse.new true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION + end + end + + def purchase money, options = {} + requires!(options, :token, :payer_id) + + case normalize(options[:token]) + when '1' + PaypalExpressResponse.new false, FAILURE_MESSAGE, {:amount => money}, :test => true + else + PaypalExpressResponse.new true, SUCCESS_MESSAGE, {:amount => money}, :test => true, :authorization => AUTHORIZATION + end + end + + def redirect_url_for token + REDIRECT_URL + end + + end + end +end + + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_ca.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_ca.rb new file mode 100644 index 000000000..69c94ec3c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_ca.rb @@ -0,0 +1,13 @@ +require File.dirname(__FILE__) + '/paypal' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # The PayPal gateway for PayPal Website Payments Pro Canada only supports Visa and MasterCard + class PaypalCaGateway < PaypalGateway + self.supported_cardtypes = [:visa, :master] + self.supported_countries = ['CA'] + self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside' + self.display_name = 'PayPal Website Payments Pro (CA)' + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_digital_goods.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_digital_goods.rb new file mode 100644 index 000000000..ce5824cea --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_digital_goods.rb @@ -0,0 +1,43 @@ +require File.dirname(__FILE__) + '/paypal/paypal_common_api' +require File.dirname(__FILE__) + '/paypal/paypal_express_response' +require File.dirname(__FILE__) + '/paypal_express_common' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaypalDigitalGoodsGateway < PaypalExpressGateway + self.test_redirect_url = 'https://www.sandbox.paypal.com/incontext' + self.live_redirect_url = 'https://www.paypal.com/incontext' + + self.supported_countries = %w(AU CA CN FI GB ID IN IT MY NO NZ PH PL SE SG TH VN) + self.homepage_url = 'https://www.x.com/community/ppx/xspaces/digital_goods' + self.display_name = 'PayPal Express Checkout for Digital Goods' + + def redirect_url_for(token, options = {}) + "#{redirect_url}?token=#{token}&useraction=commit" + end + + # GATEWAY.setup_purchase(100, + # :ip => "127.0.0.1", + # :description => "Test Title", + # :return_url => "http://return.url", + # :cancel_return_url => "http://cancel.url", + # :items => [ { :name => "Charge", + # :number => "1", + # :quantity => "1", + # :amount => 100, + # :description => "Description", + # :category => "Digital" } ] ) + def build_setup_request(action, money, options) + requires!(options, :items) + raise ArgumentError, "Must include at least 1 Item" unless options[:items].length > 0 + options[:items].each do |item| + requires!(item, :name, :number, :quantity, :amount, :description, :category) + raise ArgumentError, "Each of the items must have the category 'Digital'" unless item[:category] == 'Digital' + end + + super + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express.rb new file mode 100644 index 000000000..4657a6f8b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express.rb @@ -0,0 +1,222 @@ +require File.dirname(__FILE__) + '/paypal/paypal_common_api' +require File.dirname(__FILE__) + '/paypal/paypal_express_response' +require File.dirname(__FILE__) + '/paypal/paypal_recurring_api' +require File.dirname(__FILE__) + '/paypal_express_common' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaypalExpressGateway < Gateway + include PaypalCommonAPI + include PaypalExpressCommon + include PaypalRecurringApi + + NON_STANDARD_LOCALE_CODES = { + 'DK' => 'da_DK', + 'IL' => 'he_IL', + 'ID' => 'id_ID', + 'JP' => 'jp_JP', + 'NO' => 'no_NO', + 'BR' => 'pt_BR', + 'RU' => 'ru_RU', + 'SE' => 'sv_SE', + 'TH' => 'th_TH', + 'TR' => 'tr_TR', + 'CN' => 'zh_CN', + 'HK' => 'zh_HK', + 'TW' => 'zh_TW' + } + + self.test_redirect_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr' + self.supported_countries = ['US'] + self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside' + self.display_name = 'PayPal Express Checkout' + + def setup_authorization(money, options = {}) + requires!(options, :return_url, :cancel_return_url) + + commit 'SetExpressCheckout', build_setup_request('Authorization', money, options) + end + + def setup_purchase(money, options = {}) + requires!(options, :return_url, :cancel_return_url) + + commit 'SetExpressCheckout', build_setup_request('Sale', money, options) + end + + def details_for(token) + commit 'GetExpressCheckoutDetails', build_get_details_request(token) + end + + def authorize(money, options = {}) + requires!(options, :token, :payer_id) + + commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Authorization', money, options) + end + + def purchase(money, options = {}) + requires!(options, :token, :payer_id) + + commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Sale', money, options) + end + + def store(token, options = {}) + commit 'CreateBillingAgreement', build_create_billing_agreement_request(token, options) + end + + def authorize_reference_transaction(money, options = {}) + requires!(options, :reference_id, :payment_type, :invoice_id, :description, :ip) + + commit 'DoReferenceTransaction', build_reference_transaction_request('Authorization', money, options) + end + + def reference_transaction(money, options = {}) + requires!(options, :reference_id) + + commit 'DoReferenceTransaction', build_reference_transaction_request('Sale', money, options) + end + + private + def build_get_details_request(token) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'GetExpressCheckoutDetailsReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'GetExpressCheckoutDetailsRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'Token', token + end + end + + xml.target! + end + + def build_sale_or_authorization_request(action, money, options) + currency_code = options[:currency] || currency(money) + + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'DoExpressCheckoutPaymentReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'DoExpressCheckoutPaymentRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:DoExpressCheckoutPaymentRequestDetails' do + xml.tag! 'n2:PaymentAction', action + xml.tag! 'n2:Token', options[:token] + xml.tag! 'n2:PayerID', options[:payer_id] + add_payment_details(xml, money, currency_code, options) + end + end + end + + xml.target! + end + + def build_setup_request(action, money, options) + currency_code = options[:currency] || currency(money) + options[:payment_action] = action + options[:express_request] = true + options[:shipping_address] ||= options[:address] + + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'SetExpressCheckoutReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'SetExpressCheckoutRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:SetExpressCheckoutRequestDetails' do + xml.tag! 'n2:ReturnURL', options[:return_url] + xml.tag! 'n2:CancelURL', options[:cancel_return_url] + if options[:max_amount] + xml.tag! 'n2:MaxAmount', localized_amount(options[:max_amount], currency_code), 'currencyID' => currency_code + end + xml.tag! 'n2:NoShipping', options[:no_shipping] ? '1' : '0' + xml.tag! 'n2:AddressOverride', options[:address_override] ? '1' : '0' + xml.tag! 'n2:LocaleCode', locale_code(options[:locale]) unless options[:locale].blank? + xml.tag! 'n2:BrandName', options[:brand_name] unless options[:brand_name].blank? + # Customization of the payment page + xml.tag! 'n2:PageStyle', options[:page_style] unless options[:page_style].blank? + xml.tag! 'n2:cpp-header-image', options[:header_image] unless options[:header_image].blank? + xml.tag! 'n2:cpp-header-border-color', options[:header_border_color] unless options[:header_border_color].blank? + xml.tag! 'n2:cpp-header-back-color', options[:header_background_color] unless options[:header_background_color].blank? + xml.tag! 'n2:cpp-payflow-color', options[:background_color] unless options[:background_color].blank? + if options[:allow_guest_checkout] + xml.tag! 'n2:SolutionType', 'Sole' + xml.tag! 'n2:LandingPage', options[:landing_page] || 'Billing' + end + xml.tag! 'n2:BuyerEmail', options[:email] unless options[:email].blank? + + if options[:billing_agreement] + xml.tag! 'n2:BillingAgreementDetails' do + xml.tag! 'n2:BillingType', options[:billing_agreement][:type] + xml.tag! 'n2:BillingAgreementDescription', options[:billing_agreement][:description] + xml.tag! 'n2:PaymentType', options[:billing_agreement][:payment_type] || 'InstantOnly' + end + end + + if !options[:allow_note].nil? + xml.tag! 'n2:AllowNote', options[:allow_note] ? '1' : '0' + end + xml.tag! 'n2:CallbackURL', options[:callback_url] unless options[:callback_url].blank? + + add_payment_details(xml, money, currency_code, options) + if options[:shipping_options] + options[:shipping_options].each do |shipping_option| + xml.tag! 'n2:FlatRateShippingOptions' do + xml.tag! 'n2:ShippingOptionIsDefault', shipping_option[:default] + xml.tag! 'n2:ShippingOptionAmount', localized_amount(shipping_option[:amount], currency_code), 'currencyID' => currency_code + xml.tag! 'n2:ShippingOptionName', shipping_option[:name] + end + end + end + + xml.tag! 'n2:CallbackTimeout', options[:callback_timeout] unless options[:callback_timeout].blank? + xml.tag! 'n2:CallbackVersion', options[:callback_version] unless options[:callback_version].blank? + + if options.has_key?(:allow_buyer_optin) + xml.tag! 'n2:BuyerEmailOptInEnable', (options[:allow_buyer_optin] ? '1' : '0') + end + end + end + end + + xml.target! + end + + def build_create_billing_agreement_request(token, options = {}) + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'CreateBillingAgreementReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'CreateBillingAgreementRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'Token', token + end + end + + xml.target! + end + + def build_reference_transaction_request(action, money, options) + currency_code = options[:currency] || currency(money) + + # I am not sure why it's set like this for express gateway + # but I don't want to break the existing behavior + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'DoReferenceTransactionReq', 'xmlns' => PAYPAL_NAMESPACE do + xml.tag! 'DoReferenceTransactionRequest', 'xmlns:n2' => EBAY_NAMESPACE do + xml.tag! 'n2:Version', API_VERSION + xml.tag! 'n2:DoReferenceTransactionRequestDetails' do + xml.tag! 'n2:ReferenceID', options[:reference_id] + xml.tag! 'n2:PaymentAction', action + xml.tag! 'n2:PaymentType', options[:payment_type] || 'Any' + add_payment_details(xml, money, currency_code, options) + xml.tag! 'n2:IPAddress', options[:ip] + end + end + end + + xml.target! + end + + def build_response(success, message, response, options = {}) + PaypalExpressResponse.new(success, message, response, options) + end + + def locale_code(country_code) + NON_STANDARD_LOCALE_CODES[country_code] || country_code + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express_common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express_common.rb new file mode 100644 index 000000000..47cf830d3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paypal_express_common.rb @@ -0,0 +1,30 @@ +module ActiveMerchant + module Billing + module PaypalExpressCommon + def self.included(base) + if base.respond_to?(:class_attribute) + base.class_attribute :test_redirect_url + base.class_attribute :live_redirect_url + else + base.class_inheritable_accessor :test_redirect_url + base.class_inheritable_accessor :live_redirect_url + end + base.live_redirect_url = 'https://www.paypal.com/cgibin/webscr' + end + + def redirect_url + test? ? test_redirect_url : live_redirect_url + end + + def redirect_url_for(token, options = {}) + options = {:review => true, :mobile => false}.update(options) + + cmd = options[:mobile] ? '_express-checkout-mobile' : '_express-checkout' + url = "#{redirect_url}?cmd=#{cmd}&token=#{token}" + url += '&useraction=commit' unless options[:review] + + url + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paystation.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paystation.rb new file mode 100644 index 000000000..af8518101 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/paystation.rb @@ -0,0 +1,199 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PaystationGateway < Gateway + + self.live_url = self.test_url = "https://www.paystation.co.nz/direct/paystation.dll" + + # an "error code" of "0" means "No error - transaction successful" + SUCCESSFUL_RESPONSE_CODE = '0' + + # an "error code" of "34" means "Future Payment Stored OK" + SUCCESSFUL_FUTURE_PAYMENT = '34' + + # TODO: check this with paystation + self.supported_countries = ['NZ'] + + # TODO: check this with paystation (amex and diners need to be enabled) + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club ] + + self.homepage_url = 'http://paystation.co.nz' + self.display_name = 'Paystation' + + self.default_currency = 'NZD' + self.money_format = :cents + + def initialize(options = {}) + requires!(options, :paystation_id, :gateway_id) + super + end + + def authorize(money, credit_card, options = {}) + post = new_request + + add_invoice(post, options) + add_amount(post, money, options) + + add_credit_card(post, credit_card) + + add_authorize_flag(post, options) + + commit(post) + end + + def capture(money, authorization_token, options = {}) + post = new_request + + add_invoice(post, options) + add_amount(post, money, options) + + add_authorization_token(post, authorization_token, options[:credit_card_verification]) + + commit(post) + end + + def purchase(money, payment_source, options = {}) + post = new_request + + add_invoice(post, options) + add_amount(post, money, options) + + if payment_source.is_a?(String) + add_token(post, payment_source) + else + add_credit_card(post, payment_source) + end + + add_customer_data(post, options) if options.has_key?(:customer) + + commit(post) + end + + def store(credit_card, options = {}) + post = new_request + + add_invoice(post, options) + add_credit_card(post, credit_card) + store_credit_card(post, options) + + commit(post) + end + + private + + def new_request + { + :pi => @options[:paystation_id], # paystation account id + :gi => @options[:gateway_id], # paystation gateway id + "2p" => "t", # two-party transaction type + :nr => "t", # -- redirect?? + :df => "yymm" # date format: optional sometimes, required others + } + end + + def add_customer_data(post, options) + post[:mc] = options[:customer] + end + + def add_invoice(post, options) + requires!(options, :order_id) + + post[:ms] = options[:order_id] # "Merchant Session", must be unique per request + post[:mo] = options[:invoice] # "Order Details", displayed in Paystation Admin + post[:mr] = options[:description] # "Merchant Reference Code", seen from Paystation Admin + end + + def add_credit_card(post, credit_card) + + post[:cn] = credit_card.number + post[:ct] = credit_card.brand + post[:ex] = format_date(credit_card.month, credit_card.year) + post[:cc] = credit_card.verification_value if credit_card.verification_value? + + end + + # bill a token (stored via "store") rather than a Credit Card + def add_token(post, token) + post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing + post[:ft] = token + end + + def store_credit_card(post, options) + + post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing + post[:fs] = "t" # tells paystation to store right now, not bill + post[:ft] = options[:token] if options[:token] # specify a token to use that, or let Paystation generate one + + end + + def add_authorize_flag(post, options) + post[:pa] = "t" # tells Paystation that this is a pre-auth authorisation payment (account must be in pre-auth mode) + end + + def add_authorization_token(post, auth_token, verification_value = nil) + post[:cp] = "t" # Capture Payment flag – tells Paystation this transaction should be treated as a capture payment + post[:cx] = auth_token + post[:cc] = verification_value + end + + def add_amount(post, money, options) + + post[:am] = amount(money) + post[:cu] = options[:currency] || currency(money) + + end + + def parse(xml_response) + response = {} + + xml = REXML::Document.new(xml_response) + + # for normal payments, the root node is + # for "future payments", it's + xml.elements.each("#{xml.root.name}/*") do |element| + response[element.name.underscore.to_sym] = element.text + end + + response + end + + def commit(post) + + post[:tm] = "T" if test? # test mode + + pstn_prefix_params = post.collect { |key, value| "pstn_#{key}=#{CGI.escape(value.to_s)}" }.join("&") + + # need include paystation param as "initiator flag for payment engine" + data = ssl_post(self.live_url, "#{pstn_prefix_params}&paystation=_empty") + response = parse(data) + message = message_from(response) + + PaystationResponse.new(success?(response), message, response, + :test => (response[:tm] && response[:tm].downcase == "t"), + :authorization => response[:paystation_transaction_id] + ) + end + + def success?(response) + (response[:ec] == SUCCESSFUL_RESPONSE_CODE) || (response[:ec] == SUCCESSFUL_FUTURE_PAYMENT) + end + + def message_from(response) + response[:em] + end + + def format_date(month, year) + "#{format(year, :two_digits)}#{format(month, :two_digits)}" + end + + end + + class PaystationResponse < Response + # add a method to response so we can easily get the token + # for Validate transactions + def token + @params["future_payment_token"] + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payway.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payway.rb new file mode 100644 index 000000000..10777f7b0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/payway.rb @@ -0,0 +1,207 @@ +module ActiveMerchant + module Billing + class PaywayGateway < Gateway + self.live_url = self.test_url = 'https://ccapi.client.qvalent.com/payway/ccapi' + + self.supported_countries = [ 'AU' ] + self.supported_cardtypes = [ :visa, :master, :diners_club, :american_express, :bankcard ] + self.display_name = 'Pay Way' + self.homepage_url = 'http://www.payway.com.au' + self.default_currency = 'AUD' + self.money_format = :cents + + SUMMARY_CODES = { + '0' => 'Approved', + '1' => 'Declined', + '2' => 'Erred', + '3' => 'Rejected' + } + + RESPONSE_CODES= { + '00' => 'Completed Successfully', + '01' => 'Refer to card issuer', + '03' => 'Invalid merchant', + '04' => 'Pick-up card', + '05' => 'Do not honour', + '08' => 'Honour only with identification', + '12' => 'Invalid transaction', + '13' => 'Invalid amount', + '14' => 'Invalid card number (no such number)', + '30' => 'Format error', + '36' => 'Restricted card', + '41' => 'Lost card', + '42' => 'No universal card', + '43' => 'Stolen card', + '51' => 'Not sufficient funds', + '54' => 'Expired card', + '61' => 'Exceeds withdrawal amount limits', + '62' => 'Restricted card', + '65' => 'Exceeds withdrawal frequency limit', + '91' => 'Issuer or switch is inoperative', + '92' => 'Financial institution or intermediate network facility cannot be found for routing', + '94' => 'Duplicate transmission', + 'Q1' => 'Unknown Buyer', + 'Q2' => 'Transaction Pending', + 'Q3' => 'Payment Gateway Connection Error', + 'Q4' => 'Payment Gateway Unavailable', + 'Q5' => 'Invalid Transaction', + 'Q6' => 'Duplicate Transaction - requery to determine status', + 'QA' => 'Invalid parameters or Initialisation failed', + 'QB' => 'Order type not currently supported', + 'QC' => 'Invalid Order Type', + 'QD' => 'Invalid Payment Amount - Payment amount less than minimum/exceeds maximum allowed limit', + 'QE' => 'Internal Error', + 'QF' => 'Transaction Failed', + 'QG' => 'Unknown Customer Order Number', + 'QH' => 'Unknown Customer Username or Password', + 'QI' => 'Transaction incomplete - contact Westpac to confirm reconciliation', + 'QJ' => 'Invalid Client Certificate', + 'QK' => 'Unknown Customer Merchant', + 'QL' => 'Business Group not configured for customer', + 'QM' => 'Payment Instrument not configured for customer', + 'QN' => 'Configuration Error', + 'QO' => 'Missing Payment Instrument', + 'QP' => 'Missing Supplier Account', + 'QQ' => 'Invalid Credit Card Verification Number', + 'QR' => 'Transaction Retry', + 'QS' => 'Transaction Successful', + 'QT' => 'Invalid currency', + 'QU' => 'Unknown Customer IP Address', + 'QV' => 'Invalid Original Order Number specified for Refund, Refund amount exceeds capture amount, or Previous capture was not approved', + 'QW' => 'Invalid Reference Number', + 'QX' => 'Network Error has occurred', + 'QY' => 'Card Type Not Accepted', + 'QZ' => 'Zero value transaction' + } + + TRANSACTIONS = { + :authorize => 'preauth', + :purchase => 'capture', + :capture => 'captureWithoutAuth', + :status => 'query', + :refund => 'refund', + :store => 'registerAccount' + } + + def initialize(options={}) + @options = options + + @options[:merchant] ||= 'TEST' if test? + requires!(options, :username, :password, :merchant, :pem) + + @options[:eci] ||= 'SSL' + end + + def authorize(amount, payment_method, options={}) + requires!(options, :order_id) + + post = {} + add_payment_method(post, payment_method) + add_order(post, amount, options) + commit(:authorize, post) + end + + def capture(amount, authorization, options={}) + requires!(options, :order_id) + + post = {} + add_reference(post, authorization) + add_order(post, amount, options) + commit(:capture, post) + end + + def purchase(amount, payment_method, options={}) + requires!(options, :order_id) + + post = {} + add_payment_method(post, payment_method) + add_order(post, amount, options) + commit(:purchase, post) + end + + def refund(amount, authorization, options={}) + requires!(options, :order_id) + + post = {} + add_reference(post, authorization) + add_order(post, amount, options) + commit(:refund, post) + end + + def store(credit_card, options={}) + requires!(options, :billing_id) + + post = {} + add_payment_method(post, credit_card) + add_payment_method(post, options[:billing_id]) + commit(:store, post) + end + + def status(options={}) + requires!(options, :order_id) + + commit(:status, 'customer.orderNumber' => options[:order_id]) + end + + private + + def add_payment_method(post, payment_method) + if payment_method.respond_to?(:number) + post['card.cardHolderName'] = "#{payment_method.first_name} #{payment_method.last_name}" + post['card.PAN'] = payment_method.number + post['card.CVN'] = payment_method.verification_value + post['card.expiryYear'] = payment_method.year.to_s[-2,2] + post['card.expiryMonth'] = sprintf('%02d', payment_method.month) + else + post['customer.customerReferenceNumber'] = payment_method + end + end + + def add_reference(post, reference) + post['customer.originalOrderNumber'] = reference + end + + def add_order(post, amount, options) + post['order.ECI'] = @options[:eci] + post['order.amount'] = amount + post['card.currency'] = (options[:currency] || currency(amount)) + post['customer.orderNumber'] = options[:order_id][0...20] + end + + def add_auth(post) + post['customer.username'] = @options[:username] + post['customer.password'] = @options[:password] + post['customer.merchant'] = @options[:merchant] + end + + # Creates the request and returns the summarized result + def commit(action, post) + add_auth(post) + post.merge!('order.type' => TRANSACTIONS[action]) + + request = post.map { |k, v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&") + response = ssl_post(self.live_url, request) + + params = {} + CGI.parse(response).each_pair do |key, value| + actual_key = key.split(".").last + params[actual_key.underscore.to_sym] = value[0] + end + + message = "#{SUMMARY_CODES[params[:summary_code]]} - #{RESPONSE_CODES[params[:response_code]]}" + + success = (params[:summary_code] ? (params[:summary_code] == "0") : (params[:response_code] == "00")) + + Response.new(success, message, params, + :test => (@options[:merchant].to_s == "TEST"), + :authorization => post[:order_number] + ) + rescue ActiveMerchant::ResponseError => e + raise unless e.response.code == '403' + return Response.new(false, "Invalid credentials", {}, :test => test?) + rescue ActiveMerchant::ClientCertificateError + return Response.new(false, "Invalid certificate", {}, :test => test?) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pin.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pin.rb new file mode 100644 index 000000000..8e1c2ffd0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/pin.rb @@ -0,0 +1,165 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class PinGateway < Gateway + self.test_url = 'https://test-api.pin.net.au/1' + self.live_url = 'https://api.pin.net.au/1' + + self.default_currency = 'AUD' + self.money_format = :cents + self.supported_countries = ['AU'] + self.supported_cardtypes = [:visa, :master] + self.homepage_url = 'http://www.pin.net.au/' + self.display_name = 'Pin' + + def initialize(options = {}) + requires!(options, :api_key) + super + end + + # Create a charge using a credit card, card token or customer token + # + # To charge a credit card: purchase([money], [creditcard hash], ...) + # To charge a customer: purchase([money], [token], ...) + def purchase(money, creditcard, options = {}) + post = {} + + add_amount(post, money, options) + add_customer_data(post, options) + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, creditcard, options) + + commit('charges', post, options) + end + + # Create a customer and associated credit card. The token that is returned + # can be used instead of a credit card parameter in the purchase method + def store(creditcard, options = {}) + post = {} + + add_creditcard(post, creditcard) + add_customer_data(post, options) + add_address(post, creditcard, options) + commit('customers', post, options) + end + + # Refund a transaction, note that the money attribute is ignored at the + # moment as the API does not support partial refunds. The parameter is + # kept for compatibility reasons + def refund(money, token, options = {}) + commit("charges/#{CGI.escape(token)}/refunds", { :amount => amount(money) }, options) + end + + private + def add_amount(post, money, options) + post[:amount] = amount(money) + post[:currency] = (options[:currency] || currency(money)) + post[:currency] = post[:currency].upcase if post[:currency] + end + + def add_customer_data(post, options) + post[:email] = options[:email] + post[:ip_address] = options[:ip] + end + + def add_address(post, creditcard, options) + return if creditcard.kind_of?(String) + address = (options[:billing_address] || options[:address]) + return unless address + + post[:card] ||= {} + post[:card].merge!( + :address_line1 => address[:address1], + :address_city => address[:city], + :address_postcode => address[:zip], + :address_state => address[:state], + :address_country => address[:country] + ) + end + + def add_invoice(post, options) + post[:description] = options[:description] || "Active Merchant Purchase" + end + + def add_creditcard(post, creditcard) + if creditcard.respond_to?(:number) + post[:card] ||= {} + + post[:card].merge!( + :number => creditcard.number, + :expiry_month => creditcard.month, + :expiry_year => creditcard.year, + :cvc => creditcard.verification_value, + :name => "#{creditcard.first_name} #{creditcard.last_name}" + ) + elsif creditcard.kind_of?(String) + if creditcard =~ /^card_/ + post[:card_token] = creditcard + else + post[:customer_token] = creditcard + end + end + end + + def headers(params = {}) + result = { + "Content-Type" => "application/json", + "Authorization" => "Basic #{Base64.strict_encode64(options[:api_key] + ':').strip}" + } + + result['X-Partner-Key'] = params[:partner_key] if params[:partner_key] + result['X-Safe-Card'] = params[:safe_card] if params[:safe_card] + result + end + + def commit(action, params, options) + url = "#{test? ? test_url : live_url}/#{action}" + + begin + body = parse(ssl_post(url, post_data(params), headers(options))) + rescue ResponseError => e + body = parse(e.response.body) + end + + if body["response"] + success_response(body) + elsif body["error"] + error_response(body) + end + end + + def success_response(body) + response = body["response"] + Response.new( + true, + response['status_message'], + body, + :authorization => token(response), + :test => test? + ) + end + + def error_response(body) + Response.new( + false, + body['error_description'], + body, + :authorization => nil, + :test => test? + ) + end + + def token(response) + response['token'] + end + + def parse(body) + JSON.parse(body) + end + + def post_data(parameters = {}) + parameters.to_json + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/plugnpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/plugnpay.rb new file mode 100644 index 000000000..8f743cebd --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/plugnpay.rb @@ -0,0 +1,294 @@ +module ActiveMerchant + module Billing + class PlugnpayGateway < Gateway + class PlugnpayPostData < PostData + # Fields that will be sent even if they are blank + self.required_fields = [ :publisher_name, :publisher_password, + :card_amount, :card_name, :card_number, :card_exp, :orderID ] + end + self.live_url = self.test_url = 'https://pay1.plugnpay.com/payment/pnpremote.cgi' + + CARD_CODE_MESSAGES = { + "M" => "Card verification number matched", + "N" => "Card verification number didn't match", + "P" => "Card verification number was not processed", + "S" => "Card verification number should be on card but was not indicated", + "U" => "Issuer was not certified for card verification" + } + + CARD_CODE_ERRORS = %w( N S ) + + AVS_MESSAGES = { + "A" => "Street address matches billing information, zip/postal code does not", + "B" => "Address information not provided for address verification check", + "E" => "Address verification service error", + "G" => "Non-U.S. card-issuing bank", + "N" => "Neither street address nor zip/postal match billing information", + "P" => "Address verification not applicable for this transaction", + "R" => "Payment gateway was unavailable or timed out", + "S" => "Address verification service not supported by issuer", + "U" => "Address information is unavailable", + "W" => "9-digit zip/postal code matches billing information, street address does not", + "X" => "Street address and 9-digit zip/postal code matches billing information", + "Y" => "Street address and 5-digit zip/postal code matches billing information", + "Z" => "5-digit zip/postal code matches billing information, street address does not", + } + + AVS_ERRORS = %w( A E N R W Z ) + + PAYMENT_GATEWAY_RESPONSES = { + "P01" => "AVS Mismatch Failure", + "P02" => "CVV2 Mismatch Failure", + "P21" => "Transaction may not be marked", + "P30" => "Test Tran. Bad Card", + "P35" => "Test Tran. Problem", + "P40" => "Username already exists", + "P41" => "Username is blank", + "P50" => "Fraud Screen Failure", + "P51" => "Missing PIN Code", + "P52" => "Invalid Bank Acct. No.", + "P53" => "Invalid Bank Routing No.", + "P54" => "Invalid/Missing Check No.", + "P55" => "Invalid Credit Card No.", + "P56" => "Invalid CVV2/CVC2 No.", + "P57" => "Expired. CC Exp. Date", + "P58" => "Missing Data", + "P59" => "Missing Email Address", + "P60" => "Zip Code does not match Billing State.", + "P61" => "Invalid Billing Zip Code", + "P62" => "Zip Code does not match Shipping State.", + "P63" => "Invalid Shipping Zip Code", + "P64" => "Invalid Credit Card CVV2/CVC2 Format.", + "P65" => "Maximum number of attempts has been exceeded.", + "P66" => "Credit Card number has been flagged and can not be used to access this service.", + "P67" => "IP Address is on Blocked List.", + "P68" => "Billing country does not match ipaddress country.", + "P69" => "US based ipaddresses are currently blocked.", + "P70" => "Credit Cards issued from this bank are currently not being accepted.", + "P71" => "Credit Cards issued from this bank are currently not being accepted.", + "P72" => "Daily volume exceeded.", + "P73" => "Too many transactions within allotted time.", + "P91" => "Missing/incorrect password", + "P92" => "Account not configured for mobil administration", + "P93" => "IP Not registered to username.", + "P94" => "Mode not permitted for this account.", + "P95" => "Currently Blank", + "P96" => "Currently Blank", + "P97" => "Processor not responding", + "P98" => "Missing merchant/publisher name", + "P99" => "Currently Blank" + } + + TRANSACTIONS = { + :authorization => 'auth', + :purchase => 'auth', + :capture => 'mark', + :void => 'void', + :refund => 'return', + :credit => 'newreturn' + } + + SUCCESS_CODES = [ 'pending', 'success' ] + FAILURE_CODES = [ 'badcard', 'fraud' ] + + self.default_currency = 'USD' + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.plugnpay.com/' + self.display_name = "Plug'n Pay" + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, creditcard, options = {}) + post = PlugnpayPostData.new + + add_amount(post, money, options) + add_creditcard(post, creditcard) + add_addresses(post, options) + add_invoice_data(post, options) + add_customer_data(post, options) + + post[:authtype] = 'authpostauth' + commit(:authorization, post) + end + + def authorize(money, creditcard, options = {}) + post = PlugnpayPostData.new + + add_amount(post, money, options) + add_creditcard(post, creditcard) + add_addresses(post, options) + add_invoice_data(post, options) + add_customer_data(post, options) + + post[:authtype] = 'authonly' + commit(:authorization, post) + end + + def capture(money, authorization, options = {}) + post = PlugnpayPostData.new + + post[:orderID] = authorization + + add_amount(post, money, options) + add_customer_data(post, options) + + commit(:capture, post) + end + + def void(authorization, options = {}) + post = PlugnpayPostData.new + + post[:orderID] = authorization + post[:txn_type] = 'auth' + + commit(:void, post) + end + + def credit(money, identification_or_creditcard, options = {}) + post = PlugnpayPostData.new + add_amount(post, money, options) + + if identification_or_creditcard.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification_or_creditcard, options) + else + add_creditcard(post, identification_or_creditcard) + add_addresses(post, options) + add_customer_data(post, options) + + commit(:credit, post) + end + end + + def refund(money, reference, options = {}) + post = PlugnpayPostData.new + add_amount(post, money, options) + post[:orderID] = reference + commit(:refund, post) + end + + private + def commit(action, post) + response = parse( ssl_post(self.live_url, post_data(action, post)) ) + success = SUCCESS_CODES.include?(response[:finalstatus]) + message = success ? 'Success' : message_from(response) + + Response.new(success, message, response, + :test => test?, + :authorization => response[:orderid], + :avs_result => { :code => response[:avs_code] }, + :cvv_result => response[:cvvresp] + ) + end + + def parse(body) + body = CGI.unescape(body) + results = {} + body.split('&').collect { |e| e.split('=') }.each do |key,value| + results[key.downcase.to_sym] = normalize(value.to_s.strip) + end + + results.delete(:publisher_password) + results[:avs_message] = AVS_MESSAGES[results[:avs_code]] if results[:avs_code] + results[:card_code_message] = CARD_CODE_MESSAGES[results[:cvvresp]] if results[:cvvresp] + + results + end + + def post_data(action, post) + post[:mode] = TRANSACTIONS[action] + post[:convert] = 'underscores' + post[:app_level] = 0 + post[:publisher_name] = @options[:login] + post[:publisher_password] = @options[:password] + + post.to_s + end + + def add_creditcard(post, creditcard) + post[:card_number] = creditcard.number + post[:card_cvv] = creditcard.verification_value + post[:card_exp] = expdate(creditcard) + post[:card_name] = creditcard.name.slice(0..38) + end + + def add_customer_data(post, options) + post[:email] = options[:email] + post[:dontsndmail] = 'yes' unless options[:send_email_confirmation] + post[:ipaddress] = options[:ip] + end + + def add_invoice_data(post, options) + post[:shipping] = amount(options[:shipping]) unless options[:shipping].blank? + post[:tax] = amount(options[:tax]) unless options[:tax].blank? + end + + def add_addresses(post, options) + if address = options[:billing_address] || options[:address] + post[:card_address1] = address[:address1] + post[:card_zip] = address[:zip] + post[:card_city] = address[:city] + post[:card_country] = address[:country] + post[:phone] = address[:phone] + + case address[:country] + when 'US', 'CA' + post[:card_state] = address[:state] + else + post[:card_state] = 'ZZ' + post[:card_prov] = address[:state] + end + end + + if shipping_address = options[:shipping_address] || address + post[:shipname] = shipping_address[:name] + post[:address1] = shipping_address[:address1] + post[:address2] = shipping_address[:address2] + post[:city] = shipping_address[:city] + + case shipping_address[:country] + when 'US', 'CA' + post[:state] = shipping_address[:state] + else + post[:state] = 'ZZ' + post[:province] = shipping_address[:state] + end + + post[:country] = shipping_address[:country] + post[:zip] = shipping_address[:zip] + end + end + + def add_amount(post, money, options) + post[:card_amount] = amount(money) + post[:currency] = options[:currency] || currency(money) + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def message_from(results) + PAYMENT_GATEWAY_RESPONSES[results[:resp_code]] + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + + "#{month}/#{year[-2..-1]}" + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psigate.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psigate.rb new file mode 100644 index 000000000..c30a1f20f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psigate.rb @@ -0,0 +1,227 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # This class implements the Psigate gateway for the ActiveMerchant module. + # + # Modifications by Sean O'Hara ( sohara at sohara dot com ) + # + # Usage for a PreAuth (authorize) is as follows: + # + # gateway = PsigateGateway.new( + # :login => 'teststore', + # :password => 'psigate1234' + # ) + # + # creditcard = CreditCard.new( + # :number => '4242424242424242', + # :month => 8, + # :year => 2006, + # :first_name => 'Longbob', + # :last_name => 'Longsen' + # ) + # + # twenty = 2000 + # response = @gateway.authorize(twenty, creditcard, + # :order_id => 1234, + # :billing_address => { + # :address1 => '123 fairweather Lane', + # :address2 => 'Apt B', + # :city => 'New York', + # :state => 'NY', + # :country => 'U.S.A.', + # :zip => '10010' + # }, + # :email => 'jack@yahoo.com' + # ) + class PsigateGateway < Gateway + self.test_url = 'https://dev.psigate.com:7989/Messenger/XMLMessenger' + self.live_url = 'https://secure.psigate.com:7934/Messenger/XMLMessenger' + + self.supported_cardtypes = [:visa, :master, :american_express] + self.supported_countries = ['CA'] + self.homepage_url = 'http://www.psigate.com/' + self.display_name = 'Psigate' + + SUCCESS_MESSAGE = 'Success' + FAILURE_MESSAGE = 'The transaction was declined' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, creditcard, options = {}) + requires!(options, :order_id) + options[:CardAction] = "1" + commit(money, creditcard, options) + end + + def purchase(money, creditcard, options = {}) + requires!(options, :order_id) + options[:CardAction] = "0" + commit(money, creditcard, options) + end + + def capture(money, authorization, options = {}) + options[:CardAction] = "2" + options[:order_id], options[:trans_ref_number] = split_authorization(authorization) + commit(money, nil, options) + end + + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + def refund(money, authorization, options = {}) + options[:CardAction] = "3" + options[:order_id], options[:trans_ref_number] = split_authorization(authorization) + commit(money, nil, options) + end + + def void(authorization, options = {}) + options[:CardAction] = "9" + options[:order_id], options[:trans_ref_number] = split_authorization(authorization) + commit(nil, nil, options) + end + + private + + def commit(money, creditcard, options = {}) + response = parse(ssl_post(url, post_data(money, creditcard, options))) + + Response.new(successful?(response), message_from(response), response, + :test => test?, + :authorization => build_authorization(response) , + :avs_result => { :code => response[:avsresult] }, + :cvv_result => response[:cardidresult] + ) + end + + def url + (test? ? self.test_url : self.live_url) + end + + def successful?(response) + response[:approved] == "APPROVED" + end + + def parse(xml) + response = {:message => "Global Error Receipt", :complete => false} + + xml = REXML::Document.new(xml) + xml.elements.each('//Result/*') do |node| + response[node.name.downcase.to_sym] = normalize(node.text) + end unless xml.root.nil? + + response + end + + def post_data(money, creditcard, options) + xml = REXML::Document.new + xml << REXML::XMLDecl.new + root = xml.add_element("Order") + + parameters(money, creditcard, options).each do |key, value| + root.add_element(key.to_s).text = value if value + end + + xml.to_s + end + + def parameters(money, creditcard, options = {}) + params = { + # General order parameters + :StoreID => @options[:login], + :Passphrase => @options[:password], + :TestResult => options[:test_result], + :OrderID => options[:order_id], + :UserID => options[:user_id], + :Phone => options[:phone], + :Fax => options[:fax], + :Email => options[:email], + :TransRefNumber => options[:trans_ref_number], + + # Credit Card parameters + :PaymentType => "CC", + :CardAction => options[:CardAction], + + # Financial parameters + :CustomerIP => options[:ip], + :SubTotal => amount(money), + :Tax1 => options[:tax1], + :Tax2 => options[:tax2], + :ShippingTotal => options[:shipping_total], + } + + if creditcard + exp_month = sprintf("%.2i", creditcard.month) unless creditcard.month.blank? + exp_year = creditcard.year.to_s[2,2] unless creditcard.year.blank? + card_id_code = (creditcard.verification_value.blank? ? nil : "1") + + params.update( + :CardNumber => creditcard.number, + :CardExpMonth => exp_month, + :CardExpYear => exp_year, + :CardIDCode => card_id_code, + :CardIDNumber => creditcard.verification_value + ) + end + + if(address = (options[:billing_address] || options[:address])) + params[:Bname] = address[:name] || creditcard.name + params[:Baddress1] = address[:address1] unless address[:address1].blank? + params[:Baddress2] = address[:address2] unless address[:address2].blank? + params[:Bcity] = address[:city] unless address[:city].blank? + params[:Bprovince] = address[:state] unless address[:state].blank? + params[:Bpostalcode] = address[:zip] unless address[:zip].blank? + params[:Bcountry] = address[:country] unless address[:country].blank? + params[:Bcompany] = address[:company] unless address[:company].blank? + end + + if address = options[:shipping_address] + params[:Sname] = address[:name] || creditcard.name + params[:Saddress1] = address[:address1] unless address[:address1].blank? + params[:Saddress2] = address[:address2] unless address[:address2].blank? + params[:Scity] = address[:city] unless address[:city].blank? + params[:Sprovince] = address[:state] unless address[:state].blank? + params[:Spostalcode] = address[:zip] unless address[:zip].blank? + params[:Scountry] = address[:country] unless address[:country].blank? + params[:Scompany] = address[:company] unless address[:company].blank? + end + + params + end + + def message_from(response) + if response[:approved] == "APPROVED" + return SUCCESS_MESSAGE + else + return FAILURE_MESSAGE if response[:errmsg].blank? + return response[:errmsg].gsub(/[^\w]/, ' ').split.join(" ").capitalize + end + end + + # Make a ruby type out of the response string + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def split_authorization(authorization) + order_id, trans_ref_number = authorization.split(';') + [order_id, trans_ref_number] + end + + def build_authorization(response) + [response[:orderid], response[:transrefnumber]].join(";") + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psl_card.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psl_card.rb new file mode 100644 index 000000000..758aac6fe --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/psl_card.rb @@ -0,0 +1,303 @@ +module ActiveMerchant + module Billing + # + # ActiveMerchant PSL Card Gateway + # + # Notes: + # -To be able to use the capture function, the IP address of the machine must be + # registered with PSL + # -ESALE_KEYED should only be used in situations where the cardholder perceives the + # transaction to be Internet-based, such as purchasing from a web site/on-line store. + # If the Internet is used purely for the transport of information from the merchant + # directly to the gateway then the appropriate cardholder present or not present message + # type should be used rather than the ‘E’ equivalent. + # -The CV2 / AVS policies are set up with the account settings when signing up for an account + class PslCardGateway < Gateway + self.money_format = :cents + self.default_currency = 'GBP' + + self.supported_countries = ['GB'] + # Visa Credit, Visa Debit, Mastercard, Maestro, Solo, Electron, + # American Express, Diners Club, JCB, International Maestro, + # Style, Clydesdale Financial Services, Other + + self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :jcb, :switch, :solo, :maestro ] + self.homepage_url = 'http://www.paymentsolutionsltd.com/' + self.display_name = 'PSL Payment Solutions' + + # Default ISO 3166 country code (GB) + cattr_accessor :location + self.location = 826 + + # PslCard server self.live_url - The url is the same whether testing or live - use + # the test account when testing... + self.live_url = self.test_url = 'https://pslcard3.paymentsolutionsltd.com/secure/transact.asp?' + + # eCommerce sale transaction, details keyed by merchant or cardholder + MESSAGE_TYPE = 'ESALE_KEYED' + + # The type of response that we want to get from PSL, options are HTML, XML or REDIRECT + RESPONSE_ACTION = 'HTML' + + # Currency Codes + CURRENCY_CODES = { + 'AUD' => 036, + 'GBP' => 826, + 'USD' => 840 + } + + #The terminal used - only for swipe transactions, so hard coded to 32 for online + EMV_TERMINAL_TYPE = 32 + + #Different Dispatch types + DISPATCH_LATER = 'LATER' + DISPATCH_NOW = 'NOW' + + # Return codes + APPROVED = '00' + + #Nominal amount to authorize for a 'dispatch later' type + #The nominal amount is held straight away, when the goods are ready + #to be dispatched, PSL is informed and the full amount is the + #taken. + NOMINAL_AMOUNT = 101 + + AVS_CODE = { + "ALL MATCH" => 'Y', + "SECURITY CODE MATCH ONLY" => 'N', + "ADDRESS MATCH ONLY" => 'Y', + "NO DATA MATCHES" => 'N', + "DATA NOT CHECKED" => 'R', + "SECURITY CHECKS NOT SUPPORTED" => 'X' + } + + CVV_CODE = { + "ALL MATCH" => 'M', + "SECURITY CODE MATCH ONLY" => 'M', + "ADDRESS MATCH ONLY" => 'N', + "NO DATA MATCHES" => 'N', + "DATA NOT CHECKED" => 'P', + "SECURITY CHECKS NOT SUPPORTED" => 'X' + } + + # Create a new PslCardGateway + # + # The gateway requires that a valid :login be passed in the options hash + # + # Paramaters: + # -options: + # :login - the PslCard account login (required) + def initialize(options = {}) + requires!(options, :login) + + super + end + + # Purchase the item straight away + # + # Parameters: + # -money: Amount to be charged as an Integer value in cents + # -authorization: the PSL cross reference from the previous authorization + # -options: + # + # Returns: + # -ActiveRecord::Billing::Response object + # + def purchase(money, credit_card, options = {}) + post = {} + + add_amount(post, money, DISPATCH_NOW, options) + add_credit_card(post, credit_card) + add_address(post, options) + add_invoice(post, options) + add_purchase_details(post) + + commit(post) + end + + # Authorize the transaction + # + # Reserves the funds on the customer's credit card, but does not + # charge the card. + # + # This implementation does not authorize the full amount, rather it checks that the full amount + # is available and only 'reserves' the nominal amount (currently a pound and a penny) + # + # Parameters: + # -money: Amount to be charged as an Integer value in cents + # -authorization: the PSL cross reference from the previous authorization + # -options: + # + # Returns: + # -ActiveRecord::Billing::Response object + # + def authorize(money, credit_card, options = {}) + post = {} + + add_amount(post, money, DISPATCH_LATER, options) + add_credit_card(post, credit_card) + add_address(post, options) + add_invoice(post, options) + add_purchase_details(post) + + commit(post) + end + + # Post an authorization. + # + # Captures the funds from an authorized transaction. + # + # Parameters: + # -money: Amount to be charged as an Integer value in cents + # -authorization: The PSL Cross Reference + # -options: + # + # Returns: + # -ActiveRecord::Billing::Response object + # + def capture(money, authorization, options = {}) + post = {} + + add_amount(post, money, DISPATCH_NOW, options) + add_reference(post, authorization) + add_purchase_details(post) + + commit(post) + end + + private + + def add_credit_card(post, credit_card) + post[:QAName] = credit_card.name + post[:CardNumber] = credit_card.number + post[:EMVTerminalType] = EMV_TERMINAL_TYPE + post[:ExpMonth] = credit_card.month + post[:ExpYear] = credit_card.year + + if requires_start_date_or_issue_number?(credit_card) + post[:IssueNumber] = credit_card.issue_number unless credit_card.issue_number.blank? + post[:StartMonth] = credit_card.start_month unless credit_card.start_month.blank? + post[:StartYear] = credit_card.start_year unless credit_card.start_year.blank? + end + + # CV2 check + post[:AVSCV2Check] = credit_card.verification_value? ? 'YES' : 'NO' + post[:CV2] = credit_card.verification_value if credit_card.verification_value? + end + + def add_address(post, options) + address = options[:billing_address] || options[:address] + return if address.nil? + + post[:QAAddress] = [:address1, :address2, :city, :state].collect{|a| address[a]}.reject{|a| a.blank?}.join(' ') + post[:QAPostcode] = address[:zip] + end + + def add_invoice(post, options) + post[:MerchantName] = options[:merchant] || 'Merchant Name' # May use this as the order_id field + post[:OrderID] = options[:order_id] unless options[:order_id].blank? + end + + def add_reference(post, authorization) + post[:CrossReference] = authorization + end + + def add_amount(post, money, dispatch_type, options) + post[:CurrencyCode] = currency_code(options[:currency] || currency(money)) + + if dispatch_type == DISPATCH_LATER + post[:amount] = amount(NOMINAL_AMOUNT) + post[:DispatchLaterAmount] = amount(money) + else + post[:amount] = amount(money) + end + + post[:Dispatch] = dispatch_type + end + + def add_purchase_details(post) + post[:EchoAmount] = 'YES' + post[:SCBI] = 'YES' # Return information about the transaction + post[:MessageType] = MESSAGE_TYPE + end + + # Get the currency code for the passed money object + # + # The money class stores the currency as an ISO 4217:2001 Alphanumeric, + # however PSL requires the ISO 4217:2001 Numeric code. + # + # Parameters: + # -money: Integer value in cents + # + # Returns: + # -the ISO 4217:2001 Numberic currency code + # + def currency_code(currency) + CURRENCY_CODES[currency] + end + + # Parse the PSL response and create a Response object + # + # Parameters: + # -body: The response string returned from PSL, Formatted: + # Key=value&key=value... + # + # Returns: + # -a hash with all of the values returned in the PSL response + # + def parse(body) + + fields = {} + for line in body.split('&') + key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten + fields[key] = CGI.unescape(value) + end + fields.symbolize_keys + end + + # Send the passed data to PSL for processing + # + # Parameters: + # -request: The data that is to be sent to PSL + # + # Returns: + # - ActiveMerchant::Billing::Response object + # + def commit(request) + response = parse( ssl_post(self.live_url, post_data(request)) ) + + Response.new(response[:ResponseCode] == APPROVED, response[:Message], response, + :test => test?, + :authorization => response[:CrossReference], + :cvv_result => CVV_CODE[response[:AVSCV2Check]], + :avs_result => { :code => AVS_CODE[response[:AVSCV2Check]] } + ) + end + + # Put the passed data into a format that can be submitted to PSL + # Key=Value&Key=Value... + # + # Any ampersands and equal signs are removed from the data being posted + # as PSL puts them back into the response string which then cannot be parsed. + # This is after escaping before sending the request to PSL - this is a work + # around for the time being + # + # Parameters: + # -post: Hash of all the data to be sent + # + # Returns: + # -String: the data to be sent + # + def post_data(post) + post[:CountryCode] = self.location + post[:MerchantID] = @options[:login] + post[:ValidityID] = @options[:password] + post[:ResponseAction] = RESPONSE_ACTION + + post.collect { |key, value| + "#{key}=#{CGI.escape(value.to_s.tr('&=', ' '))}" + }.join("&") + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/qbms.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/qbms.rb new file mode 100644 index 000000000..a1ca4bccc --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/qbms.rb @@ -0,0 +1,292 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class QbmsGateway < Gateway + API_VERSION = '4.0' + + class_attribute :test_url, :live_url + + self.test_url = "https://webmerchantaccount.ptc.quickbooks.com/j/AppGateway" + self.live_url = "https://webmerchantaccount.quickbooks.com/j/AppGateway" + + self.homepage_url = 'http://payments.intuit.com/' + self.display_name = 'QuickBooks Merchant Services' + self.default_currency = 'USD' + self.supported_cardtypes = [ :visa, :master, :discover, :american_express, :diners_club, :jcb ] + self.supported_countries = [ 'US' ] + + TYPES = { + :authorize => 'CustomerCreditCardAuth', + :capture => 'CustomerCreditCardCapture', + :purchase => 'CustomerCreditCardCharge', + :refund => 'CustomerCreditCardTxnVoidOrRefund', + :void => 'CustomerCreditCardTxnVoid', + :query => 'MerchantAccountQuery', + } + + # Creates a new QbmsGateway + # + # The gateway requires that a valid app id, app login, and ticket be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login -- The App Login (REQUIRED) + # * :ticket -- The Connection Ticket. (REQUIRED) + # * :pem -- The PEM-encoded SSL client key and certificate. (REQUIRED) + # * :test -- +true+ or +false+. If true, perform transactions against the test server. + # Otherwise, perform transactions against the production server. + # + def initialize(options = {}) + requires!(options, :login, :ticket) + super + end + + # Performs an authorization, which reserves the funds on the customer's credit card, but does not + # charge the card. + # + # ==== Parameters + # + # * money -- The amount to be authorized as an Integer value in cents. + # * creditcard -- The CreditCard details for the transaction. + # * options -- A hash of optional parameters. + # + def authorize(money, creditcard, options = {}) + commit(:authorize, money, options.merge(:credit_card => creditcard)) + end + + # Perform a purchase, which is essentially an authorization and capture in a single operation. + # + # ==== Parameters + # + # * money -- The amount to be purchased as an Integer value in cents. + # * creditcard -- The CreditCard details for the transaction. + # * options -- A hash of optional parameters. + # + def purchase(money, creditcard, options = {}) + commit(:purchase, money, options.merge(:credit_card => creditcard)) + end + + # Captures the funds from an authorized transaction. + # + # ==== Parameters + # + # * money -- The amount to be captured as an Integer value in cents. + # * authorization -- The authorization returned from the previous authorize request. + # + def capture(money, authorization, options = {}) + commit(:capture, money, options.merge(:transaction_id => authorization)) + end + + # Void a previous transaction + # + # ==== Parameters + # + # * authorization - The authorization returned from the previous authorize request. + # + def void(authorization, options = {}) + commit(:void, nil, options.merge(:transaction_id => authorization)) + end + + # Credit an account. + # + # This transaction is also referred to as a Refund and indicates to the gateway that + # money should flow from the merchant to the customer. + # + # ==== Parameters + # + # * money -- The amount to be credited to the customer as an Integer value in cents. + # * identification -- The ID of the original transaction against which the credit is being issued. + # * options -- A hash of parameters. + # + # + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options = {}) + end + + def refund(money, identification, options = {}) + commit(:refund, money, options.merge(:transaction_id => identification)) + end + + # Query the merchant account status + def query + commit(:query, nil, {}) + end + + private + + def hosted? + @options[:pem] + end + + def commit(action, money, parameters) + url = test? ? self.test_url : self.live_url + + type = TYPES[action] + parameters[:trans_request_id] ||= SecureRandom.hex(10) + + req = build_request(type, money, parameters) + + data = ssl_post(url, req, "Content-Type" => "application/x-qbmsxml") + response = parse(type, data) + message = (response[:status_message] || '').strip + + Response.new(success?(response), message, response, + :test => test?, + :authorization => response[:credit_card_trans_id], + :fraud_review => fraud_review?(response), + :avs_result => { :code => avs_result(response) }, + :cvv_result => cvv_result(response) + ) + end + + def success?(response) + response[:status_code] == 0 + end + + def fraud_review?(response) + [10100, 10101].member? response[:status_code] + end + + def parse(type, body) + xml = REXML::Document.new(body) + + signon = REXML::XPath.first(xml, "//SignonMsgsRs/#{hosted? ? 'SignonAppCertRs' : 'SignonDesktopRs'}") + status_code = signon.attributes["statusCode"].to_i + + if status_code != 0 + return { + :status_code => status_code, + :status_message => signon.attributes["statusMessage"], + } + end + + response = REXML::XPath.first(xml, "//QBMSXMLMsgsRs/#{type}Rs") + + results = { + :status_code => response.attributes["statusCode"].to_i, + :status_message => response.attributes["statusMessage"], + } + + response.elements.each do |e| + name = e.name.underscore.to_sym + value = e.text() + + if old_value = results[name] + results[name] = [old_value] if !old_value.kind_of?(Array) + results[name] << value + else + results[name] = value + end + end + + results + end + + def build_request(type, money, parameters = {}) + xml = Builder::XmlMarkup.new(:indent => 0) + + xml.instruct!(:xml, :version => '1.0', :encoding => 'utf-8') + xml.instruct!(:qbmsxml, :version => API_VERSION) + + xml.tag!("QBMSXML") do + xml.tag!("SignonMsgsRq") do + xml.tag!(hosted? ? "SignonAppCertRq" : "SignonDesktopRq") do + xml.tag!("ClientDateTime", Time.now.xmlschema) + xml.tag!("ApplicationLogin", @options[:login]) + xml.tag!("ConnectionTicket", @options[:ticket]) + end + end + + xml.tag!("QBMSXMLMsgsRq") do + xml.tag!("#{type}Rq") do + method("build_#{type}").call(xml, money, parameters) + end + end + end + + xml.target! + end + + def build_CustomerCreditCardAuth(xml, money, parameters) + cc = parameters[:credit_card] + name = "#{cc.first_name} #{cc.last_name}"[0...30] + + xml.tag!("TransRequestID", parameters[:trans_request_id]) + xml.tag!("CreditCardNumber", cc.number) + xml.tag!("ExpirationMonth", cc.month) + xml.tag!("ExpirationYear", cc.year) + xml.tag!("IsECommerce", "true") + xml.tag!("Amount", amount(money)) + xml.tag!("NameOnCard", name) + add_address(xml, parameters) + xml.tag!("CardSecurityCode", cc.verification_value) if cc.verification_value? + end + + def build_CustomerCreditCardCapture(xml, money, parameters) + xml.tag!("TransRequestID", parameters[:trans_request_id]) + xml.tag!("CreditCardTransID", parameters[:transaction_id]) + xml.tag!("Amount", amount(money)) + end + + def build_CustomerCreditCardCharge(xml, money, parameters) + cc = parameters[:credit_card] + name = "#{cc.first_name} #{cc.last_name}"[0...30] + + xml.tag!("TransRequestID", parameters[:trans_request_id]) + xml.tag!("CreditCardNumber", cc.number) + xml.tag!("ExpirationMonth", cc.month) + xml.tag!("ExpirationYear", cc.year) + xml.tag!("IsECommerce", "true") + xml.tag!("Amount", amount(money)) + xml.tag!("NameOnCard", name) + add_address(xml, parameters) + xml.tag!("CardSecurityCode", cc.verification_value) if cc.verification_value? + end + + def build_CustomerCreditCardTxnVoidOrRefund(xml, money, parameters) + xml.tag!("TransRequestID", parameters[:trans_request_id]) + xml.tag!("CreditCardTransID", parameters[:transaction_id]) + xml.tag!("Amount", amount(money)) + end + + def build_CustomerCreditCardTxnVoid(xml, money, parameters) + xml.tag!("TransRequestID", parameters[:trans_request_id]) + xml.tag!("CreditCardTransID", parameters[:transaction_id]) + end + + # Called reflectively by build_request + def build_MerchantAccountQuery(xml, money, parameters) + end + + def add_address(xml, parameters) + if address = parameters[:billing_address] || parameters[:address] + xml.tag!("CreditCardAddress", (address[:address1] || "")[0...30]) + xml.tag!("CreditCardPostalCode", (address[:zip] || "")[0...9]) + end + end + + def cvv_result(response) + case response[:card_security_code_match] + when "Pass" then 'M' + when "Fail" then 'N' + when "NotAvailable" then 'P' + end + end + + def avs_result(response) + case "#{response[:avs_street]}|#{response[:avs_zip]}" + when "Pass|Pass" then "D" + when "Pass|Fail" then "A" + when "Pass|NotAvailable" then "B" + when "Fail|Pass" then "Z" + when "Fail|Fail" then "C" + when "Fail|NotAvailable" then "N" + when "NotAvailable|Pass" then "P" + when "NotAvailable|Fail" then "N" + when "NotAvailable|NotAvailable" then "U" + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quantum.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quantum.rb new file mode 100644 index 000000000..7d8b51be1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quantum.rb @@ -0,0 +1,276 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # ActiveMerchant Implementation for Quantum Gateway XML Requester Service + # Based on API Doc from 8/6/2009 + # + # Important Notes + # * Support is included for a customer id via the :customer option, invoice number via :invoice option, invoice description via :merchant option and memo via :description option + # * You can force email of receipt with :email_receipt => true + # * You can force email of merchant receipt with :merchant_receipt => true + # * You can exclude CVV with :ignore_cvv => true + # * All transactions use dollar values. + class QuantumGateway < Gateway + self.live_url = self.test_url = 'https://secure.quantumgateway.com/cgi/xml_requester.php' + + # visa, master, american_express, discover + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.supported_countries = ['US'] + self.default_currency = 'USD' + self.money_format = :dollars + self.homepage_url = 'http://www.quantumgateway.com' + self.display_name = 'Quantum Gateway' + + # These are the options that can be used when creating a new Quantum Gateway object. + # + # :login => Your Quantum Gateway Gateway ID + # + # :password => Your Quantum Gateway Vault Key or Restrict Key + # + # NOTE: For testing supply your test GatewayLogin and GatewayKey + # + # :email_receipt => true if you want a receipt sent to the customer (false be default) + # + # :merchant_receipt => true if you want to override receiving the merchant receipt + # + # :ignore_avs => true ignore both AVS and CVV verification + # :ignore_cvv => true don't want to use CVV so continue processing even if CVV would have failed + # + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Request an authorization for an amount from CyberSource + # + def authorize(money, creditcard, options = {}) + setup_address_hash(options) + commit(build_auth_request(money, creditcard, options), options ) + end + + # Capture an authorization that has previously been requested + def capture(money, authorization, options = {}) + setup_address_hash(options) + commit(build_capture_request(money, authorization, options), options) + end + + # Purchase is an auth followed by a capture + # You must supply an order_id in the options hash + def purchase(money, creditcard, options = {}) + setup_address_hash(options) + commit(build_purchase_request(money, creditcard, options), options) + end + + def void(identification, options = {}) + commit(build_void_request(identification, options), options) + end + + def refund(money, identification, options = {}) + commit(build_credit_request(money, identification, options), options) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + private + + def setup_address_hash(options) + options[:billing_address] = options[:billing_address] || options[:address] || {} + end + + def build_auth_request(money, creditcard, options) + xml = Builder::XmlMarkup.new + add_common_credit_card_info(xml,'AUTH_ONLY') + add_purchase_data(xml, money) + add_creditcard(xml, creditcard) + add_address(xml, creditcard, options[:billing_address], options) + add_invoice_details(xml, options) + add_customer_details(xml, options) + add_memo(xml, options) + add_business_rules_data(xml) + xml.target! + end + + def build_capture_request(money, authorization, options) + xml = Builder::XmlMarkup.new + add_common_credit_card_info(xml,'PREVIOUS_SALE') + transaction_id, _ = authorization_parts_from(authorization) + add_transaction_id(xml, transaction_id) + xml.target! + end + + def build_purchase_request(money, creditcard, options) + xml = Builder::XmlMarkup.new + add_common_credit_card_info(xml, @options[:ignore_avs] || @options[:ignore_cvv] ? 'SALES' : 'AUTH_CAPTURE') + add_address(xml, creditcard, options[:billing_address], options) + add_purchase_data(xml, money) + add_creditcard(xml, creditcard) + add_invoice_details(xml, options) + add_customer_details(xml, options) + add_memo(xml, options) + add_business_rules_data(xml) + xml.target! + end + + def build_void_request(authorization, options) + xml = Builder::XmlMarkup.new + add_common_credit_card_info(xml,'VOID') + transaction_id, _ = authorization_parts_from(authorization) + add_transaction_id(xml, transaction_id) + xml.target! + end + + def build_credit_request(money, authorization, options) + xml = Builder::XmlMarkup.new + add_common_credit_card_info(xml,'RETURN') + add_purchase_data(xml, money) + transaction_id, cc = authorization_parts_from(authorization) + add_transaction_id(xml, transaction_id) + xml.tag! 'CreditCardNumber', cc + xml.target! + end + + def add_common_credit_card_info(xml, process_type) + xml.tag! 'RequestType', 'ProcessSingleTransaction' + xml.tag! 'TransactionType', 'CREDIT' + xml.tag! 'PaymentType', 'CC' + xml.tag! 'ProcessType', process_type + end + + def add_business_rules_data(xml) + xml.tag!('CustomerEmail', @options[:email_receipt] ? 'Y' : 'N') + xml.tag!('MerchantEmail', @options[:merchant_receipt] ? 'Y' : 'N') + end + + def add_invoice_details(xml, options) + xml.tag! 'InvoiceNumber', options[:invoice] + xml.tag! 'InvoiceDescription', options[:merchant] + end + + def add_customer_details(xml, options) + xml.tag! 'CustomerID', options[:customer] + end + + def add_transaction_id(xml, transaction_id) + xml.tag! 'TransactionID', transaction_id + end + + def add_memo(xml, options) + xml.tag! 'Memo', options[:description] + end + + def add_purchase_data(xml, money = 0) + xml.tag! 'Amount', amount(money) + xml.tag! 'TransactionDate', Time.now + end + + def add_address(xml, creditcard, address, options, shipTo = false) + xml.tag! 'FirstName', creditcard.first_name + xml.tag! 'LastName', creditcard.last_name + xml.tag! 'Address', address[:address1] # => there is no support for address2 in quantum + xml.tag! 'City', address[:city] + xml.tag! 'State', address[:state] + xml.tag! 'ZipCode', address[:zip] + xml.tag! 'Country', address[:country] + xml.tag! 'EmailAddress', options[:email] + xml.tag! 'IPAddress', options[:ip] + end + + def add_creditcard(xml, creditcard) + xml.tag! 'PaymentType', 'CC' + xml.tag! 'CreditCardNumber', creditcard.number + xml.tag! 'ExpireMonth', format(creditcard.month, :two_digits) + xml.tag! 'ExpireYear', format(creditcard.year, :four_digits) + xml.tag!('CVV2', creditcard.verification_value) unless (@options[:ignore_cvv] || creditcard.verification_value.blank? ) + end + + # Where we actually build the full SOAP request using builder + def build_request(body, options) + xml = Builder::XmlMarkup.new + xml.instruct! + xml.tag! 'QGWRequest' do + xml.tag! 'Authentication' do + xml.tag! 'GatewayLogin', @options[:login] + xml.tag! 'GatewayKey', @options[:password] + end + xml.tag! 'Request' do + xml << body + end + end + xml.target! + end + + # Contact CyberSource, make the SOAP request, and parse the reply into a Response object + def commit(request, options) + headers = { 'Content-Type' => 'text/xml' } + response = parse(ssl_post(self.live_url, build_request(request, options), headers)) + + success = response[:request_status] == "Success" + message = response[:request_message] + + if success # => checking for connectivity success first + success = %w(APPROVED FORCED VOIDED).include?(response[:Status]) + message = response[:StatusDescription] + authorization = success ? authorization_for(response) : nil + end + + Response.new(success, message, response, + :test => test?, + :authorization => authorization, + :avs_result => { :code => response[:AVSResponseCode] }, + :cvv_result => response[:CVV2ResponseCode] + ) + end + + # Parse the SOAP response + # Technique inspired by the Paypal Gateway + def parse(xml) + reply = {} + + begin + xml = REXML::Document.new(xml) + + root = REXML::XPath.first(xml, "//QGWRequest/ResponseSummary") + parse_element(reply, root) + reply[:request_status] = reply[:Status] + reply[:request_message] = "#{reply[:Status]}: #{reply[:StatusDescription]}" + + if root = REXML::XPath.first(xml, "//QGWRequest/Result") + root.elements.to_a.each do |node| + parse_element(reply, node) + end + end + rescue Exception => e + reply[:request_status] = 'Failure' + reply[:request_message] = "Failure: There was a problem parsing the response XML" + end + + return reply + end + + def parse_element(reply, node) + if node.has_elements? + node.elements.each{|e| parse_element(reply, e) } + else + if node.parent.name =~ /item/ + parent = node.parent.name + (node.parent.attributes["id"] ? "_" + node.parent.attributes["id"] : '') + reply[(parent + '_' + node.name).to_sym] = node.text + else + reply[node.name.to_sym] = node.text + end + end + return reply + end + + def authorization_for(reply) + "#{reply[:TransactionID]};#{reply[:CreditCardNumber]}" + end + + def authorization_parts_from(authorization) + authorization.split(/;/) + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quickpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quickpay.rb new file mode 100644 index 000000000..141d1ff03 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/quickpay.rb @@ -0,0 +1,335 @@ +require 'rexml/document' +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class QuickpayGateway < Gateway + self.live_url = self.test_url = 'https://secure.quickpay.dk/api' + + self.default_currency = 'DKK' + self.money_format = :cents + self.supported_cardtypes = [:dankort, :forbrugsforeningen, :visa, :master, :american_express, :diners_club, :jcb, :maestro] + self.supported_countries = ['DK', 'SE'] + self.homepage_url = 'http://quickpay.dk/' + self.display_name = 'Quickpay' + + MD5_CHECK_FIELDS = { + 3 => { + :authorize => %w(protocol msgtype merchant ordernumber amount + currency autocapture cardnumber expirationdate + cvd cardtypelock testmode), + + :capture => %w(protocol msgtype merchant amount transaction), + + :cancel => %w(protocol msgtype merchant transaction), + + :refund => %w(protocol msgtype merchant amount transaction), + + :subscribe => %w(protocol msgtype merchant ordernumber cardnumber + expirationdate cvd cardtypelock description testmode), + + :recurring => %w(protocol msgtype merchant ordernumber amount + currency autocapture transaction), + + :status => %w(protocol msgtype merchant transaction), + + :chstatus => %w(protocol msgtype merchant) + }, + + 4 => { + :authorize => %w(protocol msgtype merchant ordernumber amount + currency autocapture cardnumber expirationdate cvd + cardtypelock testmode fraud_remote_addr + fraud_http_accept fraud_http_accept_language + fraud_http_accept_encoding fraud_http_accept_charset + fraud_http_referer fraud_http_user_agent apikey), + + :capture => %w(protocol msgtype merchant amount transaction apikey), + + :cancel => %w(protocol msgtype merchant transaction apikey), + + :refund => %w(protocol msgtype merchant amount transaction apikey), + + :subscribe => %w(protocol msgtype merchant ordernumber cardnumber + expirationdate cvd cardtypelock description testmode + fraud_remote_addr fraud_http_accept fraud_http_accept_language + fraud_http_accept_encoding fraud_http_accept_charset + fraud_http_referer fraud_http_user_agent apikey), + + :recurring => %w(protocol msgtype merchant ordernumber amount currency + autocapture transaction apikey), + + :status => %w(protocol msgtype merchant transaction apikey), + + :chstatus => %w(protocol msgtype merchant apikey) + }, + + 5 => { + :authorize => %w(protocol msgtype merchant ordernumber amount + currency autocapture cardnumber expirationdate cvd + cardtypelock testmode fraud_remote_addr + fraud_http_accept fraud_http_accept_language + fraud_http_accept_encoding fraud_http_accept_charset + fraud_http_referer fraud_http_user_agent apikey), + + :capture => %w(protocol msgtype merchant amount transaction apikey), + + :cancel => %w(protocol msgtype merchant transaction apikey), + + :refund => %w(protocol msgtype merchant amount transaction apikey), + + :subscribe => %w(protocol msgtype merchant ordernumber cardnumber + expirationdate cvd cardtypelock description testmode + fraud_remote_addr fraud_http_accept fraud_http_accept_language + fraud_http_accept_encoding fraud_http_accept_charset + fraud_http_referer fraud_http_user_agent apikey), + + :recurring => %w(protocol msgtype merchant ordernumber amount currency + autocapture transaction apikey), + + :status => %w(protocol msgtype merchant transaction apikey), + + :chstatus => %w(protocol msgtype merchant apikey) + }, + + 6 => { + :authorize => %w(protocol msgtype merchant ordernumber amount + currency autocapture cardnumber expirationdate cvd + cardtypelock testmode fraud_remote_addr + fraud_http_accept fraud_http_accept_language + fraud_http_accept_encoding fraud_http_accept_charset + fraud_http_referer fraud_http_user_agent apikey), + + :capture => %w(protocol msgtype merchant amount transaction + apikey), + + :cancel => %w(protocol msgtype merchant transaction apikey), + + :refund => %w(protocol msgtype merchant amount transaction apikey), + + :subscribe => %w(protocol msgtype merchant ordernumber cardnumber + expirationdate cvd cardtypelock description testmode + fraud_remote_addr fraud_http_accept fraud_http_accept_language + fraud_http_accept_encoding fraud_http_accept_charset + fraud_http_referer fraud_http_user_agent apikey), + + :recurring => %w(protocol msgtype merchant ordernumber amount currency + autocapture transaction apikey), + + :status => %w(protocol msgtype merchant transaction apikey), + + :chstatus => %w(protocol msgtype merchant apikey) + } + } + + APPROVED = '000' + + # The login is the QuickpayId + # The password is the md5checkword from the Quickpay manager + # To use the API-key from the Quickpay manager, specify :api-key + # Using the API-key, requires that you use version 4+. Specify :version => 4/5/6 in options. + def initialize(options = {}) + requires!(options, :login, :password) + @protocol = options.delete(:version) || 3 # default to protocol version 3 + super + end + + def authorize(money, credit_card_or_reference, options = {}) + post = {} + + action = recurring_or_authorize(credit_card_or_reference) + + add_amount(post, money, options) + add_invoice(post, options) + add_creditcard_or_reference(post, credit_card_or_reference, options) + add_autocapture(post, false) + add_fraud_parameters(post, options) if action.eql?(:authorize) + add_testmode(post) + + commit(action, post) + end + + def purchase(money, credit_card_or_reference, options = {}) + post = {} + + action = recurring_or_authorize(credit_card_or_reference) + + add_amount(post, money, options) + add_creditcard_or_reference(post, credit_card_or_reference, options) + add_invoice(post, options) + add_fraud_parameters(post, options) if action.eql?(:authorize) + add_autocapture(post, true) + + commit(action, post) + end + + def capture(money, authorization, options = {}) + post = {} + + add_reference(post, authorization) + add_amount_without_currency(post, money) + commit(:capture, post) + end + + def void(identification, options = {}) + post = {} + + add_reference(post, identification) + + commit(:cancel, post) + end + + def refund(money, identification, options = {}) + post = {} + + add_amount_without_currency(post, money) + add_reference(post, identification) + + commit(:refund, post) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + def store(creditcard, options = {}) + post = {} + + add_creditcard(post, creditcard, options) + add_invoice(post, options) + add_description(post, options) + add_fraud_parameters(post, options) + add_testmode(post) + + commit(:subscribe, post) + end + + private + + def add_amount(post, money, options = {}) + post[:amount] = amount(money) + post[:currency] = options[:currency] || currency(money) + end + + def add_amount_without_currency(post, money, options = {}) + post[:amount] = amount(money) + end + + def add_invoice(post, options) + post[:ordernumber] = format_order_number(options[:order_id]) + end + + def add_creditcard(post, credit_card, options) + post[:cardnumber] = credit_card.number + post[:cvd] = credit_card.verification_value + post[:expirationdate] = expdate(credit_card) + post[:cardtypelock] = options[:cardtypelock] unless options[:cardtypelock].blank? + end + + def add_reference(post, identification) + post[:transaction] = identification + end + + def add_creditcard_or_reference(post, credit_card_or_reference, options) + if credit_card_or_reference.is_a?(String) + add_reference(post, credit_card_or_reference) + else + add_creditcard(post, credit_card_or_reference, options) + end + end + + def add_autocapture(post, autocapture) + post[:autocapture] = autocapture ? 1 : 0 + end + + def recurring_or_authorize(credit_card_or_reference) + credit_card_or_reference.is_a?(String) ? :recurring : :authorize + end + + def add_description(post, options) + post[:description] = options[:description] + end + + def add_testmode(post) + return if post[:transaction].present? + post[:testmode] = test? ? '1' : '0' + end + + def add_fraud_parameters(post, options) + if @protocol >= 4 + post[:fraud_remote_addr] = options[:fraud_remote_addr] if options[:fraud_remote_addr] + post[:fraud_http_accept] = options[:fraud_http_accept] if options[:fraud_http_accept] + post[:fraud_http_accept_language] = options[:fraud_http_accept_language] if options[:fraud_http_accept_language] + post[:fraud_http_accept_encoding] = options[:fraud_http_accept_encoding] if options[:fraud_http_accept_encoding] + post[:fraud_http_accept_charset] = options[:fraud_http_accept_charset] if options[:fraud_http_accept_charset] + post[:fraud_http_referer] = options[:fraud_http_referer] if options[:fraud_http_referer] + post[:fraud_http_user_agent] = options[:fraud_http_user_agent] if options[:fraud_http_user_agent] + end + end + + def commit(action, params) + response = parse(ssl_post(self.live_url, post_data(action, params))) + + Response.new(successful?(response), message_from(response), response, + :test => test?, + :authorization => response[:transaction] + ) + end + + def successful?(response) + response[:qpstat] == APPROVED + end + + def parse(data) + response = {} + + doc = REXML::Document.new(data) + + doc.root.elements.each do |element| + response[element.name.to_sym] = element.text + end + + response + end + + def message_from(response) + response[:qpstatmsg].to_s + end + + def post_data(action, params = {}) + params[:protocol] = @protocol + params[:msgtype] = action.to_s + params[:merchant] = @options[:login] + params[:apikey] = @options[:apikey] if @options[:apikey] + params[:md5check] = generate_check_hash(action, params) + + params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def generate_check_hash(action, params) + string = MD5_CHECK_FIELDS[@protocol][action].collect do |key| + params[key.to_sym] + end.join('') + + # Add the md5checkword + string << @options[:password].to_s + + Digest::MD5.hexdigest(string) + end + + def expdate(credit_card) + year = format(credit_card.year, :two_digits) + month = format(credit_card.month, :two_digits) + + "#{year}#{month}" + end + + # Limited to 20 digits max + def format_order_number(number) + number.to_s.gsub(/[^\w_]/, '').rjust(4, "0")[0...20] + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/realex.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/realex.rb new file mode 100644 index 000000000..e16a3165d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/realex.rb @@ -0,0 +1,303 @@ +require 'nokogiri' +require 'digest/sha1' + +module ActiveMerchant + module Billing + # Realex is the leading CC gateway in Ireland + # see http://www.realexpayments.com + # Contributed by John Ward (john@ward.name) + # see http://thinedgeofthewedge.blogspot.com + # + # Realex works using the following + # login - The unique id of the merchant + # password - The secret is used to digitally sign the request + # account - This is an optional third part of the authentication process + # and is used if the merchant wishes do distuinguish cc traffic from the different sources + # by using a different account. This must be created in advance + # + # the Realex team decided to make the orderid unique per request, + # so if validation fails you can not correct and resend using the + # same order id + class RealexGateway < Gateway + self.live_url = self.test_url = 'https://epage.payandshop.com/epage-remote.cgi' + + CARD_MAPPING = { + 'master' => 'MC', + 'visa' => 'VISA', + 'american_express' => 'AMEX', + 'diners_club' => 'DINERS', + 'switch' => 'SWITCH', + 'solo' => 'SWITCH', + 'laser' => 'LASER' + } + + self.money_format = :cents + self.default_currency = 'EUR' + self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :switch, :solo, :laser ] + self.supported_countries = [ 'IE', 'GB' ] + self.homepage_url = 'http://www.realexpayments.com/' + self.display_name = 'Realex' + + SUCCESS, DECLINED = "Successful", "Declined" + BANK_ERROR = REALEX_ERROR = "Gateway is in maintenance. Please try again later." + ERROR = CLIENT_DEACTIVATED = "Gateway Error" + + def initialize(options = {}) + requires!(options, :login, :password) + options[:refund_hash] = Digest::SHA1.hexdigest(options[:rebate_secret]) if options.has_key?(:rebate_secret) + super + end + + def purchase(money, credit_card, options = {}) + requires!(options, :order_id) + + request = build_purchase_or_authorization_request(:purchase, money, credit_card, options) + commit(request) + end + + def authorize(money, creditcard, options = {}) + requires!(options, :order_id) + + request = build_purchase_or_authorization_request(:authorization, money, creditcard, options) + commit(request) + end + + def capture(money, authorization, options = {}) + request = build_capture_request(authorization, options) + commit(request) + end + + def refund(money, authorization, options = {}) + request = build_refund_request(money, authorization, options) + commit(request) + end + + def credit(money, authorization, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, authorization, options) + end + + def void(authorization, options = {}) + request = build_void_request(authorization, options) + commit(request) + end + + private + def commit(request) + response = parse(ssl_post(self.live_url, request)) + + Response.new(response[:result] == "00", message_from(response), response, + :test => response[:message] =~ /\[ test system \]/, + :authorization => authorization_from(response), + :cvv_result => response[:cvnresult], + :avs_result => { + :street_match => response[:avspostcoderesponse], + :postal_match => response[:avspostcoderesponse] + } + ) + end + + def parse(xml) + response = {} + + doc = Nokogiri::XML(xml) + doc.xpath('//response/*').each do |node| + if (node.elements.size == 0) + response[node.name.downcase.to_sym] = normalize(node.text) + else + node.elements.each do |childnode| + name = "#{node.name.downcase}_#{childnode.name.downcase}" + response[name.to_sym] = normalize(childnode.text) + end + end + end unless doc.root.nil? + + response + end + + def authorization_from(parsed) + [parsed[:orderid], parsed[:pasref], parsed[:authcode]].join(';') + end + + def build_purchase_or_authorization_request(action, money, credit_card, options) + timestamp = new_timestamp + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'auth' do + add_merchant_details(xml, options) + xml.tag! 'orderid', sanitize_order_id(options[:order_id]) + add_amount(xml, money, options) + add_card(xml, credit_card) + xml.tag! 'autosettle', 'flag' => auto_settle_flag(action) + add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), amount(money), (options[:currency] || currency(money)), credit_card.number) + add_comments(xml, options) + add_address_and_customer_info(xml, options) + end + xml.target! + end + + def build_capture_request(authorization, options) + timestamp = new_timestamp + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'settle' do + add_merchant_details(xml, options) + add_transaction_identifiers(xml, authorization, options) + add_comments(xml, options) + add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), nil, nil, nil) + end + xml.target! + end + + def build_refund_request(money, authorization, options) + timestamp = new_timestamp + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'rebate' do + add_merchant_details(xml, options) + add_transaction_identifiers(xml, authorization, options) + xml.tag! 'amount', amount(money), 'currency' => options[:currency] || currency(money) + xml.tag! 'refundhash', @options[:refund_hash] if @options[:refund_hash] + xml.tag! 'autosettle', 'flag' => 1 + add_comments(xml, options) + add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), amount(money), (options[:currency] || currency(money)), nil) + end + xml.target! + end + + def build_void_request(authorization, options) + timestamp = new_timestamp + xml = Builder::XmlMarkup.new :indent => 2 + xml.tag! 'request', 'timestamp' => timestamp, 'type' => 'void' do + add_merchant_details(xml, options) + add_transaction_identifiers(xml, authorization, options) + add_comments(xml, options) + add_signed_digest(xml, timestamp, @options[:login], sanitize_order_id(options[:order_id]), nil, nil, nil) + end + xml.target! + end + + def add_address_and_customer_info(xml, options) + billing_address = options[:billing_address] || options[:address] + shipping_address = options[:shipping_address] + + return unless billing_address || shipping_address || options[:customer] || options[:invoice] || options[:ip] + + xml.tag! 'tssinfo' do + xml.tag! 'custnum', options[:customer] if options[:customer] + xml.tag! 'prodid', options[:invoice] if options[:invoice] + xml.tag! 'custipaddress', options[:ip] if options[:ip] + + if billing_address + xml.tag! 'address', 'type' => 'billing' do + xml.tag! 'code', format_shipping_zip_code(billing_address[:zip]) + xml.tag! 'country', billing_address[:country] + end + end + + if shipping_address + xml.tag! 'address', 'type' => 'shipping' do + xml.tag! 'code', format_shipping_zip_code(shipping_address[:zip]) + xml.tag! 'country', shipping_address[:country] + end + end + end + end + + def add_merchant_details(xml, options) + xml.tag! 'merchantid', @options[:login] + if options[:account] || @options[:account] + xml.tag! 'account', (options[:account] || @options[:account]) + end + end + + def add_transaction_identifiers(xml, authorization, options) + options[:order_id], pasref, authcode = authorization.split(';') + xml.tag! 'orderid', sanitize_order_id(options[:order_id]) + xml.tag! 'pasref', pasref + xml.tag! 'authcode', authcode + end + + def add_comments(xml, options) + return unless options[:description] + xml.tag! 'comments' do + xml.tag! 'comment', options[:description], 'id' => 1 + end + end + + def add_amount(xml, money, options) + xml.tag! 'amount', amount(money), 'currency' => options[:currency] || currency(money) + end + + def add_card(xml, credit_card) + xml.tag! 'card' do + xml.tag! 'number', credit_card.number + xml.tag! 'expdate', expiry_date(credit_card) + xml.tag! 'chname', credit_card.name + xml.tag! 'type', CARD_MAPPING[card_brand(credit_card).to_s] + xml.tag! 'issueno', credit_card.issue_number + xml.tag! 'cvn' do + xml.tag! 'number', credit_card.verification_value + xml.tag! 'presind', (options['presind'] || (credit_card.verification_value? ? 1 : nil)) + end + end + end + + def format_shipping_zip_code(zip) + zip.to_s.gsub(/\W/, '') + end + + def new_timestamp + Time.now.strftime('%Y%m%d%H%M%S') + end + + def add_signed_digest(xml, *values) + string = Digest::SHA1.hexdigest(values.join(".")) + xml.tag! 'sha1hash', Digest::SHA1.hexdigest([string, @options[:password]].join(".")) + end + + def auto_settle_flag(action) + action == :authorization ? '0' : '1' + end + + def expiry_date(credit_card) + "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}" + end + + def normalize(field) + case field + when "true" then true + when "false" then false + when "" then nil + when "null" then nil + else field + end + end + + def message_from(response) + message = nil + case response[:result] + when "00" + message = SUCCESS + when "101" + message = response[:message] + when "102", "103" + message = DECLINED + when /^2[0-9][0-9]/ + message = BANK_ERROR + when /^3[0-9][0-9]/ + message = REALEX_ERROR + when /^5[0-9][0-9]/ + message = response[:message] + when "600", "601", "603" + message = ERROR + when "666" + message = CLIENT_DEACTIVATED + else + message = DECLINED + end + end + + def sanitize_order_id(order_id) + order_id.to_s.gsub(/[^a-zA-Z0-9\-_]/, '') + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/redsys.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/redsys.rb new file mode 100644 index 000000000..583e02539 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/redsys.rb @@ -0,0 +1,394 @@ +# coding: utf-8 +require 'nokogiri' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # = Redsys Merchant Gateway + # + # Gateway support for the Spanish "Redsys" payment gateway system. This is + # used by many banks in Spain and is particularly well supported by + # Catalunya Caixa's ecommerce department. + # + # Standard ActiveMerchant methods are supported, with one notable exception: + # :order_id must be provided and must conform to a very specific format. + # + # == Example use: + # + # gateway = ActiveMerchant::Billing::RedsysGateway.new( + # :login => "091358382", + # :secret_key => "qwertyasdf0123456789" + # ) + # + # # Run a purchase for 10 euros + # response = gateway.purchase(1000, creditcard, :order_id => "123456") + # puts reponse.success? # => true + # + # # Partially refund the purchase + # response = gateway.refund(500, response.authorization) + # + # Redsys requires an order_id be provided with each transaction of a + # specific format. The rules are as follows: + # + # * Minimum length: 4 + # * Maximum length: 12 + # * First 4 digits must be numerical + # * Remaining 8 digits may be alphanumeric + # + # Much of the code for this library is based on the active_merchant_sermepa + # integration gateway which uses essentially the same API but with the + # banks own payment screen. + # + # Written by Samuel Lown for Cabify. For implementation questions, or + # test access details please get in touch: sam@cabify.com. + class RedsysGateway < Gateway + self.live_url = "https://sis.sermepa.es/sis/operaciones" + self.test_url = "https://sis-t.sermepa.es:25443/sis/operaciones" + + # Sensible region specific defaults. + self.supported_countries = ['ES'] + self.default_currency = 'EUR' + self.money_format = :cents + + # Not all card types may be actived by the bank! + self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club] + + # Homepage URL of the gateway for reference + self.homepage_url = "http://www.redsys.es/" + + # What to call this gateway + self.display_name = "Redsys" + + CURRENCY_CODES = { + "ARS" => '032', + "AUD" => '036', + "BRL" => '986', + "BOB" => '068', + "CAD" => '124', + "CHF" => '756', + "CLP" => '152', + "COP" => '170', + "EUR" => '978', + "GBP" => '826', + "GTQ" => '320', + "JPY" => '392', + "MXN" => '484', + "NZD" => '554', + "PEN" => '604', + "RUB" => '643', + "USD" => '840', + "UYU" => '858' + } + + # The set of supported transactions for this gateway. + # More operations are supported by the gateway itself, but + # are not supported in this library. + SUPPORTED_TRANSACTIONS = { + :purchase => 'A', + :authorize => '1', + :capture => '2', + :refund => '3', + :cancel => '9' + } + + # These are the text meanings sent back by the acquirer when + # a card has been rejected. Syntax or general request errors + # are not covered here. + RESPONSE_TEXTS = { + # Accepted Codes + 0 => "Transaction Approved", + 400 => "Cancellation Accepted", + 481 => "Cancellation Accepted", + 500 => "Reconciliation Accepted", + 900 => "Refund / Confirmation approved", + + # Declined error codes + 101 => "Card expired", + 102 => "Card blocked temporarily or under susciption of fraud", + 104 => "Transaction not permitted", + 107 => "Contact the card issuer", + 109 => "Invalid identification by merchant or POS terminal", + 110 => "Invalid amount", + 114 => "Card cannot be used to the requested transaction", + 116 => "Insufficient credit", + 118 => "Non-registered card", + 125 => "Card not effective", + 129 => "CVV2/CVC2 Error", + 167 => "Contact the card issuer: suspected fraud", + 180 => "Card out of service", + 181 => "Card with credit or debit restrictions", + 182 => "Card with credit or debit restrictions", + 184 => "Authentication error", + 190 => "Refusal with no specific reason", + 191 => "Expiry date incorrect", + + # Declined, and suspected of fraud + 201 => "Card expired", + 202 => "Card blocked temporarily or under suscipition of fraud", + 204 => "Transaction not permitted", + 207 => "Contact the card issuer", + 208 => "Lost or stolen card", + 209 => "Lost or stolen card", + 280 => "CVV2/CVC2 Error", + 290 => "Declined with no specific reason", + + # More general codes for specific types of transaction + 480 => "Original transaction not located, or time-out exceeded", + 501 => "Original transaction not located, or time-out exceeded", + 502 => "Original transaction not located, or time-out exceeded", + 503 => "Original transaction not located, or time-out exceeded", + + # Declined transactions by the bank + 904 => "Merchant not registered at FUC", + 909 => "System error", + 912 => "Issuer not available", + 913 => "Duplicate transmission", + 916 => "Amount too low", + 928 => "Time-out exceeded", + 940 => "Transaction cancelled previously", + 941 => "Authorization operation already cancelled", + 942 => "Original authorization declined", + 943 => "Different details from origin transaction", + 944 => "Session error", + 945 => "Duplicate transmission", + 946 => "Cancellation of transaction while in progress", + 947 => "Duplicate tranmission while in progress", + 949 => "POS Inoperative", + 950 => "Refund not possible", + 9064 => "Card number incorrect", + 9078 => "No payment method available", + 9093 => "Non-existent card", + 9218 => "Recursive transaction in bad gateway", + 9253 => "Check-digit incorrect", + 9256 => "Preauth not allowed for merchant", + 9257 => "Preauth not allowed for card", + 9261 => "Operating limit exceeded", + 9912 => "Issuer not available", + 9913 => "Confirmation error", + 9914 => "KO Confirmation" + } + + # Creates a new instance + # + # Redsys requires a login and secret_key, and optionally also accepts a + # non-default terminal. + # + # ==== Options + # + # * :login -- The Redsys Merchant ID (REQUIRED) + # * :secret_key -- The Redsys Secret Key. (REQUIRED) + # * :terminal -- The Redsys Terminal. Defaults to 1. (OPTIONAL) + # * :test -- +true+ or +false+. Defaults to +false+. (OPTIONAL) + def initialize(options = {}) + requires!(options, :login, :secret_key) + options[:terminal] ||= 1 + super + end + + def purchase(money, creditcard, options = {}) + requires!(options, :order_id) + + data = {} + add_action(data, :purchase) + add_amount(data, money, options) + add_order(data, options[:order_id]) + add_creditcard(data, creditcard) + + commit data + end + + def authorize(money, creditcard, options = {}) + requires!(options, :order_id) + + data = {} + add_action(data, :authorize) + add_amount(data, money, options) + add_order(data, options[:order_id]) + add_creditcard(data, creditcard) + + commit data + end + + def capture(money, authorization, options = {}) + data = {} + add_action(data, :capture) + add_amount(data, money, options) + order_id, _, _ = split_authorization(authorization) + add_order(data, order_id) + + commit data + end + + def void(authorization, options = {}) + data = {} + add_action(data, :cancel) + order_id, amount, currency = split_authorization(authorization) + add_amount(data, amount, :currency => currency) + add_order(data, order_id) + + commit data + end + + def refund(money, authorization, options = {}) + data = {} + add_action(data, :refund) + add_amount(data, money, options) + order_id, _, _ = split_authorization(authorization) + add_order(data, order_id) + + commit data + end + + private + + def add_action(data, action) + data[:action] = transaction_code(action) + end + + def add_amount(data, money, options) + data[:amount] = amount(money).to_s + data[:currency] = currency_code(options[:currency] || currency(money)) + end + + def add_order(data, order_id) + raise ArgumentError.new("Invalid order_id format") unless(/^\d{4}[\da-zA-Z]{0,8}$/ =~ order_id) + data[:order_id] = order_id + end + + def url + test? ? test_url : live_url + end + + def add_creditcard(data, card) + name = [card.first_name, card.last_name].join(' ').slice(0, 60) + year = sprintf("%.4i", card.year) + month = sprintf("%.2i", card.month) + data[:card] = { + :name => name, + :pan => card.number, + :date => "#{year[2..3]}#{month}", + :cvv => card.verification_value + } + end + + def commit(data) + headers = { + 'Content-Type' => 'application/x-www-form-urlencoded' + } + xml = build_xml_request(data) + parse(ssl_post(url, "entrada=#{CGI.escape(xml)}", headers)) + end + + def build_signature(data) + str = data[:amount] + + data[:order_id].to_s + + @options[:login].to_s + + data[:currency] + + if card = data[:card] + str << card[:pan] + str << card[:cvv] if card[:cvv] + end + + str << data[:action] + str << @options[:secret_key] + + Digest::SHA1.hexdigest(str) + end + + def build_xml_request(data) + xml = Builder::XmlMarkup.new :indent => 2 + xml.DATOSENTRADA do + # Basic elements + xml.DS_Version 0.1 + xml.DS_MERCHANT_CURRENCY data[:currency] + xml.DS_MERCHANT_AMOUNT data[:amount] + xml.DS_MERCHANT_ORDER data[:order_id] + xml.DS_MERCHANT_TRANSACTIONTYPE data[:action] + xml.DS_MERCHANT_TERMINAL @options[:terminal] + xml.DS_MERCHANT_MERCHANTCODE @options[:login] + xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data) + + # Only when card is present + if data[:card] + xml.DS_MERCHANT_TITULAR data[:card][:name] + xml.DS_MERCHANT_PAN data[:card][:pan] + xml.DS_MERCHANT_EXPIRYDATE data[:card][:date] + xml.DS_MERCHANT_CVV2 data[:card][:cvv] + end + end + xml.target! + end + + def parse(data) + params = {} + success = false + message = "" + options = @options.merge(:test => test?) + xml = Nokogiri::XML(data) + code = xml.xpath("//RETORNOXML/CODIGO").text + if code == "0" + op = xml.xpath("//RETORNOXML/OPERACION") + op.children.each do |element| + params[element.name.downcase.to_sym] = element.text + end + + if validate_signature(params) + message = response_text(params[:ds_response]) + options[:authorization] = build_authorization(params) + success = is_success_response?(params[:ds_response]) + else + message = "Response failed validation check" + end + else + # Some kind of programmer error with the request! + message = "#{code} ERROR" + end + + Response.new(success, message, params, options) + end + + def validate_signature(data) + str = data[:ds_amount] + + data[:ds_order].to_s + + data[:ds_merchantcode] + + data[:ds_currency] + + data[:ds_response] + + data[:ds_cardnumber].to_s + + data[:ds_transactiontype].to_s + + data[:ds_securepayment].to_s + + @options[:secret_key] + + sig = Digest::SHA1.hexdigest(str) + data[:ds_signature].to_s.downcase == sig + end + + def build_authorization(params) + [params[:ds_order], params[:ds_amount], params[:ds_currency]].join("|") + end + + def split_authorization(authorization) + order_id, amount, currency = authorization.split("|") + [order_id, amount.to_i, currency] + end + + def currency_code(currency) + return currency if currency =~ /^\d+$/ + CURRENCY_CODES[currency] + end + + def transaction_code(type) + SUPPORTED_TRANSACTIONS[type] + end + + def response_text(code) + code = code.to_i + code = 0 if code < 100 + RESPONSE_TEXTS[code] || "Unkown code, please check in manual" + end + + def is_success_response?(code) + (code.to_i < 100) || [400, 481, 500, 900].include?(code.to_i) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage.rb new file mode 100644 index 000000000..5fbae0df9 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage.rb @@ -0,0 +1,152 @@ +require File.dirname(__FILE__) + '/sage/sage_bankcard' +require File.dirname(__FILE__) + '/sage/sage_virtual_check' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SageGateway < Gateway + self.supported_countries = SageBankcardGateway.supported_countries + self.supported_cardtypes = SageBankcardGateway.supported_cardtypes + + self.abstract_class = true + + # Creates a new SageGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * :login - The Sage Payment Solutions Merchant ID Number. + # * :password - The Sage Payment Solutions Merchant Key Number. + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Performs an authorization transaction + # + # ==== Parameters + # * money - The amount to be authorized as an integer value in cents. + # * credit_card - The CreditCard object to be used as the funding source for the transaction. + # * options - A hash of optional parameters. + # * :order_id - A unique reference for this order. (maximum of 20 characters). + # * :email - The customer's email address + # * :customer - The Customer Number for Purchase Card Level II Transactions + # * :billing_address - The customer's billing address as a hash of address information. + # * :address1 - The billing address street + # * :city - The billing address city + # * :state - The billing address state + # * :country - The 2 digit ISO billing address country code + # * :zip - The billing address zip code + # * :phone - The billing address phone number + # * :fax - The billing address fax number + # * :shipping_address - The customer's shipping address as a hash of address information. + # * :name - The name at the shipping address + # * :address1 - The shipping address street + # * :city - The shipping address city + # * :state - The shipping address state code + # * :country - The 2 digit ISO shipping address country code + # * :zip - The shipping address zip code + # * :tax - The tax amount for the transaction as an Integer value in cents. Maps to Sage T_tax. + # * :shipping - The shipping amount for the transaction as an Integer value in cents. Maps to Sage T_shipping. + def authorize(money, credit_card, options = {}) + bankcard.authorize(money, credit_card, options) + end + + # Performs a purchase, which is essentially an authorization and capture in a single operation. + # + # ==== Parameters + # + # * money - The amount to be authorized as an integer value in cents. + # * source - The CreditCard or Check object to be used as the funding source for the transaction. + # * options - A hash of optional parameters. + # * :order_id - A unique reference for this order. (maximum of 20 characters). + # * :email - The customer's email address + # * :customer - The Customer Number for Purchase Card Level II Transactions + # * :billing_address - The customer's billing address as a hash of address information. + # * :address1 - The billing address street + # * :city - The billing address city + # * :state - The billing address state + # * :country - The 2 digit ISO billing address country code + # * :zip - The billing address zip code + # * :phone - The billing address phone number + # * :fax - The billing address fax number + # * :shipping_address - The customer's shipping address as a hash of address information. + # * :name - The name at the shipping address + # * :address1 - The shipping address street + # * :city - The shipping address city + # * :state - The shipping address state code + # * :country - The 2 digit ISO shipping address country code + # * :zip - The shipping address zip code + # * :tax - The tax amount for the transaction as an integer value in cents. Maps to Sage T_tax. + # * :shipping - The shipping amount for the transaction as an integer value in cents. Maps to Sage T_shipping. + # + # ==== Additional options in the +options+ hash for when using a Check as the funding source + # * :originator_id - 10 digit originator. If not provided, Sage will use the default Originator ID for the specific customer type. + # * :addenda - Transaction addenda. + # * :ssn - The customer's Social Security Number. + # * :drivers_license_state - The customer's drivers license state code. + # * :drivers_license_number - The customer's drivers license number. + # * :date_of_birth - The customer's date of birth as a Time or Date object or a string in the format mm/dd/yyyy. + def purchase(money, source, options = {}) + if card_brand(source) == "check" + virtual_check.purchase(money, source, options) + else + bankcard.purchase(money, source, options) + end + end + + # Captures authorized funds. + # + # ==== Parameters + # + # * money - The amount to be authorized as an integer value in cents. Sage doesn't support changing the capture amount, so the full amount of the initial transaction will be captured. + # * reference - The authorization reference string returned by the original transaction's Response#authorization. + def capture(money, reference, options = {}) + bankcard.capture(money, reference, options) + end + + # Voids a prior transaction. Works for both CreditCard and Check transactions. + # + # ==== Parameters + # + # * reference - The authorization reference string returned by the original transaction's Response#authorization. + def void(reference, options = {}) + if reference.split(";").last == "virtual_check" + virtual_check.void(reference, options) + else + bankcard.void(reference, options) + end + end + + def credit(money, source, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, source, options) + end + + # Performs a refund transaction. + # + # ==== Parameters + # + # * money - The amount to be authorized as an integer value in cents. + # * source - The CreditCard or Check object to be used as the target for the refund. + def refund(money, source, options = {}) + if card_brand(source) == "check" + virtual_check.refund(money, source, options) + else + bankcard.refund(money, source, options) + end + end + + private + def bankcard + @bankcard ||= SageBankcardGateway.new(@options) + end + + def virtual_check + @virtual_check ||= SageVirtualCheckGateway.new(@options) + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb new file mode 100644 index 000000000..893db3ee4 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb @@ -0,0 +1,93 @@ +require File.dirname(__FILE__) + '/sage_core' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SageBankcardGateway < Gateway #:nodoc: + include SageCore + self.live_url = 'https://www.sagepayments.net/cgi-bin/eftBankcard.dll?transaction' + self.source = 'bankcard' + + # Credit cards supported by Sage + # * VISA + # * MasterCard + # * AMEX + # * Diners + # * Carte Blanche + # * Discover + # * JCB + # * Sears + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club] + + def authorize(money, credit_card, options = {}) + post = {} + add_credit_card(post, credit_card) + add_transaction_data(post, money, options) + commit(:authorization, post) + end + + def purchase(money, credit_card, options = {}) + post = {} + add_credit_card(post, credit_card) + add_transaction_data(post, money, options) + commit(:purchase, post) + end + + # The +money+ amount is not used. The entire amount of the + # initial authorization will be captured. + def capture(money, reference, options = {}) + post = {} + add_reference(post, reference) + commit(:capture, post) + end + + def void(reference, options = {}) + post = {} + add_reference(post, reference) + commit(:void, post) + end + + def credit(money, credit_card, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, credit_card, options) + end + + def refund(money, credit_card, options = {}) + post = {} + add_credit_card(post, credit_card) + add_transaction_data(post, money, options) + commit(:credit, post) + end + + private + def exp_date(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + def add_credit_card(post, credit_card) + post[:C_name] = credit_card.name + post[:C_cardnumber] = credit_card.number + post[:C_exp] = exp_date(credit_card) + post[:C_cvv] = credit_card.verification_value if credit_card.verification_value? + end + + def parse(data) + response = {} + response[:success] = data[1,1] + response[:code] = data[2,6] + response[:message] = data[8,32].strip + response[:front_end] = data[40, 2] + response[:cvv_result] = data[42, 1] + response[:avs_result] = data[43, 1].strip + response[:risk] = data[44, 2] + response[:reference] = data[46, 10] + + response[:order_number], response[:recurring] = data[57...-1].split("\034") + response + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_core.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_core.rb new file mode 100644 index 000000000..41580d8cc --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_core.rb @@ -0,0 +1,114 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module SageCore #:nodoc: + def self.included(base) + base.cattr_accessor :source + base.supported_countries = ['US', 'CA'] + base.homepage_url = 'http://www.sagepayments.com' + base.display_name = 'Sage Payment Solutions' + end + + # Transactions types: + # 01 - Sale + # 02 - AuthOnly + # 03 - Force/PriorAuthSale + # 04 - Void + # 06 - Credit + # 11 - PriorAuthSale by Reference* + TRANSACTIONS = { + :purchase => '01', + :authorization => '02', + :capture => '11', + :void => '04', + :credit => '06' + } + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + private + def add_invoice(post, options) + post[:T_ordernum] = options[:order_id].slice(0, 20) + post[:T_tax] = amount(options[:tax]) unless options[:tax].blank? + post[:T_shipping] = amount(options[:shipping]) unless options[:shipping].blank? + end + + def add_reference(post, reference) + ref, source = reference.to_s.split(";") + post[:T_reference] = ref + end + + def add_amount(post, money) + post[:T_amt] = amount(money) + end + + def add_customer_data(post, options) + post[:T_customer_number] = options[:customer] if Float(options[:customer]) rescue nil + end + + def add_addresses(post, options) + billing_address = options[:billing_address] || options[:address] || {} + + post[:C_address] = billing_address[:address1] + post[:C_city] = billing_address[:city] + + if ['US', 'CA'].include?(billing_address[:country]) + post[:C_state] = billing_address[:state] + else + post[:C_state] = "Outside of United States" + end + + post[:C_zip] = billing_address[:zip] + post[:C_country] = billing_address[:country] + post[:C_telephone] = billing_address[:phone] + post[:C_fax] = billing_address[:fax] + post[:C_email] = options[:email] + + if shipping_address = options[:shipping_address] + post[:C_ship_name] = shipping_address[:name] + post[:C_ship_address] = shipping_address[:address1] + post[:C_ship_city] = shipping_address[:city] + post[:C_ship_state] = shipping_address[:state] + post[:C_ship_zip] = shipping_address[:zip] + post[:C_ship_country] = shipping_address[:country] + end + end + + def add_transaction_data(post, money, options) + add_amount(post, money) + add_invoice(post, options) + add_addresses(post, options) + add_customer_data(post, options) + end + + def commit(action, params) + response = parse(ssl_post(self.live_url, post_data(action, params))) + + Response.new(success?(response), response[:message], response, + :test => test?, + :authorization => authorization_from(response), + :avs_result => { :code => response[:avs_result] }, + :cvv_result => response[:cvv_result] + ) + end + + def authorization_from(response) + "#{response[:reference]};#{source}" + end + + def success?(response) + response[:success] == 'A' + end + + def post_data(action, params = {}) + params[:M_id] = @options[:login] + params[:M_key] = @options[:password] + params[:T_code] = TRANSACTIONS[action] + + params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb new file mode 100644 index 000000000..e197fe5d1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb @@ -0,0 +1,102 @@ +require File.dirname(__FILE__) + '/sage_core' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SageVirtualCheckGateway < Gateway #:nodoc: + include SageCore + self.live_url = 'https://www.sagepayments.net/cgi-bin/eftVirtualCheck.dll?transaction' + self.source = 'virtual_check' + + def purchase(money, credit_card, options = {}) + post = {} + add_check(post, credit_card) + add_check_customer_data(post, options) + add_transaction_data(post, money, options) + commit(:purchase, post) + end + + def void(reference, options = {}) + post = {} + add_reference(post, reference) + commit(:void, post) + end + + def credit(money, credit_card, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, source, options) + end + + def refund(money, credit_card, options = {}) + post = {} + add_check(post, credit_card) + add_check_customer_data(post, options) + add_transaction_data(post, money, options) + commit(:credit, post) + end + + private + def add_check(post, check) + post[:C_first_name] = check.first_name + post[:C_last_name] = check.last_name + post[:C_rte] = check.routing_number + post[:C_acct] = check.account_number + post[:C_check_number] = check.number + post[:C_acct_type] = account_type(check) + end + + def add_check_customer_data(post, options) + # Required  Customer Type – (NACHA Transaction Class) + # CCD for Commercial, Merchant Initiated + # PPD for Personal, Merchant Initiated + # WEB for Internet, Consumer Initiated + # RCK for Returned Checks + # ARC for Account Receivable Entry + # TEL for TelephoneInitiated + post[:C_customer_type] = "WEB" + + # Optional  10  Digit Originator  ID – Assigned  By for  each transaction  class  or  business  purpose. If  not provided, the default Originator ID for the specific  Customer Type will be applied.  + post[:C_originator_id] = options[:originator_id] + + # Optional  Transaction Addenda + post[:T_addenda] = options[:addenda] + + # Required  Check  Writer  Social  Security  Number  (  Numbers Only, No Dashes )  + post[:C_ssn] = options[:ssn].to_s.gsub(/[^\d]/, '') + + post[:C_dl_state_code] = options[:drivers_license_state] + post[:C_dl_number] = options[:drivers_license_number] + post[:C_dob] = format_birth_date(options[:date_of_birth]) + end + + def format_birth_date(date) + date.respond_to?(:strftime) ? date.strftime("%m/%d/%Y") : date + end + + # DDA for Checking + # SAV for Savings  + def account_type(check) + case check.account_type + when 'checking' then 'DDA' + when 'savings' then 'SAV' + else raise ArgumentError, "Unknown account type #{check.account_type}" + end + end + + def parse(data) + response = {} + response[:success] = data[1,1] + response[:code] = data[2,6].strip + response[:message] = data[8,32].strip + response[:risk] = data[40, 2] + response[:reference] = data[42, 10] + + extra_data = data[53...-1].split("\034") + response[:order_number] = extra_data[0] + response[:authentication_indicator] = extra_data[1] + response[:authentication_disclosure] = extra_data[2] + response + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage_pay.rb new file mode 100644 index 000000000..41a649a6c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sage_pay.rb @@ -0,0 +1,324 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SagePayGateway < Gateway + cattr_accessor :simulate + self.simulate = false + + class_attribute :simulator_url + + self.test_url = 'https://test.sagepay.com/gateway/service' + self.live_url = 'https://live.sagepay.com/gateway/service' + self.simulator_url = 'https://test.sagepay.com/Simulator' + + APPROVED = 'OK' + + TRANSACTIONS = { + :purchase => 'PAYMENT', + :credit => 'REFUND', + :authorization => 'DEFERRED', + :capture => 'RELEASE', + :void => 'VOID', + :abort => 'ABORT' + } + + CREDIT_CARDS = { + :visa => "VISA", + :master => "MC", + :delta => "DELTA", + :solo => "SOLO", + :switch => "MAESTRO", + :maestro => "MAESTRO", + :american_express => "AMEX", + :electron => "UKE", + :diners_club => "DC", + :jcb => "JCB" + } + + ELECTRON = /^(424519|42496[23]|450875|48440[6-8]|4844[1-5][1-5]|4917[3-5][0-9]|491880)\d{10}(\d{3})?$/ + + AVS_CVV_CODE = { + "NOTPROVIDED" => nil, + "NOTCHECKED" => 'X', + "MATCHED" => 'Y', + "NOTMATCHED" => 'N' + } + + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :switch, :solo, :maestro, :diners_club] + self.supported_countries = ['GB'] + self.default_currency = 'GBP' + + self.homepage_url = 'http://www.sagepay.com' + self.display_name = 'SagePay' + + def initialize(options = {}) + requires!(options, :login) + super + end + + def purchase(money, credit_card, options = {}) + requires!(options, :order_id) + + post = {} + + add_amount(post, money, options) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, options) + add_customer_data(post, options) + add_optional_data(post, options) + + commit(:purchase, post) + end + + def authorize(money, credit_card, options = {}) + requires!(options, :order_id) + + post = {} + + add_amount(post, money, options) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, options) + add_customer_data(post, options) + add_optional_data(post, options) + + commit(:authorization, post) + end + + # You can only capture a transaction once, even if you didn't capture the full amount the first time. + def capture(money, identification, options = {}) + post = {} + + add_reference(post, identification) + add_release_amount(post, money, options) + + commit(:capture, post) + end + + def void(identification, options = {}) + post = {} + + add_reference(post, identification) + action = abort_or_void_from(identification) + + commit(action, post) + end + + # Refunding requires a new order_id to passed in, as well as a description + def refund(money, identification, options = {}) + requires!(options, :order_id, :description) + + post = {} + + add_credit_reference(post, identification) + add_amount(post, money, options) + add_invoice(post, options) + + commit(:credit, post) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + private + def add_reference(post, identification) + order_id, transaction_id, authorization, security_key = identification.split(';') + + add_pair(post, :VendorTxCode, order_id) + add_pair(post, :VPSTxId, transaction_id) + add_pair(post, :TxAuthNo, authorization) + add_pair(post, :SecurityKey, security_key) + end + + def add_credit_reference(post, identification) + order_id, transaction_id, authorization, security_key = identification.split(';') + + add_pair(post, :RelatedVendorTxCode, order_id) + add_pair(post, :RelatedVPSTxId, transaction_id) + add_pair(post, :RelatedTxAuthNo, authorization) + add_pair(post, :RelatedSecurityKey, security_key) + end + + def add_amount(post, money, options) + currency = options[:currency] || currency(money) + add_pair(post, :Amount, localized_amount(money, currency), :required => true) + add_pair(post, :Currency, currency, :required => true) + end + + # doesn't actually use the currency -- dodgy! + def add_release_amount(post, money, options) + add_pair(post, :ReleaseAmount, amount(money), :required => true) + end + + def add_customer_data(post, options) + add_pair(post, :CustomerEMail, options[:email][0,255]) unless options[:email].blank? + add_pair(post, :BillingPhone, options[:phone].gsub(/[^0-9+]/, '')[0,20]) unless options[:phone].blank? + add_pair(post, :ClientIPAddress, options[:ip]) + end + + def add_optional_data(post, options) + add_pair(post, :GiftAidPayment, options[:gift_aid_payment]) unless options[:gift_aid_payment].blank? + add_pair(post, :Apply3DSecure, options[:apply_3d_secure]) unless options[:apply_3d_secure].blank? + end + + def add_address(post, options) + if billing_address = options[:billing_address] || options[:address] + first_name, last_name = parse_first_and_last_name(billing_address[:name]) + add_pair(post, :BillingSurname, last_name) + add_pair(post, :BillingFirstnames, first_name) + add_pair(post, :BillingAddress1, billing_address[:address1]) + add_pair(post, :BillingAddress2, billing_address[:address2]) + add_pair(post, :BillingCity, billing_address[:city]) + add_pair(post, :BillingState, billing_address[:state]) if billing_address[:country] == 'US' + add_pair(post, :BillingCountry, billing_address[:country]) + add_pair(post, :BillingPostCode, billing_address[:zip]) + end + + if shipping_address = options[:shipping_address] || billing_address + first_name, last_name = parse_first_and_last_name(shipping_address[:name]) + add_pair(post, :DeliverySurname, last_name) + add_pair(post, :DeliveryFirstnames, first_name) + add_pair(post, :DeliveryAddress1, shipping_address[:address1]) + add_pair(post, :DeliveryAddress2, shipping_address[:address2]) + add_pair(post, :DeliveryCity, shipping_address[:city]) + add_pair(post, :DeliveryState, shipping_address[:state]) if shipping_address[:country] == 'US' + add_pair(post, :DeliveryCountry, shipping_address[:country]) + add_pair(post, :DeliveryPostCode, shipping_address[:zip]) + end + end + + def add_invoice(post, options) + add_pair(post, :VendorTxCode, sanitize_order_id(options[:order_id]), :required => true) + add_pair(post, :Description, options[:description] || options[:order_id]) + end + + def add_credit_card(post, credit_card) + add_pair(post, :CardHolder, credit_card.name, :required => true) + add_pair(post, :CardNumber, credit_card.number, :required => true) + + add_pair(post, :ExpiryDate, format_date(credit_card.month, credit_card.year), :required => true) + + if requires_start_date_or_issue_number?(credit_card) + add_pair(post, :StartDate, format_date(credit_card.start_month, credit_card.start_year)) + add_pair(post, :IssueNumber, credit_card.issue_number) + end + add_pair(post, :CardType, map_card_type(credit_card)) + + add_pair(post, :CV2, credit_card.verification_value) + end + + def sanitize_order_id(order_id) + order_id.to_s.gsub(/[^-a-zA-Z0-9._]/, '') + end + + def map_card_type(credit_card) + raise ArgumentError, "The credit card type must be provided" if card_brand(credit_card).blank? + + card_type = card_brand(credit_card).to_sym + + # Check if it is an electron card + if card_type == :visa && credit_card.number =~ ELECTRON + CREDIT_CARDS[:electron] + else + CREDIT_CARDS[card_type] + end + end + + # MMYY format + def format_date(month, year) + return nil if year.blank? || month.blank? + + year = sprintf("%.4i", year) + month = sprintf("%.2i", month) + + "#{month}#{year[-2..-1]}" + end + + def commit(action, parameters) + response = parse( ssl_post(url_for(action), post_data(action, parameters)) ) + + Response.new(response["Status"] == APPROVED, message_from(response), response, + :test => test?, + :authorization => authorization_from(response, parameters, action), + :avs_result => { + :street_match => AVS_CVV_CODE[ response["AddressResult"] ], + :postal_match => AVS_CVV_CODE[ response["PostCodeResult"] ], + }, + :cvv_result => AVS_CVV_CODE[ response["CV2Result"] ] + ) + end + + def authorization_from(response, params, action) + [ params[:VendorTxCode], + response["VPSTxId"], + response["TxAuthNo"], + response["SecurityKey"], + action ].join(";") + end + + def abort_or_void_from(identification) + original_transaction = identification.split(';').last + original_transaction == 'authorization' ? :abort : :void + end + + def url_for(action) + simulate ? build_simulator_url(action) : build_url(action) + end + + def build_url(action) + endpoint = [ :purchase, :authorization ].include?(action) ? "vspdirect-register" : TRANSACTIONS[action].downcase + "#{test? ? self.test_url : self.live_url}/#{endpoint}.vsp" + end + + def build_simulator_url(action) + endpoint = [ :purchase, :authorization ].include?(action) ? "VSPDirectGateway.asp" : "VSPServerGateway.asp?Service=Vendor#{TRANSACTIONS[action].capitalize}Tx" + "#{self.simulator_url}/#{endpoint}" + end + + def message_from(response) + response['Status'] == APPROVED ? 'Success' : (response['StatusDetail'] || 'Unspecified error') # simonr 20080207 can't actually get non-nil blanks, so this is shorter + end + + def post_data(action, parameters = {}) + parameters.update( + :Vendor => @options[:login], + :TxType => TRANSACTIONS[action], + :VPSProtocol => "2.23" + ) + + parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + # SagePay returns data in the following format + # Key1=value1 + # Key2=value2 + def parse(body) + result = {} + body.to_s.each_line do |pair| + result[$1] = $2 if pair.strip =~ /\A([^=]+)=(.+)\Z/im + end + result + end + + def add_pair(post, key, value, options = {}) + post[key] = value if !value.blank? || options[:required] + end + + def parse_first_and_last_name(value) + name = value.to_s.split(' ') + + last_name = name.pop || '' + first_name = name.join(' ') + [ first_name[0,20], last_name[0,20] ] + end + + def localized_amount(money, currency) + amount = amount(money) + CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s) ? amount.split('.').first : amount + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sallie_mae.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sallie_mae.rb new file mode 100644 index 000000000..1098790d2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/sallie_mae.rb @@ -0,0 +1,143 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SallieMaeGateway < Gateway + self.live_url = self.test_url = 'https://trans.salliemae.com/cgi-bin/process.cgi' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.salliemae.com/' + + # The name of the gateway + self.display_name = 'Sallie Mae' + + def initialize(options = {}) + requires!(options, :login) + super + end + + def test? + @options[:login] == "TEST0" + end + + def authorize(money, creditcard, options = {}) + post = PostData.new + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, creditcard, options) + add_customer_data(post, options) + + commit(:authonly, money, post) + end + + def purchase(money, creditcard, options = {}) + post = PostData.new + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, creditcard, options) + add_customer_data(post, options) + + commit(:sale, money, post) + end + + def capture(money, authorization, options = {}) + post = PostData.new + post[:postonly] = authorization + commit(:capture, money, post) + end + + private + + def add_customer_data(post, options) + if address = options[:billing_address] || options[:shipping_address] || options[:address] + post[:ci_phone] = address[:phone].to_s + end + + post[:ci_email] = options[:email].to_s unless options[:email].blank? + post[:ci_IP] = options[:ip].to_s unless options[:ip].blank? + end + + def add_address(post, creditcard, options) + if address = options[:billing_address] || options[:address] + post[:ci_billaddr1] = address[:address1].to_s + post[:ci_billaddr2] = address[:address2].to_s unless address[:address2].blank? + post[:ci_billcity] = address[:city].to_s + post[:ci_billstate] = address[:state].to_s + post[:ci_billzip] = address[:zip].to_s + end + + if shipping_address = options[:shipping_address] || options[:address] + post[:ci_shipaddr1] = shipping_address[:address1].to_s + post[:ci_shipaddr2] = shipping_address[:address2].to_s unless shipping_address[:address2].blank? + post[:ci_shipcity] = shipping_address[:city].to_s + post[:ci_shipstate] = shipping_address[:state].to_s + post[:ci_shipzip] = shipping_address[:zip].to_s + end + end + + def add_invoice(post, options) + memo = "OrderID: #{options[:order_id]}\nDescription: #{options[:description]}" + post[:ci_memo] = memo + end + + def add_creditcard(post, creditcard) + post[:ccnum] = creditcard.number.to_s + post[:ccname] = creditcard.name.to_s + post[:cvv2] = creditcard.verification_value.to_s if creditcard.verification_value? + post[:expmon] = creditcard.month.to_s + post[:expyear] = creditcard.year.to_s + end + + def parse(body) + h = {} + body.gsub!("", "") + body. + split("\r\n"). + map do |i| + a = i.split("=") + h[a.first] = a.last unless a.first.nil? + end + h + end + + def commit(action, money, parameters) + parameters[:acctid] = @options[:login].to_s + parameters[:subid] = @options[:sub_id].to_s unless @options[:sub_id].blank? + parameters[:amount] = amount(money) + + case action + when :sale + parameters[:action] = "ns_quicksale_cc" + when :authonly + parameters[:action] = "ns_quicksale_cc" + parameters[:authonly] = 1 + when :capture + parameters[:action] = "ns_quicksale_cc" + end + + response = parse(ssl_post(self.live_url, parameters.to_post_data) || "") + Response.new(successful?(response), message_from(response), response, + :test => test?, + :authorization => response["refcode"] + ) + end + + def successful?(response) + response["Status"] == "Accepted" + end + + def message_from(response) + if successful?(response) + "Accepted" + else + response["Reason"].split(":")[2].capitalize unless response["Reason"].nil? + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/samurai.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/samurai.rb new file mode 100644 index 000000000..c263c79f0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/samurai.rb @@ -0,0 +1,118 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SamuraiGateway < Gateway + + self.homepage_url = 'https://samurai.feefighters.com' + self.display_name = 'Samurai' + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club] + self.default_currency = 'USD' + self.money_format = :dollars + + def initialize(options = {}) + begin + require 'samurai' + rescue LoadError + raise "Could not load the samurai gem (>= 0.2.25). Use `gem install samurai` to install it." + end + + requires!(options, :login, :password, :processor_token) + Samurai.options = { + :merchant_key => options[:login], + :merchant_password => options[:password], + :processor_token => options[:processor_token] + } + + super + end + + def authorize(money, credit_card_or_vault_id, options = {}) + token = payment_method_token(credit_card_or_vault_id, options) + return token if token.is_a?(Response) + + authorize = Samurai::Processor.authorize(token, amount(money), processor_options(options)) + handle_result(authorize) + end + + def purchase(money, credit_card_or_vault_id, options = {}) + token = payment_method_token(credit_card_or_vault_id, options) + return token if token.is_a?(Response) + + purchase = Samurai::Processor.purchase(token, amount(money), processor_options(options)) + handle_result(purchase) + end + + def capture(money, authorization_id, options = {}) + transaction = Samurai::Transaction.find(authorization_id) + handle_result(transaction.capture(amount(money))) + end + + def refund(money, transaction_id, options = {}) + transaction = Samurai::Transaction.find(transaction_id) + handle_result(transaction.credit(amount(money))) + end + + def void(transaction_id, options = {}) + transaction = Samurai::Transaction.find(transaction_id) + handle_result(transaction.void) + end + + def store(creditcard, options = {}) + address = options[:billing_address] || options[:address] || {} + + result = Samurai::PaymentMethod.create({ + :card_number => creditcard.number, + :expiry_month => creditcard.month.to_s.rjust(2, "0"), + :expiry_year => creditcard.year.to_s, + :cvv => creditcard.verification_value, + :first_name => creditcard.first_name, + :last_name => creditcard.last_name, + :address_1 => address[:address1], + :address_2 => address[:address2], + :city => address[:city], + :zip => address[:zip], + :sandbox => test? + }) + result.retain if options[:retain] && result.is_sensitive_data_valid && result.payment_method_token + + Response.new(result.is_sensitive_data_valid, + message_from_result(result), + { :payment_method_token => result.is_sensitive_data_valid && result.payment_method_token }) + end + + private + + def payment_method_token(credit_card_or_vault_id, options) + return credit_card_or_vault_id if credit_card_or_vault_id.is_a?(String) + store_result = store(credit_card_or_vault_id, options) + store_result.success? ? store_result.params["payment_method_token"] : store_result + end + + def handle_result(result) + response_params, response_options = {}, {} + if result.success? + response_options[:test] = test? + response_options[:authorization] = result.reference_id + response_params[:reference_id] = result.reference_id + response_params[:transaction_token] = result.transaction_token + response_params[:payment_method_token] = result.payment_method.payment_method_token + end + + response_options[:avs_result] = { :code => result.processor_response && result.processor_response.avs_result_code } + response_options[:cvv_result] = result.processor_response && result.processor_response.cvv_result_code + + message = message_from_result(result) + Response.new(result.success?, message, response_params, response_options) + end + + def message_from_result(result) + return "OK" if result.success? + result.errors.map {|_, messages| messages }.join(" ") + end + + def processor_options(options) + options.slice(:billing_reference, :customer_reference, :custom, :descriptor) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_net.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_net.rb new file mode 100644 index 000000000..52973b89d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_net.rb @@ -0,0 +1,329 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SecureNetGateway < Gateway + + API_VERSION = "4.0" + + TRANSACTIONS = { + :auth_only => "0000", # + :partial_auth_only => "0001", + :auth_capture => "0100", # + :partial_auth_capture => "0101", + :prior_auth_capture => "0200", + :capture_only => "0300", # + :void => "0400", # + :partial_void => "0401", + :credit => "0500", # + :credit_authonly => "0501", + :credit_priorauthcapture => "0502", + :force_credit => "0600", + :force_credit_authonly => "0601", + :force_credit_priorauthcapture => "0602", + :verification => "0700", + :auth_increment => "0800", + :issue => "0900", + :activate => "0901", + :redeem => "0902", + :redeem_partial => "0903", + :deactivate => "0904", + :reactivate => "0905", + :inquiry_balance => "0906" + } + + XML_ATTRIBUTES = { 'xmlns' => "http://gateway.securenet.com/API/Contracts", + 'xmlns:i' => "http://www.w3.org/2001/XMLSchema-instance" + } + NIL_ATTRIBUTE = { 'i:nil' => "true" } + +# SUCCESS = "true" +# SENSITIVE_FIELDS = [ :verification_str2, :expiry_date, :card_number ] + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.securenet.com/' + self.display_name = 'SecureNet' +# self.wiredump_device = STDOUT + +# self.test_url = 'https://certify.securenet.com/api/Gateway.svc' + self.test_url = 'https://certify.securenet.com/API/gateway.svc/webHttp/ProcessTransaction' + self.live_url = 'https://gateway.securenet.com/api/Gateway.svc' + + APPROVED, DECLINED, ERROR = 1, 2, 3 + + RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3 + AVS_RESULT_CODE, CARD_CODE_RESPONSE_CODE, TRANSACTION_ID = 5, 6, 8 + + CARD_CODE_ERRORS = %w( N S ) + AVS_ERRORS = %w( A E N R W Z ) + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, creditcard, options = {}) + commit(build_sale_or_authorization_request(creditcard, options, :auth_only), money) + end + + def purchase(money, creditcard, options = {}) + commit(build_sale_or_authorization_request(creditcard, options, :auth_capture), money) + end + + def capture(money, creditcard, authorization, options = {}) + commit(build_capture_request(authorization, creditcard, options, :prior_auth_capture), money) + end + + def void(money, creditcard, authorization, options = {}) + commit(build_void_request(authorization, creditcard, options, :void), money) + end + + def credit(money, creditcard, authorization, options = {}) + commit(build_credit_request(authorization, creditcard, options, :credit), money) + end + + private + def commit(request, money) + xml = build_request(request, money) + data = ssl_post(self.test_url, xml, "Content-Type" => "text/xml") + response = parse(data) + + test_mode = test? + Response.new(success?(response), message_from(response), response, + :test => test_mode, + :authorization => response[:transactionid], + :avs_result => { :code => response[:avs_result_code] }, + :cvv_result => response[:card_code_response_code] + ) + end + + def build_request(request, money) + xml = Builder::XmlMarkup.new + + xml.instruct! + xml.tag!("TRANSACTION", XML_ATTRIBUTES) do + xml.tag! 'AMOUNT', amount(money) + xml << request + end + + xml.target! + end + + def build_sale_or_authorization_request(creditcard, options, action) + xml = Builder::XmlMarkup.new + + add_credit_card(xml, creditcard) + xml.tag! 'CODE', TRANSACTIONS[action] + add_customer_data(xml, options) + add_address(xml, creditcard, options) + xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID + xml.tag! 'INSTALLMENT_SEQUENCENUM', 1 + add_invoice(xml, options) + add_merchant_key(xml, options) + xml.tag! 'METHOD', 'CC' + xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id] + xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it + xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!? + xml.tag! 'TEST', 'TRUE' + xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0 + xml.tag! 'TRANSACTION_SERVICE', 0 + + xml.target! + end + + def build_capture_or_credit_request(identification, options) + xml = Builder::XmlMarkup.new + + add_identification(xml, identification) + add_customer_data(xml, options) + + xml.target! + end + + def build_capture_request(authorization, creditcard, options, action) + xml = Builder::XmlMarkup.new + + add_credit_card(xml, creditcard) + xml.tag! 'CODE', TRANSACTIONS[action] + add_customer_data(xml, options) + xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID + xml.tag! 'INSTALLMENT_SEQUENCENUM', 1 + add_merchant_key(xml, options) + xml.tag! 'METHOD', 'CC' + xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id] + xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it + xml.tag! 'REF_TRANSID', authorization + xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!? + xml.tag! 'TEST', 'TRUE' + xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0 + xml.tag! 'TRANSACTION_SERVICE', 0 + + xml.target! + end + + def build_credit_request(authorization, creditcard, options, action) +# requires!(options, :card_number) + xml = Builder::XmlMarkup.new + + add_credit_card(xml, creditcard) + xml.tag! 'CODE', TRANSACTIONS[action] + add_customer_data(xml, options) + xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID + xml.tag! 'INSTALLMENT_SEQUENCENUM', 1 + add_merchant_key(xml, options) + xml.tag! 'METHOD', 'CC' + xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id] + xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it + xml.tag! 'REF_TRANSID', authorization + xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!? + xml.tag! 'TEST', 'TRUE' + xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0 + xml.tag! 'TRANSACTION_SERVICE', 0 + + xml.target! + end + + def build_void_request(authorization, creditcard, options, action) + xml = Builder::XmlMarkup.new + + add_credit_card(xml, creditcard) + xml.tag! 'CODE', TRANSACTIONS[action] + add_customer_data(xml, options) + xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID + xml.tag! 'INSTALLMENT_SEQUENCENUM', 1 + add_merchant_key(xml, options) + xml.tag! 'METHOD', 'CC' + xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id] + xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it + xml.tag! 'REF_TRANSID', authorization + xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!? + xml.tag! 'TEST', 'TRUE' + xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0 + xml.tag! 'TRANSACTION_SERVICE', 0 + + xml.target! + end + + ######################################################################### + # FUNCTIONS RELATED TO BUILDING THE XML + ######################################################################### + def add_credit_card(xml, creditcard) + xml.tag!("CARD") do + xml.tag! 'CARDCODE', creditcard.verification_value if creditcard.verification_value? + xml.tag! 'CARDNUMBER', creditcard.number + xml.tag! 'EXPDATE', expdate(creditcard) + end + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + + "#{month}#{year[-2..-1]}" + end + + def add_customer_data(xml, options) + if options.has_key? :customer + xml.tag! 'CUSTOMERID', options[:customer] + end + + if options.has_key? :ip + xml.tag! 'CUSTOMERIP', options[:ip] + end + end + + def add_address(xml, creditcard, options) + + if address = options[:billing_address] || options[:address] + xml.tag!("CUSTOMER_BILL") do + xml.tag! 'ADDRESS', address[:address1].to_s + xml.tag! 'CITY', address[:city].to_s + xml.tag! 'COMPANY', address[:company].to_s + xml.tag! 'COUNTRY', address[:country].to_s + if options.has_key? :email + xml.tag! 'EMAIL', options[:email] +# xml.tag! 'EMAIL', 'myemail@yahoo.com' + xml.tag! 'EMAILRECEIPT', 'FALSE' + end + xml.tag! 'FIRSTNAME', creditcard.first_name + xml.tag! 'LASTNAME', creditcard.last_name + xml.tag! 'PHONE', address[:phone].to_s + xml.tag! 'STATE', address[:state].blank? ? 'n/a' : address[:state] + xml.tag! 'ZIP', address[:zip].to_s + end + end + + if address = options[:shipping_address] + xml.tag!("CUSTOMER_SHIP") do + xml.tag! 'ADDRESS', address[:address1].to_s + xml.tag! 'CITY', address[:city].to_s + xml.tag! 'COMPANY', address[:company].to_s + xml.tag! 'COUNTRY', address[:country].to_s + xml.tag! 'FIRSTNAME', address[:first_name].to_s + xml.tag! 'LASTNAME', address[:last_name].to_s + xml.tag! 'STATE', address[:state].blank? ? 'n/a' : address[:state] + xml.tag! 'ZIP', address[:zip].to_s + end + else + xml.tag!('CUSTOMER_SHIP', NIL_ATTRIBUTE) do + end + end + + end + + def add_invoice(xml, options) + xml.tag! 'INVOICEDESC', options[:description] + xml.tag! 'INVOICENUM', 'inv-8' + end + + def add_merchant_key(xml, options) + xml.tag!("MERCHANT_KEY") do + xml.tag! 'GROUPID', 0 + xml.tag! 'SECUREKEY', @options[:password] + xml.tag! 'SECURENETID', @options[:login] + end + end + + ######################################################################### + # FUNCTIONS RELATED TO THE RESPONSE + ######################################################################### + def success?(response) + response[:response_code].to_i == APPROVED + end + + def message_from(response) + if response[:response_code].to_i == DECLINED + return CVVResult.messages[ response[:card_code_response_code] ] if CARD_CODE_ERRORS.include?(response[:card_code_response_code]) + return AVSResult.messages[ response[:avs_result_code] ] if AVS_ERRORS.include?(response[:avs_result_code]) + end + + return response[:response_reason_text].nil? ? '' : response[:response_reason_text][0..-1] + end + + def parse(xml) + response = {} + xml = REXML::Document.new(xml) + root = REXML::XPath.first(xml, "//GATEWAYRESPONSE")# || +# root = REXML::XPath.first(xml, "//ProcessTransactionResponse")# || +# REXML::XPath.first(xml, "//ErrorResponse") + if root + root.elements.to_a.each do |node| + recurring_parse_element(response, node) + end + end + + response + end + + def recurring_parse_element(response, node) + if node.has_elements? + node.elements.each{|e| recurring_parse_element(response, e) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay.rb new file mode 100644 index 000000000..96aca9e82 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay.rb @@ -0,0 +1,28 @@ +require File.dirname(__FILE__) + '/authorize_net' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SecurePayGateway < AuthorizeNetGateway + self.live_url = self.test_url = 'https://www.securepay.com/AuthSpayAdapter/process.aspx' + + self.homepage_url = 'http://www.securepay.com/' + self.display_name = 'SecurePay' + + # Limit support to purchase() for the time being + # JRuby chokes here + # undef_method :authorize, :capture, :void, :credit + + undef_method :authorize + undef_method :capture + undef_method :void + undef_method :credit + + private + + def split(response) + response.split(',') + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_au.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_au.rb new file mode 100644 index 000000000..dd552114e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_au.rb @@ -0,0 +1,279 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SecurePayAuGateway < Gateway + API_VERSION = 'xml-4.2' + PERIODIC_API_VERSION = 'spxml-3.0' + + class_attribute :test_periodic_url, :live_periodic_url + + self.test_url = 'https://www.securepay.com.au/test/payment' + self.live_url = 'https://www.securepay.com.au/xmlapi/payment' + + self.test_periodic_url = 'https://test.securepay.com.au/xmlapi/periodic' + self.live_periodic_url = 'https://api.securepay.com.au/xmlapi/periodic' + + self.supported_countries = ['AU'] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb] + + # The homepage URL of the gateway + self.homepage_url = 'http://securepay.com.au' + + # The name of the gateway + self.display_name = 'SecurePay' + + class_attribute :request_timeout + self.request_timeout = 60 + + self.money_format = :cents + self.default_currency = 'AUD' + + # 0 Standard Payment + # 4 Refund + # 6 Client Reversal (Void) + # 10 Preauthorise + # 11 Preauth Complete (Advice) + TRANSACTIONS = { + :purchase => 0, + :authorization => 10, + :capture => 11, + :void => 6, + :refund => 4 + } + + PERIODIC_ACTIONS = { + :add_triggered => "add", + :remove_triggered => "delete", + :trigger => "trigger" + } + + PERIODIC_TYPES = { + :add_triggered => 4, + :remove_triggered => nil, + :trigger => nil + } + + SUCCESS_CODES = [ '00', '08', '11', '16', '77' ] + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card_or_stored_id, options = {}) + if credit_card_or_stored_id.respond_to?(:number) + requires!(options, :order_id) + commit :purchase, build_purchase_request(money, credit_card_or_stored_id, options) + else + options[:billing_id] = credit_card_or_stored_id.to_s + commit_periodic(build_periodic_item(:trigger, money, nil, options)) + end + end + + def authorize(money, credit_card, options = {}) + requires!(options, :order_id) + commit :authorization, build_purchase_request(money, credit_card, options) + end + + def capture(money, reference, options = {}) + commit :capture, build_reference_request(money, reference) + end + + def refund(money, reference, options = {}) + commit :refund, build_reference_request(money, reference) + end + + def credit(money, reference, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, reference) + end + + def void(reference, options = {}) + commit :void, build_reference_request(nil, reference) + end + + def store(creditcard, options = {}) + requires!(options, :billing_id, :amount) + commit_periodic(build_periodic_item(:add_triggered, options[:amount], creditcard, options)) + end + + def unstore(identification, options = {}) + options[:billing_id] = identification + commit_periodic(build_periodic_item(:remove_triggered, options[:amount], nil, options)) + end + + private + + def build_purchase_request(money, credit_card, options) + xml = Builder::XmlMarkup.new + + xml.tag! 'amount', amount(money) + xml.tag! 'currency', options[:currency] || currency(money) + xml.tag! 'purchaseOrderNo', options[:order_id].to_s.gsub(/[ ']/, '') + + xml.tag! 'CreditCardInfo' do + xml.tag! 'cardNumber', credit_card.number + xml.tag! 'expiryDate', expdate(credit_card) + xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value? + end + + xml.target! + end + + def build_reference_request(money, reference) + xml = Builder::XmlMarkup.new + + transaction_id, order_id, preauth_id, original_amount = reference.split('*') + + xml.tag! 'amount', (money ? amount(money) : original_amount) + xml.tag! 'currency', options[:currency] || currency(money) + xml.tag! 'txnID', transaction_id + xml.tag! 'purchaseOrderNo', order_id + xml.tag! 'preauthID', preauth_id + + xml.target! + end + + def build_request(action, body) + xml = Builder::XmlMarkup.new + xml.instruct! + xml.tag! 'SecurePayMessage' do + xml.tag! 'MessageInfo' do + xml.tag! 'messageID', ActiveMerchant::Utils.generate_unique_id.slice(0, 30) + xml.tag! 'messageTimestamp', generate_timestamp + xml.tag! 'timeoutValue', request_timeout + xml.tag! 'apiVersion', API_VERSION + end + + xml.tag! 'MerchantInfo' do + xml.tag! 'merchantID', @options[:login] + xml.tag! 'password', @options[:password] + end + + xml.tag! 'RequestType', 'Payment' + xml.tag! 'Payment' do + xml.tag! 'TxnList', "count" => 1 do + xml.tag! 'Txn', "ID" => 1 do + xml.tag! 'txnType', TRANSACTIONS[action] + xml.tag! 'txnSource', 23 + xml << body + end + end + end + end + + xml.target! + end + + def commit(action, request) + response = parse(ssl_post(test? ? self.test_url : self.live_url, build_request(action, request))) + + Response.new(success?(response), message_from(response), response, + :test => test?, + :authorization => authorization_from(response) + ) + end + + def build_periodic_item(action, money, credit_card, options) + xml = Builder::XmlMarkup.new + + xml.tag! 'actionType', PERIODIC_ACTIONS[action] + xml.tag! 'clientID', options[:billing_id].to_s + + if credit_card + xml.tag! 'CreditCardInfo' do + xml.tag! 'cardNumber', credit_card.number + xml.tag! 'expiryDate', expdate(credit_card) + xml.tag! 'cvv', credit_card.verification_value if credit_card.verification_value? + end + end + xml.tag! 'amount', amount(money) + xml.tag! 'periodicType', PERIODIC_TYPES[action] if PERIODIC_TYPES[action] + + xml.target! + end + + def build_periodic_request(body) + xml = Builder::XmlMarkup.new + xml.instruct! + xml.tag! 'SecurePayMessage' do + xml.tag! 'MessageInfo' do + xml.tag! 'messageID', ActiveMerchant::Utils.generate_unique_id.slice(0, 30) + xml.tag! 'messageTimestamp', generate_timestamp + xml.tag! 'timeoutValue', request_timeout + xml.tag! 'apiVersion', PERIODIC_API_VERSION + end + + xml.tag! 'MerchantInfo' do + xml.tag! 'merchantID', @options[:login] + xml.tag! 'password', @options[:password] + end + + xml.tag! 'RequestType', 'Periodic' + xml.tag! 'Periodic' do + xml.tag! 'PeriodicList', "count" => 1 do + xml.tag! 'PeriodicItem', "ID" => 1 do + xml << body + end + end + end + end + xml.target! + end + + def commit_periodic(request) + my_request = build_periodic_request(request) + #puts my_request + response = parse(ssl_post(test? ? self.test_periodic_url : self.live_periodic_url, my_request)) + + Response.new(success?(response), message_from(response), response, + :test => test?, + :authorization => authorization_from(response) + ) + end + + def success?(response) + SUCCESS_CODES.include?(response[:response_code]) + end + + def authorization_from(response) + [response[:txn_id], response[:purchase_order_no], response[:preauth_id], response[:amount]].join('*') + end + + def message_from(response) + response[:response_text] || response[:status_description] + end + + def expdate(credit_card) + "#{format(credit_card.month, :two_digits)}/#{format(credit_card.year, :two_digits)}" + end + + def parse(body) + xml = REXML::Document.new(body) + + response = {} + + xml.root.elements.to_a.each do |node| + parse_element(response, node) + end + + response + end + + def parse_element(response, node) + if node.has_elements? + node.elements.each{|element| parse_element(response, element) } + else + response[node.name.underscore.to_sym] = node.text + end + end + + # YYYYDDMMHHNNSSKKK000sOOO + def generate_timestamp + time = Time.now.utc + time.strftime("%Y%d%m%H%M%S#{time.usec}+000") + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_tech.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_tech.rb new file mode 100644 index 000000000..7ab6f62e1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/secure_pay_tech.rb @@ -0,0 +1,112 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SecurePayTechGateway < Gateway + class SecurePayTechPostData < PostData + self.required_fields = [ :OrderReference, :CardNumber, :CardExpiry, :CardHolderName, :CardType, :MerchantID, :MerchantKey, :Amount, :Currency ] + end + + self.live_url = self.test_url = 'https://tx.securepaytech.com/web/HttpPostPurchase' + + PAYMENT_GATEWAY_RESPONSES = { + 1 => "Transaction OK", + 2 => "Insufficient funds", + 3 => "Card expired", + 4 => "Card declined", + 5 => "Server error", + 6 => "Communications error", + 7 => "Unsupported transaction type", + 8 => "Bad or malformed request", + 9 => "Invalid card number" + } + + self.default_currency = 'NZD' + self.supported_countries = ['NZ'] + self.supported_cardtypes = [:visa, :master, :american_express, :diners_club] + self.homepage_url = 'http://www.securepaytech.com/' + self.display_name = 'SecurePayTech' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, creditcard, options = {}) + post = SecurePayTechPostData.new + + add_invoice(post, money, options) + add_creditcard(post, creditcard) + + commit(:purchase, post) + end + + private + + def add_invoice(post, money, options) + post[:Amount] = amount(money) + post[:Currency] = options[:currency] || currency(money) + + post[:OrderReference] = options[:order_id] + end + + def add_creditcard(post, creditcard) + post[:CardNumber] = creditcard.number + post[:CardExpiry] = expdate(creditcard) + post[:CardHolderName] = creditcard.name + + if creditcard.verification_value? + post[:EnableCSC] = true + post[:CSC] = creditcard.verification_value + end + + # SPT will autodetect this + post[:CardType] = 0 + end + + def parse(body) + response = CGI.unescape(body).split(',') + + result = {} + result[:result_code] = response[0].to_i + + if response.length == 2 + result[:fail_reason] = response[1] + else + result[:merchant_transaction_reference] = response[1] + result[:receipt_number] = response[2] + result[:transaction_number] = response[3] + result[:authorisation_id] = response[4] + result[:batch_number] = response[5] + end + + result + end + + def commit(action, post) + response = parse( ssl_post(self.live_url, post_data(action, post) ) ) + + Response.new(response[:result_code] == 1, message_from(response), response, + :test => test?, + :authorization => response[:merchant_transaction_reference] + ) + end + + def message_from(result) + PAYMENT_GATEWAY_RESPONSES[result[:result_code]] + end + + def post_data(action, post) + post[:MerchantID] = @options[:login] + post[:MerchantKey] = @options[:password] + post.to_s + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + + "#{month}#{year[-2..-1]}" + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/skip_jack.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/skip_jack.rb new file mode 100644 index 000000000..f694bc81c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/skip_jack.rb @@ -0,0 +1,453 @@ +#!ruby19 +# encoding: utf-8 + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SkipJackGateway < Gateway + API_VERSION = '?.?' + + self.live_url = "https://www.skipjackic.com" + self.test_url = "https://developer.skipjackic.com" + + BASIC_PATH = "/scripts/evolvcc.dll" + ADVANCED_PATH = "/evolvcc/evolvcc.aspx" + + ACTIONS = { + :authorization => 'AuthorizeAPI', + :change_status => 'SJAPI_TransactionChangeStatusRequest', + :get_status => 'SJAPI_TransactionStatusRequest' + } + + SUCCESS_MESSAGE = 'The transaction was successful.' + + MONETARY_CHANGE_STATUSES = ['SETTLE', 'AUTHORIZE', 'AUTHORIZE ADDITIONAL', 'CREDIT', 'SPLITSETTLE'] + + CARD_CODE_ERRORS = %w( N S "" ) + + CARD_CODE_MESSAGES = { + "M" => "Card verification number matched", + "N" => "Card verification number didn't match", + "P" => "Card verification number was not processed", + "S" => "Card verification number should be on card but was not indicated", + "U" => "Issuer was not certified for card verification", + "" => "Transaction failed because incorrect card verification number was entered or no number was entered" + } + + AVS_ERRORS = %w( A B C E I N O P R W Z ) + + AVS_MESSAGES = { + "A" => "Street address matches billing information, zip/postal code does not", + "B" => "Street address match for international transaction. Postal code not verified due to incompatible formats", + "C" => "Street address and postal code not verified for internation transaction due to incompatible formats", + "D" => "Street address and postal code match for international transaction", + "E" => "Address verification service error", + "I" => "Address information not verified by international issuer", + "M" => "Street address and postal code match for international transaction", + "N" => "Neither street address nor zip/postal match billing information", + "O" => "Non-US issuer does not participate", + "P" => "Postal codes match for international transaction but street address not verified due to incompatible formats", + "P" => "Address verification not applicable for this transaction", + "R" => "Payment gateway was unavailable or timed out", + "S" => "Address verification service not supported by issuer", + "U" => "Address information is unavailable", + "W" => "9-digit zip/postal code matches billing information, street address does not", + "X" => "Street address and 9-digit zip/postal code matches billing information", + "Y" => "Street address and 5-digit zip/postal code matches billing information", + "Z" => "5-digit zip/postal code matches billing information, street address does not", + } + + CHANGE_STATUS_ERROR_MESSAGES = { + '0' => 'Success', + '-1' => 'Invalid Command', + '-2' => 'Parameter Missing', + '-3' => 'Failed retrieving response', + '-4' => 'Invalid Status', + '-5' => 'Failed reading security flags', + '-6' => 'Developer serial number not found', + '-7' => 'Invalid Serial Number' + } + + TRANSACTION_CURRENT_STATUS = { + '0' => 'Idle', + '1' => 'Authorized', + '2' => 'Denied', + '3' => 'Settled', + '4' => 'Credited', + '5' => 'Deleted', + '6' => 'Archived', + '7' => 'Pre-Authorized', + '8' => 'Split Settled' + } + + TRANSACTION_PENDING_STATUS = { + '0' => 'Idle', + '1' => 'Pending Credit', + '2' => 'Pending Settlement', + '3' => 'Pending Authorization', + '4' => 'Pending Manual Settlement', + '5' => 'Pending Recurring' + } + + RETURN_CODE_MESSAGES = { + '-1' => 'Data was not by received intact by Skipjack Transaction Network.', + '0' => 'Communication Failure. Error in Request and Response at IP level.', + '1' => 'Valid Data. Authorization request was valid.', + '-35' => 'Invalid credit card number. Retry with correct credit card number.', + '-37' => 'Merchant Processor Unavailable. Skipjack is unable to communicate with payment Processor. Retry', + '-39' => 'Length or value of HTML Serial. Number Invalid serial number. Check HTML Serial Number length and that it is a correct/valid number. Confirm you are sending to the correct environment (Development or Production)', + '-51' => 'The value or length for billing zip code is incorrect.', + '-52' => 'The value or length for shipping zip code is incorrect.', + '-53' => 'The value or length for credit card expiration month is incorrect.', + '-54' => 'The value or length of the month or year of the credit card account number was incorrect.', + '-55' => 'The value or length or billing street address is incorrect.', + '-56' => 'The value or length of the shipping address is incorrect.', + '-57' => 'The length of the transaction amount must be at least 3 digits long (excluding the decimal place).', + '-58' => 'Length or value in Merchant Name Merchant Name associated with Skipjack account is misconfigured or invalid', + '-59' => 'Length or value in Merchant Address Merchant Address associated with Skipjack account is misconfigured or invalid', + '-60' => 'Length or value in Merchant State Merchant State associated with Skipjack account is misconfigured or invalid', + '-61' => 'The value or length for shipping state/province is empty.', + '-62' => 'The value for length orderstring is empty.', + '-64' => 'The value for the phone number is incorrect.', + '-65' => 'The value or length for billing name is empty.', + '-66' => 'The value or length for billing e-mail is empty.', + '-67' => 'The value or length for billing street address is empty.', + '-68' => 'The value or length for billing city is empty.', + '-69' => 'The value or length for billing state is empty.', + '-70' => 'Empty zipcode Zip Code field is empty.', + '-71' => 'Empty ordernumber Ordernumber field is empty.', + '-72' => 'Empty accountnumber Accountnumber field is empty', + '-73' => 'Empty month Month field is empty.', + '-74' => 'Empty year Year field is empty.', + '-75' => 'Empty serialnumber Serialnumber field is empty.', + '-76' => 'Empty transactionamount Transaction amount field is empty.', + '-77' => 'Empty orderstring Orderstring field is empty.', + '-78' => 'Empty shiptophone Shiptophone field is empty.', + '-79' => 'The value or length for billing name is empty.', + '-80' => 'Length shipto name Error in the length or value of shiptophone.', + '-81' => 'Length or value of Customer location', + '-82' => 'The value or length for billing state is empty.', + '-83' => 'The value or length for shipping phone is empty.', + '-84' => 'There is already an existing pending transaction in the register sharing the posted Order Number.', + '-85' => 'Airline leg info invalid Airline leg field value is invalid or empty.', + '-86' => 'Airline ticket info invalid Airline ticket info field is invalid or empty', + '-87' => 'Point of Sale check routing number must be 9 numeric digits Point of Sale check routing number is invalid or empty.', + '-88' => 'Point of Sale check account number missing or invalid Point of Sale check account number is invalid or empty.', + '-89' => 'Point of Sale check MICR missing or invalid Point of Sale check MICR invalid or empty.', + '-90' => 'Point of Sale check number missing or invalid Point of Sale check number invalid or empty.', + '-91' => 'CVV2 Invalid or empty "Make CVV a required field feature" enabled (New feature 01 April 2006) in the Merchant Account Setup interface but no CVV code was sent in the transaction data.', + '-92' => 'Approval Code Invalid Approval Code Invalid. Approval Code is a 6 digit code.', + '-93' => 'Blind Credits Request Refused "Allow Blind Credits" option must be enabled on the Skipjack Merchant Account.', + '-94' => 'Blind Credits Failed', + '-95' => 'Voice Authorization Request Refused Voice Authorization option must be enabled on the Skipjack Merchant Account.', + '-96' => 'Voice Authorizations Failed', + '-97' => 'Fraud Rejection Violates Velocity Settling.', + '-98' => 'Invalid Discount Amount', + '-99' => 'POS PIN Debit Pin Block Debit-specific', + '-100' => 'POS PIN Debit Invalid Key Serial Number Debit-specific', + '-101' => 'Invalid Authentication Data Data for Verified by Visa/MC Secure Code is invalid.', + '-102' => 'Authentication Data Not Allowed', + '-103' => 'POS Check Invalid Birth Date POS check dateofbirth variable contains a birth date in an incorrect format. Use MM/DD/YYYY format for this variable.', + '-104' => 'POS Check Invalid Identification Type POS check identificationtype variable contains a identification type value which is invalid. Use the single digit value where Social Security Number=1, Drivers License=2 for this variable.', + '-105' => 'Invalid trackdata Track Data is in invalid format.', + '-106' => 'POS Check Invalid Account Type', + '-107' => 'POS PIN Debit Invalid Sequence Number', + '-108' => 'Invalid Transaction ID', + '-109' => 'Invalid From Account Type', + '-110' => 'Pos Error Invalid To Account Type', + '-112' => 'Pos Error Invalid Auth Option', + '-113' => 'Pos Error Transaction Failed', + '-114' => 'Pos Error Invalid Incoming Eci', + '-115' => 'POS Check Invalid Check Type', + '-116' => 'POS Check Invalid Lane Number POS Check lane or cash register number is invalid. Use a valid lane or cash register number that has been configured in the Skipjack Merchant Account.', + '-117' => 'POS Check Invalid Cashier Number' + } + + self.supported_countries = ['US', 'CA'] + self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover, :diners_club] + self.homepage_url = 'http://www.skipjack.com/' + self.display_name = 'SkipJack' + + # Creates a new SkipJackGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * <tt>:login</tt> -- The SkipJack Merchant Serial Number. + # * <tt>:password</tt> -- The SkipJack Developer Serial Number. + # * <tt>:test => +true+ or +false+</tt> -- Use the test or live SkipJack url. + # * <tt>:advanced => +true+ or +false+</tt> -- Set to true if you're using an advanced processor + # See the SkipJack Integration Guide for details. (default: +false+) + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, creditcard, options = {}) + requires!(options, :order_id, :email) + post = {} + add_invoice(post, options) + add_creditcard(post, creditcard) + add_address(post, options) + add_customer_data(post, options) + commit(:authorization, money, post) + end + + def purchase(money, creditcard, options = {}) + post = {} + authorization = authorize(money, creditcard, options) + if authorization.success? + capture(money, authorization.authorization) + else + authorization + end + end + + # Captures the funds from an authorized transaction. + # + # ==== Parameters + # + # * <tt>money</tt> -- The amount to be capture as an Integer in cents. + # * <tt>authorization</tt> -- The authorization returned from the previous authorize request. + # * <tt>options</tt> -- A hash of optional parameters. + # + # ==== Options + # + # * <tt>:force_settlement</tt> -- Force the settlement to occur as soon as possible. This option is not supported by other gateways. See the SkipJack API reference for more details + def capture(money, authorization, options = {}) + post = { } + add_status_action(post, 'SETTLE') + add_forced_settlement(post, options) + add_transaction_id(post, authorization) + commit(:change_status, money, post) + end + + def void(authorization, options = {}) + post = {} + add_status_action(post, 'DELETE') + add_forced_settlement(post, options) + add_transaction_id(post, authorization) + commit(:change_status, nil, post) + end + + def refund(money, identification, options = {}) + post = {} + add_status_action(post, 'CREDIT') + add_forced_settlement(post, options) + add_transaction_id(post, identification) + commit(:change_status, money, post) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + def status(order_id) + commit(:get_status, nil, :szOrderNumber => order_id) + end + + private + + def advanced? + @options[:advanced] + end + + def add_forced_settlement(post, options) + post[:szForceSettlement] = options[:force_settlment] ? 1 : 0 + end + + def add_status_action(post, action) + post[:szDesiredStatus] = action + end + + def commit(action, money, parameters) + response = parse( ssl_post( url_for(action), post_data(action, money, parameters) ), action ) + + # Pass along the original transaction id in the case an update transaction + Response.new(response[:success], message_from(response, action), response, + :test => test?, + :authorization => response[:szTransactionFileName] || parameters[:szTransactionId], + :avs_result => { :code => response[:szAVSResponseCode] }, + :cvv_result => response[:szCVV2ResponseCode] + ) + end + + def url_for(action) + result = test? ? self.test_url : self.live_url + result += advanced? && action == :authorization ? ADVANCED_PATH : BASIC_PATH + result += "?#{ACTIONS[action]}" + end + + def add_credentials(params, action) + if action == :authorization + params[:SerialNumber] = @options[:login] + params[:DeveloperSerialNumber] = @options[:password] + else + params[:szSerialNumber] = @options[:login] + params[:szDeveloperSerialNumber] = @options[:password] + end + end + + def add_amount(params, action, money) + if action == :authorization + params[:TransactionAmount] = amount(money) + else + params[:szAmount] = amount(money) if MONETARY_CHANGE_STATUSES.include?(params[:szDesiredStatus]) + end + end + + def parse(body, action) + case action + when :authorization + parse_authorization_response(body) + when :get_status + parse_status_response(body, [ :SerialNumber, :TransactionAmount, :TransactionStatusCode, :TransactionStatusMessage, :OrderNumber, :TransactionDateTime, :TransactionID, :ApprovalCode, :BatchNumber ]) + else + parse_status_response(body, [ :SerialNumber, :TransactionAmount, :DesiredStatus, :StatusResponse, :StatusResponseMessage, :OrderNumber, :AuditID ]) + end + end + + def split_lines(body) + body.split(/[\r\n]+/) + end + + def split_line(line) + line.split(/","/).collect { |key| key.sub(/"*([^"]*)"*/, '\1').strip; } + end + + def authorize_response_map(body) + lines = split_lines(body) + keys, values = split_line(lines[0]), split_line(lines[1]) + Hash[*(keys.zip(values).flatten)].symbolize_keys + end + + def parse_authorization_response(body) + result = authorize_response_map(body) + result[:success] = (result[:szIsApproved] == '1') + result + end + + def parse_status_response(body, response_keys) + lines = split_lines(body) + + keys = [ :szSerialNumber, :szErrorCode, :szNumberRecords] + values = split_line(lines[0])[0..2] + + result = Hash[*(keys.zip(values).flatten)] + + result[:szErrorMessage] = '' + result[:success] = (result[:szErrorCode] == '0') + + if result[:success] + lines[1..-1].each do |line| + values = split_line(line) + response_keys.each_with_index do |key, index| + result[key] = values[index] + end + end + else + result[:szErrorMessage] = lines[1] + end + result + end + + def post_data(action, money, params = {}) + add_credentials(params, action) + add_amount(params, action, money) + sorted_params = params.to_a.sort{|a,b| a.to_s <=> b.to_s}.reverse + sorted_params.collect { |key, value| "#{key.to_s}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def add_transaction_id(post, transaction_id) + post[:szTransactionId] = transaction_id + end + + def add_invoice(post, options) + post[:OrderNumber] = sanitize_order_id(options[:order_id]) + post[:CustomerCode] = options[:customer].to_s.slice(0, 17) + post[:InvoiceNumber] = options[:invoice] + post[:OrderDescription] = options[:description] + + if order_items = options[:items] + post[:OrderString] = order_items.collect { |item| "#{item[:sku]}~#{item[:description].tr('~','-')}~#{item[:declared_value]}~#{item[:quantity]}~#{item[:taxable]}~~~~~~~~#{item[:tax_rate]}~||"}.join + else + post[:OrderString] = '1~None~0.00~0~N~||' + end + end + + def add_creditcard(post, creditcard) + post[:AccountNumber] = creditcard.number + post[:Month] = creditcard.month + post[:Year] = creditcard.year + post[:CVV2] = creditcard.verification_value if creditcard.verification_value? + post[:SJName] = creditcard.name + end + + def add_customer_data(post, options) + post[:Email] = options[:email] + end + + def add_address(post, options) + if address = options[:billing_address] || options[:address] + post[:StreetAddress] = address[:address1] + post[:StreetAddress2] = address[:address2] + post[:City] = address[:city] + post[:State] = address[:state] + post[:ZipCode] = address[:zip] + post[:Country] = address[:country] + post[:Phone] = address[:phone] + post[:Fax] = address[:fax] + end + + if address = options[:shipping_address] + post[:ShipToName] = address[:name] + post[:ShipToStreetAddress] = address[:address1] + post[:ShipToStreetAddress2] = address[:address2] + post[:ShipToCity] = address[:city] + post[:ShipToState] = address[:state] + post[:ShipToZipCode] = address[:zip] + post[:ShipToCountry] = address[:country] + post[:ShipToPhone] = address[:phone] + post[:ShipToFax] = address[:fax] + end + + # The phone number for the shipping address is required + # Use the billing address phone number if a shipping address + # phone number wasn't provided + post[:ShipToPhone] = post[:Phone] if post[:ShipToPhone].blank? + end + + def message_from(response, action) + case action + when :authorization + message_from_authorization(response) + when :get_status + message_from_status(response) + else + message_from_status(response) + end + end + + def message_from_authorization(response) + if response[:success] + return SUCCESS_MESSAGE + else + return CARD_CODE_MESSAGES[response[:szCVV2ResponseCode]] if CARD_CODE_ERRORS.include?(response[:szCVV2ResponseCode]) + return AVS_MESSAGES[response[:szAVSResponseMessage]] if AVS_ERRORS.include?(response[:szAVSResponseCode]) + return RETURN_CODE_MESSAGES[response[:szReturnCode]] if response[:szReturnCode] != '1' + return response[:szAuthorizationDeclinedMessage] + end + end + + def message_from_status(response) + response[:success] ? SUCCESS_MESSAGE : response[:szErrorMessage] + end + + def sanitize_order_id(value) + value.to_s.gsub(/[^\w.]/, '') + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/smart_ps.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/smart_ps.rb new file mode 100644 index 000000000..bc1690e9e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/smart_ps.rb @@ -0,0 +1,272 @@ +require File.join(File.dirname(__FILE__), '..', 'check.rb') + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class SmartPs < Gateway #:nodoc: + + ## + # This is the base gateway for processors who use the smartPS processing system + + self.abstract_class = true + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Pass :store => true in the options to store the + # payment info at the gateway and get a generated + # customer_vault_id in the response. + # Pass :store => some_number_or_string to specify the + # customer_vault_id the gateway should use (make sure it's + # unique). + def authorize(money, creditcard, options = {}) + post = {} + add_invoice(post, options) + add_payment_source(post, creditcard,options) + add_address(post, options[:billing_address] || options[:address]) + add_address(post, options[:shipping_address], "shipping") + add_customer_data(post, options) + add_currency(post, money, options) + add_taxes(post, options) + add_processor(post, options) + commit('auth', money, post) + end + + def purchase(money, payment_source, options = {}) + post = {} + add_invoice(post, options) + add_payment_source(post, payment_source, options) + add_address(post, options[:billing_address] || options[:address]) + add_address(post, options[:shipping_address], "shipping") + add_customer_data(post, options) + add_currency(post, money, options) + add_taxes(post, options) + add_processor(post, options) + commit('sale', money, post) + end + + def capture(money, authorization, options = {}) + post ={} + post[:transactionid] = authorization + commit('capture', money, post) + end + + def void(authorization, options = {}) + post ={} + post[:transactionid] = authorization + commit('void', nil, post) + end + + def credit(money, payment_source, options = {}) + post = {} + add_invoice(post, options) + add_payment_source(post, payment_source, options) + add_address(post, options[:billing_address] || options[:address]) + add_customer_data(post, options) + add_sku(post,options) + add_currency(post, money, options) + add_processor(post, options) + commit('credit', money, post) + end + + def refund(money, auth, options = {}) + post = {} + add_transaction(post, auth) + commit('refund', money, post) + end + + + # Update the values (such as CC expiration) stored at + # the gateway. The CC number must be supplied in the + # CreditCard object. + def update(vault_id, creditcard, options = {}) + post = {} + post[:customer_vault] = "update_customer" + add_customer_vault_id(post, vault_id) + add_creditcard(post, creditcard, options) + add_address(post, options[:billing_address] || options[:address]) + add_customer_data(post, options) + + commit(nil, nil, post) + end + + # Amend an existing transaction + def amend(auth, options = {}) + post = {} + add_invoice(post, options) + add_transaction(post, auth) + commit('update', nil, post) + end + + + def delete(vault_id) + post = {} + post[:customer_vault] = "delete_customer" + add_customer_vault_id(post, vault_id) + commit(nil, nil, post) + end + + # To match the other stored-value gateways, like TrustCommerce, + # store and unstore need to be defined + def store(payment_source, options = {}) + post = {} + billing_id = options.delete(:billing_id).to_s || true + add_payment_source(post, payment_source, :store => billing_id) + add_address(post, options[:billing_address] || options[:address]) + add_customer_data(post, options) + commit(nil, nil, post) + end + + alias_method :unstore, :delete + + private + def add_customer_data(post, options) + if options.has_key? :email + post[:email] = options[:email] + end + + if options.has_key? :ip + post[:ipaddress] = options[:ip] + end + end + + def add_address(post, address,prefix="") + prefix +="_" unless prefix.blank? + unless address.blank? or address.values.blank? + post[prefix+"address1"] = address[:address1].to_s + post[prefix+"address2"] = address[:address2].to_s unless address[:address2].blank? + post[prefix+"company"] = address[:company].to_s + post[prefix+"phone"] = address[:phone].to_s + post[prefix+"zip"] = address[:zip].to_s + post[prefix+"city"] = address[:city].to_s + post[prefix+"country"] = address[:country].to_s + post[prefix+"state"] = address[:state].blank? ? 'n/a' : address[:state] + end + end + + def add_currency(post, money, options) + post[:currency] = options[:currency] || currency(money) + end + + def add_taxes(post, options) + post[:tax] = amount(options[:tax]) + end + + def add_processor(post, options) + post[:processor] = options[:processor] unless options[:processor].nil? + end + + def add_invoice(post, options) + post[:orderid] = options[:order_id].to_s.gsub(/[^\w.]/, '') + end + + def add_payment_source(params, source, options={}) + case determine_funding_source(source) + when :vault then add_customer_vault_id(params, source) + when :credit_card then add_creditcard(params, source, options) + when :check then add_check(params, source, options) + end + end + + def add_customer_vault_id(params, vault_id) + params[:customer_vault_id] = vault_id + end + + def add_creditcard(post, creditcard, options) + if options[:store] + post[:customer_vault] = "add_customer" + post[:customer_vault_id] = options[:store] unless options[:store] == true + end + post[:ccnumber] = creditcard.number + post[:cvv] = creditcard.verification_value if creditcard.verification_value? + post[:ccexp] = expdate(creditcard) + post[:firstname] = creditcard.first_name + post[:lastname] = creditcard.last_name + end + + def add_check(post, check, options) + if options[:store] + post[:customer_vault] = "add_customer" + post[:customer_vault_id] = options[:store] unless options[:store] == true + end + + post[:payment] = 'check' # Set transaction to ACH + post[:checkname] = check.name # The name on the customer's Checking Account + post[:checkaba] = check.routing_number # The customer's bank routing number + post[:checkaccount] = check.account_number # The customer's account number + post[:account_holder_type] = check.account_holder_type # The customer's type of ACH account + post[:account_type] = check.account_type # The customer's type of ACH account + end + + def add_sku(post,options) + post["product_sku_#"] = options[:sku] || options["product_sku_#"] + end + + def add_transaction(post, auth) + post[:transactionid] = auth + end + + def parse(body) + results = {} + body.split(/&/).each do |pair| + key,val = pair.split(/=/) + results[key] = val + end + + results + end + + def commit(action, money, parameters) + parameters[:amount] = amount(money) if money + response = parse( ssl_post(self.live_url, post_data(action,parameters)) ) + Response.new(response["response"] == "1", message_from(response), response, + :authorization => (response["transactionid"] || response["customer_vault_id"]), + :test => test?, + :cvv_result => response["cvvresponse"], + :avs_result => { :code => response["avsresponse"] } + ) + + end + + def expdate(creditcard) + year = sprintf("%.04i", creditcard.year.to_i) + month = sprintf("%.02i", creditcard.month.to_i) + + "#{month}#{year[-2..-1]}" + end + + + def message_from(response) + case response["responsetext"] + when "SUCCESS", "Approved", nil # This is dubious, but responses from UPDATE are nil. + "This transaction has been approved" + when "DECLINE" + "This transaction has been declined" + else + response["responsetext"] + end + end + + def post_data(action, parameters = {}) + post = {} + post[:username] = @options[:login] + post[:password] = @options[:password] + post[:type] = action if action + + request = post.merge(parameters).map {|key,value| "#{key}=#{CGI.escape(value.to_s)}"}.join("&") + request + end + + def determine_funding_source(source) + case + when source.is_a?(String) then :vault + when CreditCard.card_companies.keys.include?(card_brand(source)) then :credit_card + when card_brand(source) == 'check' then :check + else raise ArgumentError, "Unsupported funding source provided" + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/spreedly_core.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/spreedly_core.rb new file mode 100644 index 000000000..1a07ab062 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/spreedly_core.rb @@ -0,0 +1,233 @@ +require 'nokogiri' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # Public: This gateway allows you to interact with any gateway you've + # created in Spreedly (https://spreedly.com). It's an adapter which can be + # particularly useful if you already have code interacting with + # ActiveMerchant and want to easily take advantage of Spreedly's vault. + class SpreedlyCoreGateway < Gateway + self.live_url = 'https://core.spreedly.com/v1' + + self.supported_countries = %w(AD AE AT AU BD BE BG BN CA CH CY CZ DE DK EE EG ES FI FR GB + GI GR HK HU ID IE IL IM IN IS IT JO KW LB LI LK LT LU LV MC + MT MU MV MX MY NL NO NZ OM PH PL PT QA RO SA SE SG SI SK SM + TR TT UM US VA VN ZA) + + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'https://spreedly.com' + self.display_name = 'Spreedly' + self.money_format = :cents + self.default_currency = 'USD' + + # Public: Create a new Spreedly gateway. + # + # options - A hash of options: + # :login - The environment key. + # :password - The access secret. + # :gateway_token - The token of the gateway you've created in + # Spreedly. + def initialize(options = {}) + requires!(options, :login, :password, :gateway_token) + super + end + + # Public: Run a purchase transaction. + # + # money - The monetary amount of the transaction in cents. + # payment_method - The CreditCard or the Spreedly payment method token. + # options - A standard ActiveMerchant options hash + def purchase(money, payment_method, options = {}) + if payment_method.is_a?(String) + purchase_with_token(money, payment_method, options) + else + MultiResponse.run do |r| + r.process { save_card(false, payment_method, options) } + r.process { purchase_with_token(money, r.authorization, options) } + end + end + end + + # Public: Run an authorize transaction. + # + # money - The monetary amount of the transaction in cents. + # payment_method - The CreditCard or the Spreedly payment method token. + # options - A standard ActiveMerchant options hash + def authorize(money, payment_method, options = {}) + if payment_method.is_a?(String) + authorize_with_token(money, payment_method, options) + else + MultiResponse.run do |r| + r.process { save_card(false, payment_method, options) } + r.process { authorize_with_token(money, r.authorization, options) } + end + end + end + + def capture(money, authorization, options={}) + request = build_xml_request('transaction') do |doc| + add_invoice(doc, money, options) + end + + commit("transactions/#{authorization}/capture.xml", request) + end + + def refund(money, authorization, options={}) + request = build_xml_request('transaction') do |doc| + add_invoice(doc, money, options) + end + + commit("transactions/#{authorization}/credit.xml", request) + end + + def void(authorization, options={}) + commit("transactions/#{authorization}/void.xml", '') + end + + # Public: Store a credit card in the Spreedly vault and retain it. + # + # credit_card - The CreditCard to store + # options - A standard ActiveMerchant options hash + def store(credit_card, options={}) + save_card(true, credit_card, options) + end + + # Public: Redact the CreditCard in Spreedly. This wipes the sensitive + # payment information from the card. + # + # credit_card - The CreditCard to store + # options - A standard ActiveMerchant options hash + def unstore(authorization, options={}) + commit("payment_methods/#{authorization}/redact.xml", '', :put) + end + + private + def save_card(retain, credit_card, options) + request = build_xml_request('payment_method') do |doc| + add_credit_card(doc, credit_card, options) + add_data(doc, options) + doc.retained(true) if retain + end + + commit("payment_methods.xml", request, :post, :payment_method_token) + end + + def purchase_with_token(money, payment_method_token, options) + request = auth_purchase_request(money, payment_method_token, options) + commit("gateways/#{@options[:gateway_token]}/purchase.xml", request) + end + + def authorize_with_token(money, payment_method_token, options) + request = auth_purchase_request(money, payment_method_token, options) + commit("gateways/#{@options[:gateway_token]}/authorize.xml", request) + end + + def auth_purchase_request(money, payment_method_token, options) + build_xml_request('transaction') do |doc| + add_invoice(doc, money, options) + doc.payment_method_token(payment_method_token) + end + end + + def add_invoice(doc, money, options) + doc.amount amount(money) + doc.currency_code(options[:currency] || currency(money) || default_currency) + end + + def add_credit_card(doc, credit_card, options) + doc.credit_card do + doc.number(credit_card.number) + doc.first_name(credit_card.first_name) + doc.last_name(credit_card.last_name) + doc.month(credit_card.month) + doc.year(credit_card.year) + doc.email(options[:email]) + doc.address1(options[:billing_address].try(:[], :address1)) + doc.address2(options[:billing_address].try(:[], :address2)) + doc.city(options[:billing_address].try(:[], :city)) + doc.state(options[:billing_address].try(:[], :state)) + doc.zip(options[:billing_address].try(:[], :zip)) + end + end + + def add_data(doc, options) + doc.data do + data_to_doc(doc, options[:data]) + end + end + + def data_to_doc(doc, value) + return doc.text value unless value.kind_of? Hash + value.each do |k, v| + doc.send(k) do + data_to_doc(doc, v) + end + end + end + + def parse(xml) + response = {} + + doc = Nokogiri::XML(xml) + doc.root.xpath('*').each do |node| + if (node.elements.empty?) + response[node.name.downcase.to_sym] = node.text + else + node.elements.each do |childnode| + childnode_to_response(response, node, childnode) + end + end + end + + response + end + + def childnode_to_response(response, node, childnode) + name = "#{node.name.downcase}_#{childnode.name.downcase}" + if name == 'payment_method_data' && !childnode.elements.empty? + response[name.to_sym] = Hash.from_xml(childnode.to_s).values.first + else + response[name.to_sym] = childnode.text + end + end + + def build_xml_request(root) + builder = Nokogiri::XML::Builder.new + builder.__send__(root) do |doc| + yield(doc) + end + builder.to_xml + end + + def commit(relative_url, request, method = :post, authorization_field = :token) + begin + raw_response = ssl_request(method, "#{live_url}/#{relative_url}", request, headers) + rescue ResponseError => e + raw_response = e.response.body + end + + response_from(raw_response, authorization_field) + end + + def response_from(raw_response, authorization_field) + parsed = parse(raw_response) + options = { + :authorization => parsed[authorization_field], + :test => (parsed[:on_test_gateway] == 'true'), + :avs_result => { :code => parsed[:response_avs_code] }, + :cvv_result => parsed[:response_cvv_code] + } + + Response.new(parsed[:succeeded] == 'true', parsed[:message] || parsed[:error], parsed, options) + end + + def headers + { + 'Authorization' => ('Basic ' + Base64.strict_encode64("#{@options[:login]}:#{@options[:password]}").chomp), + 'Content-Type' => 'text/xml' + } + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/stripe.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/stripe.rb new file mode 100644 index 000000000..4c1f7e42d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/stripe.rb @@ -0,0 +1,255 @@ +require 'json' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class StripeGateway < Gateway + self.live_url = 'https://api.stripe.com/v1/' + + AVS_CODE_TRANSLATOR = { + 'line1: pass, zip: pass' => 'Y', + 'line1: pass, zip: fail' => 'A', + 'line1: pass, zip: unchecked' => 'B', + 'line1: fail, zip: pass' => 'Z', + 'line1: fail, zip: fail' => 'N', + 'line1: unchecked, zip: pass' => 'P', + 'line1: unchecked, zip: unchecked' => 'I' + } + + CVC_CODE_TRANSLATOR = { + 'pass' => 'M', + 'fail' => 'N', + 'unchecked' => 'P' + } + + self.supported_countries = ['US', 'CA'] + self.default_currency = 'USD' + self.money_format = :cents + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club] + + self.homepage_url = 'https://stripe.com/' + self.display_name = 'Stripe' + + def initialize(options = {}) + requires!(options, :login) + @api_key = options[:login] + super + end + + def authorize(money, creditcard, options = {}) + post = create_post_for_auth_or_purchase(money, creditcard, options) + post[:capture] = "false" + meta = generate_meta(options) + + commit(:post, 'charges', post, meta) + end + + # To create a charge on a card or a token, call + # + # purchase(money, card_hash_or_token, { ... }) + # + # To create a charge on a customer, call + # + # purchase(money, nil, { :customer => id, ... }) + def purchase(money, creditcard, options = {}) + post = create_post_for_auth_or_purchase(money, creditcard, options) + meta = generate_meta(options) + + commit(:post, 'charges', post, meta) + end + + def capture(money, authorization, options = {}) + commit(:post, "charges/#{CGI.escape(authorization)}/capture", {:amount => amount(money)}) + end + + def void(identification, options = {}) + commit(:post, "charges/#{CGI.escape(identification)}/refund", {}) + end + + def refund(money, identification, options = {}) + meta = generate_meta(options) + post = {} + + post[:amount] = amount(money) if money + + commit(:post, "charges/#{CGI.escape(identification)}/refund", post, meta) + end + + def store(creditcard, options = {}) + post = {} + add_creditcard(post, creditcard, options) + post[:description] = options[:description] + post[:email] = options[:email] + + meta = generate_meta(options) + path = if options[:customer] + "customers/#{CGI.escape(options[:customer])}" + else + 'customers' + end + + commit(:post, path, post, meta) + end + + def update(customer_id, creditcard, options = {}) + options = options.merge(:customer => customer_id) + store(creditcard, options) + end + + def unstore(customer_id, options = {}) + meta = generate_meta(options) + commit(:delete, "customers/#{CGI.escape(customer_id)}", nil, meta) + end + + private + + def create_post_for_auth_or_purchase(money, creditcard, options) + post = {} + add_amount(post, money, options) + add_creditcard(post, creditcard, options) + add_customer(post, options) + add_customer_data(post,options) + post[:description] = options[:description] || options[:email] + post[:application_fee] = options[:application_fee] if options[:application_fee] + add_flags(post, options) + post + end + + def add_amount(post, money, options) + post[:amount] = amount(money) + post[:currency] = (options[:currency] || currency(money)).downcase + end + + def add_customer_data(post, options) + metadata_options = [:description,:browser_ip,:user_agent,:referrer] + post.update(options.slice(*metadata_options)) + + post[:external_id] = options[:order_id] + post[:payment_user_agent] = "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}" + end + + def add_address(post, options) + return unless post[:card] && post[:card].kind_of?(Hash) + if address = options[:billing_address] || options[:address] + post[:card][:address_line1] = address[:address1] if address[:address1] + post[:card][:address_line2] = address[:address2] if address[:address2] + post[:card][:address_country] = address[:country] if address[:country] + post[:card][:address_zip] = address[:zip] if address[:zip] + post[:card][:address_state] = address[:state] if address[:state] + post[:card][:address_city] = address[:city] if address[:city] + end + end + + def add_creditcard(post, creditcard, options) + if creditcard.respond_to?(:number) + card = {} + card[:number] = creditcard.number + card[:exp_month] = creditcard.month + card[:exp_year] = creditcard.year + card[:cvc] = creditcard.verification_value if creditcard.verification_value? + card[:name] = creditcard.name if creditcard.name + post[:card] = card + + add_address(post, options) + elsif creditcard.kind_of?(String) + post[:card] = creditcard + end + end + + def add_customer(post, options) + post[:customer] = options[:customer] if options[:customer] && !post[:card] + end + + def add_flags(post, options) + post[:uncaptured] = true if options[:uncaptured] + end + + def parse(body) + JSON.parse(body) + end + + def post_data(params) + return nil unless params + + params.map do |key, value| + next if value.blank? + if value.is_a?(Hash) + h = {} + value.each do |k, v| + h["#{key}[#{k}]"] = v unless v.blank? + end + post_data(h) + else + "#{key}=#{CGI.escape(value.to_s)}" + end + end.compact.join("&") + end + + def generate_meta(options) + {:ip => options[:ip]} + end + + def headers(meta={}) + @@ua ||= JSON.dump({ + :bindings_version => ActiveMerchant::VERSION, + :lang => 'ruby', + :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})", + :platform => RUBY_PLATFORM, + :publisher => 'active_merchant', + :uname => (RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil) + }) + + { + "Authorization" => "Basic " + Base64.encode64(@api_key.to_s + ":").strip, + "User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}", + "X-Stripe-Client-User-Agent" => @@ua, + "X-Stripe-Client-User-Metadata" => meta.to_json + } + end + + def commit(method, url, parameters=nil, meta={}) + raw_response = response = nil + success = false + begin + raw_response = ssl_request(method, self.live_url + url, post_data(parameters), headers(meta)) + response = parse(raw_response) + success = !response.key?("error") + rescue ResponseError => e + raw_response = e.response.body + response = response_error(raw_response) + rescue JSON::ParserError + response = json_error(raw_response) + end + + card = response["card"] || response["active_card"] || {} + avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"] + cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]] + Response.new(success, + success ? "Transaction approved" : response["error"]["message"], + response, + :test => response.has_key?("livemode") ? !response["livemode"] : false, + :authorization => response["id"], + :avs_result => { :code => avs_code }, + :cvv_result => cvc_code + ) + end + + def response_error(raw_response) + begin + parse(raw_response) + rescue JSON::ParserError + json_error(raw_response) + end + end + + def json_error(raw_response) + msg = 'Invalid response received from the Stripe API. Please contact support@stripe.com if you continue to receive this message.' + msg += " (The raw response returned by the API was #{raw_response.inspect})" + { + "error" => { + "message" => msg + } + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trans_first.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trans_first.rb new file mode 100644 index 000000000..013fdf581 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trans_first.rb @@ -0,0 +1,126 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class TransFirstGateway < Gateway + self.live_url = self.test_url = 'https://webservices.primerchants.com/creditcard.asmx/CCSale' + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.transfirst.com/' + self.display_name = 'TransFirst' + + UNUSED_FIELDS = %w(ECIValue UserId CAVVData TrackData POSInd EComInd MerchZIP MerchCustPNum MCC InstallmentNum InstallmentOf POSEntryMode POSConditionCode AuthCharInd CardCertData) + + DECLINED = 'The transaction was declined' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card, options = {}) + post = {} + + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, options) + + commit(post) + end + + private + def add_amount(post, money) + add_pair(post, :Amount, amount(money), :required => true) + end + + def add_address(post, options) + address = options[:billing_address] || options[:address] + + if address + add_pair(post, :Address, address[:address1]) + add_pair(post, :ZipCode, address[:zip]) + end + end + + def add_invoice(post, options) + add_pair(post, :RefID, options[:order_id], :required => true) + add_pair(post, :PONumber, options[:invoice], :required => true) + add_pair(post, :SaleTaxAmount, amount(options[:tax] || 0)) + add_pair(post, :PaymentDesc, options[:description], :required => true) + add_pair(post, :TaxIndicator, 0) + end + + def add_credit_card(post, credit_card) + add_pair(post, :CardHolderName, credit_card.name, :required => true) + add_pair(post, :CardNumber, credit_card.number, :required => true) + + add_pair(post, :Expiration, expdate(credit_card), :required => true) + add_pair(post, :CVV2, credit_card.verification_value) + end + + def add_unused_fields(post) + UNUSED_FIELDS.each do |f| + post[f] = "" + end + end + + def expdate(credit_card) + year = format(credit_card.year, :two_digits) + month = format(credit_card.month, :two_digits) + + "#{month}#{year}" + end + + def parse(data) + response = {} + + xml = REXML::Document.new(data) + root = REXML::XPath.first(xml, "//CCSaleDebitResponse") + + if root.nil? + response[:message] = data.to_s.strip + else + root.elements.to_a.each do |node| + response[node.name.underscore.to_sym] = node.text + end + end + + response + end + + def commit(params) + response = parse( ssl_post(self.live_url, post_data(params)) ) + + Response.new(response[:status] == "Authorized", message_from(response), response, + :test => test?, + :authorization => response[:trans_id], + :avs_result => { :code => response[:avs_code] }, + :cvv_result => response[:cvv2_code] + ) + end + + def message_from(response) + case response[:message] + when 'Call Voice Center' + DECLINED + else + response[:message] + end + end + + def post_data(params = {}) + add_unused_fields(params) + params[:MerchantID] = @options[:login] + params[:RegKey] = @options[:password] + + request = params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") + request + end + + def add_pair(post, key, value, options = {}) + post[key] = value if !value.blank? || options[:required] + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transax.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transax.rb new file mode 100644 index 000000000..c11c830ba --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transax.rb @@ -0,0 +1,23 @@ +require File.join(File.dirname(__FILE__),'smart_ps.rb') + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class TransaxGateway < SmartPs + self.live_url = self.test_url = 'https://secure.nelixtransax.net/api/transact.php' + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['US'] + + # The card types supported by the payment gateway + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + # The homepage URL of the gateway + self.homepage_url = 'https://www.nelixtransax.com/' + + # The name of the gateway + self.display_name = 'NELiX TransaX' + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transnational.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transnational.rb new file mode 100644 index 000000000..5c49489ba --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/transnational.rb @@ -0,0 +1,239 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class TransnationalGateway < Gateway + self.live_url = self.test_url = 'https://secure.networkmerchants.com/api/transact.php' + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + + self.homepage_url = 'http://www.tnbci.com/' + self.display_name = 'Transnational' + + self.money_format = :dollars + self.default_currency = 'USD' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def authorize(money, creditcard_or_vault_id, options = {}) + post = build_auth_post(money, creditcard_or_vault_id, options) + commit('auth', post) + end + + def purchase(money, creditcard_or_vault_id, options = {}) + post = build_purchase_post(money, creditcard_or_vault_id, options) + commit('sale', post) + end + + def capture(money, authorization, options = {}) + post = build_capture_post(money, authorization, options) + commit('capture', post) + end + + def void(authorization, options = {}) + post = build_void_post(authorization, options) + commit('void', post) + end + + def refund(money, authorization, options = {}) + post = build_refund_post(money, authorization, options) + commit('refund', post) + end + + def store(creditcard, options = {}) + post = build_store_post(creditcard, options) + commit_vault('add_customer', post) + end + + def unstore(customer_vault_id, options = {}) + post = build_unstore_post(customer_vault_id, options) + commit_vault('delete_customer', post) + end + + private + + def build_auth_post(money, creditcard_or_vault_id, options) + post = {} + add_order(post, options) + add_address(post, options) + add_shipping_address(post, options) + add_payment_method(post, creditcard_or_vault_id, options) + add_amount(post, money) + post + end + + def build_purchase_post(money, creditcard, options) + build_auth_post(money, creditcard, options) + end + + def build_capture_post(money, authorization, option) + post = {} + post[:transactionid] = authorization + add_amount(post, money) + post + end + + def build_void_post(authorization, options) + post = {} + post[:transactionid] = authorization + post + end + + def build_refund_post(money, authorization, options) + post = {} + post[:transactionid] = authorization + add_amount(post, money) + post + end + + def build_store_post(creditcard_or_check, options) + post = {} + add_address(post, options) + add_shipping_address(post, options) + add_payment_method(post, creditcard_or_check, options) + post + end + + def build_unstore_post(customer_vault_id, options) + post = {} + post['customer_vault_id'] = customer_vault_id + post + end + + def add_order(post, options) + post[:orderid] = options[:order_id] + post[:orderdescription] = options[:description] + end + + def add_address(post, options) + post[:email] = options[:email] + post[:ipaddress] = options[:ip] + + address = options[:billing_address] || options[:address] || {} + post[:address1] = address[:address1] + post[:address2] = address[:address2] + post[:city] = address[:city] + post[:state] = address[:state] + post[:zip] = address[:zip] + post[:country] = address[:country] + post[:phone] = address[:phone] + end + + def add_shipping_address(post, options) + shipping_address = options[:shipping_address] || {} + post[:shipping_address1] = shipping_address[:address1] + post[:shipping_address2] = shipping_address[:address2] + post[:shipping_city] = shipping_address[:city] + post[:shipping_state] = shipping_address[:state] + post[:shipping_zip] = shipping_address[:zip] + post[:shipping_country] = shipping_address[:country] + end + + def add_swipe_data(post, options) + # unencrypted tracks + post[:track_1] = options[:track_1] + post[:track_2] = options[:track_2] + post[:track_3] = options[:track_3] + + # encrypted tracks + post[:magnesafe_track_1] = options[:magnesafe_track_1] + post[:magnesafe_track_2] = options[:magnesafe_track_2] + post[:magnesafe_track_3] = options[:magnesafe_track_3] + post[:magnesafe_magneprint] = options[:magnesafe_magneprint] + post[:magnesafe_ksn] = options[:magnesafe_ksn] + post[:magnesafe_magneprint_status] = options[:magnesafe_magneprint_status] + end + + def add_payment_method(post, creditcard_or_check_or_vault_id, options) + post[:processor_id] = options[:processor_id] + post[:customer_vault] = 'add_customer' if options[:store] + + add_swipe_data(post, options) + + # creditcard_or_check can be blank if using swipe data + if creditcard_or_check_or_vault_id.is_a?(CreditCard) # creditcard or check + creditcard = creditcard_or_check_or_vault_id + post[:firstname] = creditcard.first_name + post[:lastname] = creditcard.last_name + post[:ccnumber] = creditcard.number + post[:ccexp] = format(creditcard.month, :two_digits) + format(creditcard.year, :two_digits) + post[:cvv] = creditcard.verification_value + post[:payment] = 'creditcard' + elsif creditcard_or_check_or_vault_id.is_a?(Check) + check = creditcard_or_check_or_vault_id + post[:firstname] = check.first_name + post[:lastname] = check.last_name + post[:checkname] = check.name + post[:checkaba] = check.routing_number + post[:checkaccount] = check.account_number + post[:account_type] = check.account_type + post[:account_holder_type] = check.account_holder_type + post[:payment] = 'check' + else + post[:customer_vault_id] = creditcard_or_check_or_vault_id + end + end + + def add_login(post) + post[:username] = @options[:login] + post[:password] = @options[:password] + end + + def add_amount(post, money) + post[:currency] = options[:currency] || currency(money) + post[:amount] = amount(money) + end + + def commit_vault(action, parameters) + commit(nil, parameters.merge(:customer_vault => action)) + end + + def commit(action, parameters) + raw = parse(ssl_post(self.live_url, build_request(action, parameters))) + + success = (raw['response'] == ResponseCodes::APPROVED) + + authorization = authorization_from(success, parameters, raw) + + Response.new(success, raw['responsetext'], raw, + :test => test?, + :authorization => authorization, + :avs_result => { :code => raw['avsresponse']}, + :cvv_result => raw['cvvresponse'] + ) + end + + def build_request(action, parameters) + parameters[:type] = action if action + add_login(parameters) + parameters.to_query + end + + def authorization_from(success, parameters, response) + return nil unless success + + authorization = response['transactionid'] + if(parameters[:customer_vault] && (authorization.nil? || authorization.empty?)) + authorization = response['customer_vault_id'] + end + + authorization + end + + class ResponseCodes + APPROVED = '1' + DENIED = '2' + ERROR = '3' + end + + def parse(raw_response) + rsp = CGI.parse(raw_response) + rsp.keys.each { |k| rsp[k] = rsp[k].first } # flatten out the values + rsp + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trust_commerce.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trust_commerce.rb new file mode 100644 index 000000000..e0a5b9c27 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/trust_commerce.rb @@ -0,0 +1,421 @@ +begin + require 'tclink' +rescue LoadError + # Falls back to an SSL post to TrustCommerce +end + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # TO USE: + # First, make sure you have everything setup correctly and all of your dependencies in place with: + # + # require 'rubygems' + # require 'active_merchant' + # + # ActiveMerchant expects amounts to be Integer values in cents + # + # tendollar = 1000 + # + # Next, create a credit card object using a TC approved test card. + # + # creditcard = ActiveMerchant::Billing::CreditCard.new( + # :number => '4111111111111111', + # :month => 8, + # :year => 2006, + # :first_name => 'Longbob', + # :last_name => 'Longsen' + # ) + # + # To finish setting up, create the active_merchant object you will be using, with the TrustCommerce gateway. If you have a + # functional TrustCommerce account, replace login and password with your account info. Otherwise the defaults will work for + # testing. + # + # gateway = ActiveMerchant::Billing::Base.gateway(:trust_commerce).new(:login => "TestMerchant", :password => "password") + # + # Now we are ready to process our transaction + # + # response = gateway.purchase(tendollar, creditcard) + # + # Sending a transaction to TrustCommerce with active_merchant returns a Response object, which consistently allows you to: + # + # 1) Check whether the transaction was successful + # + # response.success? + # + # 2) Retrieve any message returned by TrustCommerce, either a "transaction was successful" note or an explanation of why the + # transaction was rejected. + # + # response.message + # + # 3) Retrieve and store the unique transaction ID returned by Trust Commerece, for use in referencing the transaction in the future. + # + # response.params["transid"] + # + # For higher performance and failover with the TrustCommerceGateway you can install the TCLink library from http://www.trustcommerce.com/tclink.html. + # Follow the instructions available there to get it working on your system. ActiveMerchant will automatically use tclink if available. + # + # The TCLink library has the following added benefits: + # * Good transaction times. Transaction duration under 1.2 seconds are common. + # * Fail-over to geographically distributed servers for extreme reliability + # + # Once it is installed, you should be able to make sure + # that it is visible to your ruby install by opening irb and typing "require 'tclink'", which should return "true". + # + # This should be enough to get you started with Trust Commerce and active_merchant. For further information, review the methods + # below and the rest of active_merchant's documentation, as well as Trust Commerce's user and developer documentation. + + class TrustCommerceGateway < Gateway + self.live_url = self.test_url = 'https://vault.trustcommerce.com/trans/' + + SUCCESS_TYPES = ["approved", "accepted"] + + DECLINE_CODES = { + "decline" => "The credit card was declined", + "avs" => "AVS failed; the address entered does not match the billing address on file at the bank", + "cvv" => "CVV failed; the number provided is not the correct verification number for the card", + "call" => "The card must be authorized manually over the phone", + "expiredcard" => "Issuer was not certified for card verification", + "carderror" => "Card number is invalid", + "authexpired" => "Attempt to postauth an expired (more than 14 days old) preauth", + "fraud" => "CrediGuard fraud score was below requested threshold", + "blacklist" => "CrediGuard blacklist value was triggered", + "velocity" => "CrediGuard velocity control value was triggered", + "dailylimit" => "Daily limit in transaction count or amount as been reached", + "weeklylimit" => "Weekly limit in transaction count or amount as been reached", + "monthlylimit" => "Monthly limit in transaction count or amount as been reached" + } + + BADDATA_CODES = { + "missingfields" => "One or more parameters required for this transaction type were not sent", + "extrafields" => "Parameters not allowed for this transaction type were sent", + "badformat" => "A field was improperly formatted, such as non-digit characters in a number field", + "badlength" => "A field was longer or shorter than the server allows", + "merchantcantaccept" => "The merchant can't accept data passed in this field", + "mismatch" => "Data in one of the offending fields did not cross-check with the other offending field" + } + + ERROR_CODES = { + "cantconnect" => "Couldn't connect to the TrustCommerce gateway", + "dnsfailure" => "The TCLink software was unable to resolve DNS hostnames", + "linkfailure" => "The connection was established, but was severed before the transaction could complete", + "failtoprocess" => "The bank servers are offline and unable to authorize transactions" + } + + TEST_LOGIN = 'TestMerchant' + TEST_PASSWORD = 'password' + + self.money_format = :cents + self.supported_cardtypes = [:visa, :master, :discover, :american_express, :diners_club, :jcb] + self.supported_countries = ['US'] + self.homepage_url = 'http://www.trustcommerce.com/' + self.display_name = 'TrustCommerce' + + def self.tclink? + defined?(TCLink) + end + + # Creates a new TrustCommerceGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * <tt>:login</tt> -- The TrustCommerce account login. + # * <tt>:password</tt> -- The TrustCommerce account password. + # * <tt>:test => +true+ or +false+</tt> -- Perform test transactions + # + # ==== Test Account Credentials + # * <tt>:login</tt> -- TestMerchant + # * <tt>:password</tt> -- password + def initialize(options = {}) + requires!(options, :login, :password) + + super + end + + def tclink? + self.class.tclink? + end + + def test? + ((@options[:login] == TEST_LOGIN && @options[:password] == TEST_PASSWORD) || super) + end + + # authorize() is the first half of the preauth(authorize)/postauth(capture) model. The TC API docs call this + # preauth, we preserve active_merchant's nomenclature of authorize() for consistency with the rest of the library. This + # method simply checks to make sure funds are available for a transaction, and returns a transid that can be used later to + # postauthorize (capture) the funds. + + def authorize(money, creditcard_or_billing_id, options = {}) + parameters = { + :amount => amount(money), + } + + add_order_id(parameters, options) + add_customer_data(parameters, options) + add_payment_source(parameters, creditcard_or_billing_id) + add_addresses(parameters, options) + commit('preauth', parameters) + end + + # purchase() is a simple sale. This is one of the most common types of transactions, and is extremely simple. All that you need + # to process a purchase are an amount in cents or a money object and a creditcard object or billingid string. + def purchase(money, creditcard_or_billing_id, options = {}) + parameters = { + :amount => amount(money), + } + + add_order_id(parameters, options) + add_customer_data(parameters, options) + add_payment_source(parameters, creditcard_or_billing_id) + add_addresses(parameters, options) + commit('sale', parameters) + end + + # capture() is the second half of the preauth(authorize)/postauth(capture) model. The TC API docs call this + # postauth, we preserve active_merchant's nomenclature of capture() for consistency with the rest of the library. To process + # a postauthorization with TC, you need an amount in cents or a money object, and a TC transid. + def capture(money, authorization, options = {}) + parameters = { + :amount => amount(money), + :transid => authorization, + } + + commit('postauth', parameters) + end + + # refund() allows you to return money to a card that was previously billed. You need to supply the amount, in cents or a money object, + # that you want to refund, and a TC transid for the transaction that you are refunding. + def refund(money, identification, options = {}) + parameters = { + :amount => amount(money), + :transid => identification + } + + commit('credit', parameters) + end + + def credit(money, identification, options = {}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + # void() clears an existing authorization and releases the reserved fund + # s back to the cardholder. The TC API refers to this transaction as a + # reversal. After voiding, you will no longer be able to capture funds + # from this authorization. TrustCommerce seems to always return a status + # of "accepted" even if the transid you are trying to deauthorize has + # already been captured. Note: Your account needs to be configured by + # TrustCommerce to allow for reversal transactions before you can use this + # method. + # + # NOTE: AMEX preauth's cannot be reversed. If you want to clear it more + # quickly than the automatic expiration (7-10 days), you will have to + # capture it and then immediately issue a credit for the same amount + # which should clear the customers credit card with 48 hours according to + # TC. + def void(authorization, options = {}) + parameters = { + :transid => authorization, + } + + commit('reversal', parameters) + end + + # recurring() a TrustCommerce account that is activated for Citatdel, TrustCommerce's + # hosted customer billing info database. + # + # Recurring billing uses the same TC action as a plain-vanilla 'store', but we have a separate method for clarity. It can be called + # like store, with the addition of a required 'periodicity' parameter: + # + # The parameter :periodicity should be specified as either :bimonthly, :monthly, :biweekly, :weekly, :yearly or :daily + # + # gateway.recurring(tendollar, creditcard, :periodicity => :weekly) + # + # You can optionally specify how long you want payments to continue using 'payments' + def recurring(money, creditcard, options = {}) + requires!(options, [:periodicity, :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily] ) + + cycle = case options[:periodicity] + when :monthly + '1m' + when :bimonthly + '2m' + when :weekly + '1w' + when :biweekly + '2w' + when :yearly + '1y' + when :daily + '1d' + end + + parameters = { + :amount => amount(money), + :cycle => cycle, + :verify => options[:verify] || 'y', + :billingid => options[:billingid] || nil, + :payments => options[:payments] || nil, + } + + add_creditcard(parameters, creditcard) + + commit('store', parameters) + end + + # store() requires a TrustCommerce account that is activated for Citatdel. You can call it with a credit card and a billing ID + # you would like to use to reference the stored credit card info for future captures. Use 'verify' to specify whether you want + # to simply store the card in the DB, or you want TC to verify the data first. + + def store(creditcard, options = {}) + parameters = { + :verify => options[:verify] || 'y', + :billingid => options[:billingid] || options[:billing_id] || nil, + } + + add_creditcard(parameters, creditcard) + add_addresses(parameters, options) + commit('store', parameters) + end + + # To unstore a creditcard stored in Citadel using store() or recurring(), all that is required is the billing id. When you run + # unstore() the information will be removed and a Response object will be returned indicating the success of the action. + def unstore(identification, options = {}) + parameters = { + :billingid => identification, + } + + commit('unstore', parameters) + end + + private + def add_payment_source(params, source) + if source.is_a?(String) + add_billing_id(params, source) + else + add_creditcard(params, source) + end + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + + "#{month}#{year[-2..-1]}" + end + + def add_creditcard(params, creditcard) + params[:media] = "cc" + params[:name] = creditcard.name + params[:cc] = creditcard.number + params[:exp] = expdate(creditcard) + params[:cvv] = creditcard.verification_value if creditcard.verification_value? + end + + def add_order_id(params, options) + params[:ticket] = options[:order_id] unless options[:order_id].blank? + end + + def add_billing_id(params, billingid) + params[:billingid] = billingid + end + + def add_customer_data(params, options) + params[:email] = options[:email] unless options[:email].blank? + params[:ip] = options[:ip] unless options[:ip].blank? + end + + def add_addresses(params, options) + address = options[:billing_address] || options[:address] + + if address + params[:address1] = address[:address1] unless address[:address1].blank? + params[:address2] = address[:address2] unless address[:address2].blank? + params[:city] = address[:city] unless address[:city].blank? + params[:state] = address[:state] unless address[:state].blank? + params[:zip] = address[:zip] unless address[:zip].blank? + params[:country] = address[:country] unless address[:country].blank? + params[:avs] = 'n' + end + + if shipping_address = options[:shipping_address] + params[:shipto_name] = shipping_address[:name] unless shipping_address[:name].blank? + params[:shipto_address1] = shipping_address[:address1] unless shipping_address[:address1].blank? + params[:shipto_address2] = shipping_address[:address2] unless shipping_address[:address2].blank? + params[:shipto_city] = shipping_address[:city] unless shipping_address[:city].blank? + params[:shipto_state] = shipping_address[:state] unless shipping_address[:state].blank? + params[:shipto_zip] = shipping_address[:zip] unless shipping_address[:zip].blank? + params[:shipto_country] = shipping_address[:country] unless shipping_address[:country].blank? + end + end + + def clean_and_stringify_params(parameters) + # TCLink wants us to send a hash with string keys, and activemerchant pushes everything around with + # symbol keys. Before sending our input to TCLink, we convert all our keys to strings and dump the symbol keys. + # We also remove any pairs with nil values, as these confuse TCLink. + parameters.keys.reverse.each do |key| + if parameters[key] + parameters[key.to_s] = parameters[key] + end + parameters.delete(key) + end + end + + def post_data(parameters) + parameters.collect { |key, value| "#{key}=#{ CGI.escape(value.to_s)}" }.join("&") + end + + def commit(action, parameters) + parameters[:custid] = @options[:login] + parameters[:password] = @options[:password] + parameters[:demo] = test? ? 'y' : 'n' + parameters[:action] = action + + clean_and_stringify_params(parameters) + + data = if tclink? + TCLink.send(parameters) + else + parse( ssl_post(self.live_url, post_data(parameters)) ) + end + + # to be considered successful, transaction status must be either "approved" or "accepted" + success = SUCCESS_TYPES.include?(data["status"]) + message = message_from(data) + Response.new(success, message, data, + :test => test?, + :authorization => data["transid"], + :cvv_result => data["cvv"], + :avs_result => { :code => data["avs"] } + ) + end + + def parse(body) + results = {} + + body.split(/\n/).each do |pair| + key,val = pair.split(/=/) + results[key] = val + end + + results + end + + def message_from(data) + status = case data["status"] + when "decline" + return DECLINE_CODES[data["declinetype"]] + when "baddata" + return BADDATA_CODES[data["error"]] + when "error" + return ERROR_CODES[data["errortype"]] + else + return "The transaction was successful" + end + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay.rb new file mode 100644 index 000000000..2ca57cdd0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay.rb @@ -0,0 +1,25 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + ## + # Delegates to the appropriate gateway, either the Transaction or Advanced + # depending on options passed to new. + # + class UsaEpayGateway < Gateway + + self.abstract_class = true + + ## + # Creates an instance of UsaEpayTransactionGateway by default, but if + # :software id or :live_url are passed in the options hash it will + # create an instance of UsaEpayAdvancedGateway. + # + def self.new(options={}) + unless options.has_key?(:software_id) || options.has_key?(:live_url) + UsaEpayTransactionGateway.new(options) + else + UsaEpayAdvancedGateway.new(options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_advanced.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_advanced.rb new file mode 100644 index 000000000..6b3faeb31 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_advanced.rb @@ -0,0 +1,1501 @@ +require 'securerandom' +require 'digest' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + # ==== USA ePay Advanced SOAP Interface + # + # This class encapuslates USA ePay's Advanced SOAP Interface. The Advanced Soap Interface allows + # standard transactions, storing customer information, and recurring billing. Storing sensitive + # information on USA ePay's servers can help with PCI DSS compliance, since customer and card data + # do not need to be stored locally. + # + # Make sure you have enabled this functionality for your account with USA ePay. + # + # Information about the Advanced SOAP interface is available on the {USA ePay wiki}[http://wiki.usaepay.com/developer/soap]. + # + # ==== Login, Password, and Software ID + # + # Please follow all of USA ePay's directions for acquiring all accounts and settings. + # + # The value used for <tt>:login</tt> is the Key value found in the Merchant Console under Settings > Source + # Key. You will have to add this key in the USA ePay Merchant Console. + # + # The value used for <tt>:password</tt> is the pin value also found and assigned in the Merchant Console under + # Settings > Source Key. The pin is required to use all but basic transactions in the SOAP interface. + # You will have to add the pin to your source key, as it defaults to none. + # + # The value used for the <tt>:software_id</tt> is found in the Developer's Login under the Developers Center + # in your WSDL. It is the 8 character value in <soap:address> tag. A masked example: + # <soap:address location="https://www.usaepay.com/soap/gate/XXXXXXXX"/> + # It is also found in the link to your WSDL. This is required as every account has a different path + # SOAP requests are submitted to. Optionally, you can provide the entire urls via <tt>:live_url</tt> and <tt>:test_url</tt>, if your prefer. + # + # ==== Responses + # * <tt>#success?</tt> -- +true+ if transmitted and returned correctly + # * <tt>#message</tt> -- response or fault message + # * <tt>#authorization</tt> -- reference_number or nil + # * <tt>#params</tt> -- hash of entire soap response contents + # + # ==== Address Options + # * <tt>:billing_address/:shipping_address</tt> -- contains some extra options + # * <tt>:name</tt> -- virtual attribute; will split to first and last name + # * <tt>:first_name</tt> + # * <tt>:last_name</tt> + # * <tt>:address1 </tt> + # * <tt>:address2 </tt> + # * <tt>:city </tt> + # * <tt>:state </tt> + # * <tt>:zip </tt> + # * <tt>:country </tt> + # * <tt>:phone</tt> + # * <tt>:email</tt> + # * <tt>:fax</tt> + # * <tt>:company</tt> + # + # ==== Support: + # * Questions: post to {active_merchant google group}[http://groups.google.com/group/activemerchant] + # * Feedback/fixes: matt (at) nearapogee (dot) com + # + # ==== Links: + # * {USA ePay Merchant Console}[https://sandbox.usaepay.com/login] + # * {USA ePay Developer Login}[https://www.usaepay.com/developer/login] + # + class UsaEpayAdvancedGateway < Gateway + API_VERSION = "1.4" + + TEST_URL_BASE = 'https://sandbox.usaepay.com/soap/gate/' #:nodoc: + LIVE_URL_BASE = 'https://www.usaepay.com/soap/gate/' #:nodoc: + + self.test_url = TEST_URL_BASE + self.live_url = LIVE_URL_BASE + + FAILURE_MESSAGE = "Default Failure" #:nodoc: + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb] + self.homepage_url = 'http://www.usaepay.com/' + self.display_name = 'USA ePay Advanced SOAP Interface' + + CUSTOMER_OPTIONS = { + :id => [:string, 'CustomerID'], # merchant assigned number + :notes => [:string, 'Notes'], + :data => [:string, 'CustomData'], + :url => [:string, 'URL'], + # Recurring Billing + :enabled => [:boolean, 'Enabled'], + :schedule => [:string, 'Schedule'], + :number_left => [:integer, 'NumLeft'], + :currency => [:string, 'Currency'], + :description => [:string, 'Description'], + :order_id => [:string, 'OrderID'], + :user => [:string, 'User'], + :source => [:string, 'Source'], + :send_receipt => [:boolean, 'SendReceipt'], + :receipt_note => [:string, 'ReceiptNote'], + # Point of Sale + :price_tier => [:string, 'PriceTier'], + :tax_class => [:string, 'TaxClass'], + :lookup_code => [:string, 'LookupCode'] + } #:nodoc: + + ADDRESS_OPTIONS = { + :first_name => [:string, 'FirstName'], + :last_name => [:string, 'LastName'], + :address1 => [:string, 'Street'], + :address2 => [:string, 'Street2'], + :city => [:string, 'City'], + :state => [:string, 'State'], + :zip => [:string, 'Zip'], + :country => [:string, 'Country'], + :phone => [:string, 'Phone'], + :email => [:string, 'Email'], + :fax => [:string, 'Fax'], + :company => [:string, 'Company'] + } #:nodoc: + + CUSTOMER_TRANSACTION_REQUEST_OPTIONS = { + :command => [:string, 'Command'], + :ignore_duplicate => [:boolean, 'IgnoreDuplicate'], + :client_ip => [:string, 'ClientIP'], + :customer_receipt => [:boolean, 'CustReceipt'], + :customer_email => [:boolean, 'CustReceiptEmail'], + :customer_template => [:boolean, 'CustReceiptName'], + :merchant_receipt => [:boolean, 'MerchReceipt'], + :merchant_email => [:boolean, 'MerchReceiptEmail'], + :merchant_template => [:boolean, 'MerchReceiptName'], + :verification_value => [:boolean, 'isRecurring'], + :software => [:string, 'Software'] + } #:nodoc: + + TRANSACTION_REQUEST_OBJECT_OPTIONS = { + :command => [:string, 'Command'], + :ignore_duplicate => [:boolean, 'IgnoreDuplicate'], + :authorization_code => [:string, 'AuthCode'], + :reference_number => [:string, 'RefNum'], + :account_holder => [:string, 'AccountHolder'], + :client_ip => [:string, 'ClientIP'], + :customer_id => [:string, 'CustomerID'], + :customer_receipt => [:boolean, 'CustReceipt'], + :customer_template => [:boolean, 'CustReceiptName'], + :software => [:string, 'Software'] + } #:nodoc: + + TRANSACTION_DETAIL_OPTIONS = { + :invoice => [:string, 'Invoice'], + :po_number => [:string, 'PONum'], + :order_id => [:string, 'OrderID'], + :clerk => [:string, 'Clerk'], + :terminal => [:string, 'Terminal'], + :table => [:string, 'Table'], + :description => [:string, 'Description'], + :comments => [:string, 'Comments'], + :allow_partial_auth => [:boolean, 'AllowPartialAuth'], + :currency => [:string, 'Currency'], + :non_tax => [:boolean, 'NonTax'], + } #:nodoc: + + TRANSACTION_DETAIL_MONEY_OPTIONS = { + :amount => [:double, 'Amount'], + :tax => [:double, 'Tax'], + :tip => [:double, 'Tip'], + :non_tax => [:boolean, 'NonTax'], + :shipping => [:double, 'Shipping'], + :discount => [:double, 'Discount'], + :subtotal => [:double, 'Subtotal'] + } #:nodoc: + + CREDIT_CARD_DATA_OPTIONS = { + :magnetic_stripe => [:string, 'MagStripe'], + :dukpt => [:string, 'DUKPT'], + :signature => [:string, 'Signature'], + :terminal_type => [:string, 'TermType'], + :magnetic_support => [:string, 'MagSupport'], + :xid => [:string, 'XID'], + :cavv => [:string, 'CAVV'], + :eci => [:integer, 'ECI'], + :internal_card_authorization => [:boolean, 'InternalCardAuth'], + :pares => [:string, 'Pares'] + } #:nodoc: + + CHECK_DATA_OPTIONS = { + :check_number => [:integer, 'CheckNumber'], + :drivers_license => [:string, 'DriversLicense'], + :drivers_license_state => [:string, 'DriversLicenseState'], + :record_type => [:string, 'RecordType'], + :aux_on_us => [:string, 'AuxOnUS'], + :epc_code => [:string, 'EpcCode'], + :front_image => [:string, 'FrontImage'], + :back_image => [:string, 'BackImage'] + } #:nodoc: + + RECURRING_BILLING_OPTIONS = { + :schedule => [:string, 'Schedule'], + :number_left => [:integer, 'NumLeft'], + :enabled => [:boolean, 'Enabled'] + } #:nodoc: + + AVS_RESULTS = { + 'Y' => %w( YYY Y YYA YYD ), + 'Z' => %w( NYZ Z ), + 'A' => %w( YNA A YNY ), + 'N' => %w( NNN N NN ), + 'X' => %w( YYX X ), + 'W' => %w( NYW W ), + 'XXW' => %w( XXW ), + 'XXU' => %w( XXU ), + 'R' => %w( XXR R U E ), + 'S' => %w( XXS S ), + 'XXE' => %w( XXE ), + 'G' => %w( XXG G C I ), + 'B' => %w( YYG B M ), + 'D' => %w( GGG D ), + 'P' => %w( YGG P ) + }.inject({}) do |map, (type, codes)| + codes.each { |code| map[code] = type } + map + end #:nodoc: + + AVS_CUSTOM_MESSAGES = { + 'XXW' => 'Card number not on file.', + 'XXU' => 'Address information not verified for domestic transaction.', + 'XXE' => 'Address verification not allowed for card type.' + } #:nodoc: + + # Create a new gateway. + # + # ==== Required + # * At least the live_url OR the software_id must be present. + # * <tt>:software_id</tt> -- 8 character software id + # OR + # * <tt>:test_url</tt> -- full url for testing + # * <tt>:live_url</tt> -- full url for live/production + # + # ==== Optional + # * <tt>:soap_response</tt> -- set to +true+ to add :soap_response to the params hash containing the entire soap xml message + # + def initialize(options = {}) + requires!(options, :login, :password) + + if options[:software_id] + self.live_url = "#{LIVE_URL_BASE}#{options[:software_id].to_s}" + self.test_url = "#{TEST_URL_BASE}#{options[:software_id].to_s}" + else + self.live_url = options[:live_url].to_s + self.test_url = options[:test_url].to_s if options[:test_url] + end + + super + end + + # Standard Gateway Methods ====================================== + + # Make a purchase with a credit card. (Authorize and + # capture for settlement.) + # + # Note: See run_transaction for additional options. + # + def purchase(money, creditcard, options={}) + run_sale(options.merge!(:amount => money, :payment_method => creditcard)) + end + + # Authorize an amount on a credit card or account. + # + # Note: See run_transaction for additional options. + # + def authorize(money, creditcard, options={}) + run_auth_only(options.merge!(:amount => money, :payment_method => creditcard)) + end + + # Capture an authorized transaction. + # + # Note: See run_transaction for additional options. + # + def capture(money, identification, options={}) + capture_transaction(options.merge!(:amount => money, :reference_number => identification)) + end + + # Void a previous transaction that has not been settled. + # + # Note: See run_transaction for additional options. + # + def void(identification, options={}) + void_transaction(options.merge!(:reference_number => identification)) + end + + # Refund a previous transaction. + # + # Note: See run_transaction for additional options. + # + def refund(money, identification, options={}) + refund_transaction(options.merge!(:amount => money, :reference_number => identification)) + end + + def credit(money, identification, options={}) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, identification, options) + end + + # Customer ====================================================== + + # Add a customer. + # + # ==== Options + # * <tt>:id</tt> -- merchant assigned id + # * <tt>:notes</tt> -- notes about customer + # * <tt>:data</tt> -- base64 data about customer + # * <tt>:url</tt> -- customer website + # * <tt>:billing_address</tt> -- usual options + # * <tt>:payment_methods</tt> -- array of payment method hashes. + # * <tt>:method</tt> -- credit_card or check + # * <tt>:name</tt> -- optional name/label for the method + # * <tt>:sort</tt> -- optional integer value specifying the backup sort order, 0 is default + # + # ==== Recurring Options + # * <tt>:enabled</tt> -- +true+ enables recurring + # * <tt>:schedule</tt> -- daily, weekly, bi-weekly (every two weeks), monthly, bi-monthly (every two months), quarterly, bi-annually (every six months), annually, first of month, last day of month + # * <tt>:number_left</tt> -- number of payments left; -1 for unlimited + # * <tt>:next</tt> -- date of next payment (Date/Time) + # * <tt>:amount</tt> -- amount of recurring payment + # * <tt>:tax</tt> -- tax portion of amount + # * <tt>:currency</tt> -- numeric currency code + # * <tt>:description</tt> -- description of transaction + # * <tt>:order_id</tt> -- transaction order id + # * <tt>:user</tt> -- merchant username assigned to transaction + # * <tt>:source</tt> -- name of source key assigned to billing + # * <tt>:send_receipt</tt> -- +true+ to send client a receipt + # * <tt>:receipt_note</tt> -- leave a note on the receipt + # + # ==== Point of Sale Options + # * <tt>:price_tier</tt> -- name of customer price tier + # * <tt>:tax_class</tt> -- tax class + # * <tt>:lookup_code</tt> -- lookup code from customer/member id card; barcode or magnetic stripe; can be assigned by merchant; defaults to system assigned if blank + # + # ==== Response + # * <tt>#message</tt> -- customer number assigned by gateway + # + def add_customer(options={}) + request = build_request(__method__, options) + commit(__method__, request) + end + + # Update a customer by replacing all of the customer details.. + # + # Use quickUpdateCustomer to just update a few attributes. + # + # ==== Options + # * Same as add_customer + # + def update_customer(options={}) + requires! options, :customer_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Enable a customer for recurring billing. + # + # Note: Customer does not need to have all recurring paramerters to succeed. + # + # ==== Required + # * <tt>:customer_number</tt> + # + def enable_customer(options={}) + requires! options, :customer_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Disable a customer for recurring billing. + # + # ==== Required + # * <tt>:customer_number</tt> + # + def disable_customer(options={}) + requires! options, :customer_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Add a payment method to a customer. + # + # ==== Required + # * <tt>:customer_number</tt> -- number returned by add_customer response.message + # * <tt>:payment_method</tt> + # * <tt>:method</tt> -- credit_card or check + # * <tt>:name</tt> -- optional name/label for the method + # * <tt>:sort</tt> -- an integer value specifying the backup sort order, 0 is default + # + # ==== Optional + # * <tt>:make_default</tt> -- set +true+ to make default + # * <tt>:verify</tt> -- set +true+ to run auth_only verification; throws fault if cannot verify + # + # ==== Response + # * <tt>#message</tt> -- method_id of new customer payment method + # + def add_customer_payment_method(options={}) + requires! options, :customer_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Retrive all of the payment methods belonging to a customer + # + # ==== Required + # * <tt>:customer_number</tt> + # + # ==== Response + # * <tt>#message</tt> -- either a single hash or an array of hashes of payment methods + # + def get_customer_payment_methods(options={}) + requires! options, :customer_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Retrive one of the payment methods belonging to a customer + # + # ==== Required + # * <tt>:customer_number</tt> + # * <tt>:method_id</tt> + # + # ==== Response + # * <tt>#message</tt> -- hash of payment method + # + def get_customer_payment_method(options={}) + requires! options, :customer_number, :method_id + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Update a customer payment method. + # + # ==== Required + # * <tt>:method_id</tt> -- method_id to update + # + # ==== Options + # * <tt>:method</tt> -- credit_card or check + # * <tt>:name</tt> -- optional name/label for the method + # * <tt>:sort</tt> -- an integer value specifying the backup sort order, 0 is default + # * <tt>:verify</tt> -- set +true+ to run auth_only verification; throws fault if cannot verify + # + # ==== Response + # * <tt>#message</tt> -- hash of payment method + # + def update_customer_payment_method(options={}) + requires! options, :method_id + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Delete one the payment methods beloning to a customer + # + # ==== Required + # * <tt>:customer_number</tt> + # * <tt>:method_id</tt> + # + def delete_customer_payment_method(options={}) + requires! options, :customer_number, :method_id + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Delete a customer. + # + # ==== Required + # * <tt>:customer_number</tt> + # + def delete_customer(options={}) + requires! options, :customer_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Run a transaction for an existing customer in the database. + # + # ==== Required Options + # * <tt>:customer_number</tt> -- gateway assigned identifier + # * <tt>:command</tt> -- Sale, AuthOnly, Credit, Check, CheckCredit + # * <tt>:amount</tt> -- total amount + # + # ==== Options + # * <tt>:method_id</tt> -- which payment method to use, 0/nil/omitted for default method + # * <tt>:ignore_duplicate</tt> -- +true+ overrides duplicate transaction + # * <tt>:client_ip</tt> -- client ip address + # * <tt>:customer_receipt</tt> -- +true+, sends receipt to customer. active_merchant defaults to +false+ + # * <tt>:customer_email</tt> -- specify if different than customer record + # * <tt>:customer_template</tt> -- name of template + # * <tt>:merchant_receipt</tt> -- +true+, sends receipt to merchant. active_merchant defaults to +false+ + # * <tt>:merchant_email</tt> -- required if :merchant_receipt set to +true+ + # * <tt>:merchant_template</tt> -- name of template + # * <tt>:recurring</tt> -- defaults to +false+ *see documentation* + # * <tt>:verification_value</tt> -- pci forbids storage of this value, only required for CVV2 validation + # * <tt>:software</tt> -- active_merchant sets to required gateway option value + # * <tt>:line_items</tt> -- XXX not implemented yet + # * <tt>:custom_fields</tt> -- XXX not implemented yet + # + # ==== Transaction Options + # * <tt>:invoice</tt> -- transaction invoice number; truncated to 10 characters; defaults to reference_number + # * <tt>:po_number</tt> -- commercial purchase order number; upto 25 characters + # * <tt>:order_id</tt> -- should be used to assign a unique id; upto 64 characters + # * <tt>:clerk</tt> -- sales clerk + # * <tt>:terminal</tt> -- terminal name + # * <tt>:table</tt> -- table name/number + # * <tt>:description</tt> -- description + # * <tt>:comments</tt> -- comments + # * <tt>:allow_partial_auth</tt> -- allow partial authorization if full amount is not available; defaults +false+ + # * <tt>:currency</tt> -- numeric currency code + # * <tt>:tax</tt> -- tax portion of amount + # * <tt>:tip</tt> -- tip portion of amount + # * <tt>:non_tax</tt> -- +true+ if transaction is non-taxable + # * <tt>:shipping</tt> -- shipping portion of amount + # * <tt>:discount</tt> -- amount of discount + # * <tt>:subtotal</tt> -- amount of transaction before tax, tip, shipping, and discount are applied + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def run_customer_transaction(options={}) + requires! options, :customer_number, :command, :amount + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Transactions ================================================== + + # Run a transaction. + # + # Note: run_sale, run_auth_only, run_credit, run_check_sale, run_check_credit + # methods are also available. Each takes the same options as + # run_transaction, but the :command option is not required. + # + # Recurring Note: If recurring options are included USA ePay will create a + # new customer record with the supplied information. The customer number + # will be returned in the response. + # + # ==== Options + # * <tt>:method</tt> -- credit_card or check + # * <tt>:command</tt> -- sale, credit, void, creditvoid, authonly, capture, postauth, check, checkcredit; defaults to sale; only required for run_transaction when other than sale + # * <tt>:reference_number</tt> -- for the original transaction; obtained by sale or authonly + # * <tt>:authorization_code</tt> -- required for postauth; obtained offline + # * <tt>:ignore_duplicate</tt> -- set +true+ if you want to override the duplicate tranaction handling + # * <tt>:account_holder</tt> -- name of account holder + # * <tt>:customer_id</tt> -- merchant assigned id + # * <tt>:customer_receipt</tt> -- set +true+ to email receipt to billing email address + # * <tt>:customer_template</tt> -- name of template + # * <tt>:software</tt> -- stamp merchant software version for tracking + # * <tt>:billing_address</tt> -- see UsaEpayCimGateway documentation for all address fields + # * <tt>:shipping_address</tt> -- see UsaEpayCimGateway documentation for all address fields + # * <tt>:recurring</tt> -- used for recurring billing transactions + # * <tt>:schedule</tt> -- disabled, daily, weekly, bi-weekly (every two weeks), monthly, bi-monthly (every two months), quarterly, bi-annually (every six months), annually + # * <tt>:next</tt> -- date customer billed next (Date/Time) + # * <tt>:expire</tt> -- date the recurring transactions end (Date/Time) + # * <tt>:number_left</tt> -- transactions remaining in billing cycle + # * <tt>:amount</tt> -- amount to be billed each recurring transaction + # * <tt>:enabled</tt> -- states if currently active + # * <tt>:line_items</tt> -- XXX not implemented yet + # * <tt>:custom_fields</tt> -- XXX not implemented yet + # + # ==== Transaction Options + # * <tt>:amount</tt> -- total amount + # * <tt>:invoice</tt> -- transaction invoice number; truncated to 10 characters; defaults to reference_number + # * <tt>:po_number</tt> -- commercial purchase order number; upto 25 characters + # * <tt>:order_id</tt> -- should be used to assign a unique id; upto 64 characters + # * <tt>:clerk</tt> -- sales clerk + # * <tt>:terminal</tt> -- terminal name + # * <tt>:table</tt> -- table name/number + # * <tt>:description</tt> -- description + # * <tt>:comments</tt> -- comments + # * <tt>:allow_partial_auth</tt> -- allow partial authorization if full amount is not available; defaults +false+ + # * <tt>:currency</tt> -- numeric currency code + # * <tt>:tax</tt> -- tax portion of amount + # * <tt>:tip</tt> -- tip portion of amount + # * <tt>:non_tax</tt> -- +true+ if transaction is non-taxable + # * <tt>:shipping</tt> -- shipping portion of amount + # * <tt>:discount</tt> -- amount of discount + # * <tt>:subtotal</tt> -- amount of transaction before tax, tip, shipping, and discount are applied + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def run_transaction(options={}) + request = build_request(__method__, options) + commit(__method__, request) + end + + TRANSACTION_METHODS = [ + :run_sale, :run_auth_only, :run_credit, + :run_check_sale, :run_check_credit + ] #:nodoc: + + TRANSACTION_METHODS.each do |method| + define_method method do |options| + request = build_request(method, options) + commit(method, request) + end + end + + # Post an authorization code obtained offline. + # + # ==== Required + # * <tt>:authorization_code</tt> -- obtained offline + # + # ==== Options + # * Same as run_transaction + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def post_auth(options={}) + requires! options, :authorization_code + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Capture an authorized transaction and move it into the current batch + # for settlement. + # + # Note: Check with merchant bank for details/restrictions on differing + # amounts than the original authorization. + # + # ==== Required + # * <tt>:reference_number</tt> + # + # ==== Options + # * <tt>:amount</tt> -- may be different than original amount; 0 will void authorization + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def capture_transaction(options={}) + requires! options, :reference_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Void a transaction. + # + # Note: Can only be voided before being settled. + # + # ==== Required + # * <tt>:reference_number</tt> + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def void_transaction(options={}) + requires! options, :reference_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Refund transaction. + # + # Note: Required after a transaction has been settled. Refunds + # both credit card and check transactions. + # + # ==== Required + # * <tt>:reference_number</tt> + # * <tt>:amount</tt> -- amount to refund; 0 will refund original amount + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def refund_transaction(options={}) + requires! options, :reference_number, :amount + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Override transaction flagged for mananager approval. + # + # Note: Checks only! + # + # ==== Required + # * <tt>:reference_number</tt> + # + # ==== Options + # * <tt>:reason</tt> + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def override_transaction(options={}) + requires! options, :reference_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Quick Transactions ============================================ + + # Run a sale transaction based off of a past transaction. + # + # Transfers referenced transaction's payment method to this + # transaction. As of 6/2011, USA ePay blocks credit card numbers + # at 3 years. + # + # ==== Required + # * <tt>:reference_number</tt> -- transaction to reference payment from + # * <tt>:amount</tt> -- total amount + # + # ==== Options + # * <tt>:authorize_only</tt> -- set +true+ if you just want to authorize + # + # ==== Transaction Options + # * <tt>:invoice</tt> -- transaction invoice number; truncated to 10 characters; defaults to reference_number + # * <tt>:po_number</tt> -- commercial purchase order number; upto 25 characters + # * <tt>:order_id</tt> -- should be used to assign a unique id; upto 64 characters + # * <tt>:clerk</tt> -- sales clerk + # * <tt>:terminal</tt> -- terminal name + # * <tt>:table</tt> -- table name/number + # * <tt>:description</tt> -- description + # * <tt>:comments</tt> -- comments + # * <tt>:allow_partial_auth</tt> -- allow partial authorization if full amount is not available; defaults +false+ + # * <tt>:currency</tt> -- numeric currency code + # * <tt>:tax</tt> -- tax portion of amount + # * <tt>:tip</tt> -- tip portion of amount + # * <tt>:non_tax</tt> -- +true+ if transaction is non-taxable + # * <tt>:shipping</tt> -- shipping portion of amount + # * <tt>:discount</tt> -- amount of discount + # * <tt>:subtotal</tt> -- amount of transaction before tax, tip, shipping, and discount are applied + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def run_quick_sale(options={}) + requires! options, :reference_number, :amount + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Run a credit based off of a past transaction. + # + # Transfers referenced transaction's payment method to this + # transaction. As of 6/2011, USA ePay blocks credit card numbers + # at 3 years. + # + # ==== Required + # * <tt>:reference_number</tt> -- transaction to reference payment from + # + # ==== Transaction Options + # * <tt>:amount</tt> -- total amount + # * <tt>:invoice</tt> -- transaction invoice number; truncated to 10 characters; defaults to reference_number + # * <tt>:po_number</tt> -- commercial purchase order number; upto 25 characters + # * <tt>:order_id</tt> -- should be used to assign a unique id; upto 64 characters + # * <tt>:clerk</tt> -- sales clerk + # * <tt>:terminal</tt> -- terminal name + # * <tt>:table</tt> -- table name/number + # * <tt>:description</tt> -- description + # * <tt>:comments</tt> -- comments + # * <tt>:allow_partial_auth</tt> -- allow partial authorization if full amount is not available; defaults +false+ + # * <tt>:currency</tt> -- numeric currency code + # * <tt>:tax</tt> -- tax portion of amount + # * <tt>:tip</tt> -- tip portion of amount + # * <tt>:non_tax</tt> -- +true+ if transaction is non-taxable + # * <tt>:shipping</tt> -- shipping portion of amount + # * <tt>:discount</tt> -- amount of discount + # * <tt>:subtotal</tt> -- amount of transaction before tax, tip, shipping, and discount are applied + # + # ==== Response + # * <tt>#message</tt> -- transaction response hash + # + def run_quick_credit(options={}) + requires! options, :reference_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Transaction Status ============================================ + + # Retrieve details of a specified transaction. + # + # ==== Required + # * <tt>:reference_number</tt> + # + # ==== Response + # * <tt>#message</tt> -- transaction hash + # + def get_transaction(options={}) + requires! options, :reference_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Check status of a transaction. + # + # ==== Required + # * <tt>:reference_number</tt> + # + # ==== Response + # * <tt>response.success</tt> -- success of the referenced transaction + # * <tt>response.message</tt> -- message of the referenced transaction + # * <tt>response.authorization</tt> -- same as :reference_number in options + # + def get_transaction_status(options={}) + requires! options, :reference_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Check status of a transaction (custom). + # + # ==== Required + # * <tt>:reference_number</tt> + # * <tt>:fields</tt> -- string array of fields to retrieve + # * <tt>Response.AuthCode</tt> + # * <tt>Response.AvsResult</tt> + # * <tt>Response.AvsResultCode</tt> + # * <tt>Response.BatchNum</tt> + # * <tt>Response.CardCodeResult</tt> + # * <tt>Response.CardCodeResultCode</tt> + # * <tt>Response.ConversionRate</tt> + # * <tt>Response.ConvertedAmount</tt> + # * <tt>Response.ConvertedAmountCurrency</tt> + # * <tt>Response.Error</tt> + # * <tt>Response.ErrorCode</tt> + # * <tt>Response.RefNum</tt> + # * <tt>Response.Result</tt> + # * <tt>Response.ResultCode</tt> + # * <tt>Response.Status</tt> + # * <tt>Response.StatusCode</tt> + # * <tt>CheckTrace.TrackingNum</tt> + # * <tt>CheckTrace.Effective</tt> + # * <tt>CheckTrace.Processed</tt> + # * <tt>CheckTrace.Settled</tt> + # * <tt>CheckTrace.Returned</tt> + # * <tt>CheckTrace.BankNote</tt> + # * <tt>DateTime</tt> + # * <tt>AccountHolder</tt> + # * <tt>Details.Invoice</tt> + # * <tt>Details.PoNum</tt> + # * <tt>Details.OrderID</tt> + # * <tt>Details.Clerk</tt> + # * <tt>Details.Terminal</tt> + # * <tt>Details.Table</tt> + # * <tt>Details.Description</tt> + # * <tt>Details.Amount</tt> + # * <tt>Details.Currency</tt> + # * <tt>Details.Tax</tt> + # * <tt>Details.Tip</tt> + # * <tt>Details.NonTax</tt> + # * <tt>Details.Shipping</tt> + # * <tt>Details.Discount</tt> + # * <tt>Details.Subtotal</tt> + # * <tt>CreditCardData.CardType</tt> + # * <tt>CreditCardData.CardNumber</tt> + # * <tt>CreditCardData.CardExpiration</tt> + # * <tt>CreditCardData.CardCode</tt> + # * <tt>CreditCardData.AvsStreet</tt> + # * <tt>CreditCardData.AvsZip</tt> + # * <tt>CreditCardData.CardPresent</tt> + # * <tt>CheckData.CheckNumber</tt> + # * <tt>CheckData.Routing</tt> + # * <tt>CheckData.Account</tt> + # * <tt>CheckData.SSN</tt> + # * <tt>CheckData.DriversLicense</tt> + # * <tt>CheckData.DriversLicenseState</tt> + # * <tt>CheckData.RecordType</tt> + # * <tt>User</tt> + # * <tt>Source</tt> + # * <tt>ServerIP</tt> + # * <tt>ClientIP</tt> + # * <tt>CustomerID</tt> + # * <tt>BillingAddress.FirstName</tt> + # * <tt>BillingAddress.LastName</tt> + # * <tt>BillingAddress.Company</tt> + # * <tt>BillingAddress.Street</tt> + # * <tt>BillingAddress.Street2</tt> + # * <tt>BillingAddress.City</tt> + # * <tt>BillingAddress.State</tt> + # * <tt>BillingAddress.Zip</tt> + # * <tt>BillingAddress.Country</tt> + # * <tt>BillingAddress.Phone</tt> + # * <tt>BillingAddress.Fax</tt> + # * <tt>BillingAddress.Email</tt> + # * <tt>ShippingAddress.FirstName</tt> + # * <tt>ShippingAddress.LastName</tt> + # * <tt>ShippingAddress.Company</tt> + # * <tt>ShippingAddress.Street</tt> + # * <tt>ShippingAddress.Street2</tt> + # * <tt>ShippingAddress.City</tt> + # * <tt>ShippingAddress.State</tt> + # * <tt>ShippingAddress.Zip</tt> + # * <tt>ShippingAddress.Country</tt> + # * <tt>ShippingAddress.Phone</tt> + # * <tt>ShippingAddress.Fax</tt> + # * <tt>ShippingAddress.Email</tt> + # + # ==== Response + # * <tt>#message</tt> -- hash; keys are the field values + # + def get_transaction_custom(options={}) + requires! options, :reference_number, :fields + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Check status of a check transaction. + # + # ==== Required + # * <tt>:reference_number</tt> + # + # ==== Response + # * <tt>#message</tt> -- check trace hash + # + def get_check_trace(options={}) + requires! options, :reference_number + + request = build_request(__method__, options) + commit(__method__, request) + end + + # Account ======================================================= + + # Retrieve merchant account details + # + # ==== Response + # * <tt>#message</tt> -- account hash + # + def get_account_details + request = build_request(__method__) + commit(__method__, request) + end + + # Builders ====================================================== + + private + + # Build soap header, etc. + def build_request(action, options = {}) + soap = Builder::XmlMarkup.new + soap.instruct!(:xml, :version => '1.0', :encoding => 'utf-8') + soap.tag! "SOAP-ENV:Envelope", + 'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/', + 'xmlns:ns1' => 'urn:usaepay', + 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', + 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', + 'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/', + 'SOAP-ENV:encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/' do |soap| + soap.tag! "SOAP-ENV:Body" do |soap| + send("build_#{action}", soap, options) + end + end + soap.target! + end + + # Build generic tag. + def build_tag(soap, type, tag, value) + soap.tag!(tag, value, 'xsi:type' => "xsd:#{type}") if value != nil + end + + # Build token. + def build_token(soap, options) + seed = SecureRandom.base64(32) + hash = Digest::SHA1.hexdigest("#{@options[:login]}#{seed}#{@options[:password].to_s.strip}") + soap.Token 'xsi:type' => 'ns1:ueSecurityToken' do |soap| + build_tag soap, :string, 'ClientIP', options[:client_ip] + soap.PinHash 'xsi:type' => 'ns1:ueHash' do |soap| + build_tag soap, :string, "HashValue", hash + build_tag soap, :string, "Seed", seed + build_tag soap, :string, "Type", 'sha1' + end + build_tag soap, :string, 'SourceKey', @options[:login] + end + end + + # Customer ====================================================== + + def build_add_customer(soap, options) + soap.tag! "ns1:addCustomer" do |soap| + build_token soap, options + build_customer_data soap, options + build_tag soap, :double, 'Amount', amount(options[:amount]) + build_tag soap, :double, 'Tax', amount(options[:tax]) + build_tag soap, :string, 'Next', options[:next].strftime("%Y-%m-%d") if options[:next] + end + end + + def build_customer(soap, options, type, add_customer_data=false) + soap.tag! "ns1:#{type}" do |soap| + build_token soap, options + build_tag soap, :integer, 'CustNum', options[:customer_number] + build_customer_data soap, options if add_customer_data + end + end + + def build_update_customer(soap, options) + build_customer(soap, options, 'updateCustomer', true) + end + + def build_enable_customer(soap, options) + build_customer(soap, options, 'enableCustomer') + end + + def build_disable_customer(soap, options) + build_customer(soap, options, 'disableCustomer') + end + + def build_delete_customer(soap, options) + build_customer(soap, options, 'deleteCustomer') + end + + def build_add_customer_payment_method(soap, options) + soap.tag! "ns1:addCustomerPaymentMethod" do |soap| + build_token soap, options + build_tag soap, :integer, 'CustNum', options[:customer_number] + build_customer_payment_methods soap, options + build_tag soap, :boolean, 'MakeDefault', options[:make_default] + build_tag soap, :boolean, 'Verify', options[:verify] + end + end + + def build_get_customer_payment_method(soap, options) + soap.tag! 'ns1:getCustomerPaymentMethod' do |soap| + build_token soap, options + build_tag soap, :integer, 'CustNum', options[:customer_number] + build_tag soap, :integer, 'MethodID', options[:method_id] + end + end + + def build_get_customer_payment_methods(soap, options) + build_customer(soap, options, 'getCustomerPaymentMethods') + end + + def build_update_customer_payment_method(soap, options) + soap.tag! 'ns1:updateCustomerPaymentMethod' do |soap| + build_token soap, options + build_customer_payment_methods soap, options + build_tag soap, :boolean, 'Verify', options[:verify] + end + end + + def build_delete_customer_payment_method(soap, options) + soap.tag! "ns1:deleteCustomerPaymentMethod" do |soap| + build_token soap, options + build_tag soap, :integer, 'Custnum', options[:customer_number] + build_tag soap, :integer, 'PaymentMethodID', options[:method_id] + end + end + + def build_run_customer_transaction(soap, options) + soap.tag! "ns1:runCustomerTransaction" do |soap| + build_token soap, options + build_tag soap, :integer, 'CustNum', options[:customer_number] + build_tag soap, :integer, 'PaymentMethodID', options[:method_id] || 0 + build_customer_transaction soap, options + end + end + + # Transactions ================================================== + + def build_run_transaction(soap, options) + soap.tag! 'ns1:runTransaction' do |soap| + build_token soap, options + build_transaction_request_object soap, options, 'Parameters' + end + end + + def build_run_sale(soap, options) + soap.tag! 'ns1:runSale' do |soap| + build_token soap, options + build_transaction_request_object soap, options + end + end + + def build_run_auth_only(soap, options) + soap.tag! 'ns1:runAuthOnly' do |soap| + build_token soap, options + build_transaction_request_object soap, options + end + end + + def build_run_credit(soap, options) + soap.tag! 'ns1:runCredit' do |soap| + build_token soap, options + build_transaction_request_object soap, options + end + end + + def build_run_check_sale(soap, options) + soap.tag! 'ns1:runCheckSale' do |soap| + build_token soap, options + build_transaction_request_object soap, options + end + end + + def build_run_check_credit(soap, options) + soap.tag! 'ns1:runCheckCredit' do |soap| + build_token soap, options + build_transaction_request_object soap, options + end + end + + def build_post_auth(soap, options) + soap.tag! 'ns1:postAuth' do |soap| + build_token soap, options + build_transaction_request_object soap, options + end + end + + def build_run_quick_sale(soap, options) + soap.tag! 'ns1:runQuickSale' do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + build_transaction_detail soap, options + build_tag soap, :boolean, 'AuthOnly', options[:authorize_only] || false + end + end + + def build_run_quick_credit(soap, options) + soap.tag! 'ns1:runQuickCredit' do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + build_transaction_detail soap, options + end + end + + def build_get_transaction(soap, options) + soap.tag! "ns1:getTransaction" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + end + end + + def build_get_transaction_status(soap, options) + soap.tag! "ns1:getTransactionStatus" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + end + end + + def build_get_transaction_custom(soap, options) + soap.tag! "ns1:getTransactionCustom" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + build_transaction_field_array soap, options + end + end + + def build_get_check_trace(soap, options) + soap.tag! "ns1:getCheckTrace" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + end + end + + def build_capture_transaction(soap, options) + soap.tag! "ns1:captureTransaction" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + build_tag soap, :double, 'RefNum', amount(options[:amount]) + end + end + + def build_void_transaction(soap, options) + soap.tag! "ns1:voidTransaction" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + end + end + + def build_refund_transaction(soap, options) + soap.tag! "ns1:refundTransaction" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + build_tag soap, :integer, 'Amount', amount(options[:amount]) + end + end + + def build_override_transaction(soap, options) + soap.tag! "ns1:overrideTransaction" do |soap| + build_token soap, options + build_tag soap, :integer, 'RefNum', options[:reference_number] + build_tag soap, :string, 'Reason', options[:reason] + end + end + + # Account ======================================================= + + def build_get_account_details(soap, options) + soap.tag! "ns1:getAccountDetails" do |soap| + build_token soap, options + end + end + + # Customer Helpers ============================================== + + def build_customer_data(soap, options) + soap.CustomerData 'xsi:type' => 'ns1:CustomerObject' do + CUSTOMER_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[k] + end + build_billing_address soap, options + build_customer_payments soap, options + build_custom_fields soap, options + end + end + + def build_customer_payments(soap, options) + if options[:payment_methods] + length = options[:payment_methods].length + soap.PaymentMethods 'SOAP-ENC:arrayType' => "ns1:PaymentMethod[#{length}]", + 'xsi:type' =>"ns1:PaymentMethodArray" do |soap| + build_customer_payment_methods soap, options + end + end + end + + def extract_methods_and_tag(options) + case + when options[:payment_method] && !options[:payment_methods] + payment_methods = [options[:payment_method]] + tag_name = 'PaymentMethod' + when options[:payment_methods] && !options[:payment_method] + payment_methods = options[:payment_methods] + tag_name = 'item' + else + payment_methods = [options] + tag_name = 'PaymentMethod' + end + [payment_methods, tag_name] + end + + def build_credit_card_or_check(soap, payment_method) + case + when payment_method[:method].kind_of?(ActiveMerchant::Billing::CreditCard) + build_tag soap, :string, 'CardNumber', payment_method[:method].number + build_tag soap, :string, 'CardExpiration', + "#{"%02d" % payment_method[:method].month}#{payment_method[:method].year}" + if options[:billing_address] + build_tag soap, :string, 'AvsStreet', options[:billing_address][:address1] + build_tag soap, :string, 'AvsZip', options[:billing_address][:zip] + end + build_tag soap, :string, 'CardCode', payment_method[:method].verification_value + when payment_method[:method].kind_of?(ActiveMerchant::Billing::Check) + build_tag soap, :string, 'Account', payment_method[:method].number + build_tag soap, :string, 'Routing', payment_method[:method].routing_number + build_tag soap, :string, 'AccountType', payment_method[:method].account_type.capitalize + build_tag soap, :string, 'DriversLicense', options[:drivers_license] + build_tag soap, :string, 'DriversLicenseState', options[:drivers_license_state] + build_tag soap, :string, 'RecordType', options[:record_type] + end + end + + def build_customer_payment_methods(soap, options) + payment_methods, tag_name = extract_methods_and_tag(options) + payment_methods.each do |payment_method| + soap.tag! tag_name, 'xsi:type' => "ns1:PaymentMethod" do |soap| + build_tag soap, :integer, 'MethodID', payment_method[:method_id] + build_tag soap, :string, 'MethodType', payment_method[:type] + build_tag soap, :string, 'MethodName', payment_method[:name] + build_tag soap, :integer, 'SecondarySort', payment_method[:sort] + build_credit_card_or_check(soap, payment_method) + end + end + end + + def build_customer_transaction(soap, options) + soap.Parameters 'xsi:type' => "ns1:CustomerTransactionRequest" do |soap| + build_transaction_detail soap, options + CUSTOMER_TRANSACTION_REQUEST_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[k] + end + build_custom_fields soap, options + build_line_items soap, options + end + end + + # Transaction Helpers =========================================== + + def build_transaction_request_object(soap, options, name='Params') + soap.tag! name, 'xsi:type' => "ns1:TransactionRequestObject" do |soap| + TRANSACTION_REQUEST_OBJECT_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[k] + end + case + when options[:payment_method] == nil + when options[:payment_method].kind_of?(ActiveMerchant::Billing::CreditCard) + build_credit_card_data soap, options + when options[:payment_method].kind_of?(ActiveMerchant::Billing::Check) + build_check_data soap, options + else + raise ArgumentError, 'options[:payment_method] must be a CreditCard or Check' + end + build_transaction_detail soap, options + build_billing_address soap, options + build_shipping_address soap, options + build_recurring_billing soap, options + build_line_items soap, options + build_custom_fields soap, options + end + end + + def build_transaction_detail(soap, options) + soap.Details 'xsi:type' => "ns1:TransactionDetail" do |soap| + TRANSACTION_DETAIL_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[k] + end + TRANSACTION_DETAIL_MONEY_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], amount(options[k]) + end + end + end + + def build_credit_card_data(soap, options) + soap.CreditCardData 'xsi:type' => "ns1:CreditCardData" do |soap| + build_tag soap, :string, 'CardNumber', options[:payment_method].number + build_tag soap, :string, 'CardExpiration', + "#{"%02d" % options[:payment_method].month}#{options[:payment_method].year}" + if options[:billing_address] + build_tag soap, :string, 'AvsStreet', options[:billing_address][:address1] + build_tag soap, :string, 'AvsZip', options[:billing_address][:zip] + end + build_tag soap, :string, 'CardCode', options[:payment_method].verification_value + build_tag soap, :boolean, 'CardPresent', options[:card_present] || false + CREDIT_CARD_DATA_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[k] + end + end + end + + def build_check_data(soap, options) + soap.CheckData 'xsi:type' => "ns1:CheckData" do |soap| + build_tag soap, :string, 'Account', options[:payment_method].account_number + build_tag soap, :string, 'Routing', options[:payment_method].routing_number + build_tag soap, :string, 'AccountType', options[:payment_method].account_type.capitalize + CHECK_DATA_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[k] + end + end + end + + def build_recurring_billing(soap, options) + if options[:recurring] + soap.RecurringBilling 'xsi:type' => "ns1:RecurringBilling" do |soap| + build_tag soap, :double, 'Amount', amount(options[:recurring][:amount]) + build_tag soap, :string, 'Next', options[:recurring][:next].strftime("%Y-%m-%d") if options[:recurring][:next] + build_tag soap, :string, 'Expire', options[:recurring][:expire].strftime("%Y-%m-%d") if options[:recurring][:expire] + RECURRING_BILLING_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[:recurring][k] + end + end + end + end + + def build_transaction_field_array(soap, options) + soap.Fields 'SOAP-ENC:arryType' => "xsd:string[#{options[:fields].length}]", 'xsi:type' => 'ns1:stringArray' do |soap| + options[:fields].each do |field| + build_tag soap, :string, 'item', field + end + end + end + + # General Helpers =============================================== + + def build_billing_address(soap, options) + if options[:billing_address] + if options[:billing_address][:name] + name = options[:billing_address][:name].split(nil,2) # divide name + options[:billing_address][:first_name], options[:billing_address][:last_name] = name[0], name[1] + end + soap.BillingAddress 'xsi:type' => "ns1:Address" do + ADDRESS_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[:billing_address][k] + end + end + end + end + + def build_shipping_address(soap, options) + if options[:shipping_address] + if options[:shipping_address][:name] + name = options[:shipping_address][:name].split(nil,2) # divide name + options[:shipping_address][:first_name], options[:shipping_address][:last_name] = name[0], name[1] + end + soap.ShippingAddress 'xsi:type' => "ns1:Address" do + ADDRESS_OPTIONS.each do |k,v| + build_tag soap, v[0], v[1], options[:shipping_address][k] + end + end + end + end + + def build_line_items(soap, options) # TODO + end + + def build_custom_fields(soap, options) # TODO + end + + # Request ======================================================= + + def commit(action, request) + url = test? ? test_url : live_url + + begin + soap = ssl_post(url, request, "Content-Type" => "text/xml") + rescue ActiveMerchant::ResponseError => error + soap = error.response.body + end + + response = build_response(action, soap) + end + + def build_response(action, soap) + response_params, success, message, authorization, avs, cvv = parse(action, soap) + + response_params.merge!('soap_response' => soap) if @options[:soap_response] + + response = Response.new( + success, message, response_params, + :test => test?, :authorization => authorization, + :avs_result => avs_from(avs), + :cvv_result => cvv + ) + end + + def avs_from(avs) + avs_params = { :code => avs } + avs_params.merge!(:message => AVS_CUSTOM_MESSAGES[avs]) if AVS_CUSTOM_MESSAGES.key?(avs) + avs_params + end + + def parse(action, soap) + xml = REXML::Document.new(soap) + root = REXML::XPath.first(xml, "//SOAP-ENV:Body") + response = root ? parse_element(root[0]) : { :response => soap } + + success, message, authorization, avs, cvv = false, FAILURE_MESSAGE, nil, nil, nil + + fault = (!response) || (response.length < 1) || response.has_key?('faultcode') + return [response, success, response['faultstring'], authorization, avs, cvv] if fault + + if response.respond_to?(:[]) && p = response["#{action}_return"] + if p.respond_to?(:key?) && p.key?('result_code') + success = p['result_code'] == 'A' ? true : false + authorization = p['ref_num'] + avs = AVS_RESULTS[p['avs_result_code']] + cvv = p['card_code_result_code'] + else + success = true + end + message = case action + when :get_customer_payment_methods + p['item'] + when :get_transaction_custom + p['item'].inject({}) { |map, field| map[field['field']] = field['value']; map } + else + p + end + elsif response.respond_to?(:[]) && p = response[:response] + message = p # when response is html + end + + [response, success, message, authorization, avs, cvv] + end + + def parse_element(node) + if node.has_elements? + response = {} + node.elements.each do |e| + key = e.name.underscore + value = parse_element(e) + if response.has_key?(key) + if response[key].is_a?(Array) + response[key].push(value) + else + response[key] = [response[key], value] + end + else + response[key] = parse_element(e) + end + end + else + response = node.text + end + + response + end + + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_transaction.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_transaction.rb new file mode 100644 index 000000000..8adfeb516 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/usa_epay_transaction.rb @@ -0,0 +1,201 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + class UsaEpayTransactionGateway < Gateway + self.test_url = self.live_url = 'https://www.usaepay.com/gate.php' + + self.supported_cardtypes = [:visa, :master, :american_express] + self.supported_countries = ['US'] + self.homepage_url = 'http://www.usaepay.com/' + self.display_name = 'USA ePay' + + TRANSACTIONS = { + :authorization => 'authonly', + :purchase => 'sale', + :capture => 'capture', + :refund => 'refund', + :void => 'void' + } + + def initialize(options = {}) + requires!(options, :login) + super + end + + def authorize(money, credit_card, options = {}) + post = {} + + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, credit_card, options) + add_customer_data(post, options) + + commit(:authorization, post) + end + + def purchase(money, credit_card, options = {}) + post = {} + + add_amount(post, money) + add_invoice(post, options) + add_credit_card(post, credit_card) + add_address(post, credit_card, options) + add_customer_data(post, options) + + commit(:purchase, post) + end + + def capture(money, authorization, options = {}) + post = { :refNum => authorization } + + add_amount(post, money) + commit(:capture, post) + end + + def refund(money, authorization, options = {}) + post = { :refNum => authorization } + + add_amount(post, money) + commit(:refund, post) + end + + def void(authorization, options = {}) + post = { :refNum => authorization } + commit(:void, post) + end + + private + + def add_amount(post, money) + post[:amount] = amount(money) + end + + def expdate(credit_card) + year = format(credit_card.year, :two_digits) + month = format(credit_card.month, :two_digits) + + "#{month}#{year}" + end + + def add_customer_data(post, options) + address = options[:billing_address] || options[:address] || {} + post[:street] = address[:address1] + post[:zip] = address[:zip] + + if options.has_key? :email + post[:custemail] = options[:email] + post[:custreceipt] = 'No' + end + + if options.has_key? :customer + post[:custid] = options[:customer] + end + + if options.has_key? :ip + post[:ip] = options[:ip] + end + end + + def add_address(post, credit_card, options) + billing_address = options[:billing_address] || options[:address] + + add_address_for_type(:billing, post, credit_card, billing_address) if billing_address + add_address_for_type(:shipping, post, credit_card, options[:shipping_address]) if options[:shipping_address] + end + + def add_address_for_type(type, post, credit_card, address) + prefix = address_key_prefix(type) + + post[address_key(prefix, 'fname')] = credit_card.first_name + post[address_key(prefix, 'lname')] = credit_card.last_name + post[address_key(prefix, 'company')] = address[:company] unless address[:company].blank? + post[address_key(prefix, 'street')] = address[:address1] unless address[:address1].blank? + post[address_key(prefix, 'street2')] = address[:address2] unless address[:address2].blank? + post[address_key(prefix, 'city')] = address[:city] unless address[:city].blank? + post[address_key(prefix, 'state')] = address[:state] unless address[:state].blank? + post[address_key(prefix, 'zip')] = address[:zip] unless address[:zip].blank? + post[address_key(prefix, 'country')] = address[:country] unless address[:country].blank? + post[address_key(prefix, 'phone')] = address[:phone] unless address[:phone].blank? + end + + def address_key_prefix(type) + case type + when :shipping then 'ship' + when :billing then 'bill' + end + end + + def address_key(prefix, key) + "#{prefix}#{key}".to_sym + end + + def add_invoice(post, options) + post[:invoice] = options[:order_id] + post[:description] = options[:description] + end + + def add_credit_card(post, credit_card) + post[:card] = credit_card.number + post[:cvv2] = credit_card.verification_value if credit_card.verification_value? + post[:expir] = expdate(credit_card) + post[:name] = credit_card.name + end + + def parse(body) + fields = {} + for line in body.split('&') + key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten + fields[key] = CGI.unescape(value.to_s) + end + + { + :status => fields['UMstatus'], + :auth_code => fields['UMauthCode'], + :ref_num => fields['UMrefNum'], + :batch => fields['UMbatch'], + :avs_result => fields['UMavsResult'], + :avs_result_code => fields['UMavsResultCode'], + :cvv2_result => fields['UMcvv2Result'], + :cvv2_result_code => fields['UMcvv2ResultCode'], + :vpas_result_code => fields['UMvpasResultCode'], + :result => fields['UMresult'], + :error => fields['UMerror'], + :error_code => fields['UMerrorcode'], + :acs_url => fields['UMacsurl'], + :payload => fields['UMpayload'] + }.delete_if{|k, v| v.nil?} + end + + def commit(action, parameters) + response = parse( ssl_post(self.live_url, post_data(action, parameters)) ) + + Response.new(response[:status] == 'Approved', message_from(response), response, + :test => test?, + :authorization => response[:ref_num], + :cvv_result => response[:cvv2_result_code], + :avs_result => { :code => response[:avs_result_code] } + ) + end + + def message_from(response) + if response[:status] == "Approved" + return 'Success' + else + return 'Unspecified error' if response[:error].blank? + return response[:error] + end + end + + def post_data(action, parameters = {}) + parameters[:command] = TRANSACTIONS[action] + parameters[:key] = @options[:login] + parameters[:software] = 'Active Merchant' + parameters[:testmode] = (@options[:test] ? 1 : 0) + + parameters.collect { |key, value| "UM#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/verifi.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/verifi.rb new file mode 100644 index 000000000..c0ff6765c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/verifi.rb @@ -0,0 +1,232 @@ +require 'rexml/document' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class VerifiGateway < Gateway + class VerifiPostData < PostData + # Fields that will be sent even if they are blank + self.required_fields = [ :amount, :type, :ccnumber, :ccexp, :firstname, :lastname, + :company, :address1, :address2, :city, :state, :zip, :country, :phone ] + end + + self.live_url = self.test_url = 'https://secure.verifi.com/gw/api/transact.php' + + RESPONSE_CODE_MESSAGES = { + "100" => "Transaction was Approved", + "200" => "Transaction was Declined by Processor", + "201" => "Do Not Honor", + "202" => "Insufficient Funds", + "203" => "Over Limit", + "204" => "Transaction not allowed", + "220" => "Incorrect payment Data", + "221" => "No Such Card Issuer", + "222" => "No Card Number on file with Issuer", + "223" => "Expired Card", + "224" => "Invalid Expiration Date", + "225" => "Invalid Card Security Code", + "240" => "Call Issuer for Further Information", + "250" => "Pick Up Card", + "251" => "Lost Card", + "252" => "Stolen Card", + "253" => "Fraudulent Card", + "260" => "Declined With further Instructions Available (see response text)", + "261" => "Declined - Stop All Recurring Payments", + "262" => "Declined - Stop this Recurring Program", + "263" => "Declined - Update Cardholder Data Available", + "264" => "Declined - Retry in a few days", + "300" => "Transaction was Rejected by Gateway", + "400" => "Transaction Error Returned by Processor", + "410" => "Invalid Merchant Configuration", + "411" => "Merchant Account is Inactive", + "420" => "Communication Error", + "421" => "Communication Error with Issuer", + "430" => "Duplicate Transaction at Processor", + "440" => "Processor Format Error", + "441" => "Invalid Transaction Information", + "460" => "Processor Feature Not Available", + "461" => "Unsupported Card Type" + } + + SUCCESS = 1 + + TRANSACTIONS = { + :authorization => 'auth', + :purchase => 'sale', + :capture => 'capture', + :void => 'void', + :credit => 'credit', + :refund => 'refund' + } + + self.supported_countries = ['US'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.verifi.com/' + self.display_name = 'Verifi' + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, credit_card, options = {}) + sale_authorization_or_credit_template(:purchase, money, credit_card, options) + end + + def authorize(money, credit_card, options = {}) + sale_authorization_or_credit_template(:authorization, money, credit_card, options) + end + + def capture(money, authorization, options = {}) + capture_void_or_refund_template(:capture, money, authorization, options) + end + + def void(authorization, options = {}) + capture_void_or_refund_template(:void, 0, authorization, options) + end + + def credit(money, credit_card_or_authorization, options = {}) + if credit_card_or_authorization.is_a?(String) + deprecated CREDIT_DEPRECATION_MESSAGE + refund(money, credit_card_or_authorization, options) + else + sale_authorization_or_credit_template(:credit, money, credit_card_or_authorization, options) + end + end + + def refund(money, reference, options = {}) + capture_void_or_refund_template(:refund, money, reference, options) + end + + private + + def sale_authorization_or_credit_template(trx_type, money, credit_card, options = {}) + post = VerifiPostData.new + add_security_key_data(post, options, money) + add_credit_card(post, credit_card) + add_addresses(post, options) + add_customer_data(post, options) + add_invoice_data(post, options) + add_optional_data(post, options) + commit(trx_type, money, post) + end + + def capture_void_or_refund_template(trx_type, money, authorization, options) + post = VerifiPostData.new + post[:transactionid] = authorization + + commit(trx_type, money, post) + end + + def add_credit_card(post, credit_card) + post[:ccnumber] = credit_card.number + post[:ccexp] = expdate(credit_card) + post[:firstname] = credit_card.first_name + post[:lastname] = credit_card.last_name + post[:cvv] = credit_card.verification_value + end + + def expdate(credit_card) + year = sprintf("%.4i", credit_card.year) + month = sprintf("%.2i", credit_card.month) + + "#{month}#{year[-2..-1]}" + end + + def add_addresses(post, options) + if billing_address = options[:billing_address] || options[:address] + post[:company] = billing_address[:company] + post[:address1] = billing_address[:address1] + post[:address2] = billing_address[:address2] + post[:city] = billing_address[:city] + post[:state] = billing_address[:state] + post[:zip] = billing_address[:zip] + post[:country] = billing_address[:country] + post[:phone] = billing_address[:phone] + post[:fax] = billing_address[:fax] + end + + if shipping_address = options[:shipping_address] + post[:shipping_firstname] = shipping_address[:first_name] + post[:shipping_lastname] = shipping_address[:last_name] + post[:shipping_company] = shipping_address[:company] + post[:shipping_address1] = shipping_address[:address1] + post[:shipping_address2] = shipping_address[:address2] + post[:shipping_city] = shipping_address[:city] + post[:shipping_state] = shipping_address[:state] + post[:shipping_zip] = shipping_address[:zip] + post[:shipping_country] = shipping_address[:country] + post[:shipping_email] = shipping_address[:email] + end + end + + def add_customer_data(post, options) + post[:email] = options[:email] + post[:ipaddress] = options[:ip] + end + + def add_invoice_data(post, options) + post[:orderid] = options[:order_id] + post[:ponumber] = options[:invoice] + post[:orderdescription] = options[:description] + post[:tax] = options[:tax] + post[:shipping] = options[:shipping] + end + + def add_optional_data(post, options) + post[:billing_method] = options[:billing_method] + post[:website] = options[:website] + post[:descriptor] = options[:descriptor] + post[:descriptor_phone] = options[:descriptor_phone] + post[:cardholder_auth] = options[:cardholder_auth] + post[:cavv] = options[:cavv] + post[:xid] = options[:xid] + post[:customer_receipt] = options[:customer_receipt] + end + + def add_security_key_data(post, options, money) + # MD5(username|password|orderid|amount|time) + now = Time.now.to_i.to_s + md5 = Digest::MD5.new + md5 << @options[:login].to_s + "|" + md5 << @options[:password].to_s + "|" + md5 << options[:order_id].to_s + "|" + md5 << amount(money).to_s + "|" + md5 << now + post[:key] = md5.hexdigest + post[:time] = now + end + + def commit(trx_type, money, post) + post[:amount] = amount(money) + + response = parse( ssl_post(self.live_url, post_data(trx_type, post)) ) + + Response.new(response[:response].to_i == SUCCESS, message_from(response), response, + :test => test?, + :authorization => response[:transactionid], + :avs_result => { :code => response[:avsresponse] }, + :cvv_result => response[:cvvresponse] + ) + end + + def message_from(response) + response[:response_code_message] ? response[:response_code_message] : "" + end + + def parse(body) + results = {} + CGI.parse(body).each { |key, value| results[key.intern] = value[0] } + results[:response_code_message] = RESPONSE_CODE_MESSAGES[results[:response_code]] if results[:response_code] + results + end + + def post_data(trx_type, post) + post[:username] = @options[:login] + post[:password] = @options[:password] + post[:type] = TRANSACTIONS[trx_type] + + post.to_s + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/viaklix.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/viaklix.rb new file mode 100644 index 000000000..307933e65 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/viaklix.rb @@ -0,0 +1,189 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class ViaklixGateway < Gateway + class_attribute :test_url, :live_url, :delimiter, :actions + + self.test_url = 'https://demo.viaklix.com/process.asp' + self.live_url = 'https://www.viaklix.com/process.asp' + self.delimiter = "\r\n" + + self.actions = { + :purchase => 'SALE', + :credit => 'CREDIT' + } + + APPROVED = '0' + + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.supported_countries = ['US'] + self.display_name = 'ViaKLIX' + self.homepage_url = 'http://viaklix.com' + + # Initialize the Gateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * <tt>:login</tt> -- Merchant ID + # * <tt>:password</tt> -- PIN + # * <tt>:user</tt> -- Specify a subuser of the account (optional) + # * <tt>:test => +true+ or +false+</tt> -- Force test transactions + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + # Make a purchase + def purchase(money, creditcard, options = {}) + form = {} + add_invoice(form, options) + add_creditcard(form, creditcard) + add_address(form, options) + add_customer_data(form, options) + add_test_mode(form, options) + commit(:purchase, money, form) + end + + # Make a credit to a card (Void can only be done from the virtual terminal) + # Viaklix does not support credits by reference. You must pass in the credit card + def credit(money, creditcard, options = {}) + if creditcard.is_a?(String) + raise ArgumentError, "Reference credits are not supported. Please supply the original credit card" + end + + form = {} + add_invoice(form, options) + add_creditcard(form, creditcard) + add_address(form, options) + add_customer_data(form, options) + add_test_mode(form, options) + commit(:credit, money, form) + end + + private + def add_test_mode(form, options) + form[:test_mode] = 'TRUE' if options[:test_mode] + end + + def add_customer_data(form, options) + form[:email] = options[:email].to_s.slice(0, 100) unless options[:email].blank? + form[:customer_code] = options[:customer].to_s.slice(0, 10) unless options[:customer].blank? + end + + def add_invoice(form,options) + form[:invoice_number] = (options[:order_id] || options[:invoice]).to_s.slice(0, 10) + form[:description] = options[:description].to_s.slice(0, 255) + end + + def add_address(form,options) + billing_address = options[:billing_address] || options[:address] + + if billing_address + form[:avs_address] = billing_address[:address1].to_s.slice(0, 30) + form[:address2] = billing_address[:address2].to_s.slice(0, 30) + form[:avs_zip] = billing_address[:zip].to_s.slice(0, 10) + form[:city] = billing_address[:city].to_s.slice(0, 30) + form[:state] = billing_address[:state].to_s.slice(0, 10) + form[:company] = billing_address[:company].to_s.slice(0, 50) + form[:phone] = billing_address[:phone].to_s.slice(0, 20) + form[:country] = billing_address[:country].to_s.slice(0, 50) + end + + if shipping_address = options[:shipping_address] + first_name, last_name = parse_first_and_last_name(shipping_address[:name]) + form[:ship_to_first_name] = first_name.to_s.slice(0, 20) + form[:ship_to_last_name] = last_name.to_s.slice(0, 30) + form[:ship_to_address] = shipping_address[:address1].to_s.slice(0, 30) + form[:ship_to_city] = shipping_address[:city].to_s.slice(0, 30) + form[:ship_to_state] = shipping_address[:state].to_s.slice(0, 10) + form[:ship_to_company] = shipping_address[:company].to_s.slice(0, 50) + form[:ship_to_country] = shipping_address[:country].to_s.slice(0, 50) + form[:ship_to_zip] = shipping_address[:zip].to_s.slice(0, 10) + end + end + + def parse_first_and_last_name(value) + name = value.to_s.split(' ') + + last_name = name.pop || '' + first_name = name.join(' ') + [ first_name, last_name ] + end + + def add_creditcard(form, creditcard) + form[:card_number] = creditcard.number + form[:exp_date] = expdate(creditcard) + + if creditcard.verification_value? + add_verification_value(form, creditcard) + end + + form[:first_name] = creditcard.first_name.to_s.slice(0, 20) + form[:last_name] = creditcard.last_name.to_s.slice(0, 30) + end + + def add_verification_value(form, creditcard) + form[:cvv2cvc2] = creditcard.verification_value + form[:cvv2] = 'present' + end + + def preamble + result = { + 'merchant_id' => @options[:login], + 'pin' => @options[:password], + 'show_form' => 'false', + 'result_format' => 'ASCII' + } + + result['user_id'] = @options[:user] unless @options[:user].blank? + result + end + + def commit(action, money, parameters) + parameters[:amount] = amount(money) + parameters[:transaction_type] = self.actions[action] + + response = parse( ssl_post(test? ? self.test_url : self.live_url, post_data(parameters)) ) + + Response.new(response['result'] == APPROVED, message_from(response), response, + :test => @options[:test] || test?, + :authorization => authorization_from(response), + :avs_result => { :code => response['avs_response'] }, + :cvv_result => response['cvv2_response'] + ) + end + + def authorization_from(response) + response['txn_id'] + end + + def message_from(response) + response['result_message'] + end + + def post_data(parameters) + result = preamble + result.merge!(parameters) + result.collect { |key, value| "ssl_#{key}=#{CGI.escape(value.to_s)}" }.join("&") + end + + def expdate(creditcard) + year = sprintf("%.4i", creditcard.year) + month = sprintf("%.2i", creditcard.month) + "#{month}#{year[2..3]}" + end + + # Parse the response message + def parse(msg) + resp = {} + msg.split(self.delimiter).collect{|li| + key, value = li.split("=") + resp[key.strip.gsub(/^ssl_/, '')] = value.to_s.strip + } + resp + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/vindicia.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/vindicia.rb new file mode 100644 index 000000000..1d091ef00 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/vindicia.rb @@ -0,0 +1,361 @@ +begin + require "vindicia-api" +rescue LoadError + raise "Could not load the vindicia-api gem. Use `gem install vindicia-api` to install it." +end + +require 'i18n/core_ext/string/interpolate' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + + # For more information on the Vindicia Gateway please visit their {website}[http://vindicia.com/] + # + # The login and password are not the username and password you use to + # login to the Vindicia Merchant Portal. + # + # ==== Recurring Billing + # + # AutoBills are an feature of Vindicia's API that allows for creating and managing subscriptions. + # + # For more information about Vindicia's API and various other services visit their {Resource Center}[http://www.vindicia.com/resources/index.html] + class VindiciaGateway < Gateway + self.supported_countries = %w{US CA GB AU MX BR DE KR CN HK} + self.supported_cardtypes = [:visa, :master, :american_express, :discover] + self.homepage_url = 'http://www.vindicia.com/' + self.display_name = 'Vindicia' + + class_attribute :test_url, :live_url + + self.test_url = "https://soap.prodtest.sj.vindicia.com/soap.pl" + self.live_url = "http://soap.vindicia.com/soap.pl" + + # Creates a new VindiciaGateway + # + # The gateway requires that a valid login and password be passed + # in the +options+ hash. + # + # ==== Options + # + # * <tt>:login</tt> -- Vindicia SOAP login (REQUIRED) + # * <tt>:password</tt> -- Vindicia SOAP password (REQUIRED) + # * <tt>:api_version</tt> -- Vindicia API Version - defaults to 3.6 (OPTIONAL) + # * <tt>:account_id</tt> -- Account Id which all transactions will be run against. (REQUIRED) + # * <tt>:transaction_prefix</tt> -- Prefix to order id for one-time transactions - defaults to 'X' (OPTIONAL + # * <tt>:min_chargeback_probability</tt> -- Minimum score for chargebacks - defaults to 65 (OPTIONAL) + # * <tt>:cvn_success</tt> -- Array of valid CVN Check return values - defaults to [M, P] (OPTIONAL) + # * <tt>:avs_success</tt> -- Array of valid AVS Check return values - defaults to [X, Y, A, W, Z] (OPTIONAL) + def initialize(options = {}) + requires!(options, :login, :password) + super + + config = lambda do |config| + config.login = options[:login] + config.password = options[:password] + config.api_version = options[:api_version] || "3.6" + config.endpoint = test? ? self.test_url : self.live_url + config.namespace = "http://soap.vindicia.com" + end + + if Vindicia.config.is_configured? + config.call(Vindicia.config) + else + Vindicia.configure(&config) + end + + requires!(options, :account_id) + @account_id = options[:account_id] + + @transaction_prefix = options[:transaction_prefix] || "X" + + @min_chargeback_probability = options[:min_chargeback_probability] || 65 + @cvn_success = options[:cvn_success] || %w{M P} + @avs_success = options[:avs_success] || %w{X Y A W Z} + + @allowed_authorization_statuses = %w{Authorized} + end + + # Perform a purchase, which is essentially an authorization and capture in a single operation. + # + # ==== Parameters + # + # * <tt>money</tt> -- The amount to be purchased as an Integer value in cents. + # * <tt>creditcard</tt> -- The CreditCard details for the transaction. + # * <tt>options</tt> -- A hash of optional parameters. + def purchase(money, creditcard, options = {}) + response = authorize(money, creditcard, options) + return response if !response.success? || response.fraud_review? + + capture(money, response.authorization, options) + end + + # Performs an authorization, which reserves the funds on the customer's credit card, but does not + # charge the card. + # + # ==== Parameters + # + # * <tt>money</tt> -- The amount to be authorized as an Integer value in cents. + # * <tt>creditcard</tt> -- The CreditCard details for the transaction. + # * <tt>options</tt> -- A hash of optional parameters. + def authorize(money, creditcard, options = {}) + vindicia_transaction = authorize_transaction(money, creditcard, options) + response = check_transaction(vindicia_transaction) + + # if this response is under fraud review because of our AVS/CVV checks void the transaction + if !response.success? && response.fraud_review? && !response.authorization.blank? + void_response = void([vindicia_transaction[:transaction][:merchantTransactionId]], options) + if void_response.success? + return response + else + return void_response + end + end + + response + end + + # Captures the funds from an authorized transaction. + # + # ==== Parameters + # + # * <tt>money</tt> -- The amount to be captured as an Integer value in cents. + # * <tt>identification</tt> -- The authorization returned from the previous authorize request. + def capture(money, identification, options = {}) + response = post(Vindicia::Transaction.capture({ + :transactions => [{ :merchantTransactionId => identification }] + })) + + if response[:return][:returnCode] != '200' || response[:qtyFail].to_i > 0 + return fail(response) + end + + success(response, identification) + end + + # Void a previous transaction + # + # ==== Parameters + # + # * <tt>identification</tt> - The authorization returned from the previous authorize request. + # * <tt>options</tt> - Extra options (currently only :ip used) + def void(identification, options = {}) + response = post(Vindicia::Transaction.cancel({ + :transactions => [{ + :account => { :merchantAccountId => @account_id }, + :merchantTransactionId => identification, + :sourceIp => options[:ip] + }] + })) + + if response[:return][:returnCode] == '200' && response[:qtyFail].to_i == 0 + success(response, identification) + else + fail(response) + end + end + + # Perform a recurring billing, which is essentially a purchase and autobill setup in a single operation. + # + # ==== Parameters + # + # * <tt>money</tt> -- The amount to be purchased as an Integer value in cents. + # * <tt>creditcard</tt> -- The CreditCard details for the transaction. + # * <tt>options</tt> -- A hash of parameters. + # + # ==== Options + # + # * <tt>:product_sku</tt> -- The subscription product's sku + # * <tt>:autobill_prefix</tt> -- Prefix to order id for subscriptions - defaults to 'A' (OPTIONAL) + def recurring(money, creditcard, options={}) + options[:recurring] = true + @autobill_prefix = options[:autobill_prefix] || "A" + + response = authorize(money, creditcard, options) + return response if !response.success? || response.fraud_review? + + capture_resp = capture(money, response.authorization, options) + return capture_resp if !response.success? + + # Setting up a recurring AutoBill requires an associated product + requires!(options, :product_sku) + autobill_response = check_subscription(authorize_subscription(options.merge(:product_sku => options[:product_sku]))) + + if autobill_response.success? + autobill_response + else + # If the AutoBill fails to set-up, void the transaction and return it as the response + void_response = void(capture_resp.authorization, options) + if void_response.success? + return autobill_response + else + return void_response + end + end + end + + protected + + def post(body) + parse(ssl_post(Vindicia.config.endpoint, body, "Content-Type" => "text/xml")) + end + + def parse(response) + # Vindicia always returns in the form of request_type_response => { actual_response } + Hash.from_xml(response)["Envelope"]["Body"].values.first.with_indifferent_access + end + + def check_transaction(vindicia_transaction) + if vindicia_transaction[:return][:returnCode] == '200' + status_log = vindicia_transaction[:transaction][:statusLog].first + if status_log[:creditCardStatus] + avs = status_log[:creditCardStatus][:avsCode] + cvn = status_log[:creditCardStatus][:cvnCode] + end + + if @allowed_authorization_statuses.include?(status_log[:status]) && + check_cvn(cvn) && check_avs(avs) + + success(vindicia_transaction, + vindicia_transaction[:transaction][:merchantTransactionId], + avs, cvn) + else + # If the transaction is authorized, but it didn't pass our AVS/CVV checks send the authorization along so + # that is gets voided. Otherwise, send no authorization. + fail(vindicia_transaction, avs, cvn, false, + @allowed_authorization_statuses.include?(status_log[:status]) ? vindicia_transaction[:transaction][:merchantTransactionId] : "") + end + else + # 406 = Chargeback risk score is higher than minChargebackProbability, transaction not authorized. + fail(vindicia_transaction, nil, nil, vindicia_transaction[:return][:return_code] == '406') + end + end + + def authorize_transaction(money, creditcard, options) + parameters = { + :amount => amount(money), + :currency => options[:currency] || currency(money) + } + + add_account_data(parameters, options) + add_customer_data(parameters, options) + add_payment_source(parameters, creditcard, options) + + post(Vindicia::Transaction.auth({ + :transaction => parameters, + :minChargebackProbability => @min_chargeback_probability + })) + end + + def add_account_data(parameters, options) + parameters[:account] = { :merchantAccountId => @account_id } + parameters[:sourceIp] = options[:ip] if options[:ip] + end + + def add_customer_data(parameters, options) + parameters[:merchantTransactionId] = transaction_id(options[:order_id]) + parameters[:shippingAddress] = convert_am_address_to_vindicia(options[:shipping_address]) + + # Transaction items must be provided for tax purposes + requires!(options, :line_items) + parameters[:transactionItems] = options[:line_items] + + if options[:recurring] + parameters[:nameValues] = [{:name => 'merchantAutoBillIdentifier', :value => autobill_id(options[:order_id])}] + end + end + + def add_payment_source(parameters, creditcard, options) + parameters[:sourcePaymentMethod] = { + :type => 'CreditCard', + :creditCard => { :account => creditcard.number, :expirationDate => "%4d%02d" % [creditcard.year, creditcard.month] }, + :accountHolderName => creditcard.name, + :nameValues => [{ :name => 'CVN', :value => creditcard.verification_value }], + :billingAddress => convert_am_address_to_vindicia(options[:billing_address] || options[:address]), + :customerSpecifiedType => creditcard.brand.capitalize, + :active => !!options[:recurring] + } + end + + def authorize_subscription(options) + parameters = {} + + add_account_data(parameters, options) + add_subscription_information(parameters, options) + + post(Vindicia::AutoBill.update({ + :autobill => parameters, + :validatePaymentMethod => false, + :minChargebackProbability => 100 + })) + end + + def check_subscription(vindicia_transaction) + if vindicia_transaction[:return][:returnCode] == '200' + if vindicia_transaction[:autobill] && vindicia_transaction[:autobill][:status] == "Active" + success(vindicia_transaction, + vindicia_transaction[:autobill][:merchantAutoBillId]) + else + fail(vindicia_transaction) + end + else + fail(vindicia_transaction) + end + end + + def add_subscription_information(parameters, options) + requires!(options, :product_sku) + + if options[:shipping_address] + parameters[:account][:shipping_address] = options[:shipping_address] + end + + parameters[:merchantAutoBillId] = autobill_id(options[:order_id]) + parameters[:product] = { :merchantProductId => options[:product_sku] } + end + + def check_avs(avs) + avs.blank? || @avs_success.include?(avs) + end + + def check_cvn(cvn) + cvn.blank? || @cvn_success.include?(cvn) + end + + def success(response, authorization, avs_code = nil, cvn_code = nil) + ActiveMerchant::Billing::Response.new(true, response[:return][:returnString], response, + { :fraud_review => false, :authorization => authorization, :test => test?, + :avs_result => { :code => avs_code }, :cvv_result => cvn_code }) + end + + def fail(response, avs_code = nil, cvn_code = nil, fraud_review = false, authorization = "") + ActiveMerchant::Billing::Response.new(false, response[:return][:returnString], response, + { :fraud_review => fraud_review || !authorization.blank?, + :authorization => authorization, :test => test?, + :avs_result => { :code => avs_code }, :cvv_result => cvn_code }) + + end + + def autobill_id(order_id) + "#{@autobill_prefix}#{order_id}" + end + + def transaction_id(order_id) + "#{@transaction_prefix}#{order_id}" + end + + # Converts valid ActiveMerchant address hash to proper Vindicia format + def convert_am_address_to_vindicia(address) + return if address.nil? + + convs = { :address1 => :addr1, :address2 => :addr2, + :state => :district, :zip => :postalCode } + + vindicia_address = {} + address.each do |key, val| + vindicia_address[convs[key] || key] = val + end + vindicia_address + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/webpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/webpay.rb new file mode 100644 index 000000000..f8730fc47 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/webpay.rb @@ -0,0 +1,53 @@ +require 'json' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class WebpayGateway < StripeGateway + self.live_url = 'https://api.webpay.jp/v1/' + + self.supported_countries = ['JP'] + self.default_currency = 'JPY' + self.money_format = :cents + self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club] + + self.homepage_url = 'https://webpay.jp/' + self.display_name = 'WebPay' + + def authorize(money, credit_card, options = {}) + raise NotImplementedError.new + end + + def capture(money, credit_card, options = {}) + raise NotImplementedError.new + end + + def json_error(raw_response) + msg = 'Invalid response received from the WebPay API. Please contact support@webpay.jp if you continue to receive this message.' + msg += " (The raw response returned by the API was #{raw_response.inspect})" + { + "error" => { + "message" => msg + } + } + end + + def headers(meta={}) + @@ua ||= JSON.dump({ + :bindings_version => ActiveMerchant::VERSION, + :lang => 'ruby', + :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})", + :platform => RUBY_PLATFORM, + :publisher => 'active_merchant', + :uname => (RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil) + }) + + { + "Authorization" => "Basic " + Base64.encode64(@api_key.to_s + ":").strip, + "User-Agent" => "Webpay/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}", + "X-Webpay-Client-User-Agent" => @@ua, + "X-Webpay-Client-User-Metadata" => meta.to_json + } + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/wirecard.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/wirecard.rb new file mode 100644 index 000000000..2f1885280 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/wirecard.rb @@ -0,0 +1,313 @@ +require 'base64' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class WirecardGateway < Gateway + # Test server location + self.test_url = 'https://c3-test.wirecard.com/secure/ssl-gateway' + + # Live server location + self.live_url = 'https://c3.wirecard.com/secure/ssl-gateway' + + # The Namespaces are not really needed, because it just tells the System, that there's actually no namespace used. + # It's just specified here for completeness. + ENVELOPE_NAMESPACES = { + 'xmlns:xsi' => 'http://www.w3.org/1999/XMLSchema-instance', + 'xsi:noNamespaceSchemaLocation' => 'wirecard.xsd' + } + + PERMITTED_TRANSACTIONS = %w[ PREAUTHORIZATION CAPTURE PURCHASE ] + + RETURN_CODES = %w[ ACK NOK ] + + # Wirecard only allows phone numbers with a format like this: +xxx(yyy)zzz-zzzz-ppp, where: + # xxx = Country code + # yyy = Area or city code + # zzz-zzzz = Local number + # ppp = PBX extension + # For example, a typical U.S. or Canadian number would be "+1(202)555-1234-739" indicating PBX extension 739 at phone + # number 5551234 within area code 202 (country code 1). + VALID_PHONE_FORMAT = /\+\d{1,3}(\(?\d{3}\)?)?\d{3}-\d{4}-\d{3}/ + + # The countries the gateway supports merchants from as 2 digit ISO country codes + self.supported_countries = ['DE'] + + # Wirecard supports all major credit and debit cards: + # Visa, Mastercard, American Express, Diners Club, + # JCB, Switch, VISA Carte Bancaire, Visa Electron and UATP cards. + # They also support the latest anti-fraud systems such as Verified by Visa or Master Secure Code. + self.supported_cardtypes = [ + :visa, :master, :american_express, :diners_club, :jcb, :switch + ] + + # The homepage URL of the gateway + self.homepage_url = 'http://www.wirecard.com' + + # The name of the gateway + self.display_name = 'Wirecard' + + # The currency should normally be EUROs + self.default_currency = 'EUR' + + # 100 is 1.00 Euro + self.money_format = :cents + + def initialize(options = {}) + # verify that username and password are supplied + requires!(options, :login, :password) + # unfortunately Wirecard also requires a BusinessCaseSignature in the XML request + requires!(options, :signature) + super + end + + # Authorization + def authorize(money, creditcard, options = {}) + options[:credit_card] = creditcard + commit(:preauthorization, money, options) + end + + # Capture Authorization + def capture(money, authorization, options = {}) + options[:preauthorization] = authorization + commit(:capture, money, options) + end + + # Purchase + def purchase(money, creditcard, options = {}) + options[:credit_card] = creditcard + commit(:purchase, money, options) + end + + private + + def prepare_options_hash(options) + result = @options.merge(options) + setup_address_hash!(result) + result + end + + # Create all address hash key value pairs so that + # it still works if only provided with one or two of them + def setup_address_hash!(options) + options[:billing_address] = options[:billing_address] || options[:address] || {} + options[:shipping_address] = options[:shipping_address] || {} + # Include Email in address-hash from options-hash + options[:billing_address][:email] = options[:email] if options[:email] + end + + # Contact WireCard, make the XML request, and parse the + # reply into a Response object + def commit(action, money, options) + request = build_request(action, money, options) + + headers = { 'Content-Type' => 'text/xml', + 'Authorization' => encoded_credentials } + + response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers)) + # Pending Status also means Acknowledged (as stated in their specification) + success = response[:FunctionResult] == "ACK" || response[:FunctionResult] == "PENDING" + message = response[:Message] + authorization = response[:GuWID] + + Response.new(success, message, response, + :test => test?, + :authorization => authorization, + :avs_result => { :code => response[:avsCode] }, + :cvv_result => response[:cvCode] + ) + rescue ResponseError => e + if e.response.code == "401" + return Response.new(false, "Invalid Login") + else + raise + end + end + + # Generates the complete xml-message, that gets sent to the gateway + def build_request(action, money, options) + options = prepare_options_hash(options) + options[:action] = action + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! + xml.tag! 'WIRECARD_BXML' do + xml.tag! 'W_REQUEST' do + xml.tag! 'W_JOB' do + xml.tag! 'JobID', '' + # UserID for this transaction + xml.tag! 'BusinessCaseSignature', options[:signature] || options[:login] + # Create the whole rest of the message + add_transaction_data(xml, money, options) + end + end + end + xml.target! + end + + # Includes the whole transaction data (payment, creditcard, address) + def add_transaction_data(xml, money, options) + options[:order_id] ||= generate_unique_id + + xml.tag! "FNC_CC_#{options[:action].to_s.upcase}" do + xml.tag! 'FunctionID', options[:description].to_s.slice(0,32) + xml.tag! 'CC_TRANSACTION' do + xml.tag! 'TransactionID', options[:order_id] + case options[:action] + when :preauthorization, :purchase + add_invoice(xml, money, options) + add_creditcard(xml, options[:credit_card]) + add_address(xml, options[:billing_address]) + when :capture + xml.tag! 'GuWID', options[:preauthorization] + add_amount(xml, money) + end + end + end + end + + # Includes the payment (amount, currency, country) to the transaction-xml + def add_invoice(xml, money, options) + add_amount(xml, money) + xml.tag! 'Currency', options[:currency] || currency(money) + xml.tag! 'CountryCode', options[:billing_address][:country] + xml.tag! 'RECURRING_TRANSACTION' do + xml.tag! 'Type', options[:recurring] || 'Single' + end + end + + # Include the amount in the transaction-xml + def add_amount(xml, money) + xml.tag! 'Amount', amount(money) + end + + # Includes the credit-card data to the transaction-xml + def add_creditcard(xml, creditcard) + raise "Creditcard must be supplied!" if creditcard.nil? + xml.tag! 'CREDIT_CARD_DATA' do + xml.tag! 'CreditCardNumber', creditcard.number + xml.tag! 'CVC2', creditcard.verification_value + xml.tag! 'ExpirationYear', creditcard.year + xml.tag! 'ExpirationMonth', format(creditcard.month, :two_digits) + xml.tag! 'CardHolderName', [creditcard.first_name, creditcard.last_name].join(' ') + end + end + + # Includes the IP address of the customer to the transaction-xml + def add_customer_data(xml, options) + return unless options[:ip] + xml.tag! 'CONTACT_DATA' do + xml.tag! 'IPAddress', options[:ip] + end + end + + # Includes the address to the transaction-xml + def add_address(xml, address) + return if address.nil? + xml.tag! 'CORPTRUSTCENTER_DATA' do + xml.tag! 'ADDRESS' do + xml.tag! 'Address1', address[:address1] + xml.tag! 'Address2', address[:address2] if address[:address2] + xml.tag! 'City', address[:city] + xml.tag! 'ZipCode', address[:zip] + + if address[:state] =~ /[A-Za-z]{2}/ && address[:country] =~ /^(us|ca)$/i + xml.tag! 'State', address[:state].upcase + end + + xml.tag! 'Country', address[:country] + xml.tag! 'Phone', address[:phone] if address[:phone] =~ VALID_PHONE_FORMAT + xml.tag! 'Email', address[:email] + end + end + end + + # Read the XML message from the gateway and check if it was successful, + # and also extract required return values from the response. + def parse(xml) + basepath = '/WIRECARD_BXML/W_RESPONSE' + response = {} + + xml = REXML::Document.new(xml) + if root = REXML::XPath.first(xml, "#{basepath}/W_JOB") + parse_response(response, root) + elsif root = REXML::XPath.first(xml, "//ERROR") + parse_error(response, root) + else + response[:Message] = "No valid XML response message received. \ + Propably wrong credentials supplied with HTTP header." + end + + response + end + + # Parse the <ProcessingStatus> Element which containts all important information + def parse_response(response, root) + status = nil + # get the root element for this Transaction + root.elements.to_a.each do |node| + if node.name =~ /FNC_CC_/ + status = REXML::XPath.first(node, "CC_TRANSACTION/PROCESSING_STATUS") + end + end + message = "" + if status + if info = status.elements['Info'] + message << info.text + end + # Get basic response information + status.elements.to_a.each do |node| + response[node.name.to_sym] = (node.text || '').strip + end + end + parse_error(root, message) + response[:Message] = message + end + + # Parse a generic error response from the gateway + def parse_error(root, message = "") + # Get errors if available and append them to the message + errors = errors_to_string(root) + unless errors.strip.blank? + message << ' - ' unless message.strip.blank? + message << errors + end + message + end + + # Parses all <ERROR> elements in the response and converts the information + # to a single string + def errors_to_string(root) + # Get context error messages (can be 0..*) + errors = [] + REXML::XPath.each(root, "//ERROR") do |error_elem| + error = {} + error[:Advice] = [] + error[:Message] = error_elem.elements['Message'].text + error_elem.elements.each('Advice') do |advice| + error[:Advice] << advice.text + end + errors << error + end + # Convert all messages to a single string + string = '' + errors.each do |error| + string << error[:Message] + error[:Advice].each_with_index do |advice, index| + string << ' (' if index == 0 + string << "#{index+1}. #{advice}" + string << ' and ' if index < error[:Advice].size - 1 + string << ')' if index == error[:Advice].size - 1 + end + end + string + end + + # Encode login and password in Base64 to supply as HTTP header + # (for http basic authentication) + def encoded_credentials + credentials = [@options[:login], @options[:password]].join(':') + "Basic " << Base64.encode64(credentials).strip + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/worldpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/worldpay.rb new file mode 100644 index 000000000..930cf1c8e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/gateways/worldpay.rb @@ -0,0 +1,302 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class WorldpayGateway < Gateway + self.test_url = 'https://secure-test.worldpay.com/jsp/merchant/xml/paymentService.jsp' + self.live_url = 'https://secure.worldpay.com/jsp/merchant/xml/paymentService.jsp' + + self.default_currency = 'GBP' + self.money_format = :cents + self.supported_countries = ['HK', 'US', 'GB', 'AU'] + self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :laser] + self.homepage_url = 'http://www.worldpay.com/' + self.display_name = 'WorldPay' + + CARD_CODES = { + 'visa' => 'VISA-SSL', + 'master' => 'ECMC-SSL', + 'discover' => 'DISCOVER-SSL', + 'american_express' => 'AMEX-SSL', + 'jcb' => 'JCB-SSL', + 'maestro' => 'MAESTRO-SSL', + 'laser' => 'LASER-SSL' + } + + def initialize(options = {}) + requires!(options, :login, :password) + super + end + + def purchase(money, payment_method, options = {}) + MultiResponse.run do |r| + r.process{authorize(money, payment_method, options)} + r.process{capture(money, r.authorization, options.merge(:authorization_validated => true))} + end + end + + def authorize(money, payment_method, options = {}) + requires!(options, :order_id) + authorize_request(money, payment_method, options) + end + + def capture(money, authorization, options = {}) + MultiResponse.run do |r| + r.process{inquire_request(authorization, options, "AUTHORISED")} unless options[:authorization_validated] + if r.params + authorization_currency = r.params['amount_currency_code'] + options = options.merge(:currency => authorization_currency) if authorization_currency.present? + end + r.process{capture_request(money, authorization, options)} + end + end + + def void(authorization, options = {}) + MultiResponse.run do |r| + r.process{inquire_request(authorization, options, "AUTHORISED")} + r.process{cancel_request(authorization, options)} + end + end + + def refund(money, authorization, options = {}) + MultiResponse.run do |r| + r.process{inquire_request(authorization, options, "CAPTURED", "SETTLED")} + r.process{refund_request(money, authorization, options)} + end + end + + private + + def authorize_request(money, payment_method, options) + commit('authorize', build_authorization_request(money, payment_method, options), "AUTHORISED") + end + + def capture_request(money, authorization, options) + commit('capture', build_capture_request(money, authorization, options), :ok) + end + + def cancel_request(authorization, options) + commit('cancel', build_void_request(authorization, options), :ok) + end + + def inquire_request(authorization, options, *success_criteria) + commit('inquiry', build_order_inquiry_request(authorization, options), *success_criteria) + end + + def refund_request(money, authorization, options) + commit('refund', build_refund_request(money, authorization, options), :ok) + end + + def build_request + xml = Builder::XmlMarkup.new :indent => 2 + xml.instruct! :xml, :encoding => 'ISO-8859-1' + xml.declare! :DOCTYPE, :paymentService, :PUBLIC, "-//WorldPay//DTD WorldPay PaymentService v1//EN", "http://dtd.wp3.rbsworldpay.com/paymentService_v1.dtd" + xml.tag! 'paymentService', 'version' => "1.4", 'merchantCode' => @options[:login] do + yield xml + end + xml.target! + end + + def build_order_modify_request(authorization) + build_request do |xml| + xml.tag! 'modify' do + xml.tag! 'orderModification', 'orderCode' => authorization do + yield xml + end + end + end + end + + def build_order_inquiry_request(authorization, options) + build_request do |xml| + xml.tag! 'inquiry' do + xml.tag! 'orderInquiry', 'orderCode' => authorization + end + end + end + + def build_authorization_request(money, payment_method, options) + build_request do |xml| + xml.tag! 'submit' do + xml.tag! 'order', {'orderCode' => options[:order_id], 'installationId' => @options[:inst_id]}.reject{|_,v| !v} do + xml.description(options[:description].blank? ? "Purchase" : options[:description]) + add_amount(xml, money, options) + if options[:order_content] + xml.tag! 'orderContent' do + xml.cdata! options[:order_content] + end + end + add_payment_method(xml, money, payment_method, options) + end + end + end + end + + def build_capture_request(money, authorization, options) + build_order_modify_request(authorization) do |xml| + xml.tag! 'capture' do + time = Time.now + xml.tag! 'date', 'dayOfMonth' => time.day, 'month' => time.month, 'year'=> time.year + add_amount(xml, money, options) + end + end + end + + def build_void_request(authorization, options) + build_order_modify_request(authorization) do |xml| + xml.tag! 'cancel' + end + end + + def build_refund_request(money, authorization, options) + build_order_modify_request(authorization) do |xml| + xml.tag! 'refund' do + add_amount(xml, money, options.merge(:debit_credit_indicator => "credit")) + end + end + end + + def add_amount(xml, money, options) + currency = options[:currency] || currency(money) + amount = localized_amount(money, currency) + + amount_hash = { + :value => amount, + 'currencyCode' => currency, + 'exponent' => 2 + } + + if options[:debit_credit_indicator] + amount_hash.merge!('debitCreditIndicator' => options[:debit_credit_indicator]) + end + + xml.tag! 'amount', amount_hash + end + + def add_payment_method(xml, amount, payment_method, options) + if payment_method.is_a?(String) + xml.tag! 'payAsOrder', 'orderCode' => payment_method do + add_amount(xml, amount, options) + end + else + xml.tag! 'paymentDetails' do + xml.tag! CARD_CODES[card_brand(payment_method)] do + xml.tag! 'cardNumber', payment_method.number + xml.tag! 'expiryDate' do + xml.tag! 'date', 'month' => format(payment_method.month, :two_digits), 'year' => format(payment_method.year, :four_digits) + end + + xml.tag! 'cardHolderName', payment_method.name + xml.tag! 'cvc', payment_method.verification_value + + add_address(xml, 'cardAddress', (options[:billing_address] || options[:address])) + end + end + end + end + + def add_address(xml, element, address) + return if address.nil? + + xml.tag! element do + xml.tag! 'address' do + if m = /^\s*([^\s]+)\s+(.+)$/.match(address[:name]) + xml.tag! 'firstName', m[1] + xml.tag! 'lastName', m[2] + end + if m = /^\s*(\d+)\s+(.+)$/.match(address[:address1]) + xml.tag! 'street', m[2] + house_number = m[1] + else + xml.tag! 'street', address[:address1] + end + xml.tag! 'houseName', address[:address2] if address[:address2] + xml.tag! 'houseNumber', house_number if house_number.present? + xml.tag! 'postalCode', (address[:zip].present? ? address[:zip] : "0000") + xml.tag! 'city', address[:city] if address[:city] + xml.tag! 'state', (address[:state].present? ? address[:state] : 'N/A') + xml.tag! 'countryCode', address[:country] + xml.tag! 'telephoneNumber', address[:phone] if address[:phone] + end + end + end + + def parse(action, xml) + parse_element({:action => action}, REXML::Document.new(xml)) + end + + def parse_element(raw, node) + node.attributes.each do |k, v| + raw["#{node.name.underscore}_#{k.underscore}".to_sym] = v + end + if node.has_elements? + raw[node.name.underscore.to_sym] = true unless node.name.blank? + node.elements.each{|e| parse_element(raw, e) } + else + raw[node.name.underscore.to_sym] = node.text unless node.text.nil? + end + raw + end + + def commit(action, request, *success_criteria) + xmr = ssl_post(url, request, 'Content-Type' => 'text/xml', 'Authorization' => encoded_credentials) + raw = parse(action, xmr) + success, message = success_and_message_from(raw, success_criteria) + + Response.new( + success, + message, + raw, + :authorization => authorization_from(raw), + :test => test?) + + rescue ActiveMerchant::ResponseError => e + if e.response.code.to_s == "401" + return Response.new(false, "Invalid credentials", {}, :test => test?) + else + raise e + end + end + + def url + test? ? self.test_url : self.live_url + end + + # success_criteria can be: + # - a string or an array of strings (if one of many responses) + # - An array of strings if one of many responses could be considered a + # success. + def success_and_message_from(raw, success_criteria) + success = (success_criteria.include?(raw[:last_event]) || raw[:ok].present?) + if success + message = "SUCCESS" + else + message = (raw[:iso8583_return_code_description] || raw[:error] || required_status_message(raw, success_criteria)) + end + + [ success, message ] + end + + def required_status_message(raw, success_criteria) + if(!success_criteria.include?(raw[:last_event])) + "A transaction status of #{success_criteria.collect{|c| "'#{c}'"}.join(" or ")} is required." + end + end + + def authorization_from(raw) + pair = raw.detect{|k,v| k.to_s =~ /_order_code$/} + (pair ? pair.last : nil) + end + + def encoded_credentials + credentials = "#{@options[:login]}:#{@options[:password]}" + "Basic #{[credentials].pack('m').strip}" + end + + def localized_amount(money, currency) + amount = amount(money) + return amount unless CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s) + + amount.to_i / 100 * 100 + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations.rb new file mode 100644 index 000000000..27d8bd220 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations.rb @@ -0,0 +1,17 @@ +module ActiveMerchant + module Billing + module Integrations + + Dir[File.dirname(__FILE__) + '/integrations/*.rb'].each do |f| + + # Get camelized class name + filename = File.basename(f, '.rb') + # Camelize the string to get the class name + gateway_class = filename.camelize.to_sym + + # Register for autoloading + autoload gateway_class, f + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator.rb new file mode 100644 index 000000000..9ac093aed --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator.rb @@ -0,0 +1,26 @@ +require File.dirname(__FILE__) + '/a1agregator/helper.rb' +require File.dirname(__FILE__) + '/a1agregator/notification.rb' +require File.dirname(__FILE__) + '/a1agregator/status.rb' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module A1agregator + + mattr_accessor :service_url + self.service_url = 'https://partner.a1agregator.ru/a1lite/input/' + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'check' + + def self.notification(*args) + Notification.new(*args) + end + + def self.status(login, password) + Status.new(login, password) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/helper.rb new file mode 100644 index 000000000..cddf1f853 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/helper.rb @@ -0,0 +1,31 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module A1agregator + class Helper < ActiveMerchant::Billing::Integrations::Helper + + # public key + mapping :account, 'key' + + mapping :amount, 'cost' + + mapping :order, 'order_id' + + mapping :customer, :email => 'email', + :phone => 'phone_number' + + # payment description + mapping :credential2, 'name' + + mapping :credential3, 'comment' + + # on error + # 1 - raise error + # 0 - redirect + mapping :credential4, 'verbose' + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/notification.rb new file mode 100644 index 000000000..d714f3d48 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/notification.rb @@ -0,0 +1,186 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module A1agregator + class Notification < ActiveMerchant::Billing::Integrations::Notification + + self.production_ips = [ + '78.108.178.206', + '79.137.235.129', + '95.163.96.79', + '212.24.38.100' + ] + + def initialize(*args) + super + guess_notification_type + end + + # Simple notification request params: + # tid + # name + # comment + # partner_id + # service_id + # order_id + # type + # partner_income + # system_income + + def complete? + true + end + + def transaction_id + params['tid'] + end + + def title + params['name'] + end + + def comment + params['comment'] + end + + def partner_id + params['partner_id'] + end + + def service_id + params['service_id'] + end + + def item_id + params['order_id'] + end + + def type + params['type'] + end + + def partner_income + params['partner_income'] + end + + def system_income + params['system_income'] + end + + # Additional notification request params: + # tid + # name + # comment + # partner_id + # service_id + # order_id + # type + # cost + # income_total + # income + # partner_income + # system_income + # command + # phone_number + # email + # resultStr + # date_created + # version + # check + + def inclome_total + params['income_total'] + end + + def income + params['income'] + end + + def partner_income + params['partner_income'] + end + + def system_income + params['system_income'] + end + + def command + params['command'] + end + + def phone_number + params['phone_number'] + end + + def payer_email + params['email'] + end + + def result_string + params['resultStr'] + end + + def received_at + params['date_created'] + end + + def version + params['version'] + end + + def security_key + params[A1agregator.signature_parameter_name].to_s.downcase + end + + # the money amount we received in X.2 decimal. + alias_method :gross, :system_income + + def currency + 'RUB' + end + + # Was this a test transaction? + def test? + params['test'] == '1' + end + + def simple_notification? + @notification_type == :simple + end + + def additional_notification? + @notification_type == :additional + end + + def acknowledge + security_key == signature + end + + private + + def signature + data = "#{params['tid']}\ +#{params['name']}\ +#{params['comment']}\ +#{params['partner_id']}\ +#{params['service_id']}\ +#{params['order_id']}\ +#{params['type']}\ +#{params['partner_income']}\ +#{params['system_income']}\ +#{params['test']}\ +#{@options[:secret]}" + Digest::MD5.hexdigest(data) + end + + def guess_notification_type + @notification_type = params['version'] ? :additional : :simple + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/status.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/status.rb new file mode 100644 index 000000000..264db72da --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/a1agregator/status.rb @@ -0,0 +1,38 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module A1agregator + + class Status + include PostsData + + STATUS_TEST_URL = 'https://partner.a1pay.ru/a1lite/info/' + + attr_accessor :login, :password + + def initialize(login, password) + @login, @password = login, password + end + + # agregator provides two methods: + # by tid - transaction id + # by order_id & service_id + def update(options = {}) + data = PostData.new + data[:user] = @login + data[:pass] = @password + if options[:tid] + data[:tid] = options[:tid] + else + data[:ord_id] = options[:ord_id] + data[:service_id] = options[:service_id] + end + + ssl_post(STATUS_TEST_URL, data.to_post_data) + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/action_view_helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/action_view_helper.rb new file mode 100644 index 000000000..7fed361e7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/action_view_helper.rb @@ -0,0 +1,73 @@ +require 'action_pack' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module ActionViewHelper + # This helper allows the usage of different payment integrations + # through a single form helper. Payment integrations are the + # type of service where the user is redirected to the secure + # site of the service, like Paypal or Chronopay. + # + # The helper creates a scope around a payment service helper + # which provides the specific mapping for that service. + # + # <% payment_service_for 1000, 'paypalemail@mystore.com', + # :amount => 50.00, + # :currency => 'CAD', + # :service => :paypal, + # :html => { :id => 'payment-form' } do |service| %> + # + # <% service.customer :first_name => 'Cody', + # :last_name => 'Fauser', + # :phone => '(555)555-5555', + # :email => 'cody@example.com' %> + # + # <% service.billing_address :city => 'Ottawa', + # :address1 => '21 Snowy Brook Lane', + # :address2 => 'Apt. 36', + # :state => 'ON', + # :country => 'CA', + # :zip => 'K1J1E5' %> + # + # <% service.invoice '#1000' %> + # <% service.shipping '0.00' %> + # <% service.tax '0.00' %> + # + # <% service.notify_url url_for(:only_path => false, :action => 'notify') %> + # <% service.return_url url_for(:only_path => false, :action => 'done') %> + # <% service.cancel_return_url 'http://mystore.com' %> + # <% end %> + # + def payment_service_for(order, account, options = {}, &proc) + raise ArgumentError, "Missing block" unless block_given? + + integration_module = ActiveMerchant::Billing::Integrations.const_get(options.delete(:service).to_s.camelize) + service_class = integration_module.const_get('Helper') + + form_options = options.delete(:html) || {} + service = service_class.new(order, account, options) + form_options[:method] = service.form_method + result = [] + result << form_tag(integration_module.service_url, form_options) + + result << capture(service, &proc) + + service.form_fields.each do |field, value| + result << hidden_field_tag(field, value) + end + + service.raw_html_fields.each do |field, value| + result << "<input id=\"#{field}\" name=\"#{field}\" type=\"hidden\" value=\"#{value}\" />\n" + end + + result << '</form>' + result= result.join("\n") + + concat(result.respond_to?(:html_safe) ? result.html_safe : result) + nil + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim.rb new file mode 100644 index 000000000..e4a56576e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim.rb @@ -0,0 +1,38 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module AuthorizeNetSim + autoload :Helper, 'active_merchant/billing/integrations/authorize_net_sim/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/authorize_net_sim/notification.rb' + + # Overwrite this if you want to change the ANS test url + mattr_accessor :test_url + self.test_url = 'https://test.authorize.net/gateway/transact.dll' + + # Overwrite this if you want to change the ANS production url + mattr_accessor :production_url + self.production_url = 'https://secure.authorize.net/gateway/transact.dll' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post) + Notification.new(post) + end + + def self.return(query_string) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb new file mode 100644 index 000000000..8709b31b0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb @@ -0,0 +1,228 @@ +require 'active_support/core_ext/float/rounding.rb' # Float#round(precision) + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module AuthorizeNetSim + # An example. Note the username as a parameter and transaction key you + # will want to use later. The amount that you pass in will be *rounded*, + # so preferably pass in X.2 decimal so that no rounding occurs. It is + # rounded because if it looks like 00.000 Authorize.Net fails the + # transaction as incorrectly formatted. + # + # payment_service_for('order_id', 'authorize_net_account', :service => :authorize_net_sim, :amount => 157.0) do |service| + # + # # You must call setup_hash and invoice + # + # service.setup_hash :transaction_key => '8CP6zJ7uD875J6tY', + # :order_timestamp => 1206836763 + # service.customer_id 8 + # service.customer :first_name => 'g', + # :last_name => 'g', + # :email => 'g@g.com', + # :phone => '3' + # service.billing_address :zip => 'g', + # :country => 'United States of America', + # :address => 'g' + # + # service.ship_to_address :first_name => 'g', + # :last_name => 'g', + # :city => '', + # :address => 'g', + # :address2 => '', + # :state => address.state, + # :country => 'United States of America', + # :zip => 'g' + # + # service.invoice "516428355" # your invoice number + # # The end-user is presented with the HTML produced by the notify_url. + # service.notify_url "http://t/authorize_net_sim/payment_received_notification_sub_step" + # service.payment_header 'My store name' + # service.add_line_item :name => 'item name', :quantity => 1, :unit_price => 0 + # service.test_request 'true' # only if it's just a test + # service.shipping '25.0' + # # Tell it to display a "0" line item for shipping, with the price in + # # the name, otherwise it isn't shown at all, leaving the end user to + # # wonder why the total is different than the sum of the line items. + # service.add_shipping_as_line_item + # server.add_tax_as_line_item # same with tax + # # See the helper.rb file for various custom fields + # end + + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :order, 'x_fp_sequence' + mapping :account, 'x_login' + + mapping :customer, :first_name => 'x_first_name', + :last_name => 'x_last_name', + :email => 'x_email', + :phone => 'x_phone' + + mapping :notify_url, 'x_relay_url' + mapping :return_url, '' # unused + mapping :cancel_return_url, '' # unused + + # Custom fields for Authorize.net SIM. + # See http://www.Authorize.Net/support/SIM_guide.pdf for more descriptions. + mapping :fax, 'x_fax' + mapping :customer_id, 'x_cust_id' + mapping :description, 'x_description' + mapping :tax, 'x_tax' + mapping :shipping, 'x_freight' + + # True or false, or 0 or 1 same effect [not required to send one, + # defaults to false]. + mapping :test_request, 'x_test_request' + + # This one is necessary for the notify url to be able to parse its + # information later! They also pass back customer id, if that's + # useful. + def invoice(number) + add_field 'x_invoice_num', number + end + + # Set the billing address. Call like service.billing_address {:city => + # 'provo, :state => 'UT'}... + def billing_address(options) + for setting in [:city, :state, :zip, :country, :po_num] do + add_field 'x_' + setting.to_s, options[setting] + end + raise 'must use address1 and address2' if options[:address] + add_field 'x_address', (options[:address1].to_s + ' ' + options[:address2].to_s).strip + end + + # Adds a custom field which you submit to Authorize.Net. These fields + # are all passed back to you verbatim when it does its relay + # (callback) to you note that if you call it twice with the same name, + # this function only uses keeps the second value you called it with. + def add_custom_field(name, value) + add_field name, value + end + + # Displays tax as a line item, so they can see it. Otherwise it isn't + # displayed. + def add_tax_as_line_item + raise unless @fields['x_tax'] + add_line_item :name => 'Total Tax', :quantity => 1, :unit_price => @fields['x_tax'], :tax => 0, :line_title => 'Tax' + end + + # Displays shipping as a line item, so they can see it. Otherwise it + # isn't displayed. + def add_shipping_as_line_item(extra_options = {}) + raise 'must set shipping/freight before calling this' unless @fields['x_freight'] + add_line_item extra_options.merge({:name => 'Shipping and Handling Cost', :quantity => 1, :unit_price => @fields['x_freight'], :line_title => 'Shipping'}) + end + + # Add ship_to_address in the same format as the normal address is + # added. + def ship_to_address(options) + for setting in [:first_name, :last_name, :company, :city, :state, :zip, :country] do + if options[setting] then + add_field 'x_ship_to_' + setting.to_s, options[setting] + end + end + raise 'must use :address1 and/or :address2' if options[:address] + add_field 'x_ship_to_address', (options[:address1].to_s + ' ' + options[:address2].to_s).strip + end + + # These control the look of the SIM payment page. Note that you can + # include a CSS header in descriptors, etc. + mapping :color_link, 'x_color_link' + mapping :color_text, 'x_color_text' + mapping :logo_url, 'x_logo_url' + mapping :background_url, 'x_background_url' # background image url for the page + mapping :payment_header, 'x_header_html_payment_form' + mapping :payment_footer, 'x_footer_html_payment_form' + + # For this to work you must have also passed in an email for the + # purchaser. + def yes_email_customer_from_authorizes_side + add_field 'x_email_customer', 'TRUE' + end + + # Add a line item to Authorize.Net. + # Call line add_line_item {:name => 'orange', :unit_price => 30, :tax_value => 'Y', :quantity => 3, } + # Note you can't pass in a negative unit price, and you can add an + # optional :line_title => 'special name' if you don't want it to say + # 'Item 1' or what not, the default coded here. + # Cannot have a negative price, nor a name with "'s or $ + # You can use the :line_title for the product name and then :name for description, if desired + def add_line_item(options) + raise 'needs name' unless options[:name] + + if @line_item_count == 30 + # Add a note that we are not showing at least one -- AN doesn't + # display more than 30 or so. + description_of_last = @raw_html_fields[-1][1] + # Pull off the second to last section, which is the description. + description_of_last =~ />([^>]*)<\|>[YN]$/ + # Create a new description, which can't be too big, so truncate here. + @raw_html_fields[-1][1] = description_of_last.gsub($1, $1[0..200] + ' + more unshown items after this one.') + end + + name = options[:name] + quantity = options[:quantity] || 1 + line_title = options[:line_title] || ('Item ' + (@line_item_count + 1).to_s) # left most field + unit_price = options[:unit_price] || 0 + unit_price = unit_price.to_f.round(2) + tax_value = options[:tax_value] || 'N' + + # Sanitization, in case they include a reserved word here, following + # their guidelines; unfortunately, they require 'raw' fields here, + # not CGI escaped, using their own delimiters. + # + # Authorize.net ignores the second field (sanitized_short_name) + raise 'illegal char for line item <|>' if name.include? '<|>' + raise 'illegal char for line item "' if name.include? '"' + raise 'cannot pass in dollar sign' if unit_price.to_s.include? '$' + raise 'must have positive or 0 unit price' if unit_price.to_f < 0 + # Using CGI::escape causes the output to be formated incorrectly in + # the HTML presented to the end-user's browser (e.g., spaces turn + # into +'s). + sanitized_short_name = name[0..30] + name = name[0..255] + + add_raw_html_field "x_line_item", "#{line_title}<|>#{sanitized_short_name}<|>#{name}<|>#{quantity}<|>#{unit_price}<|>#{tax_value}" + + @line_item_count += 1 + end + + # If you call this it will e-mail to this address a copy of a receipt + # after successful, from Authorize.Net. + def email_merchant_from_authorizes_side(to_this_email) + add_field 'x_email_merchant', to_this_email + end + + # You MUST call this at some point for it to actually work. Options + # must include :transaction_key and :order_timestamp + def setup_hash(options) + raise unless options[:transaction_key] + raise unless options[:order_timestamp] + amount = @fields['x_amount'] + data = "#{@fields['x_login']}^#{@fields['x_fp_sequence']}^#{options[:order_timestamp].to_i}^#{amount}^#{@fields['x_currency_code']}" + hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('md5'), options[:transaction_key], data) + add_field 'x_fp_hash', hmac + add_field 'x_fp_timestamp', options[:order_timestamp].to_i + end + + # Note that you should call #invoice and #setup_hash as well, for the + # response_url to actually work. + def initialize(order, account, options = {}) + super + raise 'missing parameter' unless order and account and options[:amount] + raise 'error -- amount with no digits!' unless options[:amount].to_s =~ /\d/ + add_field('x_type', 'AUTH_CAPTURE') # the only one we deal with, for now. Not refunds or anything else, currently. + add_field 'x_show_form', 'PAYMENT_FORM' + add_field 'x_relay_response', 'TRUE' + add_field 'x_duplicate_window', '28800' # large default duplicate window. + add_field 'x_currency_code', currency_code + add_field 'x_version' , '3.1' # version from doc + add_field 'x_amount', options[:amount].to_f.round(2) + @line_item_count = 0 + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb new file mode 100644 index 000000000..d2e36ab5c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb @@ -0,0 +1,340 @@ +require 'net/http' +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + # # Example: + # parser = AuthorizeNetSim::Notification.new(request.raw_post) + # passed = parser.complete? + # + # order = Order.find_by_order_number(parser.invoice_num) + # + # unless order + # @message = 'Error--unable to find your transaction! Please contact us directly.' + # return render :partial => 'authorize_net_sim_payment_response' + # end + # + # if order.total != parser.gross.to_f + # logger.error "Authorize.Net sim said they paid for #{parser.gross} and it should have been #{order.total}!" + # passed = false + # end + # + # # Theoretically, Authorize.net will *never* pass us the same transaction + # # ID twice, but we can double check that... by using + # # parser.transaction_id, and checking against previous orders' transaction + # # id's (which you can save when the order is completed).... + # unless parser.acknowledge MD5_HASH_SET_IN_AUTHORIZE_NET, AUTHORIZE_LOGIN + # passed = false + # logger.error "ALERT POSSIBLE FRAUD ATTEMPT either that or you haven't setup your md5 hash setting right in #{__FILE__} + # because a transaction came back from Authorize.Net with the wrong hash value--rejecting!" + # end + # + # unless parser.cavv_matches? and parser.avs_code_matches? + # logger.error 'Warning--non matching CC!' + params.inspect + # # Could fail them here, as well (recommended)... + # end + # + # if passed + # # Set up your session, and render something that will redirect them to + # # your site, most likely. + # else + # # Render failure or redirect them to your site where you will render failure + # end + + module AuthorizeNetSim + class Notification < ActiveMerchant::Billing::Integrations::Notification + + def unescape(val) #:nodoc: + if val + CGI::unescape val + else + val + end + end + + # Passes a hash of the address the user entered in at Authorize.Net + def billing_address + all = {} + [:fax, :city, :company, :last_name, :country, :zip, :first_name, :address, :email, :state].each do |key_out| + all[key_out] = unescape params['x_' + key_out.to_s] + end + all + end + + def customer_id + unescape params['x_cust_id'] + end + + def auth_code + unescape params['x_auth_code'] + end + + def po_num + unescape params['x_po_num'] + end + + def ship_to_address + all = {} + [:city, :last_name, :first_name, :country, :zip, :address].each do |key_out| + all[key_out] = unescape params['x_ship_to_' + key_out.to_s] + end + all + end + + # Tax amount we sent them. + def tax + unescape params['x_tax'] + end + + # Transaction type (probably going to be auth_capture, since that's + # all we set it as). + def transaction_type + unescape params['x_type'] + end + + # Payment method used--almost always CC (for credit card). + def method + unescape params['x_method'] + end + + # Ff our payment method is available. Almost always "true". + def method_available + params['x_method_available'] + end + + # Invoice num we passed in as invoice_num to them. + def invoice_num + item_id + end + + # If you pass any values to authorize that aren't its expected, it + # will pass them back to you verbatim, returned by this method. + # custom values: + def all_custom_values_passed_in_and_now_passed_back_to_us + all = {} + params.each do |key, value| + if key[0..1] != 'x_' + all[key] = unescape value + end + end + all + end + + def duty + unescape params['x_duty'] + end + + # Shipping we sent them. + def freight + unescape params['x_freight'] + end + alias_method :shipping, :freight + + def description + unescape params['x_description'] + end + + # Returns the response code as a symbol. + # {'1' => :approved, '2' => :declined, '3' => :error, '4' => :held_for_review} + def response_code_as_ruby_symbol + map = {'1' => :approved, '2' => :declined, '3' => :error, '4' => :held_for_review} + map[params['x_response_code']] + end + + def response_reason_text + unescape params['x_response_reason_text'] + end + + # The response reason text's numeric id [equivalent--just a number] + def response_reason_code + unescape params['x_response_reason_code'] + end + + # 'used internally by their gateway' + def response_subcode + params['x_response_subcode'] + end + + # They pass back a tax_exempt value. + def tax_exempt + params['x_tax_exempt'] + end + + # avs [address verification] code + # A = Address (Street) + # matches, ZIP does not + # B = Address information + # not provided for AVS + # check + # E = AVS error + # G = Non-U.S. Card Issuing + # Bank + # N = No Match on Address + # (Street) or ZIP + # P = AVS not applicable for + # this transaction + # R = Retry – System + # unavailable or timed out + # S = Service not supported + # by issuer + # U = Address information is + # unavailable + # W = Nine digit ZIP + # matches, Address (Street) + # does not + # X = Address (Street) and + # nine digit ZIP match + # Y = Address (Street) and + # five digit ZIP match + # Z = Five digit ZIP matches + # Address (Street) does not + def avs_code + params['x_avs_code'] + end + + # Returns true if their address completely matched [Y or X, P from + # #avs_code, which mean 'add+zip match', 'address + 9-zip match', and + # not applicable, respectively]. + def avs_code_matches? + return ['Y', 'X', 'P'].include? params['x_avs_code'] + end + + # cvv2 response + # M = Match + # N = No Match + # P = Not Processed + # S = Should have been + # present + # U = Issuer unable to + # process request + def cvv2_resp_code + params['x_cvv2_resp_code'] + end + + # check if #cvv2_resp_code == 'm' for Match. otherwise false + def cvv2_resp_code_matches? + return ['M'].include? cvv2_resp_code + end + + # cavv_response--'cardholder authentication verification response code'--most likely not use for SIM + # Blank or not present = + # CAVV not validated + # 0 = CAVV not validated + # because erroneous data + # was submitted + # 1 = CAVV failed validation + # 2 = CAVV passed + # validation + # 3 = CAVV validation could + # not be performed; issuer + # attempt incomplete + # 4 = CAVV validation could + # not be performed; issuer + # system error + # 5 = Reserved for future + # use + # 6 = Reserved for future + # use + # 7 = CAVV attempt – failed + # validation – issuer + # available (U.S.-issued + # card/non-U.S acquirer) + # 8 = CAVV attempt – + # passed validation – issuer + # available (U.S.-issued + # card/non-U.S. acquirer) + # 9 = CAVV attempt – failed + # validation – issuer + def cavv_response + params['x_cavv_response'] + end + + # Check if #cavv_response == '', '2', '8' one of those [non failing] + # [blank means no validated, 2 is passed, 8 is passed issuer + # available] + def cavv_matches? + ['','2','8'].include? cavv_response + end + + # Payment is complete -- returns true if x_response_code == '1' + def complete? + params["x_response_code"] == '1' + end + + # Alias for invoice number--this is the only id they pass back to us + # that we passed to them, except customer id is also passed back. + def item_id + unescape params['x_invoice_num'] + end + + # They return this number to us [it's unique to Authorize.net]. + def transaction_id + params['x_trans_id'] + end + + # When was this payment was received by the client. --unimplemented -- + # always returns nil + def received_at + nil + end + + # End-user's email + def payer_email + unescape params['x_email'] + end + + # They don't pass merchant email back to us -- unimplemented -- always + # returns nil + def receiver_email + nil + end + + # md5 hash used internally + def security_key + params['x_MD5_Hash'] + end + + # The money amount we received in X.2 decimal. Returns a string + def gross + unescape params['x_amount'] + end + + # Was this a test transaction? + def test? + params['x_test_request'] == 'true' + end + + # #method_available alias + def status + complete? + end + + # Called to request back and check if it was a valid request. + # Authorize.net passes us back a hash that includes a hash of our + # 'unique' MD5 value that we set within their system. + # + # Example: + # acknowledge('my secret md5 hash that I set within Authorize.Net', 'authorize_login') + # + # Note this is somewhat unsafe unless you actually set that md5 hash + # to something (defaults to '' in their system). + def acknowledge(md5_hash_set_in_authorize_net, authorize_net_login_name) + Digest::MD5.hexdigest(md5_hash_set_in_authorize_net + authorize_net_login_name + params['x_trans_id'] + gross) == params['x_MD5_Hash'].downcase + end + + private + + # Take the posted data and move the relevant data into a hash. + def parse(post) + @raw = post + post.split('&').each do |line| + key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten + params[key] = value + end + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus.rb new file mode 100644 index 000000000..6de2b0cc8 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus.rb @@ -0,0 +1,23 @@ + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Bogus + autoload :Return, 'active_merchant/billing/integrations/bogus/return.rb' + autoload :Helper, 'active_merchant/billing/integrations/bogus/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/bogus/notification.rb' + + mattr_accessor :service_url + self.service_url = 'http://www.bogus.com' + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/helper.rb new file mode 100644 index 000000000..ffb5e2142 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/helper.rb @@ -0,0 +1,17 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Bogus + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'account' + mapping :order, 'order' + mapping :amount, 'amount' + mapping :currency, 'currency' + mapping :customer, :first_name => 'first_name', + :last_name => 'last_name' + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/notification.rb new file mode 100644 index 000000000..77630ffad --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/notification.rb @@ -0,0 +1,11 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Bogus + class Notification < ActiveMerchant::Billing::Integrations::Notification + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/return.rb new file mode 100644 index 000000000..d41ef8061 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/bogus/return.rb @@ -0,0 +1,10 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Bogus + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay.rb new file mode 100644 index 000000000..6137772ac --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay.rb @@ -0,0 +1,23 @@ + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Chronopay + autoload :Return, 'active_merchant/billing/integrations/chronopay/return.rb' + autoload :Helper, 'active_merchant/billing/integrations/chronopay/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/chronopay/notification.rb' + + mattr_accessor :service_url + self.service_url = 'https://secure.chronopay.com/index_shop.cgi' + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/helper.rb new file mode 100644 index 000000000..4f62465cb --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/helper.rb @@ -0,0 +1,120 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Chronopay + class Helper < ActiveMerchant::Billing::Integrations::Helper + # All currently supported checkout languages: + # es (Spanish) + # en (English) + # de (German) + # pt (Portuguese) + # lv (Latvian) + # cn1 (Chinese Version 1) + # cn2 (Chinese version 2) + # nl (Dutch) + # ru (Russian) + COUNTRIES_FOR_LANG = { + 'ES' => %w( AR BO CL CO CR CU DO EC SV GQ GT HN MX NI PA PY PE ES UY VE), + 'DE' => %w( DE AT CH LI ), + 'PT' => %w( AO BR CV GW MZ PT ST TL), + 'RU' => %w( BY KG KZ RU ), + 'LV' => %w( LV ), + 'CN1' => %w( CN ), + 'NL' => %w( NL ) + } + + LANG_FOR_COUNTRY = COUNTRIES_FOR_LANG.inject(Hash.new("EN")) do |memo, (lang, countries)| + countries.each do |code| + memo[code] = lang + end + memo + end + + + self.country_format = :alpha3 + + def initialize(order, account, options = {}) + super + add_field('cb_type', 'p') + end + + # product_id + mapping :account, 'product_id' + # product_name + mapping :invoice, 'product_name' + # product_price + mapping :amount, 'product_price' + # product_price_currency + mapping :currency, 'product_price_currency' + + # f_name + # s_name + # email + mapping :customer, :first_name => 'f_name', + :last_name => 's_name', + :phone => 'phone', + :email => 'email' + + # city + # street + # state + # zip + # country - The country must be a 3 digit country code + # phone + + mapping :billing_address, :city => 'city', + :address1 => 'street', + :state => 'state', + :zip => 'zip', + :country => 'country' + + def billing_address(mapping = {}) + # Gets the country code in the appropriate format or returns what we were given + # The appropriate format for Chronopay is the alpha 3 country code + country_code = lookup_country_code(mapping.delete(:country)) + add_field(mappings[:billing_address][:country], country_code) + + countries_with_supported_states = ['USA', 'CAN'] + if !countries_with_supported_states.include?(country_code) + mapping.delete(:state) + add_field(mappings[:billing_address][:state], 'XX') + end + mapping.each do |k, v| + field = mappings[:billing_address][k] + add_field(field, v) unless field.nil? + end + add_field('language', checkout_language_from_country(country_code)) + end + + # card_no + # exp_month + # exp_year + mapping :credit_card, :number => 'card_no', + :expiry_month => 'exp_month', + :expiry_year => 'exp_year' + + # cb_url + mapping :notify_url, 'cb_url' + + # cs1 + mapping :order, 'cs1' + + # cs2 + # cs3 + # decline_url + + + private + + def checkout_language_from_country(country_code) + country = Country.find(country_code) + short_code = country.code(:alpha2).to_s + LANG_FOR_COUNTRY[short_code] + rescue InvalidCountryCodeError + 'EN' + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/notification.rb new file mode 100644 index 000000000..4942c50a1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/notification.rb @@ -0,0 +1,158 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Chronopay + class Notification < ActiveMerchant::Billing::Integrations::Notification + def complete? + status == 'Completed' + end + + # Status of transaction. List of possible values: + # <tt>onetime – one time payment has been made, no repayment required;</tt>:: + # <tt>initial – first payment has been made, repayment required in corresponding period;</tt>:: + # <tt>decline – charge request has been rejected;</tt>:: + # <tt>rebill – repayment has been made together with initial transaction;</ttt>:: + # <tt>cancel – repayments has been disabled;</tt>:: + # <tt>expire – customer’s access to restricted zone membership has been expired;</tt>:: + # <tt>refund – request to refund has been received;</tt>:: + # <tt>chargeback – request to chargeback has been received.</tt>:: + # + # This implementation of Chronopay does not support subscriptions. + # The status codes used are matched to the status codes that Paypal + # sends. See Paypal::Notification#status for more details + def status + case params['transaction_type'] + when 'onetime' + 'Completed' + when 'refund' + 'Refunded' + when 'chargeback' + 'Reversed' + else + 'Failed' + end + end + + # Unique ID of transaction + def transaction_id + params['transaction_id'] + end + + # Unique ID of customer + def customer_id + params['customer_id'] + end + + # Unique ID of Merchant’s web-site + def site_id + params['site_id'] + end + + # ID of a product that was purchased + def product_id + params['product_id'] + end + + # Language + def language + params['language'] + end + + def received_at + # Date should be formatted "dd-mm-yy" to be parsed by 1.8 and 1.9 the same way + formatted_date = Date.strptime(date, "%m/%d/%Y").strftime("%d-%m-%Y") + Time.parse("#{formatted_date} #{time}") unless date.blank? || time.blank? + end + + # Date of transaction in MM/DD/YYYY format + def date + params['date'] + end + + # Time of transaction in HH:MM:SS format + def time + params['time'] + end + + # The customer's full name + def name + params['name'] + end + + # The customer's email address + def email + params['email'] + end + + # The customer's street address + def street + params['street'] + end + + # The customer's country - 3 digit country code + def country + params['country'] + end + + # The customer's city + def city + params['city'] + end + + # The customer's zip + def zip + params['zip'] + end + + # The customer's state. Only useful for US Customers + def state + params['state'] + end + + # Customer’s login for restricted access zone of Merchant’s Web-site + def username + params['username'] + end + + # Customer's password for restricted access zone of Merchant’s Web-site, as chosen + def password + params['password'] + end + + # The item id passed in the first custom parameter + def item_id + params['cs1'] + end + + # Additional parameter + def custom2 + params['cs2'] + end + + # Additional parameter + def custom3 + params['cs3'] + end + + # The currency the purchase was made in + def currency + params['currency'] + end + + # the money amount we received in X.2 decimal. + def gross + params['total'] + end + + def test? + date.blank? && time.blank? && transaction_id.blank? + end + + def acknowledge + true + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/return.rb new file mode 100644 index 000000000..399b258b3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/chronopay/return.rb @@ -0,0 +1,10 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Chronopay + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay.rb new file mode 100644 index 000000000..62e3956ff --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay.rb @@ -0,0 +1,41 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + autoload :Helper, File.dirname(__FILE__) + '/direc_pay/helper.rb' + autoload :Return, File.dirname(__FILE__) + '/direc_pay/return.rb' + autoload :Notification, File.dirname(__FILE__) + '/direc_pay/notification.rb' + autoload :Status, File.dirname(__FILE__) + '/direc_pay/status.rb' + + mattr_accessor :production_url, :test_url + + self.production_url = "https://www.timesofmoney.com/direcpay/secure/dpMerchantTransaction.jsp" + self.test_url = "https://test.direcpay.com/direcpay/secure/dpMerchantTransaction.jsp" + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string, options) + end + + def self.request_status_update(mid, transaction_id, notification_url) + Status.new(mid).update(transaction_id, notification_url) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/helper.rb new file mode 100644 index 000000000..dddbfd9a3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/helper.rb @@ -0,0 +1,200 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'MID' + mapping :order, 'Merchant Order No' + mapping :amount, 'Amount' + mapping :currency, 'Currency' + mapping :country, 'Country' + + mapping :billing_address, :city => 'custCity', + :address1 => 'custAddress', + :state => 'custState', + :zip => 'custPinCode', + :country => 'custCountry', + :phone => 'custMobileNo' + + mapping :shipping_address, :name => 'deliveryName', + :city => 'deliveryCity', + :address1 => 'deliveryAddress', + :state => 'deliveryState', + :zip => 'deliveryPinCode', + :country => 'deliveryCountry', + :phone => 'deliveryMobileNo' + + mapping :customer, :name => 'custName', + :email => 'custEmailId' + + mapping :description, 'otherNotes' + mapping :edit_allowed, 'editAllowed' + + mapping :return_url, 'Success URL' + mapping :failure_url, 'Failure URL' + + mapping :operating_mode, 'Operating Mode' + mapping :other_details, 'Other Details' + mapping :collaborator, 'Collaborator' + + OPERATING_MODE = 'DOM' + COUNTRY = 'IND' + CURRENCY = 'INR' + OTHER_DETAILS = 'NULL' + EDIT_ALLOWED = 'Y' + + PHONE_CODES = { + 'IN' => '91', + 'US' => '01', + 'CA' => '01' + } + + ENCODED_PARAMS = [ :account, :operating_mode, :country, :currency, :amount, :order, :other_details, :return_url, :failure_url, :collaborator ] + + + def initialize(order, account, options = {}) + super + collaborator = ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] ? 'TOML' : 'DirecPay' + add_field(mappings[:collaborator], collaborator) + add_field(mappings[:country], 'IND') + add_field(mappings[:operating_mode], OPERATING_MODE) + add_field(mappings[:other_details], OTHER_DETAILS) + add_field(mappings[:edit_allowed], EDIT_ALLOWED) + end + + + def customer(params = {}) + add_field(mappings[:customer][:name], full_name(params)) + add_field(mappings[:customer][:email], params[:email]) + end + + # Need to format the amount to have 2 decimal places + def amount=(money) + cents = money.respond_to?(:cents) ? money.cents : money + if money.is_a?(String) or cents.to_i <= 0 + raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.' + end + add_field(mappings[:amount], sprintf("%.2f", cents.to_f/100)) + end + + def shipping_address(params = {}) + super(update_address(:shipping_address, params)) + end + + def billing_address(params = {}) + super(update_address(:billing_address, params)) + end + + def form_fields + add_failure_url + add_request_parameters + + unencoded_parameters + end + + + private + + def add_request_parameters + params = ENCODED_PARAMS.map{ |param| fields[mappings[param]] } + encoded = encode_value(params.join('|')) + + add_field('requestparameter', encoded) + end + + def unencoded_parameters + params = fields.dup + # remove all encoded params from exported fields + ENCODED_PARAMS.each{ |param| params.delete(mappings[param]) } + # remove all special characters from each field value + params = params.collect{|name, value| [name, remove_special_characters(value)] } + Hash[params] + end + + def add_failure_url + if fields[mappings[:failure_url]].nil? + add_field(mappings[:failure_url], fields[mappings[:return_url]]) + end + end + + def update_address(address_type, params) + params = params.dup + address = params[:address1] + address = "#{address} #{params[:address2]}" if params[:address2].present? + address = "#{params[:company]} #{address}" if params[:company].present? + params[:address1] = address + + params[:phone] = normalize_phone_number(params[:phone]) + add_land_line_phone_for(address_type, params) + + if address_type == :shipping_address + shipping_name = full_name(params) || fields[mappings[:customer][:name]] + add_field(mappings[:shipping_address][:name], shipping_name) + end + params + end + + # Split a single phone number into the country code, area code and local number as best as possible + def add_land_line_phone_for(address_type, params) + address_field = address_type == :billing_address ? 'custPhoneNo' : 'deliveryPhNo' + + if params.has_key?(:phone2) + phone = normalize_phone_number(params[:phone2]) + phone_country_code, phone_area_code, phone_number = nil + + if params[:country] == 'IN' && phone =~ /(91)? *(\d{3}) *(\d{4,})$/ + phone_country_code, phone_area_code, phone_number = $1, $2, $3 + else + numbers = phone.split(' ') + case numbers.size + when 3 + phone_country_code, phone_area_code, phone_number = numbers + when 2 + phone_area_code, phone_number = numbers + else + phone =~ /(\d{3})(\d+)$/ + phone_area_code, phone_number = $1, $2 + end + end + + add_field("#{address_field}1", phone_country_code || phone_code_for_country(params[:country]) || '91') + add_field("#{address_field}2", phone_area_code) + add_field("#{address_field}3", phone_number) + end + end + + def normalize_phone_number(phone) + phone.gsub(/[^\d ]+/, '') if phone + end + + # Special characters are NOT allowed while posting transaction parameters on DirecPay system + def remove_special_characters(string) + string.gsub(/[~"'&#%]/, '-') + end + + def encode_value(value) + encoded = Base64.strict_encode64(value) + string_to_encode = encoded[0, 1] + "T" + encoded[1, encoded.length] + Base64.strict_encode64(string_to_encode) + end + + def decode_value(value) + decoded = Base64.decode64(value) + string_to_decode = decoded[0, 1] + decoded[2, decoded.length] + Base64.decode64(string_to_decode) + end + + def phone_code_for_country(country) + PHONE_CODES[country] + end + + def full_name(params) + return if params[:name].blank? && params[:first_name].blank? && params[:last_name].blank? + + params[:name] || "#{params[:first_name]} #{params[:last_name]}" + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/notification.rb new file mode 100644 index 000000000..bf37e9ad1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/notification.rb @@ -0,0 +1,76 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + class Notification < ActiveMerchant::Billing::Integrations::Notification + RESPONSE_PARAMS = ['DirecPay Reference ID', 'Flag', 'Country', 'Currency', 'Other Details', 'Merchant Order No', 'Amount'] + + def acknowledge + true + end + + def complete? + status == 'Completed' || status == 'Pending' + end + + def status + case params['Flag'] + when 'SUCCESS' + 'Completed' + when 'PENDING' + 'Pending' + when 'FAIL' + 'Failed' + else + 'Error' + end + end + + def item_id + params['Merchant Order No'] + end + + def transaction_id + params['DirecPay Reference ID'] + end + + # the money amount we received in X.2 decimal + def gross + params['Amount'] + end + + def currency + params['Currency'] + end + + def country + params['Country'] + end + + def other_details + params['Other Details'] + end + + def test? + false + end + + # Take the posted data and move the relevant data into a hash + def parse(post) + super + + values = params['responseparams'].to_s.split('|') + response_params = values.size == 3 ? ['DirecPay Reference ID', 'Flag', 'Error message'] : RESPONSE_PARAMS + response_params.each_with_index do |name, index| + params[name] = values[index] + end + params + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/return.rb new file mode 100644 index 000000000..2eb2497da --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/return.rb @@ -0,0 +1,32 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + module DirecPay + class Return < ActiveMerchant::Billing::Integrations::Return + + def initialize(post_data, options = {}) + @notification = Notification.new(treat_failure_as_pending(post_data), options) + end + + def success? + notification.complete? + end + + def message + notification.status + end + + + private + + # Work around the issue that the initial return from DirecPay is always either SUCCESS or FAIL, there is no PENDING + def treat_failure_as_pending(post_data) + post_data.sub(/FAIL/, 'PENDING') + end + end + end + + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/status.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/status.rb new file mode 100644 index 000000000..5b9f85200 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/direc_pay/status.rb @@ -0,0 +1,37 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + + class Status + include PostsData + + STATUS_TEST_URL = 'https://test.direcpay.com/direcpay/secure/dpMerchantTransaction.jsp' + STATUS_LIVE_URL = 'https://www.timesofmoney.com/direcpay/secure/dpPullMerchAtrnDtls.jsp' + + attr_reader :account, :options + + def initialize(account, options = {}) + @account, @options = account, options + end + + + # Use this method to manually request a status update to the provided notification_url + def update(authorization, notification_url) + url = test? ? STATUS_TEST_URL : STATUS_LIVE_URL + parameters = [ authorization, account, notification_url ] + data = PostData.new + data[:requestparams] = parameters.join('|') + + response = ssl_get("#{url}?#{data.to_post_data}") + end + + def test? + ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking.rb new file mode 100644 index 000000000..df9ad5b5d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking.rb @@ -0,0 +1,47 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Directebanking + autoload :Return, File.dirname(__FILE__) + '/directebanking/return.rb' + autoload :Helper, File.dirname(__FILE__) + '/directebanking/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/directebanking/notification.rb' + + # Supported countries: + # Germany - DE + # Austria - AT + # Belgium - BE + # Netherlands - NL + # Switzerland - CH + # Great Britain - GB + + # Overwrite this if you want to change the directebanking test url + mattr_accessor :test_url + self.test_url = 'https://www.directebanking.com/payment/start' + + # Overwrite this if you want to change the directebanking production url + mattr_accessor :production_url + self.production_url = 'https://www.directebanking.com/payment/start' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post, options = {}) + Notification.new(post, options) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/helper.rb new file mode 100644 index 000000000..5e33720b7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/helper.rb @@ -0,0 +1,90 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Directebanking + class Helper < ActiveMerchant::Billing::Integrations::Helper + + # All credentials are mandatory and need to be set + # + # credential1: User ID + # credential2: Project ID + # credential3: Project Password (Algorithm: SH1) + # credential4: Notification Password (Algorithm: SH1) + def initialize(order, account, options = {}) + super + add_field('user_variable_0', order) + add_field('project_id', options[:credential2]) + @project_password = options[:credential3] + end + + SIGNATURE_FIELDS = [ + :user_id, + :project_id, + :sender_holder, + :sender_account_number, + :sender_bank_code, + :sender_country_id, + :amount, + :currency_id, + :reason_1, + :reason_2, + :user_variable_0, + :user_variable_1, + :user_variable_2, + :user_variable_3, + :user_variable_4, + :user_variable_5 + ] + + SIGNATURE_IGNORE_AT_METHOD_CREATION_FIELDS = [ + :user_id, + :amount, + :project_id, + :currency_id, + :user_variable_0, + :user_variable_1, + :user_variable_2, + :user_variable_3 + ] + + SIGNATURE_FIELDS.each do |key| + if !SIGNATURE_IGNORE_AT_METHOD_CREATION_FIELDS.include?(key) + mapping "#{key}".to_sym, "#{key.to_s}" + end + end + + # Need to format the amount to have 2 decimal places + def amount=(money) + cents = money.respond_to?(:cents) ? money.cents : money + if money.is_a?(String) or cents.to_i <= 0 + raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.' + end + add_field mappings[:amount], sprintf("%.2f", cents.to_f/100) + end + + def generate_signature_string + # format of signature: user_id|project_id|sender_holder|sender_account_number|sender_bank_code| sender_country_id|amount|currency_id|reason_1|reason_2|user_variable_0|user_variable_1|user_variable_2|user_variable_3|user_variable_4|user_variable_5|project_password + SIGNATURE_FIELDS.map {|key| @fields[key.to_s]} * "|" + "|#{@project_password}" + end + + def generate_signature + Digest::SHA1.hexdigest(generate_signature_string) + end + + def form_fields + @fields.merge('hash' => generate_signature) + end + + mapping :account, 'user_id' + mapping :amount, 'amount' + mapping :currency, 'currency_id' + mapping :description, 'reason_1' + + mapping :return_url, 'user_variable_1' + mapping :cancel_return_url, 'user_variable_2' + mapping :notify_url, 'user_variable_3' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/notification.rb new file mode 100644 index 000000000..7b60290d8 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/notification.rb @@ -0,0 +1,120 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Directebanking + class Notification < ActiveMerchant::Billing::Integrations::Notification + + def initialize(data, options) + if options[:credential4].nil? + raise ArgumentError, "You need to provide the notification password (SH1) as the option :credential4 to verify that the notification originated from Directebanking (Payment Networks AG)" + end + super + end + + def complete? + status == 'Completed' + end + + def item_id + params['user_variable_0'] + end + + def transaction_id + params['transaction'] + end + + # When was this payment received by the client. + def received_at + Time.parse(params['created']) if params['created'] + end + + # the money amount we received in X.2 decimal. + def gross + "%.2f" % params['amount'].to_f + end + + def status + 'Completed' + end + + def currency + params['currency_id'] + end + + def test? + params['sender_bank_name'] == 'Testbank' + end + + # for verifying the signature of the URL parameters + PAYMENT_HOOK_SIGNATURE_FIELDS = [ + :transaction, + :user_id, + :project_id, + :sender_holder, + :sender_account_number, + :sender_bank_code, + :sender_bank_name, + :sender_bank_bic, + :sender_iban, + :sender_country_id, + :recipient_holder, + :recipient_account_number, + :recipient_bank_code, + :recipient_bank_name, + :recipient_bank_bic, + :recipient_iban, + :recipient_country_id, + :international_transaction, + :amount, + :currency_id, + :reason_1, + :reason_2, + :security_criteria, + :user_variable_0, + :user_variable_1, + :user_variable_2, + :user_variable_3, + :user_variable_4, + :user_variable_5, + :created + ] + + PAYMENT_HOOK_IGNORE_AT_METHOD_CREATION_FIELDS = [ + :transaction, + :amount, + :currency_id, + :user_variable_0, + :user_variable_1, + :user_variable_2, + :user_variable_3, + :created + ] + + # Provide access to raw fields + PAYMENT_HOOK_SIGNATURE_FIELDS.each do |key| + if !PAYMENT_HOOK_IGNORE_AT_METHOD_CREATION_FIELDS.include?(key) + define_method(key.to_s) do + params[key.to_s] + end + end + end + + def generate_signature_string + #format is: transaction|user_id|project_id|sender_holder|sender_account_number|sender_bank_code|sender_bank_name|sender_bank_bic|sender_iban|sender_country_id|recipient_holder|recipient_account_number|recipient_bank_code|recipient_bank_name|recipient_bank_bic|recipient_iban|recipient_country_id|international_transaction|amount|currency_id|reason_1|reason_2|security_criteria|user_variable_0|user_variable_1|user_variable_2|user_variable_3|user_variable_4|user_variable_5|created|notification_password + PAYMENT_HOOK_SIGNATURE_FIELDS.map {|key| params[key.to_s]} * "|" + "|#{@options[:credential4]}" + end + + def generate_signature + Digest::SHA1.hexdigest(generate_signature_string) + end + + def acknowledge + # signature_is_valid? + generate_signature.to_s == params['hash'].to_s + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/return.rb new file mode 100644 index 000000000..8f8825ad2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/directebanking/return.rb @@ -0,0 +1,11 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Directebanking + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay.rb new file mode 100644 index 000000000..5a130bd7c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay.rb @@ -0,0 +1,22 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dotpay + autoload :Return, File.dirname(__FILE__) + '/dotpay/return.rb' + autoload :Helper, File.dirname(__FILE__) + '/dotpay/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/dotpay/notification.rb' + + mattr_accessor :service_url + self.service_url = 'https://ssl.dotpay.pl' + + def self.notification(post, options = {}) + Notification.new(post, options) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/helper.rb new file mode 100644 index 000000000..464106cdc --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/helper.rb @@ -0,0 +1,77 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dotpay + class Helper < ActiveMerchant::Billing::Integrations::Helper + def initialize(order, account, options = {}) + options = {:currency => 'PLN'}.merge options + + super + + add_field('channel', '0') + add_field('ch_lock', '0') + add_field('lang', 'PL') + add_field('onlinetransfer', '0') + add_field('tax', '0') + add_field('type', '2') + end + + mapping :account, 'id' + mapping :amount, 'amount' + + mapping :billing_address, :street => 'street', + :street_n1 => 'street_n1', + :street_n2 => 'street_n2', + :addr2 => 'addr2', + :addr3 => 'addr3', + :city => 'city', + :postcode => 'postcode', + :phone => 'phone', + :country => 'country' + + mapping :buttontext, 'buttontext' + mapping :channel, 'channel' + mapping :ch_lock, 'ch_lock' + mapping :code, 'code' + mapping :control, 'control' + mapping :currency, 'currency' + + mapping :customer, :firstname => 'firstname', + :lastname => 'lastname', + :email => 'email' + + mapping :description, 'description' + mapping :lang, 'lang' + mapping :onlinetransfer, 'onlinetransfer' + mapping :order, 'description' + mapping :p_email, 'p_email' + mapping :p_info, 'p_info' + mapping :tax, 'tax' + mapping :type, 'type' + mapping :url, 'url' + mapping :urlc, 'urlc' + + def billing_address(params = {}) + country = lookup_country_code(params.delete(:country) { 'POL' }, :alpha3) + add_field(mappings[:billing_address][:country], country) + + # Everything else + params.each do |k, v| + field = mappings[:billing_address][k] + add_field(field, v) unless field.nil? + end + end + + private + + def lookup_country_code(name_or_code, format = country_format) + country = Country.find(name_or_code) + country.code(format).to_s + rescue InvalidCountryCodeError + name_or_code + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/notification.rb new file mode 100644 index 000000000..a403b15c3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/notification.rb @@ -0,0 +1,86 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dotpay + class Notification < ActiveMerchant::Billing::Integrations::Notification + def complete? + status == 'OK' && %w(2 4 5).include?(t_status) + end + + def currency + orginal_amount.split(' ')[1] + end + + # the money amount we received in X.2 decimal. + def gross + params['amount'] + end + + def pin=(value) + @options[:pin] = value + end + + def status + params['status'] + end + + def test? + params['t_id'].match('.*-TST\d+') ? true : false + end + + PAYMENT_HOOK_FIELDS = [ + :id, + :control, + :t_id, + :orginal_amount, + :email, + :service, + :code, + :username, + :password, + :t_status, + :description, + :md5, + :p_info, + :p_email, + :t_date + ] + + PAYMENT_HOOK_SIGNATURE_FIELDS = [ + :id, + :control, + :t_id, + :amount, + :email, + :service, + :code, + :username, + :password, + :t_status + ] + + # Provide access to raw fields + PAYMENT_HOOK_FIELDS.each do |key| + define_method(key.to_s) do + params[key.to_s] + end + end + + def generate_signature_string + "#{@options[:pin]}:" + PAYMENT_HOOK_SIGNATURE_FIELDS.map {|key| params[key.to_s]} * ":" + end + + def generate_signature + Digest::MD5.hexdigest(generate_signature_string) + end + + def acknowledge + generate_signature.to_s == md5.to_s + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/return.rb new file mode 100644 index 000000000..236db3d9d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dotpay/return.rb @@ -0,0 +1,11 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dotpay + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla.rb new file mode 100644 index 000000000..698d0f1ee --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla.rb @@ -0,0 +1,23 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + autoload :Return, 'active_merchant/billing/integrations/dwolla/return.rb' + autoload :Helper, 'active_merchant/billing/integrations/dwolla/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/dwolla/notification.rb' + autoload :Common, 'active_merchant/billing/integrations/dwolla/common.rb' + + mattr_accessor :service_url + self.service_url = 'https://www.dwolla.com/payment/pay' + + def self.notification(post, options={}) + Notification.new(post, options) + end + + def self.return(query_string, options={}) + Return.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/common.rb new file mode 100644 index 000000000..cbf1e0082 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/common.rb @@ -0,0 +1,21 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + module Common + def verify_signature(checkoutId, amount, notification_signature, secret) + if secret.nil? + raise ArgumentError, "You need to provide the Application secret as the option :credential3 to verify that the notification originated from Dwolla" + end + + expected_signature = Digest::SHA1.hexdigest(secret + ('%s&%.2f' % [checkoutId, amount])) + + if notification_signature != expected_signature + raise StandardError, "Dwolla signature verification failed." + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/helper.rb new file mode 100644 index 000000000..ca1a4c70e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/helper.rb @@ -0,0 +1,40 @@ +require 'digest/sha1' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + class Helper < ActiveMerchant::Billing::Integrations::Helper + def initialize(order, account, options = {}) + super + add_field('name', 'Store Purchase') + + if ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] + add_field('test', 'true') + end + + timestamp = Time.now.to_i.to_s + add_field('timestamp', timestamp) + add_field('allowFundingSources', 'true') + + key = options[:credential2].to_s + secret = options[:credential3].to_s + orderid = order.to_s + signature = Digest::SHA1.hexdigest(secret + "#{key}&#{timestamp}&#{orderid}") + add_field('signature', signature) + end + + mapping :account, 'destinationid' + mapping :credential2, 'key' + mapping :notify_url, 'callback' + mapping :return_url, 'redirect' + mapping :description, 'description' + mapping :amount, 'amount' + mapping :tax, 'tax' + mapping :shipping, 'shipping' + mapping :order, 'orderid' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/notification.rb new file mode 100644 index 000000000..4b53fb7ef --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/notification.rb @@ -0,0 +1,60 @@ +require 'net/http' +require 'digest/sha1' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + class Notification < ActiveMerchant::Billing::Integrations::Notification + include Common + + def complete? + (status == "Completed") + end + + def status + params["Status"] + end + + def transaction_id + params['TransactionId'] + end + + def item_id + params['OrderId'] + end + + def currency + "USD" + end + + def gross + params['Amount'] + end + + def error + params['Error'] + end + + def test? + params['TestMode'] + end + + def acknowledge + true + end + + private + + def parse(post) + @raw = post.to_s + json_post = JSON.parse(post) + verify_signature(json_post['CheckoutId'], json_post['Amount'], json_post['Signature'], @options[:credential3]) + + params.merge!(json_post) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/return.rb new file mode 100644 index 000000000..afd6fbf9f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/dwolla/return.rb @@ -0,0 +1,46 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + class Return < ActiveMerchant::Billing::Integrations::Return + include Common + + def initialize(data, options) + params = parse(data) + verify_signature(params['checkoutId'], params['amount'], params['signature'], options[:credential3]) + + super + end + + def success? + (self.error.nil? && self.callback_success?) + end + + def error + params['error'] + end + + def error_description + params['error_description'] + end + + def checkout_id + params['checkoutId'] + end + + def transaction + params['transaction'] + end + + def test? + params['test'] + end + + def callback_success? + (params['postback'] != "failure") + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans.rb new file mode 100644 index 000000000..5614a0bac --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans.rb @@ -0,0 +1,48 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module EPaymentPlans + autoload :Helper, File.dirname(__FILE__) + '/e_payment_plans/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/e_payment_plans/notification.rb' + + mattr_accessor :production_url + self.production_url = 'https://www.epaymentplans.com' + + mattr_accessor :test_url + self.test_url = 'https://test.epaymentplans.com' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + "#{production_url}/order/purchase" + when :test + "#{test_url}/order/purchase" + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification_confirmation_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + "#{production_url}/order/confirmation" + when :test + "#{test_url}/order/confirmation" + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post, options = {}) + Notification.new(post, options) + end + + def self.return(query_string, options = {}) + Return.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb new file mode 100644 index 000000000..76a561014 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/helper.rb @@ -0,0 +1,34 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module EPaymentPlans + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'order[account]' + mapping :amount, 'order[amount]' + + mapping :order, 'order[num]' + + mapping :customer, :first_name => 'order[first_name]', + :last_name => 'order[last_name]', + :email => 'order[email]', + :phone => 'order[phone]' + + mapping :billing_address, :city => 'order[city]', + :address1 => 'order[address1]', + :address2 => 'order[address2]', + :company => 'order[company]', + :state => 'order[state]', + :zip => 'order[zip]', + :country => 'order[country]' + + mapping :notify_url, 'order[notify_url]' + mapping :return_url, 'order[return_url]' + mapping :cancel_return_url, 'order[cancel_return_url]' + mapping :description, 'order[description]' + mapping :tax, 'order[tax]' + mapping :shipping, 'order[shipping]' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb new file mode 100644 index 000000000..339e25ee7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/e_payment_plans/notification.rb @@ -0,0 +1,84 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module EPaymentPlans + class Notification < ActiveMerchant::Billing::Integrations::Notification + include ActiveMerchant::PostsData + def complete? + status == "Completed" + end + + def transaction_id + params['transaction_id'] + end + + def item_id + params['item_id'] + end + + # When was this payment received by the client. + def received_at + Time.parse(params['received_at'].to_s).utc + end + + def gross + params['gross'] + end + + def currency + params['currency'] + end + + def security_key + params['security_key'] + end + + # Was this a test transaction? + def test? + params['test'] == 'test' + end + + def status + params['status'].capitalize + end + + # Acknowledge the transaction to EPaymentPlans. This method has to be called after a new + # apc arrives. EPaymentPlans will verify that all the information we received are correct + # and will return ok or a fail. + # + # Example: + # + # def ipn + # notify = EPaymentPlans.notification(request.raw_post) + # + # if notify.acknowledge + # ... process order ... if notify.complete? + # else + # ... log possible hacking attempt ... + # end + def acknowledge + payload = raw + + response = ssl_post(EPaymentPlans.notification_confirmation_url, payload) + + # Replace with the appropriate codes + raise StandardError.new("Faulty EPaymentPlans result: #{response}") unless ["AUTHORISED", "DECLINED"].include?(response) + response == "AUTHORISED" + end + + private + # Take the posted data and move the relevant data into a hash + def parse(post) + @raw = post + for line in post.split('&') + key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten + params[key] = value + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay.rb new file mode 100644 index 000000000..701f1d19b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay.rb @@ -0,0 +1,30 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + # Documentation: https://ssl.easypay.by/light/ + module EasyPay + autoload :Helper, File.dirname(__FILE__) + '/easy_pay/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/easy_pay/notification.rb' + autoload :Common, File.dirname(__FILE__) + '/easy_pay/common.rb' + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'EP_Hash' + + mattr_accessor :notify_signature_parameter_name + self.notify_signature_parameter_name = 'notify_signature' + + mattr_accessor :service_url + self.service_url = 'https://ssl.easypay.by/weborder/' + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/common.rb new file mode 100644 index 000000000..74a8e4b22 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/common.rb @@ -0,0 +1,40 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module EasyPay + module Common + def generate_signature(type) + string = case type + when :request + request_signature_string + when :notify + notify_signature_string + end + + Digest::MD5.hexdigest(string) + end + + def request_signature_string + [ + @fields[mappings[:account]], + @secret, + @fields[mappings[:order]], + @fields[mappings[:amount]] + ].join + end + + def notify_signature_string + [ + params['order_mer_code'], + params['sum'], + params['mer_no'], + params['card'], + params['purch_date'], + secret + ].join + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/helper.rb new file mode 100644 index 000000000..5df2a4f40 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/helper.rb @@ -0,0 +1,36 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module EasyPay + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Common + + def initialize(order, account, options = {}) + super + @secret = options[:credential2] + end + + def form_fields + @fields.merge(ActiveMerchant::Billing::Integrations::EasyPay.signature_parameter_name => generate_signature(:request)) + end + + def params + @fields + end + + mapping :account, 'EP_MerNo' + mapping :amount, 'EP_Sum' + mapping :order, 'EP_OrderNo' + mapping :comment, 'EP_Comment' + mapping :order_info, 'EP_OrderInfo' + mapping :expires, 'EP_Expires' + mapping :success_url, 'EP_Success_URL' + mapping :cancel_url, 'EP_Cancel_URL' + mapping :debug, 'EP_Debug' + mapping :url_type, 'EP_URL_Type' + mapping :encoding, 'EP_Encoding' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/notification.rb new file mode 100644 index 000000000..90ce7e629 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/easy_pay/notification.rb @@ -0,0 +1,59 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module EasyPay + class Notification < ActiveMerchant::Billing::Integrations::Notification + include Common + + def initialize(data, options) + if options[:credential2].nil? + raise ArgumentError, "You need to provide the md5 secret as the option :credential2 to verify that the notification originated from EasyPay" + end + + super + end + + def self.recognizes?(params) + params.has_key?('order_mer_code') && params.has_key?('sum') + end + + def complete? + true + end + + def amount + BigDecimal.new(gross) + end + + def item_id + params['order_mer_code'] + end + + def security_key + params[ActiveMerchant::Billing::Integrations::EasyPay.notify_signature_parameter_name] + end + + def gross + params['sum'] + end + + def status + 'Completed' + end + + def secret + @options[:credential2] + end + + def acknowledge + security_key == generate_signature(:notify) + end + + def success_response(*args) + { :nothing => true } + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay.rb new file mode 100644 index 000000000..24de6aae0 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay.rb @@ -0,0 +1,21 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Epay + autoload :Helper, File.dirname(__FILE__) + '/epay/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/epay/notification.rb' + + mattr_accessor :service_url + self.service_url = 'https://ssl.ditonlinebetalingssystem.dk/integration/ewindow/Default.aspx' + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/helper.rb new file mode 100644 index 000000000..650dcd661 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/helper.rb @@ -0,0 +1,55 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Epay + class Helper < ActiveMerchant::Billing::Integrations::Helper + + def initialize(order, merchantnumber, options = {}) + super + add_field('windowstate', 3) + add_field('language', '0') + add_field('orderid', format_order_number(order)) + @fields = Hash[@fields.sort] + end + + def md5secret(value) + @md5secret = value + end + + def form_fields + @fields.merge('hash' => generate_md5hash) + end + + def generate_md5string + @fields.sort.each.map { |key, value| key != 'hash' ? value.to_s : ''} * "" + @md5secret + end + + def generate_md5hash + Digest::MD5.hexdigest(generate_md5string) + end + + # Limited to 20 digits max + def format_order_number(number) + number.to_s.gsub(/[^\w_]/, '').rjust(4, "0")[0...20] + end + + mapping :account, 'merchantnumber' + mapping :language, 'language' + mapping :amount, 'amount' + mapping :currency, 'currency' + mapping :return_url, 'accepturl' + mapping :cancel_return_url, 'cancelurl' + mapping :notify_url, 'callbackurl' + mapping :autocapture, 'instantcapture' + mapping :description, 'description' + mapping :credential3, 'md5secret' + mapping :customer, '' + mapping :billing_address, {} + mapping :tax, '' + mapping :shipping, '' + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/notification.rb new file mode 100644 index 000000000..aa868ee51 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/epay/notification.rb @@ -0,0 +1,110 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Epay + class Notification < ActiveMerchant::Billing::Integrations::Notification + + CURRENCY_CODES = { + :ADP => '020', :AED => '784', :AFA => '004', :ALL => '008', :AMD => '051', + :ANG => '532', :AOA => '973', :ARS => '032', :AUD => '036', :AWG => '533', + :AZM => '031', :BAM => '977', :BBD => '052', :BDT => '050', :BGL => '100', + :BGN => '975', :BHD => '048', :BIF => '108', :BMD => '060', :BND => '096', + :BOB => '068', :BOV => '984', :BRL => '986', :BSD => '044', :BTN => '064', + :BWP => '072', :BYR => '974', :BZD => '084', :CAD => '124', :CDF => '976', + :CHF => '756', :CLF => '990', :CLP => '152', :CNY => '156', :COP => '170', + :CRC => '188', :CUP => '192', :CVE => '132', :CYP => '196', :CZK => '203', + :DJF => '262', :DKK => '208', :DOP => '214', :DZD => '012', :ECS => '218', + :ECV => '983', :EEK => '233', :EGP => '818', :ERN => '232', :ETB => '230', + :EUR => '978', :FJD => '242', :FKP => '238', :GBP => '826', :GEL => '981', + :GHC => '288', :GIP => '292', :GMD => '270', :GNF => '324', :GTQ => '320', + :GWP => '624', :GYD => '328', :HKD => '344', :HNL => '340', :HRK => '191', + :HTG => '332', :HUF => '348', :IDR => '360', :ILS => '376', :INR => '356', + :IQD => '368', :IRR => '364', :ISK => '352', :JMD => '388', :JOD => '400', + :JPY => '392', :KES => '404', :KGS => '417', :KHR => '116', :KMF => '174', + :KPW => '408', :KRW => '410', :KWD => '414', :KYD => '136', :KZT => '398', + :LAK => '418', :LBP => '422', :LKR => '144', :LRD => '430', :LSL => '426', + :LTL => '440', :LVL => '428', :LYD => '434', :MAD => '504', :MDL => '498', + :MGF => '450', :MKD => '807', :MMK => '104', :MNT => '496', :MOP => '446', + :MRO => '478', :MTL => '470', :MUR => '480', :MVR => '462', :MWK => '454', + :MXN => '484', :MXV => '979', :MYR => '458', :MZM => '508', :NAD => '516', + :NGN => '566', :NIO => '558', :NOK => '578', :NPR => '524', :NZD => '554', + :OMR => '512', :PAB => '590', :PEN => '604', :PGK => '598', :PHP => '608', + :PKR => '586', :PLN => '985', :PYG => '600', :QAR => '634', :ROL => '642', + :RUB => '643', :RUR => '810', :RWF => '646', :SAR => '682', :SBD => '090', + :SCR => '690', :SDD => '736', :SEK => '752', :SGD => '702', :SHP => '654', + :SIT => '705', :SKK => '703', :SLL => '694', :SOS => '706', :SRG => '740', + :STD => '678', :SVC => '222', :SYP => '760', :SZL => '748', :THB => '764', + :TJS => '972', :TMM => '795', :TND => '788', :TOP => '776', :TPE => '626', + :TRL => '792', :TRY => '949', :TTD => '780', :TWD => '901', :TZS => '834', + :UAH => '980', :UGX => '800', :USD => '840', :UYU => '858', :UZS => '860', + :VEB => '862', :VND => '704', :VUV => '548', :XAF => '950', :XCD => '951', + :XOF => '952', :XPF => '953', :YER => '886', :YUM => '891', :ZAR => '710', + :ZMK => '894', :ZWD => '716' + } + + def complete? + Integer(transaction_id) > 0 + end + + def item_id + params['orderid'] + end + + def transaction_id + params['txnid'] + end + + def received_at + Time.mktime(params['date'][0..3], params['date'][4..5], params['date'][6..7], params['time'][0..1], params['time'][2..3]) + end + + def gross + "%.2f" % (gross_cents / 100.0) + end + + def gross_cents + params['amount'].to_i + end + + def test? + return false + end + + %w(txnid orderid amount currency date time hash fraud payercountry issuercountry txnfee subscriptionid paymenttype cardno).each do |attr| + define_method(attr) do + params[attr] + end + end + + def currency + CURRENCY_CODES.invert[params['currency']].to_s + end + + def amount + Money.new(params['amount'].to_i, currency) + end + + def generate_md5string + md5string = String.new + for line in @raw.split('&') + key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten + md5string += params[key] if key != 'hash' + end + return md5string + @options[:credential3] + end + + def generate_md5hash + Digest::MD5.hexdigest(generate_md5string) + end + + def acknowledge + generate_md5hash == params['hash'] + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data.rb new file mode 100644 index 000000000..65e8f8474 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data.rb @@ -0,0 +1,38 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module FirstData + autoload :Helper, 'active_merchant/billing/integrations/first_data/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/first_data/notification.rb' + + # Overwrite this if you want to change the ANS test url + mattr_accessor :test_url + self.test_url = 'https://demo.globalgatewaye4.firstdata.com/payment' + + # Overwrite this if you want to change the ANS production url + mattr_accessor :production_url + self.production_url = 'https://checkout.globalgatewaye4.firstdata.com/payment' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post) + Notification.new(post) + end + + def self.return(query_string) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/helper.rb new file mode 100644 index 000000000..82cd1c0f4 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/helper.rb @@ -0,0 +1,63 @@ +require 'active_support/core_ext/float/rounding.rb' # Float#round(precision) + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module FirstData + # First Data payment pages emulates the Authorize.Net SIM API. See + # ActiveMerchant::Billing::Integrations::AuthorizeNetSim::Helper for + # more details. + # + # An example. Note the username as a parameter and transaction key you + # will want to use later. + # + # payment_service_for('order_id', 'first_data_payment_page_id', :service => :first_data, :amount => 157.0) do |service| + # + # # You must call setup_hash and invoice + # + # service.setup_hash :transaction_key => '8CP6zJ7uD875J6tY', + # :order_timestamp => 1206836763 + # service.customer_id 8 + # service.customer :first_name => 'g', + # :last_name => 'g', + # :email => 'g@g.com', + # :phone => '3' + # service.billing_address :zip => 'g', + # :country => 'United States of America', + # :address => 'g' + # + # service.ship_to_address :first_name => 'g', + # :last_name => 'g', + # :city => '', + # :address => 'g', + # :address2 => '', + # :state => address.state, + # :country => 'United States of America', + # :zip => 'g' + # + # service.invoice "516428355" # your invoice number + # # The end-user is presented with the HTML produced by the notify_url + # # (using the First Data Receipt Link feature). + # service.return_url "http://mysite/first_data_receipt_generator_page" + # service.payment_header 'My store name' + # service.add_line_item :name => 'item name', :quantity => 1, :unit_price => 0 + # service.test_request 'true' # only if it's just a test + # service.shipping '25.0' + # # Tell it to display a "0" line item for shipping, with the price in + # # the name, otherwise it isn't shown at all, leaving the end user to + # # wonder why the total is different than the sum of the line items. + # service.add_shipping_as_line_item + # server.add_tax_as_line_item # same with tax + # # See the helper.rb file for various custom fields + # end + class Helper < ActiveMerchant::Billing::Integrations::AuthorizeNetSim::Helper + # Configure notify_url to use the "Relay Response" feature + mapping :notify_url, 'x_relay_url' + + # Configure return_url to use the "Receipt Link" feature + mapping :return_url, 'x_receipt_link_url' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/notification.rb new file mode 100644 index 000000000..2e786ff3d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/first_data/notification.rb @@ -0,0 +1,56 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + # First Data payment pages emulates the Authorize.Net SIM API. See + # ActiveMerchant::Billing::Integrations::FirstData::Notification for + # more details. + # + # # Example: + # parser = FirstData::Notification.new(request.raw_post) + # passed = parser.complete? + # + # order = Order.find_by_order_number(parser.invoice_num) + # + # unless order + # @message = 'Error--unable to find your transaction! Please contact us directly.' + # return render :partial => 'first_data_payment_response' + # end + # + # if order.total != parser.gross.to_f + # logger.error "First Data said they paid for #{parser.gross} and it should have been #{order.total}!" + # passed = false + # end + # + # # Theoretically, First Data will *never* pass us the same transaction + # # ID twice, but we can double check that... by using + # # parser.transaction_id, and checking against previous orders' transaction + # # id's (which you can save when the order is completed).... + # unless parser.acknowledge FIRST_DATA_TRANSACTION_KEY, FIRST_DATA_RESPONSE_KEY + # passed = false + # logger.error "ALERT POSSIBLE FRAUD ATTEMPT" + # end + # + # unless parser.cavv_matches? and parser.avs_code_matches? + # logger.error 'Warning--non matching CC!' + params.inspect + # # Could fail them here, as well (recommended)... + # end + # + # if passed + # # Set up your session, and render something that will redirect them to + # # your site, most likely. + # else + # # Render failure or redirect them to your site where you will render failure + # end + + module FirstData + class Notification < ActiveMerchant::Billing::Integrations::AuthorizeNetSim::Notification + def acknowledge(response_key, payment_page_id) + Digest::MD5.hexdigest(response_key + payment_page_id + params['x_trans_id'] + sprintf('%.2f', gross)) == params['x_MD5_Hash'].downcase + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay.rb new file mode 100644 index 000000000..fca773c78 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay.rb @@ -0,0 +1,25 @@ +# With help from Giovanni Intini and his code for RGestPay - http://medlar.it/it/progetti/rgestpay + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Gestpay + autoload :Return, File.dirname(__FILE__) + '/gestpay/return.rb' + autoload :Common, File.dirname(__FILE__) + '/gestpay/common.rb' + autoload :Helper, File.dirname(__FILE__) + '/gestpay/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/gestpay/notification.rb' + + mattr_accessor :service_url + self.service_url = 'https://ecomm.sella.it/gestpay/pagam.asp' + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/common.rb new file mode 100644 index 000000000..213e47a12 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/common.rb @@ -0,0 +1,42 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Gestpay + module Common + VERSION = "2.0" + ENCRYPTION_PATH = "/CryptHTTPS/Encrypt.asp" + DECRYPTION_PATH = "/CryptHTTPS/Decrypt.asp" + DELIMITER = '*P1*' + + CURRENCY_MAPPING = { + 'EUR' => '242', + 'ITL' => '18', + 'BRL' => '234', + 'USD' => '1', + 'JPY' => '71', + 'HKD' => '103' + } + + def parse_response(response) + case response + when /#cryptstring#(.*)#\/cryptstring#/, /#decryptstring#(.*)#\/decryptstring#/ + $1 + when /#error#(.*)#\/error#/ + raise StandardError, "An error occurred retrieving the encrypted string from GestPay: #{$1}" + else + raise StandardError, "No response was received by GestPay" + end + end + + def ssl_get(url, path) + uri = URI.parse(url) + site = Net::HTTP.new(uri.host, uri.port) + site.use_ssl = true + site.verify_mode = OpenSSL::SSL::VERIFY_NONE + site.get(path).body + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/helper.rb new file mode 100644 index 000000000..2cb4b04e9 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/helper.rb @@ -0,0 +1,70 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Gestpay + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Common + # Valid language codes + # Italian => 1 + # English => 2 + # Spanish => 3 + # French => 4 + # Tedesco => 5 + def initialize(order, account, options = {}) + super + add_field('PAY1_IDLANGUAGE', 2) + end + + mapping :account, 'ShopLogin' + + mapping :amount, 'PAY1_AMOUNT' + mapping :currency, 'PAY1_UICCODE' + + mapping :order, 'PAY1_SHOPTRANSACTIONID' + + # Buyer name PAY1_CHNAME + mapping :customer, :email => 'PAY1_CHEMAIL' + + mapping :credit_card, :number => 'PAY1_CARDNUMBER', + :expiry_month => 'PAY1_EXPMONTH', + :expiry_year => 'PAY1_EXPYEAR', + :verification_value => 'PAY1_CVV' + + def customer(params = {}) + add_field(mappings[:customer][:email], params[:email]) + add_field('PAY1_CHNAME', "#{params[:first_name]} #{params[:last_name]}") + end + + def currency=(currency_code) + code = CURRENCY_MAPPING[currency_code] + raise StandardError, "Invalid currency code #{currency_code} specified" if code.nil? + + add_field(mappings[:currency], code) + end + + def form_fields + @encrypted_data ||= get_encrypted_string + + { + 'a' => @fields['ShopLogin'], + 'b' => @encrypted_data + } + end + + def get_encrypted_string + response = ssl_get(Gestpay.service_url, encryption_query_string) + parse_response(response) + end + + def encryption_query_string + fields = ['PAY1_AMOUNT', 'PAY1_SHOPTRANSACTIONID', 'PAY1_UICCODE'] + + encoded_params = fields.collect{ |field| "#{field}=#{CGI.escape(@fields[field])}" }.join(DELIMITER) + + "#{ENCRYPTION_PATH}?a=" + CGI.escape(@fields['ShopLogin']) + "&b=" + encoded_params + "&c=" + CGI.escape(VERSION) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/notification.rb new file mode 100644 index 000000000..27ed57736 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/notification.rb @@ -0,0 +1,85 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Gestpay + class Notification < ActiveMerchant::Billing::Integrations::Notification + include Common + + def complete? + status == 'Completed' + end + + # The important param + def item_id + params['PAY1_SHOPTRANSACTIONID'] + end + + def transaction_id + params['PAY1_BANKTRANSACTIONID'] + end + + # the money amount we received in X.2 decimal. + def gross + params['PAY1_AMOUNT'] + end + + def currency + # Ruby 1.9 compat + method = CURRENCY_MAPPING.respond_to?(:key) ? :key : :index + CURRENCY_MAPPING.send(method, params['PAY1_UICCODE']) + end + + def test? + false + end + + def status + case params['PAY1_TRANSACTIONRESULT'] + when 'OK' + 'Completed' + else + 'Failed' + end + end + + def acknowledge + true + end + + private + # Take the posted data and move the relevant data into a hash + def parse(query_string) + @raw = query_string + + return if query_string.blank? + encrypted_params = parse_delimited_string(query_string) + + return if encrypted_params['a'].blank? || encrypted_params['b'].blank? + @params = decrypt_data(encrypted_params['a'], encrypted_params['b']) + end + + def parse_delimited_string(string, delimiter = '&', unencode_cgi = false) + result = {} + for line in string.split(delimiter) + key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten + result[key] = unencode_cgi ? CGI.unescape(value) : value + end + result + end + + def decrypt_data(shop_login, encrypted_string) + response = ssl_get(Gestpay.service_url, decryption_query_string(shop_login, encrypted_string)) + encoded_response = parse_response(response) + parse_delimited_string(encoded_response, DELIMITER, true) + end + + def decryption_query_string(shop_login, encrypted_string) + "#{DECRYPTION_PATH}?a=" + CGI.escape(shop_login) + "&b=" + encrypted_string + "&c=" + CGI.escape(VERSION) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/return.rb new file mode 100644 index 000000000..0c01f286e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/gestpay/return.rb @@ -0,0 +1,10 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Gestpay + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/helper.rb new file mode 100644 index 000000000..dc742de55 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/helper.rb @@ -0,0 +1,117 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + class Helper #:nodoc: + attr_reader :fields + class_attribute :service_url + class_attribute :mappings + class_attribute :country_format + self.country_format = :alpha2 + + # The application making the calls to the gateway + # Useful for things like the PayPal build notation (BN) id fields + class_attribute :application_id + self.application_id = 'ActiveMerchant' + + def initialize(order, account, options = {}) + options.assert_valid_keys([:amount, :currency, :test, :credential2, :credential3, :credential4, :country, :account_name, :transaction_type]) + @fields = {} + @raw_html_fields = [] + @test = options[:test] + self.order = order + self.account = account + self.amount = options[:amount] + self.currency = options[:currency] + self.credential2 = options[:credential2] + self.credential3 = options[:credential3] + self.credential4 = options[:credential4] + end + + def self.mapping(attribute, options = {}) + self.mappings ||= {} + self.mappings[attribute] = options + end + + def add_field(name, value) + return if name.blank? || value.blank? + @fields[name.to_s] = value.to_s + end + + def add_fields(subkey, params = {}) + params.each do |k, v| + field = mappings[subkey][k] + add_field(field, v) unless field.blank? + end + end + + # Add a field that has characters that CGI::escape would mangle. Allows + # for multiple fields with the same name (e.g., to support line items). + def add_raw_html_field(name, value) + return if name.blank? || value.blank? + @raw_html_fields << [name, value] + end + + def raw_html_fields + @raw_html_fields + end + + def billing_address(params = {}) + add_address(:billing_address, params) + end + + def shipping_address(params = {}) + add_address(:shipping_address, params) + end + + def form_fields + @fields + end + + def test? + @test_mode ||= ActiveMerchant::Billing::Base.integration_mode == :test || @test + end + + def form_method + "POST" + end + + private + + def add_address(key, params) + return if mappings[key].nil? + + code = lookup_country_code(params.delete(:country)) + add_field(mappings[key][:country], code) + add_fields(key, params) + end + + def lookup_country_code(name_or_code, format = country_format) + country = Country.find(name_or_code) + country.code(format).to_s + rescue InvalidCountryCodeError + name_or_code + end + + def method_missing(method_id, *args) + method_id = method_id.to_s.gsub(/=$/, '').to_sym + # Return and do nothing if the mapping was not found. This allows + # For easy substitution of the different integrations + return if mappings[method_id].nil? + + mapping = mappings[method_id] + + case mapping + when Array + mapping.each{ |field| add_field(field, args.last) } + when Hash + options = args.last.is_a?(Hash) ? args.pop : {} + + mapping.each{ |key, field| add_field(field, options[key]) } + else + add_field(mapping, args.last) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust.rb new file mode 100644 index 000000000..0f661b813 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust.rb @@ -0,0 +1,27 @@ + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module HiTrust + autoload :Helper, File.dirname(__FILE__) + '/hi_trust/helper.rb' + autoload :Return, File.dirname(__FILE__) + '/hi_trust/return.rb' + autoload :Notification, File.dirname(__FILE__) + '/hi_trust/notification.rb' + + TEST_URL = 'https://testtrustlink.hitrust.com.tw/TrustLink/TrxReq' + LIVE_URL = 'https://trustlink.hitrust.com.tw/TrustLink/TrxReq' + + def self.service_url + ActiveMerchant::Billing::Base.integration_mode == :test ? TEST_URL : LIVE_URL + end + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/helper.rb new file mode 100644 index 000000000..a28672960 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/helper.rb @@ -0,0 +1,58 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module HiTrust + class Helper < ActiveMerchant::Billing::Integrations::Helper + + # Transaction types + # * Auth + # * AuthRe + # * Capture + # * CaptureRe + # * Refund + # * RefundRe + # * Query + def initialize(order, account, options = {}) + super + # Perform an authorization by default + add_field('Type', 'Auth') + + # Capture the payment right away + add_field('depositflag', '1') + + # Disable auto query - who knows what it does? + add_field('queryflag', '1') + + add_field('orderdesc', 'Store purchase') + end + + mapping :account, 'storeid' + mapping :amount, 'amount' + + def amount=(money) + cents = money.respond_to?(:cents) ? money.cents : money + + if money.is_a?(String) or cents.to_i < 0 + raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.' + end + + add_field(mappings[:amount], cents) + end + # Supported currencies include: + # * CNY:Chinese Yuan (Renminbi) + # * TWD:New Taiwan Dollar + # * HKD:Hong Kong Dollar + # * USD:US Dollar + # * AUD:Austrian Dollar + mapping :currency, 'currency' + + mapping :order, 'ordernumber' + mapping :description, 'orderdesc' + + mapping :notify_url, 'merUpdateURL' + mapping :return_url, 'returnURL' + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/notification.rb new file mode 100644 index 000000000..06a3d8f76 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/notification.rb @@ -0,0 +1,59 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module HiTrust + class Notification < ActiveMerchant::Billing::Integrations::Notification + SUCCESS = '00' + + self.production_ips = [ '203.75.242.8' ] + + def complete? + status == 'Completed' + end + + def transaction_id + params['authRRN'] + end + + def item_id + params['ordernumber'] + end + + def received_at + Time.parse(params['orderdate']) rescue nil + end + + def currency + params['currency'] + end + + def gross + sprintf("%.2f", gross_cents.to_f / 100) + end + + def gross_cents + params['approveamount'].to_i + end + + def account + params['storeid'] + end + + def status + params['retcode'] == SUCCESS ? 'Completed' : 'Failed' + end + + def test? + ActiveMerchant::Billing::Base.integration_mode == :test + end + + def acknowledge + true + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/return.rb new file mode 100644 index 000000000..ead9511d8 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/hi_trust/return.rb @@ -0,0 +1,67 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module HiTrust + class Return < ActiveMerchant::Billing::Integrations::Return + SUCCESS = "00" + CODES = { "00" => "Operation completed successfully", + "-1" => "Unable to initialize winsock dll.", + "-2" => "Can't create stream socket.", + "-3" => "No Request Message.", + "-4" => "Can't connect to server.", + "-5" => "Send socket error.", + "-6" => "Couldn't receive data.", + "-7" => "Receive Broken message.", + "-8" => "Unable to initialize Envirnment.", + "-9" => "Can't Read Server RSA File.", + "-10" => "Can't Read Client RSA File.", + "-11" => "Web Server error.", + "-12" => "Receive Message type error.", + "-13" => "No Request Message.", + "-14" => "No Response Content.", + "-18" => "Merchant Update URL not found.", + "-19" => "Server URL not find Domain or IP.", + "-20" => "Server URL only can fill http or https.", + "-21" => "Server Config File open error.", + "-22" => "Server RSA Key File open error.", + "-23" => "Server RSA Key File read error.", + "-24" => "Server Config File have some errors, Please to check it.", + "-25" => "Merchant Config File open error.", + "-26" => "Merchant RSA Key File open error.", + "-27" => "Merchant RSA Key File read error.", + "-28" => "Merchant Config File has some errors, Please to check it.", + "-29" => "Server Type is unknown.", + "-30" => "Comm Type is unknown.", + "-31" => "Input Parameter [ORDERNO] is null or empty.", + "-32" => "Input Parameter [STOREID] is null or empty.", + "-33" => "Input Parameter [ORDERDESC] is null or empty.", + "-34" => "Input Parameter [CURRENCY] is null or empty.", + "-35" => "Input Parameter [AMOUNT] is null or empty.", + "-36" => "Input Parameter [ORDERURL] is null or empty.", + "-37" => "Input Parameter [RETURNURL] is null or empty.", + "-38" => "Input Parameter [DEPOSIT] is null or empty.", + "-39" => "Input Parameter [QUERYFLAG] is null or empty.", + "-40" => "Input Parameter [UPDATEURL] is null or empty.", + "-41" => "Input Parameter [MERUPDATEURL] is null or empty.", + "-42" => "Input Parameter [KEY] is null or empty.", + "-43" => "Input Parameter [MAC] is null or empty.", + "-44" => "Input Parameter [CIPHER] is null or empty.", + "-45" => "Input Parameter [TrxType] is wrong.", + "-100" => "TrustLink Server is closed. Or Merchant Server IP is not consistent with TrustLink Server setting.", + "-101" => "TrustLink Server receives NULL.", + "-308" => "Order Number already exists.", + "positive" => "Response from Bank. Please contact with Acquirer Bank Service or HiTRUST Call Center." + } + + def success? + params['retcode'] == SUCCESS + end + + def message + CODES[ params['retcode'] ] + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay.rb new file mode 100644 index 000000000..f43e3220e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay.rb @@ -0,0 +1,30 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + # Documentation: https://www.liqpay.com/?do=pages&p=cnb10 + module Liqpay + autoload :Helper, File.dirname(__FILE__) + '/liqpay/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/liqpay/notification.rb' + autoload :Return, File.dirname(__FILE__) + '/liqpay/return.rb' + + mattr_accessor :service_url + self.service_url = 'https://liqpay.com/?do=clickNbuy' + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'signature' + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + + def self.return(query_string) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/helper.rb new file mode 100644 index 000000000..89d158c68 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/helper.rb @@ -0,0 +1,43 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Liqpay + class Helper < ActiveMerchant::Billing::Integrations::Helper + def initialize(order, account, options = {}) + @secret = options.delete(:secret) + super + + add_field 'version', '1.2' + end + + def form_fields + xml = "<request> + <version>1.2</version> + <result_url>#{@fields["result_url"]}</result_url> + <server_url>#{@fields["server_url"]}</server_url> + <merchant_id>#{@fields["merchant_id"]}</merchant_id> + <order_id>#{@fields["order_id"]}</order_id> + <amount>#{@fields["amount"]}</amount> + <currency>#{@fields["currency"]}</currency> + <description>#{@fields["description"]}</description> + <default_phone>#{@fields["default_phone"]}</default_phone> + <pay_way>card</pay_way> + </request>".strip + sign = Base64.encode64(Digest::SHA1.digest("#{@secret}#{xml}#{@secret}")).strip + {"operation_xml" => Base64.encode64(xml), "signature" => sign} + end + + mapping :account, 'merchant_id' + mapping :amount, 'amount' + mapping :currency, 'currency' + mapping :order, 'order_id' + mapping :description, 'description' + mapping :phone, 'default_phone' + + mapping :notify_url, 'server_url' + mapping :return_url, 'result_url' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/notification.rb new file mode 100644 index 000000000..2cfb7a261 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/notification.rb @@ -0,0 +1,89 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Liqpay + class Notification < ActiveMerchant::Billing::Integrations::Notification + def self.recognizes?(params) + params.has_key?('amount') && params.has_key?('order_id') + end + + def initialize(post, options = {}) + raise ArgumentError if post.blank? + super + @params.merge!(Hash.from_xml(Base64.decode64(xml))["response"]) + end + + def xml + @params["operation_xml"] + end + + def complete? + status == 'success' + end + + def account + params['merchant_id'] + end + + def amount + BigDecimal.new(gross) + end + + def item_id + params['order_id'] + end + + def transaction_id + params['transaction_id'] + end + + def action_name + params['action_name'] # either 'result_url' or 'server_url' + end + + def version + params['version'] + end + + def sender_phone + params['sender_phone'] + end + + def security_key + params[ActiveMerchant::Billing::Integrations::Liqpay.signature_parameter_name] + end + + def gross + params['amount'] + end + + def currency + params['currency'] + end + + def status + params['status'] # 'success', 'failure' or 'wait_secure' + end + + def code + params['code'] + end + + def generate_signature_string + "#{@options[:secret]}#{Base64.decode64(xml)}#{@options[:secret]}" + end + + def generate_signature + Base64.encode64(Digest::SHA1.digest(generate_signature_string)).strip + end + + def acknowledge + security_key == generate_signature + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/return.rb new file mode 100644 index 000000000..200862d25 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/liqpay/return.rb @@ -0,0 +1,83 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Liqpay + class Return < ActiveMerchant::Billing::Integrations::Return + def self.recognizes?(params) + params.has_key?('amount') && params.has_key?('order_id') + end + + def initialize(post) + super + xml = Base64.decode64(@params["operation_xml"]) + @params.merge!(Hash.from_xml(xml)["response"]) + end + + def complete? + status == 'success' + end + + def account + params['merchant_id'] + end + + def amount + BigDecimal.new(gross) + end + + def item_id + params['order_id'] + end + + def transaction_id + params['transaction_id'] + end + + def action_name + params['action_name'] # either 'result_url' or 'server_url' + end + + def version + params['version'] + end + + def sender_phone + params['sender_phone'] + end + + def security_key + params[ActiveMerchant::Billing::Integrations::Liqpay.signature_parameter_name] + end + + def gross + params['amount'] + end + + def currency + params['currency'] + end + + def status + params['status'] # 'success', 'failure' or 'wait_secure' + end + + def code + params['code'] + end + + def generate_signature_string + ['', version, @options[:secret], action_name, sender_phone, account, gross, currency, item_id, transaction_id, status, code, ''].flatten.compact.join('|') + end + + def generate_signature + Base64.encode64(Digest::SHA1.digest(generate_signature_string)).gsub(/\n/, '') + end + + def acknowledge + security_key == generate_signature + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva.rb new file mode 100644 index 000000000..1bb12bf64 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva.rb @@ -0,0 +1,86 @@ +require File.dirname(__FILE__) + '/maksuturva/helper.rb' +require File.dirname(__FILE__) + '/maksuturva/notification.rb' + +# USAGE: +# +# First define Maksuturva seller id and authcode in an initializer: +# +# MAKSUTURVA_SELLERID = "testikauppias" +# MAKSUTURVA_AUTHCODE = "11223344556677889900" +# +# Then in view do something like this (use dynamic values for your app) +# +# <% payment_service_for 2, MAKSUTURVA_SELLERID, +# :amount => "200,00", :currency => 'EUR', :credential2 => MAKSUTURVA_AUTHCODE, +# :service => :maksuturva do |service| +# service.pmt_reference = "134662" +# service.pmt_duedate = "24.06.2012" +# service.customer :phone => "0405051909", +# :email => "antti@example.com" +# service.billing_address :city => "Helsinki", +# :address1 => "Lorem street", +# :state => "-", +# :country => 'Finland', +# :zip => "00530" +# service.pmt_orderid = "2" +# service.pmt_buyername = "Antti Akonniemi" +# service.pmt_deliveryname = "Antti Akonniemi" +# service.pmt_deliveryaddress = "Köydenpunojankatu 13" +# service.pmt_deliverypostalcode = "00180" +# service.pmt_deliverycity = "Helsinki" +# service.pmt_deliverycountry = "FI" +# service.pmt_rows = 1 +# service.pmt_row_name1 = "testi" +# service.pmt_row_desc1 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." +# service.pmt_row_articlenr1 = "1" +# service.pmt_row_quantity1 = "1" +# service.pmt_row_deliverydate1 = "26.6.2012" +# service.pmt_row_price_gross1 = "200,00" +# service.pmt_row_vat1= "23,00" +# service.pmt_row_discountpercentage1 = "0,00" +# service.pmt_row_type1 = "1" +# service.pmt_charset = "UTF-8" +# service.pmt_charsethttp = "UTF-8" +# +# service.return_url "http://localhost:3000/process" +# service.cancel_return_url "http://example.com" +# service.pmt_errorreturn "http://example.com" +# +# service.pmt_delayedpayreturn "http://example.com" +# service.pmt_escrow "N" +# service.pmt_escrowchangeallowed "N" +# service.pmt_sellercosts "0,00" +# service.pmt_keygeneration "001" +# %> +# +# Then in the controller handle the return with something like this +# +# def ipn +# notify = ActiveMerchant::Billing::Integrations::Maksuturva::Notification.new(params) +# +# if notify.acknowledge(MAKSUTURVA_AUTHCODE) +# # Process order +# else +# # Show error +# end +# end +# +# For full list of available parameters etc check the integration documents +# here: +# +# https://www.maksuturva.fi/services/vendor_services/integration_guidelines.html + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Maksuturva + mattr_accessor :service_url + self.service_url = 'https://www.maksuturva.fi/NewPaymentExtended.pmt' + + def self.notification(post) + Notification.new(post) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/helper.rb new file mode 100644 index 000000000..4d6128cff --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/helper.rb @@ -0,0 +1,119 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Maksuturva + class Helper < ActiveMerchant::Billing::Integrations::Helper + def initialize(order, account, options = {}) + md5secret options.delete(:credential2) + super + add_field("pmt_action", "NEW_PAYMENT_EXTENDED") + add_field("pmt_version", "0004") + add_field("pmt_sellerid", account) + add_field("pmt_hashversion", "MD5") + end + + def md5secret(value) + @md5secret = value + end + + def form_fields + @fields.merge("pmt_hash" => generate_md5string) + end + + def generate_md5string + fields = [@fields["pmt_action"], @fields["pmt_version"]] + fields += [@fields["pmt_selleriban"]] unless @fields["pmt_selleriban"].nil? + fields += [@fields["pmt_id"], @fields["pmt_orderid"], @fields["pmt_reference"], @fields["pmt_duedate"], + @fields["pmt_amount"], @fields["pmt_currency"], @fields["pmt_okreturn"], @fields["pmt_errorreturn"], @fields["pmt_cancelreturn"], + @fields["pmt_delayedpayreturn"], @fields["pmt_escrow"], @fields["pmt_escrowchangeallowed"]] + + fields += [@fields["pmt_invoicefromseller"]] unless @fields["pmt_invoicefromseller"].nil? + fields += [@fields["pmt_paymentmethod"]] unless @fields["pmt_paymentmethod"].nil? + fields += [@fields["pmt_buyeridentificationcode"]] unless @fields["pmt_buyeridentificationcode"].nil? + + + fields += [@fields["pmt_buyername"], @fields["pmt_buyeraddress"], @fields["pmt_buyerpostalcode"], @fields["pmt_buyercity"], + @fields["pmt_buyercountry"], @fields["pmt_deliveryname"], @fields["pmt_deliveryaddress"], @fields["pmt_deliverypostalcode"], @fields["pmt_deliverycity"], + @fields["pmt_deliverycountry"], @fields["pmt_sellercosts"]] + + (1..@fields["pmt_rows"].to_i).each do |i| + fields += [@fields["pmt_row_name#{i}"], @fields["pmt_row_desc#{i}"], @fields["pmt_row_quantity#{i}"]] + fields += [@fields["pmt_row_articlenr#{i}"]] unless @fields["pmt_row_articlenr#{i}"].nil? + fields += [@fields["pmt_row_unit#{i}"]] unless @fields["pmt_row_unit#{i}"].nil? + fields += [@fields["pmt_row_deliverydate#{i}"]] + fields += [@fields["pmt_row_price_gross#{i}"]] unless @fields["pmt_row_price_gross#{i}"].nil? + fields += [@fields["pmt_row_price_net#{i}"]] unless @fields["pmt_row_price_net#{i}"].nil? + fields += [@fields["pmt_row_vat#{i}"], @fields["pmt_row_discountpercentage#{i}"], @fields["pmt_row_type#{i}"]] + end + fields += [@md5secret] + fields = fields.join("&") + "&" + Digest::MD5.hexdigest(fields).upcase + end + + mapping :pmt_selleriban, "pmt_selleriban" + mapping :pmt_reference, "pmt_reference" + mapping :pmt_duedate, "pmt_duedate" + mapping :pmt_userlocale, "pmt_userlocale" + mapping :pmt_escrow, "pmt_escrow" + mapping :pmt_escrowchangeallowed, "pmt_escrowchangeallowed" + mapping :pmt_invoicefromseller, "pmt_invoicefromseller" + mapping :pmt_paymentmethod, "pmt_paymentmethod" + mapping :pmt_buyeridentificationcode, "pmt_buyeridentificationcode" + mapping :pmt_buyername, "pmt_buyername" + + mapping :account, '' + mapping :currency, 'pmt_currency' + mapping :amount, 'pmt_amount' + + mapping :order, 'pmt_id' + mapping :pmt_orderid, 'pmt_orderid' + mapping :pmt_deliveryname, "pmt_deliveryname" + mapping :pmt_deliveryaddress, "pmt_deliveryaddress" + mapping :pmt_deliverypostalcode, "pmt_deliverypostalcode" + mapping :pmt_deliverycity, "pmt_deliverycity" + mapping :pmt_deliverycountry, "pmt_deliverycountry" + mapping :pmt_sellercosts, "pmt_sellercosts" + mapping :pmt_rows, "pmt_rows" + + (1..499.to_i).each do |i| + mapping "pmt_row_name#{i}".to_sym, "pmt_row_name#{i}" + mapping "pmt_row_desc#{i}".to_sym, "pmt_row_desc#{i}" + mapping "pmt_row_quantity#{i}".to_sym, "pmt_row_quantity#{i}" + mapping "pmt_row_articlenr#{i}".to_sym, "pmt_row_articlenr#{i}" + mapping "pmt_row_unit#{i}".to_sym, "pmt_row_unit#{i}" + mapping "pmt_row_deliverydate#{i}".to_sym, "pmt_row_deliverydate#{i}" + mapping "pmt_row_price_gross#{i}".to_sym, "pmt_row_price_gross#{i}" + mapping "pmt_row_price_net#{i}".to_sym, "pmt_row_price_net#{i}" + mapping "pmt_row_vat#{i}".to_sym, "pmt_row_vat#{i}" + mapping "pmt_row_discountpercentage#{i}".to_sym, "pmt_row_discountpercentage#{i}" + mapping "pmt_row_type#{i}".to_sym, "pmt_row_type#{i}" + end + + mapping :pmt_charset, "pmt_charset" + mapping :pmt_charsethttp, "pmt_charsethttp" + mapping :pmt_hashversion, "pmt_hashversion" + mapping :pmt_keygeneration, "pmt_keygeneration" + mapping :customer, :email => 'pmt_buyeremail', + :phone => 'pmt_buyerphone' + + mapping :billing_address, :city => 'pmt_buyercity', + :address1 => "pmt_buyeraddress", + :address2 => '', + :state => '', + :zip => "pmt_buyerpostalcode", + :country => 'pmt_buyercountry' + + mapping :notify_url, '' + mapping :return_url, 'pmt_okreturn' + mapping :pmt_errorreturn, 'pmt_errorreturn' + mapping :pmt_delayedpayreturn, 'pmt_delayedpayreturn' + mapping :cancel_return_url, 'pmt_cancelreturn' + + mapping :description, '' + mapping :tax, '' + mapping :shipping, '' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/notification.rb new file mode 100644 index 000000000..ed7cdd297 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/maksuturva/notification.rb @@ -0,0 +1,48 @@ +require "net/http" + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Maksuturva + class Notification < ActiveMerchant::Billing::Integrations::Notification + def complete? + true + end + + def transaction_id + params["pmt_id"] + end + + def security_key + params["pmt_hash"] + end + + def gross + params["pmt_amount"] + end + + def currency + params["pmt_currency"] + end + + def status + "PAID" + end + + def acknowledge(authcode) + return_authcode = [params["pmt_action"], params["pmt_version"], params["pmt_id"], params["pmt_reference"], params["pmt_amount"], params["pmt_currency"], params["pmt_sellercosts"], params["pmt_paymentmethod"], params["pmt_escrow"], authcode].join("&") + (Digest::MD5.hexdigest(return_authcode + "&").upcase == params["pmt_hash"]) + end + + private + + def parse(post) + post.each do |key, value| + params[key] = value + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers.rb new file mode 100644 index 000000000..44e034e10 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers.rb @@ -0,0 +1,26 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Moneybookers + + autoload :Notification, File.dirname(__FILE__) + '/moneybookers/notification.rb' + autoload :Helper, File.dirname(__FILE__) + '/moneybookers/helper.rb' + + mattr_accessor :production_url + self.production_url = 'https://www.moneybookers.com/app/payment.pl' + + def self.service_url + self.production_url + end + + def self.notification(post, options) + Notification.new(post, options) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/helper.rb new file mode 100644 index 000000000..47ae94648 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/helper.rb @@ -0,0 +1,75 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Moneybookers + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'pay_to_email' + mapping :order, 'transaction_id' + mapping :amount, 'amount' + mapping :currency, 'currency' + + mapping :customer, + :first_name => 'firstname', + :last_name => 'lastname', + :email => 'pay_from_email', + :phone => 'phone_number' + + mapping :billing_address, + :city => 'city', + :address1 => 'address', + :address2 => 'address2', + :state => 'state', + :zip => 'postal_code', + :country => 'country' + + mapping :notify_url, 'status_url' + mapping :return_url, 'return_url' + mapping :cancel_return_url, 'cancel_url' + mapping :description, 'detail1_text' + + MAPPED_COUNTRY_CODES = { + 'SE' => 'SV', + 'DK' => 'DA' + } + + SUPPORTED_COUNTRY_CODES = [ + 'FI', 'DE', 'ES', 'FR', + 'IT','PL', 'GR', 'RO', + 'RU', 'TR', 'CN', 'CZ', 'NL' + ] + + def initialize(order, account, options = {}) + super + add_tracking_token + add_default_parameters + add_seller_details(options) + end + + private + + def add_tracking_token + return if application_id.blank? || application_id == 'ActiveMerchant' + + add_field('merchant_fields', 'platform') + add_field('platform', application_id) + end + + def add_default_parameters + add_field('hide_login', 1) + end + + def add_seller_details(options) + add_field('recipient_description', options[:account_name]) if options[:account_name] + add_field('country', lookup_country_code(options[:country], :alpha3)) if options[:country] + add_field('language', locale_code(options[:country])) if options[:country] + end + + def locale_code(country_code) + return country_code if SUPPORTED_COUNTRY_CODES.include?(country_code) + MAPPED_COUNTRY_CODES[country_code] || 'EN' + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/notification.rb new file mode 100644 index 000000000..5d25b4cba --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/moneybookers/notification.rb @@ -0,0 +1,129 @@ +require 'net/http' +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Moneybookers + class Notification < ActiveMerchant::Billing::Integrations::Notification + + def initialize(data, options) + if options[:credential2].nil? + raise ArgumentError, "You need to provide the md5 secret as the option :credential2 to verify that the notification originated from Moneybookers" + end + super + end + + def complete? + status == 'Completed' + end + + # ‘2’ Processed – This status is sent when the transaction is processed and the funds have been received on your Moneybookers account. + # ‘0’ Pending – This status is sent when the customers pays via the pending bank transfer option. Such transactions will auto-process IF the bank transfer is received by Moneybookers. We strongly recommend that you do NOT process the order/transaction in your system upon receipt of a pending status from Moneybookers. + # ‘-1’ Cancelled – Pending transactions can either be cancelled manually by the sender in their online account history or they will auto-cancel after 14 days if still pending. + # ‘-2’ Failed – This status is sent when the customer tries to pay via Credit Card or Direct Debit but our provider declines the transaction. If you do not accept Credit Card or Direct Debit payments via Moneybookers (see page 17) then you will never receive the failed status. + # ‘-3’ Chargeback – This status could be received only if your account is configured to receive chargebacks. If this is the case, whenever a chargeback is received by Moneybookers, a -3 status will be posted on the status_url for the reversed transaction. + def status + case status_code + when '2' + 'Completed' + when '0' + 'Pending' + when '-1' + 'Cancelled' + when '-2' + 'Failed' + when '-3' + 'Reversed' + else + 'Error' + end + end + + def status_code + params['status'] + end + + def item_id + params['transaction_id'] + end + + def transaction_id + params['mb_transaction_id'] + end + + # When was this payment received by the client. + def received_at + nil + end + + def payer_email + params['pay_from_email'] + end + + def receiver_email + params['pay_to_email'] + end + + def md5sig + params['md5sig'] + end + + #Unique ID from the merchant's Moneybookers.com account, needed for calculatinon of md5 sig + def merchant_id + params['merchant_id'] + end + + # currency of the payment as posted by the merchant on the entry form + def currency + params['currency'] + end + + # amount of the payment as posted by the merchant on the entry form (ex. 39.60/39.6/39) + def gross + params['amount'] + end + + # currency of mb_amount, will always be the same as the currency of the beneficiary's account at Moneybookers.com + def merchant_currency + params['mb_currency'] + end + + # total amount of the payment in Merchants currency (ex 25.46/25.4/25) + def merchant_amount + params['mb_amount'] + end + + # Was this a test transaction? + def test? + false + end + + def secret + @options[:credential2] + end + + # Acknowledge the transaction to MoneyBooker. This method has to be called after a new + # apc arrives. It will verify that all the information we received is correct and will return a + # ok or a fail. The secret (second credential) has to be provided in the parameter :credential2 + # when instantiating the Notification object. + # + # Example: + # + # def ipn + # notify = Moneybookers.notification(request.raw_post, :credential2 => 'secret') + # + # if notify.acknowledge + # ... process order ... if notify.complete? + # else + # ... log possible hacking attempt ... + # end + def acknowledge + fields = [merchant_id, item_id, Digest::MD5.hexdigest(secret).upcase, merchant_amount, merchant_currency, status_code].join + md5sig == Digest::MD5.hexdigest(fields).upcase + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex.rb new file mode 100644 index 000000000..ff3dce6d9 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex.rb @@ -0,0 +1,88 @@ + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + # To start with Nochex, follow the instructions for installing + # ActiveMerchant as a plugin, as described on + # http://www.activemerchant.org/. + # + # The plugin will automatically add the ActionView helper for + # ActiveMerchant, which will allow you to make the Nochex payments. + # The idea behind the helper is that it generates an invisible + # forwarding screen that will automatically redirect the user. + # So you would collect all the information about the order and then + # simply render the hidden form, which redirects the user to Nochex. + # + # The syntax of the helper is as follows: + # + # <% payment_service_for 'order id', 'nochex_user_id', + # :amount => 50.00, + # :service => :nochex, + # :html => { :id => 'nochex-form' } do |service| %> + # + # <% service.customer :first_name => 'Cody', + # :last_name => 'Fauser', + # :phone => '(555)555-5555', + # :email => 'cody@example.com' %> + # + # <% service.billing_address :city => 'Ottawa', + # :address1 => '21 Snowy Brook Lane', + # :address2 => 'Apt. 36', + # :state => 'ON', + # :country => 'CA', + # :zip => 'K1J1E5' %> + # + # <% service.invoice '#1000' %> + # <% service.shipping '0.00' %> + # <% service.tax '0.00' %> + # + # <% service.notify_url url_for(:action => 'notify', :only_path => false) %> + # <% service.return_url url_for(:action => 'done', :only_path => false) %> + # <% service.cancel_return_url 'http://mystore.com' %> + # <% end %> + # + # The notify_url is the URL that the Nochex IPN will be sent. You can + # handle the notification in your controller action as follows: + # + # class NotificationController < ApplicationController + # include ActiveMerchant::Billing::Integrations + # + # def notify + # notification = Nochex::Notification.new(request.raw_post) + # + # begin + # # Acknowledge notification with Nochex + # raise StandardError, 'Illegal Notification' unless notification.acknowledge + # # Process the payment + # rescue => e + # logger.warn("Illegal notification received: #{e.message}") + # ensure + # head(:ok) + # end + # end + # end + module Nochex + autoload :Return, File.dirname(__FILE__) + '/nochex/return.rb' + autoload :Helper, File.dirname(__FILE__) + '/nochex/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/nochex/notification.rb' + + + mattr_accessor :service_url + self.service_url = 'https://secure.nochex.com' + + mattr_accessor :notification_confirmation_url + self.notification_confirmation_url = 'https://www.nochex.com/nochex.dll/apc/apc' + + # Simply a convenience method that returns a new + # ActiveMerchant::Billing::Integrations::Nochex::Notification + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/helper.rb new file mode 100644 index 000000000..e61948021 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/helper.rb @@ -0,0 +1,68 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Nochex + class Helper < ActiveMerchant::Billing::Integrations::Helper + # Required Parameters + # email + # amount + mapping :account, 'email' + mapping :amount, 'amount' + + # Set the field status = test for testing with accounts: + # Account Password + # test1@nochex.com 123456 + # test2@nochex.com 123456 + # def initialize(order, account, options = {}) + # super + # add_field('status', 'test') + # end + + # Need to format the amount to have 2 decimal places + def amount=(money) + cents = money.respond_to?(:cents) ? money.cents : money + if money.is_a?(String) or cents.to_i <= 0 + raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.' + end + add_field mappings[:amount], sprintf("%.2f", cents.to_f/100) + end + + # Optional Parameters + # ordernumber + mapping :order, 'ordernumber' + + # firstname + # lastname + # email_address_sender + mapping :customer, :first_name => 'firstname', + :last_name => 'lastname', + :email => 'email_address_sender' + + # town + # firstline + # county + # postcode + mapping :billing_address, :city => 'town', + :address1 => 'firstline', + :state => 'county', + :zip => 'postcode' + + # responderurl + mapping :notify_url, 'responderurl' + + # returnurl + mapping :return_url, 'returnurl' + + # cancelurl + mapping :cancel_return_url, 'cancelurl' + + # description + mapping :description, 'description' + + # Currently unmapped + # logo + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/notification.rb new file mode 100644 index 000000000..cf9334b3d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/notification.rb @@ -0,0 +1,94 @@ +require 'net/http' +require 'date' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Nochex + # Parser and handler for incoming Automatic Payment Confirmations from Nochex. + class Notification < ActiveMerchant::Billing::Integrations::Notification + include ActiveMerchant::PostsData + + def complete? + status == 'Completed' + end + + # Id of the order we passed to Nochex + def item_id + params['order_id'] + end + + def transaction_id + params['transaction_id'] + end + + def currency + 'GBP' + end + + # When was this payment received by the client. + def received_at + # U.K. Format: 27/09/2006 22:30:54 + return if params['transaction_date'].blank? + time = params['transaction_date'].scan(/\d+/) + Time.utc(time[2], time[1], time[0], time[3], time[4], time[5]) + end + + def payer_email + params['from_email'] + end + + def receiver_email + params['to_email'] + end + + def security_key + params['security_key'] + end + + # the money amount we received in X.2 decimal. + def gross + sprintf("%.2f", params['amount'].to_f) + end + + # Was this a test transaction? + def test? + params['status'] == 'test' + end + + def status + 'Completed' + end + + # Acknowledge the transaction to Nochex. This method has to be called after a new + # apc arrives. Nochex will verify that all the information we received are correct and will return a + # ok or a fail. This is very similar to the PayPal IPN scheme. + # + # Example: + # + # def nochex_ipn + # notify = NochexNotification.new(request.raw_post) + # + # if notify.acknowledge + # ... process order ... if notify.complete? + # else + # ... log possible hacking attempt ... + # end + def acknowledge + payload = raw + + response = ssl_post(Nochex.notification_confirmation_url, payload, + 'Content-Length' => "#{payload.size}", + 'User-Agent' => "Active Merchant -- http://activemerchant.org", + 'Content-Type' => "application/x-www-form-urlencoded" + ) + + raise StandardError.new("Faulty Nochex result: #{response}") unless ["AUTHORISED", "DECLINED"].include?(response) + + response == "AUTHORISED" + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/return.rb new file mode 100644 index 000000000..c8fd59e1a --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/nochex/return.rb @@ -0,0 +1,10 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Nochex + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/notification.rb new file mode 100644 index 000000000..56df8ee8a --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/notification.rb @@ -0,0 +1,71 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + class Notification + attr_accessor :params + attr_accessor :raw + + # set this to an array in the subclass, to specify which IPs are allowed + # to send requests + class_attribute :production_ips + + # * *Args* : + # - +doc+ -> raw post string + # - +options+ -> custom options which individual implementations can + # utilize + def initialize(post, options = {}) + @options = options + empty! + parse(post) + end + + def status + raise NotImplementedError, "Must implement this method in the subclass" + end + + # the money amount we received in X.2 decimal. + def gross + raise NotImplementedError, "Must implement this method in the subclass" + end + + def gross_cents + (gross.to_f * 100.0).round + end + + # This combines the gross and currency and returns a proper Money object. + # this requires the money library located at http://dist.leetsoft.com/api/money + def amount + return Money.new(gross_cents, currency) rescue ArgumentError + return Money.new(gross_cents) # maybe you have an own money object which doesn't take a currency? + end + + # reset the notification. + def empty! + @params = Hash.new + @raw = "" + end + + # Check if the request comes from an official IP + def valid_sender?(ip) + return true if ActiveMerchant::Billing::Base.integration_mode == :test || production_ips.blank? + production_ips.include?(ip) + end + + def test? + false + end + + private + + # Take the posted data and move the relevant data into a hash + def parse(post) + @raw = post.to_s + for line in @raw.split('&') + key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten + params[key] = CGI.unescape(value) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum.rb new file mode 100644 index 000000000..78ac7483d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum.rb @@ -0,0 +1,44 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + # Documentation: + # https://www.paxum.com/payment_docs/page.php?name=apiIntroduction + module Paxum + autoload :Helper, File.dirname(__FILE__) + '/paxum/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/paxum/notification.rb' + autoload :Return, File.dirname(__FILE__) + '/paxum/return.rb' + autoload :Common, File.dirname(__FILE__) + '/paxum/common.rb' + + mattr_accessor :test_url + self.test_url = 'https://paxum.com/payment/phrame.php?action=displayProcessPaymentLogin' + + mattr_accessor :production_url + self.production_url = 'https://paxum.com/payment/phrame.php?action=displayProcessPaymentLogin' + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'key' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/common.rb new file mode 100644 index 000000000..e158142af --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/common.rb @@ -0,0 +1,24 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paxum + module Common + def generate_signature_string + @raw_post.slice!(0) if @raw_post.starts_with?("&") + @raw_post = CGI.unescape(@raw_post) + @raw_post = "&#{@raw_post}" unless @raw_post.starts_with?("&") + arr = @raw_post.split('&') + arr.delete(arr.last) + data = arr.join('&') + + (data + secret) + end + + def generate_signature + Digest::MD5.hexdigest(generate_signature_string) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/helper.rb new file mode 100644 index 000000000..f69fb96d6 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/helper.rb @@ -0,0 +1,42 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paxum + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Common + + def initialize(order, account, options = {}) + @paxum_options = options.dup + options.delete(:description) + options.delete(:fail_url) + options.delete(:success_url) + options.delete(:result_url) + super + add_field "button_type_id", "1" + add_field "variables", "notify_url=#{@paxum_options[:result_url]}" + @paxum_options.each do |key, value| + add_field mappings[key], value + end + end + + def form_fields + @fields + end + + def params + @fields + end + + mapping :account, 'business_email' + mapping :amount, 'amount' + mapping :currency, 'currency' + mapping :order, 'item_id' + mapping :description, 'item_name' + mapping :fail_url, 'cancel_url' + mapping :success_url, 'finish_url' + mapping :result_url, 'notify_url' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/notification.rb new file mode 100644 index 000000000..06c5c64b2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paxum/notification.rb @@ -0,0 +1,33 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paxum + class Notification < ActiveMerchant::Billing::Integrations::Notification + include Common + + def initialize(post, options = {}) + @raw_post = post.dup + post.slice!(0) + super + end + + def self.recognizes?(params) + (params.has_key?('transaction_item_id') && params.has_key?('transaction_amount')) + end + + def security_key + params["key"] + end + + def secret + @options[:secret] + end + + def acknowledge + (security_key == generate_signature) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast.rb new file mode 100644 index 000000000..6e44ef55f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast.rb @@ -0,0 +1,70 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + # Documentation: + # https://www.payfast.co.za/s/std/integration-guide + module PayFast + autoload :Return, File.dirname(__FILE__) + '/pay_fast/return.rb' + autoload :Helper, File.dirname(__FILE__) + '/pay_fast/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/pay_fast/notification.rb' + autoload :Common, File.dirname(__FILE__) + '/pay_fast/common.rb' + + # Overwrite this if you want to change the PayFast sandbox url + mattr_accessor :process_test_url + self.process_test_url = 'https://sandbox.payfast.co.za/eng/process' + + # Overwrite this if you want to change the PayFast production url + mattr_accessor :process_production_url + self.process_production_url = 'https://www.payfast.co.za/eng/process' + + # Overwrite this if you want to change the PayFast sandbox url + mattr_accessor :validate_test_url + self.validate_test_url = 'https://sandbox.payfast.co.za/eng/query/validate' + + # Overwrite this if you want to change the PayFast production url + mattr_accessor :validate_production_url + self.validate_production_url = 'https://www.payfast.co.za/eng/query/validate' + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'signature' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.process_production_url + when :test + self.process_test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.validate_service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.validate_production_url + when :test + self.validate_test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/common.rb new file mode 100644 index 000000000..d5fb5dc5b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/common.rb @@ -0,0 +1,42 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayFast + module Common + def generate_signature(type) + string = case type + when :request + request_signature_string + when :notify + notify_signature_string + end + + Digest::MD5.hexdigest(string) + end + + def request_attributes + [:merchant_id, :merchant_key, :return_url, :cancel_url, + :notify_url, :name_first, :name_last, :email_address, + :payment_id, :amount, :item_name, :item_description, + :custom_str1, :custom_str2, :custom_str3, :custom_str4, + :custom_str5, :custom_int1, :custom_int2, :custom_int3, + :custom_int4, :custom_int5, :email_confirmation, + :confirmation_address] + end + + def request_signature_string + request_attributes.map do |attr| + "#{mappings[attr]}=#{CGI.escape(@fields[mappings[attr]])}" if @fields[mappings[attr]].present? + end.compact.join('&') + end + + def notify_signature_string + params.map do |key, value| + "#{key}=#{CGI.escape(value)}" unless key == PayFast.signature_parameter_name + end.compact.join('&') + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/helper.rb new file mode 100644 index 000000000..6d1a43c86 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/helper.rb @@ -0,0 +1,50 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayFast + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Common + + def initialize(order, account, options = {}) + super + add_field('merchant_id', account) + add_field('merchant_key', options.delete(:credential2)) + add_field('m_payment_id', order) + end + + def form_fields + @fields + end + + def params + @fields + end + + mapping :merchant_id, 'merchant_id' + mapping :merchant_key, 'merchant_key' + mapping :return_url, 'return_url' + mapping :cancel_return_url, 'cancel_url' + mapping :notify_url, 'notify_url' + mapping :name_first, 'name_first' + mapping :name_last, 'name_last' + mapping :email_address, 'email_address' + mapping :payment_id, 'm_payment_id' + mapping :amount, 'amount' + mapping :item_name, 'item_name' + mapping :description, 'item_name' + + mapping :customer, :first_name => 'name_first', + :last_name => 'name_last', + :email => 'email_address', + :phone => 'phone' + + 5.times { |i| mapping :"custom_str#{i}", "custom_str#{i}" } + 5.times { |i| mapping :"custom_int#{i}", "custom_int#{i}" } + + mapping :email_confirmation, 'email_confirmation' + mapping :confirmation_address, 'confirmation_address' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/notification.rb new file mode 100644 index 000000000..b0df33321 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/notification.rb @@ -0,0 +1,134 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayFast + # Parser and handler for incoming ITN from PayFast. + # The Example shows a typical handler in a rails application. + # + # Example + # + # class BackendController < ApplicationController + # include ActiveMerchant::Billing::Integrations + # + # def pay_fast_itn + # notify = PayFast::Notification.new(request.raw_post) + # + # order = Order.find(notify.item_id) + # + # if notify.acknowledge + # begin + # + # if notify.complete? and order.total == notify.amount + # order.status = 'success' + # + # shop.ship(order) + # else + # logger.error("Failed to verify Paypal's notification, please investigate") + # end + # + # rescue => e + # order.status = 'failed' + # raise + # ensure + # order.save + # end + # end + # + # render :nothing + # end + # end + class Notification < ActiveMerchant::Billing::Integrations::Notification + include PostsData + include Common + + # Was the transaction complete? + def complete? + status == "Completed" + end + + # Status of transaction. List of possible values: + # <tt>COMPLETE</tt>:: + def status + if params['payment_status'] == "COMPLETE" + "Completed" + else + "Failed" + end + end + + # Id of this transaction (uniq PayFast transaction id) + def transaction_id + params['pf_payment_id'] + end + + # Id of this transaction (uniq Shopify transaction id) + def item_id + params['m_payment_id'] + end + + # The total amount which the payer paid. + def gross + params['amount_gross'] + end + + # The total in fees which was deducated from the amount. + def fee + params['amount_fee'] + end + + # The net amount credited to the receiver's account. + def amount + params['amount_net'] + end + + # The name of the item being charged for. + def item_name + params['item_name'] + end + + # The Merchant ID as given by the PayFast system. Used to uniquely identify the receiver's account. + def merchant_id + params['merchant_id'] + end + + def currency + nil + end + # Generated hash depends on params order so use OrderedHash instead of Hash + def empty! + super + @params = ActiveSupport::OrderedHash.new + end + + # Acknowledge the transaction to PayFast. This method has to be called after a new + # ITN arrives. PayFast will verify that all the information we received are correct and will return a + # VERIFIED or INVALID status. + # + # Example: + # + # def pay_fast_itn + # notify = PayFastNotification.new(request.raw_post) + # + # if notify.acknowledge + # ... process order ... if notify.complete? + # else + # ... log possible hacking attempt ... + # end + def acknowledge + if params[PayFast.signature_parameter_name] == generate_signature(:notify) + response = ssl_post(PayFast.validate_service_url, notify_signature_string, + 'Content-Type' => "application/x-www-form-urlencoded", + 'Content-Length' => "#{notify_signature_string.size}" + ) + raise StandardError.new("Faulty PayFast result: #{response}") unless ['VALID', 'INVALID'].include?(response) + + response == "VALID" + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/return.rb new file mode 100644 index 000000000..505dc14fa --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pay_fast/return.rb @@ -0,0 +1,10 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayFast + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link.rb new file mode 100644 index 000000000..875eac688 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link.rb @@ -0,0 +1,21 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayflowLink + autoload :Helper, 'active_merchant/billing/integrations/payflow_link/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/payflow_link/notification.rb' + + mattr_accessor :service_url + self.service_url = 'https://payflowlink.paypal.com' + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + ActiveMerchant::Billing::Integrations::Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/helper.rb new file mode 100644 index 000000000..29326dcf7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/helper.rb @@ -0,0 +1,116 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayflowLink + class Helper < ActiveMerchant::Billing::Integrations::Helper + include PostsData + + def initialize(order, account, options = {}) + super + add_field('login', account) + add_field('echodata', 'True') + add_field('user2', self.test?) + add_field('invoice', order) + add_field('vendor', account) + add_field('user', options[:credential4].presence || account) + add_field('trxtype', options[:transaction_type] || 'S') + end + + mapping :account, 'login' + mapping :credential2, 'pwd' + mapping :credential3, 'partner' + mapping :order, 'user1' + + mapping :amount, 'amt' + + + mapping :billing_address, :city => 'city', + :address => 'address', + :state => 'state', + :zip => 'zip', + :country => 'country', + :phone => 'phone', + :name => 'name' + + mapping :customer, { :first_name => 'first_name', :last_name => 'last_name' } + + def description(value) + add_field('description', normalize("#{value}").delete("#")) + end + + def customer(params = {}) + add_field(mappings[:customer][:first_name], params[:first_name]) + add_field(mappings[:customer][:last_name], params[:last_name]) + end + + def billing_address(params = {}) + # Get the country code in the correct format + # Use what we were given if we can't find anything + country_code = lookup_country_code(params.delete(:country)) + add_field(mappings[:billing_address][:country], country_code) + + add_field(mappings[:billing_address][:address], [params.delete(:address1), params.delete(:address2)].compact.join(' ')) + + province_code = params.delete(:state) + add_field(mappings[:billing_address][:state], province_code.blank? ? 'N/A' : province_code.upcase) + + # Everything else + params.each do |k, v| + field = mappings[:billing_address][k] + add_field(field, v) unless field.nil? + end + end + + def form_fields + token, token_id = request_secure_token + + {"securetoken" => token, "securetokenid" => token_id, "mode" => test? ? "test" : "live"} + end + + private + + def secure_token_id + @secure_token_id ||= Utils.generate_unique_id + end + + def secure_token_url + test? ? "https://pilot-payflowpro.paypal.com" : "https://payflowpro.paypal.com" + end + + def request_secure_token + @fields["securetokenid"] = secure_token_id + @fields["createsecuretoken"] = "Y" + + fields = @fields.collect {|key, value| "#{key}[#{value.length}]=#{value}" }.join("&") + + response = ssl_post(secure_token_url, fields) + + parse_response(response) + end + + def parse_response(response) + response = response.split("&").inject({}) do |hash, param| + key, value = param.split("=") + hash[key] = value + hash + end + + [response['SECURETOKEN'], response['SECURETOKENID']] if response['RESPMSG'] && response['RESPMSG'].downcase == "approved" + end + + def normalize(text) + return unless text + + if ActiveSupport::Inflector.method(:transliterate).arity == -2 + ActiveSupport::Inflector.transliterate(text,'') + elsif RUBY_VERSION >= '1.9' + text.gsub(/[^\x00-\x7F]+/, '') + else + ActiveSupport::Inflector.transliterate(text).to_s + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/notification.rb new file mode 100644 index 000000000..f28798694 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payflow_link/notification.rb @@ -0,0 +1,78 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayflowLink + class Notification < ActiveMerchant::Billing::Integrations::Notification + + # Was the transaction complete? + def complete? + status == "Completed" + end + + # When was this payment received by the client. + # sometimes it can happen that we get the notification much later. + # One possible scenario is that our web application was down. In this case paypal tries several + # times an hour to inform us about the notification + def received_at + DateTime.parse(params['TRANSTIME']) if params['TRANSTIME'] + rescue ArgumentError + nil + end + + def status + params['RESPMSG'] + end + + # Id of this transaction (paypal number) + def transaction_id + params['PNREF'] + end + + # What type of transaction are we dealing with? + def type + params['TYPE'] + end + + # the money amount we received in X.2 decimal. + def gross + params['AMT'] + end + + # What currency have we been dealing with + def currency + nil + end + + def status + params['RESULT'] == '0' ? 'Completed' : 'Failed' + end + + # This is the item number which we submitted to paypal + def item_id + params['USER1'] + end + + # This is the invoice which you passed to paypal + def invoice + params['INVNUM'] + end + + # Was this a test transaction? + def test? + params['USER2'] == 'true' + end + + def account + params["ACCT"] + end + + def acknowledge + true + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal.rb new file mode 100644 index 000000000..13a1d277b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal.rb @@ -0,0 +1,39 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paypal + autoload :Return, 'active_merchant/billing/integrations/paypal/return.rb' + autoload :Helper, 'active_merchant/billing/integrations/paypal/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/paypal/notification.rb' + + # Overwrite this if you want to change the Paypal test url + mattr_accessor :test_url + self.test_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr' + + # Overwrite this if you want to change the Paypal production url + mattr_accessor :production_url + self.production_url = 'https://www.paypal.com/cgi-bin/webscr' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/helper.rb new file mode 100644 index 000000000..c905ae759 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/helper.rb @@ -0,0 +1,119 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paypal + class Helper < ActiveMerchant::Billing::Integrations::Helper + CANADIAN_PROVINCES = { 'AB' => 'Alberta', + 'BC' => 'British Columbia', + 'MB' => 'Manitoba', + 'NB' => 'New Brunswick', + 'NL' => 'Newfoundland', + 'NS' => 'Nova Scotia', + 'NU' => 'Nunavut', + 'NT' => 'Northwest Territories', + 'ON' => 'Ontario', + 'PE' => 'Prince Edward Island', + 'QC' => 'Quebec', + 'SK' => 'Saskatchewan', + 'YT' => 'Yukon' + } + # See https://www.paypal.com/IntegrationCenter/ic_std-variable-reference.html for details on the following options. + mapping :order, [ 'item_number', 'custom' ] + + def initialize(order, account, options = {}) + super + add_field('cmd', '_ext-enter') + add_field('redirect_cmd', '_xclick') + add_field('quantity', 1) + add_field('item_name', 'Store purchase') + add_field('no_shipping', '1') + add_field('no_note', '1') + add_field('charset', 'utf-8') + add_field('address_override', '0') + add_field('bn', application_id.to_s.slice(0,32)) unless application_id.blank? + end + + mapping :amount, 'amount' + mapping :account, 'business' + mapping :currency, 'currency_code' + mapping :notify_url, 'notify_url' + mapping :return_url, 'return' + mapping :cancel_return_url, 'cancel_return' + mapping :invoice, 'invoice' + mapping :item_name, 'item_name' + mapping :quantity, 'quantity' + mapping :no_shipping, 'no_shipping' + mapping :no_note, 'no_note' + mapping :address_override, 'address_override' + + mapping :application_id, 'bn' + + mapping :customer, :first_name => 'first_name', + :last_name => 'last_name', + :email => 'email' + + mapping :shipping_address, :city => 'city', + :address1 => 'address1', + :address2 => 'address2', + :state => 'state', + :zip => 'zip', + :country => 'country' + + def shipping_address(params = {}) + + # Get the country code in the correct format + # Use what we were given if we can't find anything + country_code = lookup_country_code(params.delete(:country)) + add_field(mappings[:shipping_address][:country], country_code) + + if params.has_key?(:phone) + phone = params.delete(:phone).to_s + + # Whipe all non digits + phone.gsub!(/\D+/, '') + + if ['US', 'CA'].include?(country_code) && phone =~ /(\d{3})(\d{3})(\d{4})$/ + add_field('night_phone_a', $1) + add_field('night_phone_b', $2) + add_field('night_phone_c', $3) + else + add_field('night_phone_b', phone) + end + end + + province_code = params.delete(:state) + + case country_code + when 'CA' + add_field(mappings[:shipping_address][:state], CANADIAN_PROVINCES[province_code.upcase]) unless province_code.nil? + when 'US' + add_field(mappings[:shipping_address][:state], province_code) + else + add_field(mappings[:shipping_address][:state], province_code.blank? ? 'N/A' : province_code) + end + + # Everything else + params.each do |k, v| + field = mappings[:shipping_address][k] + add_field(field, v) unless field.nil? + end + end + + mapping :tax, 'tax' + mapping :shipping, 'shipping' + mapping :cmd, 'cmd' + mapping :custom, 'custom' + mapping :src, 'src' + mapping :sra, 'sra' + %w(a p t).each do |l| + (1..3).each do |i| + mapping "#{l}#{i}".to_sym, "#{l}#{i}" + end + end + end + end + end + end +end + + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/notification.rb new file mode 100644 index 000000000..7fdb217da --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/notification.rb @@ -0,0 +1,227 @@ +require 'net/http' +require 'time' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paypal + # Parser and handler for incoming Instant payment notifications from paypal. + # The Example shows a typical handler in a rails application. Note that this + # is an example, please read the Paypal API documentation for all the details + # on creating a safe payment controller. + # + # Example + # + # class BackendController < ApplicationController + # include ActiveMerchant::Billing::Integrations + # + # def paypal_ipn + # notify = Paypal::Notification.new(request.raw_post) + # + # if notify.masspay? + # masspay_items = notify.items + # end + # + # order = Order.find(notify.item_id) + # + # if notify.acknowledge + # begin + # + # if notify.complete? and order.total == notify.amount + # order.status = 'success' + # + # shop.ship(order) + # else + # logger.error("Failed to verify Paypal's notification, please investigate") + # end + # + # rescue => e + # order.status = 'failed' + # raise + # ensure + # order.save + # end + # end + # + # render :nothing + # end + # end + class Notification < ActiveMerchant::Billing::Integrations::Notification + include PostsData + + def initialize(post, options = {}) + super + extend MassPayNotification if masspay? + end + + # Was the transaction complete? + def complete? + status == "Completed" + end + + # Is it a masspay notification? + def masspay? + type == "masspay" + end + + # When was this payment received by the client. + # sometimes it can happen that we get the notification much later. + # One possible scenario is that our web application was down. In this case paypal tries several + # times an hour to inform us about the notification + def received_at + parsed_time_fields = DateTime._strptime(params['payment_date'], "%H:%M:%S %b %d, %Y %Z") + Time.gm( + parsed_time_fields[:year], + parsed_time_fields[:mon], + parsed_time_fields[:mday], + parsed_time_fields[:hour], + parsed_time_fields[:min], + parsed_time_fields[:sec] + ) + Time.zone_offset(parsed_time_fields[:zone]) + end + + # Status of transaction. List of possible values: + # <tt>Canceled-Reversal</tt>:: + # <tt>Completed</tt>:: + # <tt>Denied</tt>:: + # <tt>Expired</tt>:: + # <tt>Failed</tt>:: + # <tt>In-Progress</tt>:: + # <tt>Partially-Refunded</tt>:: + # <tt>Pending</tt>:: + # <tt>Processed</tt>:: + # <tt>Refunded</tt>:: + # <tt>Reversed</tt>:: + # <tt>Voided</tt>:: + def status + params['payment_status'] + end + + # Id of this transaction (paypal number) + def transaction_id + params['txn_id'] + end + + # What type of transaction are we dealing with? + # "cart" "send_money" "web_accept" are possible here. + def type + params['txn_type'] + end + + # the money amount we received in X.2 decimal. + def gross + params['mc_gross'] + end + + # the markup paypal charges for the transaction + def fee + params['mc_fee'] + end + + # What currency have we been dealing with + def currency + params['mc_currency'] + end + + # This is the item number which we submitted to paypal + # The custom field is also mapped to item_id because PayPal + # doesn't return item_number in dispute notifications + def item_id + params['item_number'] || params['custom'] + end + + # This is the invoice which you passed to paypal + def invoice + params['invoice'] + end + + # Was this a test transaction? + def test? + params['test_ipn'] == '1' + end + + def account + params['business'] || params['receiver_email'] + end + + # Acknowledge the transaction to paypal. This method has to be called after a new + # ipn arrives. Paypal will verify that all the information we received are correct and will return a + # ok or a fail. + # + # Example: + # + # def paypal_ipn + # notify = PaypalNotification.new(request.raw_post) + # + # if notify.acknowledge + # ... process order ... if notify.complete? + # else + # ... log possible hacking attempt ... + # end + def acknowledge + payload = raw + + response = ssl_post(Paypal.service_url + '?cmd=_notify-validate', payload, + 'Content-Length' => "#{payload.size}", + 'User-Agent' => "Active Merchant -- http://activemerchant.org" + ) + + raise StandardError.new("Faulty paypal result: #{response}") unless ["VERIFIED", "INVALID"].include?(response) + + response == "VERIFIED" + end + end + + module MassPayNotification + # Mass pay returns a collection of MassPay Items, so inspect items to get the values + def transaction_id + end + + # Mass pay returns a collection of MassPay Items, so inspect items to get the values + def gross + end + + # Mass pay returns a collection of MassPay Items, so inspect items to get the values + def fee + end + + # Mass pay returns a collection of MassPay Items, so inspect items to get the values + def currency + end + + # Mass pay returns a collection of MassPay Items, so inspect items to get the values + def item_id + end + + # Mass pay returns a collection of MassPay Items, so inspect items to get the values + def account + end + + # Collection of notification items returned for MassPay transactions + def items + @items ||= (1..number_of_mass_pay_items).map do |item_number| + MassPayItem.new( + params["masspay_txn_id_#{item_number}"], + params["mc_gross_#{item_number}"], + params["mc_fee_#{item_number}"], + params["mc_currency_#{item_number}"], + params["unique_id_#{item_number}"], + params["receiver_email_#{item_number}"], + params["status_#{item_number}"] + ) + end + end + + private + + def number_of_mass_pay_items + @number_of_mass_pay_items ||= params.keys.select { |k| k.start_with? 'masspay_txn_id' }.size + end + end + + class MassPayItem < Struct.new(:transaction_id, :gross, :fee, :currency, :item_id, :account, :status) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/return.rb new file mode 100644 index 000000000..2b22a06a6 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal/return.rb @@ -0,0 +1,10 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paypal + class Return < ActiveMerchant::Billing::Integrations::Return + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced.rb new file mode 100644 index 000000000..f1741421e --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced.rb @@ -0,0 +1,20 @@ +module ActiveMerchant + module Billing + module Integrations + module PaypalPaymentsAdvanced + autoload :Helper, 'active_merchant/billing/integrations/paypal_payments_advanced/helper.rb' + + mattr_accessor :service_url + self.service_url = 'https://payflowlink.paypal.com' + + def self.notification(post, options = {}) + PayflowLink::Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced/helper.rb new file mode 100644 index 000000000..cd1889999 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paypal_payments_advanced/helper.rb @@ -0,0 +1,15 @@ +module ActiveMerchant + module Billing + module Integrations + module PaypalPaymentsAdvanced + class Helper < PayflowLink::Helper + + def initialize(order, account, options) + super + add_field('partner', 'PayPal') + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy.rb new file mode 100644 index 000000000..d74db8c4b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy.rb @@ -0,0 +1,36 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paysbuy + autoload :Helper, File.dirname(__FILE__) + '/paysbuy/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/paysbuy/notification.rb' + + mattr_accessor :test_url + self.test_url = 'https://demo.paysbuy.com/paynow.aspx' + + mattr_accessor :production_url + self.production_url = 'https://www.paysbuy.com/paynow.aspx' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/helper.rb new file mode 100644 index 000000000..3cd3430b1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/helper.rb @@ -0,0 +1,15 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paysbuy + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'biz' + mapping :amount, 'amt' + mapping :order, 'inv' + mapping :description, 'itm' + mapping :notify_url, 'postURL' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/notification.rb new file mode 100644 index 000000000..c7121a963 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/paysbuy/notification.rb @@ -0,0 +1,28 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Paysbuy + class Notification < ActiveMerchant::Billing::Integrations::Notification + SUCCESS = '00' + FAIL = '99' + + def complete? + status == 'Completed' + end + + def item_id + params['result'][2..-1] + end + + def status + params['result'][0..1] == SUCCESS ? 'Completed' : 'Failed' + end + + def acknowledge + true + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in.rb new file mode 100755 index 000000000..74933f1c7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in.rb @@ -0,0 +1,43 @@ +require 'digest/sha2' +require 'bigdecimal' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayuIn + autoload :Return, 'active_merchant/billing/integrations/payu_in/return.rb' + autoload :Helper, 'active_merchant/billing/integrations/payu_in/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/payu_in/notification.rb' + + mattr_accessor :test_url + mattr_accessor :production_url + + self.test_url = 'https://test.payu.in/_payment.php' + self.production_url = 'https://secure.payu.in/_payment.php' + + def self.service_url + ActiveMerchant::Billing::Base.integration_mode == :production ? self.production_url : self.test_url + end + + def self.notification(post, options = {}) + Notification.new(post, options) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + + def self.checksum(merchant_id, secret_key, *payload_items ) + options = payload_items.pop if Hash === payload_items.last + options ||= {} + payload = if options[:reverse] then + payload_items.dup.push( merchant_id || "" ).unshift( secret_key || "" ).collect{ |x| x.to_s }.join("|") + else + payload_items.dup.unshift( merchant_id || "" ).push( secret_key || "" ).collect{ |x| x.to_s }.join("|") + end + Digest::SHA512.hexdigest( payload ) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/helper.rb new file mode 100755 index 000000000..32048d309 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/helper.rb @@ -0,0 +1,74 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayuIn + class Helper < ActiveMerchant::Billing::Integrations::Helper + + mapping :amount, 'amount' + mapping :account, 'key' + mapping :order, 'txnid' + mapping :credential2, 'productinfo' + + mapping :customer, :first_name => 'firstname', + :last_name => 'lastname', + :email => 'email', + :phone => 'phone' + + mapping :billing_address, :city => 'city', + :address1 => 'address1', + :address2 => 'address2', + :state => 'state', + :zip => 'zip', + :country => 'country' + + # Which tab you want to be open default on PayU + # CC (CreditCard) or NB (NetBanking) + mapping :mode, 'pg' + + mapping :notify_url, 'notify_url' + mapping :return_url, ['surl', 'furl'] + mapping :cancel_return_url, 'curl' + mapping :checksum, 'hash' + + mapping :user_defined, { :var1 => 'udf1', + :var2 => 'udf2', + :var3 => 'udf3', + :var4 => 'udf4', + :var5 => 'udf5', + :var6 => 'udf6', + :var7 => 'udf7', + :var8 => 'udf8', + :var9 => 'udf9', + :var10 => 'udf10' + } + + def initialize(order, account, options = {}) + super + self.pg = 'CC' + end + + def form_fields + @fields.merge(mappings[:checksum] => generate_checksum) + end + + def generate_checksum( options = {} ) + checksum_fields = [ :order, :amount, :credential2, { :customer => [ :first_name, :email ] }, + { :user_defined => [ :var1, :var2, :var3, :var4, :var5, :var6, :var7, :var8, :var9, :var10 ] } ] + checksum_payload_items = checksum_fields.inject( [] ) do | items, field | + if Hash === field then + key = field.keys.first + field[key].inject( items ){ |s,x| items.push( @fields[ mappings[key][x] ] ) } + else + items.push( @fields[ mappings[field] ] ) + end + end + checksum_payload_items.push( options ) + PayuIn.checksum(@fields["key"], @fields["productinfo"], *checksum_payload_items ) + end + + end + + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/notification.rb new file mode 100755 index 000000000..385017862 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/notification.rb @@ -0,0 +1,167 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayuIn + class Notification < ActiveMerchant::Billing::Integrations::Notification + + def initialize(post, options = {}) + super(post, options) + @merchant_id = options[:credential1] + @secret_key = options[:credential2] + end + + def complete? + status == "success" + end + + # Status of the transaction. List of possible values: + # <tt>invalid</tt>:: transaction id is not present + # <tt>tampered</tt>:: transaction data has been tampered + # <tt>success</tt>:: transaction successful + # <tt>pending</tt>:: transaction is pending for some approval + # <tt>failure</tt>:: transaction failure + def status + @status ||= if checksum_ok? + if transaction_id.blank? + 'invalid' + else + transaction_status.downcase + end + else + 'tampered' + end + end + + def invoice_ok?( order_id ) + order_id.to_s == invoice.to_s + end + + # Order amount should be equal to gross - discount + def amount_ok?( order_amount, order_discount = BigDecimal.new( '0.0' ) ) + BigDecimal.new( gross ) == order_amount && BigDecimal.new( discount ) == order_discount + end + + # Status of transaction return from the PayU. List of possible values: + # <tt>SUCCESS</tt>:: + # <tt>PENDING</tt>:: + # <tt>FAILURE</tt>:: + def transaction_status + params['status'] + end + + # ID of this transaction (PayU.in number) + def transaction_id + params['mihpayid'] + end + + # Mode of Payment + # + # 'CC' for credit-card + # 'NB' for net-banking + # 'CD' for cheque or DD + # 'CO' for Cash Pickup + def type + params['mode'] + end + + # What currency have we been dealing with + def currency + 'INR' + end + + def item_id + params['txnid'] + end + + # This is the invoice which you passed to PayU.in + def invoice + params['txnid'] + end + + # Merchant Id provided by the PayU.in + def account + params['key'] + end + + # original amount send by merchant + def gross + params['amount'] + end + + # This is discount given to user - based on promotion set by merchants. + def discount + params['discount'] + end + + # Description offer for what PayU given the offer to user - based on promotion set by merchants. + def offer_description + params['offer'] + end + + # Information about the product as send by merchant + def product_info + params['productinfo'] + end + + # Email of the customer + def customer_email + params['email'] + end + + # Phone of the customer + def customer_phone + params['phone'] + end + + # Firstname of the customer + def customer_first_name + params['firstname'] + end + + # Lastname of the customer + def customer_last_name + params['lastname'] + end + + # Full address of the customer + def customer_address + { :address1 => params['address1'], :address2 => params['address2'], + :city => params['city'], :state => params['state'], + :country => params['country'], :zipcode => params['zipcode'] } + end + + def user_defined + return @user_defined if @user_defined + @user_defined = [] + 10.times{ |i| @user_defined.push( params[ "udf#{i+1}" ] ) } + @user_defined + end + + def checksum + params['hash'] + end + + def message + @message || params['error'] + end + + def acknowledge + checksum_ok? + end + + def checksum_ok? + fields = user_defined.dup.push( customer_email, customer_first_name, product_info, gross, invoice, :reverse => true ) + fields.unshift( transaction_status ) + unless PayuIn.checksum(@merchant_id, @secret_key, *fields ) == checksum + @message = 'Return checksum not matching the data provided' + return false + end + true + end + + end + end + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/return.rb new file mode 100755 index 000000000..c7a6d25c5 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/payu_in/return.rb @@ -0,0 +1,53 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module PayuIn + class Return < ActiveMerchant::Billing::Integrations::Return + + def initialize(query_string, options = {}) + super + @notification = Notification.new(query_string, options) + end + + # PayU Transaction Id + # + def transaction_id + @notification.transaction_id + end + + # Returns the status of the transaction as a string + # The status can be one of the following + # + # invalid - transaction id not present + # tampered - checksum does not mismatch + # mismatch - order id mismatch + # success - transaction success + # pending - transaction pending + # failure - transaction failure + # + # payu does not put the discount field in the checksum + # it can be easily forged by the attacker without detection + # + def status( order_id, order_amount ) + if @notification.invoice_ok?( order_id ) && @notification.amount_ok?( BigDecimal.new(order_amount) ) + @notification.status + else + 'mismatch' + end + end + + # check success of the transaction + # check order_id and + def success? + status( @params['txnid'], @params['amount'] ) == 'success' + end + + def message + @notification.message + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay.rb new file mode 100644 index 000000000..4973a9c96 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay.rb @@ -0,0 +1,31 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Pxpay + autoload :Helper, 'active_merchant/billing/integrations/pxpay/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/pxpay/notification.rb' + autoload :Return, 'active_merchant/billing/integrations/pxpay/return.rb' + + TOKEN_URL = 'https://sec.paymentexpress.com/pxpay/pxaccess.aspx' + + LIVE_URL = 'https://sec.paymentexpress.com/pxpay/pxpay.aspx' + + def self.token_url + TOKEN_URL + end + + def self.service_url + LIVE_URL + end + + def self.notification(post, options={}) + Notification.new(post, options) + end + + def self.return(query_string, options={}) + Return.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/helper.rb new file mode 100644 index 000000000..62214eccd --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/helper.rb @@ -0,0 +1,111 @@ +require 'active_support/core_ext/float/rounding.rb' # Float#round(precision) + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Pxpay + # An example. Note the username as a parameter and transaction key you + # will want to use later. The amount that you pass in will be *rounded*, + # so preferably pass in X.2 decimal so that no rounding occurs. You need + # to set :credential2 to your PxPay secret key. + # + # PxPay accounts have Failproof Notification enabled by default which means + # in addition to the user being redirected to your return_url, the return_url will + # be accessed by the PxPay servers directly, immediately after transaction success. + # + # payment_service_for('order_id', 'pxpay_user_ID', :service => :pxpay, + # :amount => 157.0, :currency => 'USD', :credential2 => 'pxpay_key') do |service| + # + # service.customer :email => 'customer@email.com' + # + # service.description 'Order 123 for MyStore' + # + # # Must specify both a return_url or PxPay will show an error instead of + # # capturing credit card details. + # + # service.return_url "http://t/pxpay/payment_received_notification_sub_step" + # + # # These fields will be copied verbatim to the Notification + # service.custom1 'custom text 1' + # service.custom2 '' + # service.custom3 '' + # # See the helper.rb file for various custom fields + # end + + class Helper < ActiveMerchant::Billing::Integrations::Helper + include PostsData + mapping :account, 'PxPayUserId' + mapping :credential2, 'PxPayKey' + mapping :currency, 'CurrencyInput' + mapping :description, 'MerchantReference' + mapping :order, 'TxnId' + mapping :customer, :email => 'EmailAddress' + + mapping :custom1, 'TxnData1' + mapping :custom2, 'TxnData2' + mapping :custom3, 'TxnData3' + + def initialize(order, account, options = {}) + super + add_field 'AmountInput', "%.2f" % options[:amount].to_f.round(2) + add_field 'EnableAddBillCard', '0' + add_field 'TxnType', 'Purchase' + end + + def return_url(url) + add_field 'UrlSuccess', url + add_field 'UrlFail', url + end + + def form_fields + # if either return URLs are blank PxPay will generate a token but redirect user to error page. + raise "error - must specify return_url" if @fields['UrlSuccess'].blank? + raise "error - must specify cancel_return_url" if @fields['UrlFail'].blank? + + result = request_secure_redirect + raise "error - failed to get token - message was #{result[:redirect]}" unless result[:valid] == "1" + + url = URI.parse(result[:redirect]) + + CGI.parse(url.query) + end + + def form_method + "GET" + end + + private + def generate_request + xml = REXML::Document.new + root = xml.add_element('GenerateRequest') + + @fields.each do | k, v | + v = v.slice(0, 50) if k == "MerchantReference" + root.add_element(k).text = v + end + + xml.to_s + end + + def request_secure_redirect + request = generate_request + + response = ssl_post(Pxpay.token_url, request) + xml = REXML::Document.new(response) + root = REXML::XPath.first(xml, "//Request") + valid = root.attributes["valid"] + redirect = root.elements["URI"].text + + # example positive response: + # <Request valid="1"><URI>https://sec.paymentexpress.com/pxpay/pxpay.aspx?userid=PxpayUser&amp;request=REQUEST_TOKEN</URI></Request> + + # example negative response: + # <Request valid="0"><URI>Invalid TxnType</URI></Request> + + {:valid => valid, :redirect => redirect} + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/notification.rb new file mode 100644 index 000000000..14c075f28 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/notification.rb @@ -0,0 +1,157 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + module Pxpay + class Notification < ActiveMerchant::Billing::Integrations::Notification + include PostsData + include RequiresParameters + + def initialize(query_string, options={}) + # PxPay appends ?result=...&userid=... to whatever return_url was specified, even if that URL ended with a ?query. + # So switch the first ? if present to a & + query_string[/\?/] = '&' if query_string[/\?/] + super + + @encrypted_params = @params + @params = {} + + requires! @encrypted_params, "result" + requires! @options, :credential1, :credential2 + + decrypt_transaction_result(@encrypted_params["result"]) + end + + # was the notification a validly formed request? + def acknowledge + @valid == '1' + end + + def status + return 'Failed' unless success? + return 'Completed' if complete? + 'Error' + end + + def complete? + @params['TxnType'] == 'Purchase' && success? + end + + def cancelled? + !success? + end + + # for field definitions see + # http://www.paymentexpress.com/Technical_Resources/Ecommerce_Hosted/PxPay + + def success? + @params['Success'] == '1' + end + + def gross + @params['AmountSettlement'] + end + + def currency + @params['CurrencySettlement'] + end + + def account + @params['userid'] + end + + def item_id + @params['TxnId'] + end + + def currency_input + @params['CurrencyInput'] + end + + def auth_code + @params['AuthCode'] + end + + def card_type + @params['CardName'] + end + + def card_holder_name + @params['CardHolderName'] + end + + def card_number + @params['CardNumber'] + end + + def expiry_date + @params['DateExpiry'] + end + + def client_ip + @params['ClientInfo'] + end + + def order_id + item_id + end + + def payer_email + @params['EmailAddress'] + end + + def transaction_id + @params['DpsTxnRef'] + end + + def settlement_date + @params['DateSettlement'] + end + + # Indication of the uniqueness of a card number + def txn_mac + @params['TxnMac'] + end + + def message + @params['ResponseText'] + end + + def optional_data + [@params['TxnData1'],@fields['TxnData2'],@fields['TxnData3']] + end + + # When was this payment was received by the client. + def received_at + settlement_date + end + + # Was this a test transaction? + def test? + nil + end + + private + + def decrypt_transaction_result(encrypted_result) + request_xml = REXML::Document.new + root = request_xml.add_element('ProcessResponse') + + root.add_element('PxPayUserId').text = @options[:credential1] + root.add_element('PxPayKey').text = @options[:credential2] + root.add_element('Response').text = encrypted_result + + @raw = ssl_post(Pxpay.token_url, request_xml.to_s) + + response_xml = REXML::Document.new(@raw) + root = REXML::XPath.first(response_xml) + @valid = root.attributes["valid"] + @params = {} + root.elements.each { |e| @params[e.name] = e.text } + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/return.rb new file mode 100644 index 000000000..39a546cf3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/pxpay/return.rb @@ -0,0 +1,25 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Pxpay + class Return < ActiveMerchant::Billing::Integrations::Return + def initialize(query_string, options={}) + @notification = Notification.new(query_string, options) + end + + def success? + @notification && @notification.complete? + end + + def cancelled? + @notification && @notification.cancelled? + end + + def message + @notification.message + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay.rb new file mode 100644 index 000000000..74884f8e8 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay.rb @@ -0,0 +1,21 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Quickpay + autoload :Helper, File.dirname(__FILE__) + '/quickpay/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/quickpay/notification.rb' + + mattr_accessor :service_url + self.service_url = 'https://secure.quickpay.dk/form/' + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/helper.rb new file mode 100644 index 000000000..8e3f61eb1 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/helper.rb @@ -0,0 +1,74 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Quickpay + class Helper < ActiveMerchant::Billing::Integrations::Helper + + def initialize(order, account, options = {}) + md5secret options.delete(:credential2) + super + add_field('protocol', '6') + add_field('msgtype', 'authorize') + add_field('language', 'da') + add_field('autocapture', 0) + add_field('testmode', test? ? 1 : 0) + add_field('ordernumber', format_order_number(order)) + end + + def md5secret(value) + @md5secret = value + end + + def form_fields + @fields.merge('md5check' => generate_md5check) + end + + def generate_md5string + MD5_CHECK_FIELDS.map {|key| @fields[key.to_s]} * "" + @md5secret + end + + def generate_md5check + Digest::MD5.hexdigest(generate_md5string) + end + + # Limited to 20 digits max + def format_order_number(number) + number.to_s.gsub(/[^\w]/, '').rjust(4, "0")[0...20] + end + + MD5_CHECK_FIELDS = [ + :protocol, :msgtype, :merchant, :language, :ordernumber, + :amount, :currency, :continueurl, :cancelurl, :callbackurl, + :autocapture, :cardtypelock, :description, :ipaddress, :testmode, + :deadline, :cardhash + ] + + mapping :protocol, 'protocol' + mapping :msgtype, 'msgtype' + mapping :account, 'merchant' + mapping :language, 'language' + mapping :amount, 'amount' + mapping :currency, 'currency' + + mapping :return_url, 'continueurl' + mapping :cancel_return_url, 'cancelurl' + mapping :notify_url, 'callbackurl' + + mapping :autocapture, 'autocapture' + mapping :cardtypelock, 'cardtypelock' + + mapping :description, 'description' + mapping :ipaddress, 'ipaddress' + mapping :testmode, 'testmode' + mapping :deadline, 'deadline' + mapping :cardhash, 'cardhash' + + mapping :customer, '' + mapping :billing_address, {} + mapping :tax, '' + mapping :shipping, '' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/notification.rb new file mode 100644 index 000000000..0d5da68a9 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/quickpay/notification.rb @@ -0,0 +1,137 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Quickpay + class Notification < ActiveMerchant::Billing::Integrations::Notification + def complete? + status == '000' + end + + def item_id + params['ordernumber'] + end + + def transaction_id + params['transaction'] + end + + def received_at + time = params['time'] + # If time only contains 12 integers then it's pre v5 format + time = "20#{params['time']}" if /[0-9]{12}/.match(params['time']) + Time.parse(time) + end + + def gross + "%.2f" % (gross_cents / 100.0) + end + + def gross_cents + params['amount'].to_i + end + + def status + params['qpstat'] + end + + def currency + params['currency'] + end + + # Provide access to raw fields from quickpay + %w( + msgtype + ordernumber + state + chstat + chstatmsg + qpstat + qpstatmsg + merchant + merchantemail + cardtype + cardnumber + cardhash + cardexpire + splitpayment + fraudprobability + fraudremarks + fraudreport + fee + ).each do |attr| + define_method(attr) do + params[attr] + end + end + + MD5_CHECK_FIELDS = [ + :msgtype, + :ordernumber, + :amount, + :currency, + :time, + :state, + :qpstat, + :qpstatmsg, + :chstat, + :chstatmsg, + :merchant, + :merchantemail, + :transaction, + :cardtype, + :cardnumber, + :cardhash, + :cardexpire, + :splitpayment, + :fraudprobability, + :fraudremarks, + :fraudreport, + :fee + ] + + def generate_md5string + MD5_CHECK_FIELDS.map { |key| params[key.to_s] } * "" + @options[:credential2].to_s + end + + def generate_md5check + Digest::MD5.hexdigest(generate_md5string) + end + + # Quickpay doesn't do acknowledgements of callback notifications + # Instead it uses and MD5 hash of all parameters + def acknowledge + generate_md5check == params['md5check'] + end + + # Take the posted data and move the relevant data into a hash + def parse(post) + # 30 + 12 + #------------------------------8a827a0e6829 + #Content-Disposition: form-data; name="msgtype" + # + #subscribe + #------------------------------8a827a0e6829 + #Content-Disposition: form-data; name="ordernumber" + # + #BILP94406 + + if post =~ /-{20,40}\w{6,24}/ + @raw = post.to_s + post.split(/-{20,40}\w{6,24}[\n\r]*/m).each do |part| + part.scan(/([^\n\r]+)[\n\r]+([^\n\r]*)/m) do |header, value| + if header.match(/name=["'](.*)["']/) + params[$1] = value.strip + end + end + end + else + super + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney.rb new file mode 100644 index 000000000..ff7c73a91 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney.rb @@ -0,0 +1,17 @@ +require File.dirname(__FILE__) + '/rbkmoney/helper.rb' +require File.dirname(__FILE__) + '/rbkmoney/notification.rb' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Rbkmoney + mattr_accessor :service_url + self.service_url = 'https://rbkmoney.ru/acceptpurchase.aspx' + + def self.notification(*args) + Notification.new(*args) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/helper.rb new file mode 100644 index 000000000..4d79584b2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/helper.rb @@ -0,0 +1,23 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Rbkmoney + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'eshopId' + mapping :amount, 'recipientAmount' + + # NOTE: rbkmoney uses outdated currency code 'RUR' + mapping :currency, 'recipientCurrency' + + mapping :order, 'orderId' + + mapping :customer, :email => 'user_email' + + mapping :credential2, 'serviceName' + mapping :credential3, 'successUrl' + mapping :credential4, 'failUrl' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/notification.rb new file mode 100644 index 000000000..a4ce79d79 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/rbkmoney/notification.rb @@ -0,0 +1,91 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Rbkmoney + class Notification < ActiveMerchant::Billing::Integrations::Notification + %w( + eshopId + paymentId + orderId + eshopAccount + serviceName + recipientAmount + recipientCurrency + paymentStatus + userName + userEmail + paymentData + secretKey + hash + ).each do |param_name| + define_method(param_name.underscore){ params[param_name] } + end + + def complete? + (payment_status == '5') + end + + def test? + false + end + + def status + case payment_status + when '3' + 'pending' + when '5' + 'completed' + else 'unknown' + end + end + + def user_fields + params.inject({}) do |fields, (k,v)| + if /\AuserField_[\d+]\z/.match(k) + fields[k] = v + end + fields + end + end + + alias_method :client_id, :eshop_id + alias_method :item_id, :order_id + alias_method :transaction_id, :payment_id + alias_method :received_at, :payment_data + alias_method :payer_email, :user_email + alias_method :gross, :recipient_amount + alias_method :currency, :recipient_currency + + def acknowledge + string = [ + eshop_id, + order_id, + service_name, + eshop_account, + recipient_amount, + recipient_currency, + payment_status, + user_name, + user_email, + payment_data, + @options[:secret] + ].join '::' + + signature = case hash.to_s.length + when 32 + Digest::MD5.hexdigest(string) + when 128 + Digest::SHA512.hexdigest(string) + else + return false + end + + signature == hash + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/return.rb new file mode 100644 index 000000000..579f5d10c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/return.rb @@ -0,0 +1,42 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + class Return + attr_accessor :params + attr_reader :notification + + def initialize(query_string, options = {}) + @params = parse(query_string) + @options = options + end + + # Successful by default. Overridden in the child class + def success? + true + end + + # Not cancelled by default. Overridden in the child class. + def cancelled? + false + end + + def message + + end + + def parse(query_string) + return {} if query_string.blank? + + query_string.split('&').inject({}) do |memo, chunk| + next if chunk.empty? + key, value = chunk.split('=', 2) + next if key.empty? + value = value.nil? ? nil : CGI.unescape(value) + memo[CGI.unescape(key)] = value + memo + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa.rb new file mode 100644 index 000000000..1b27ffed2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa.rb @@ -0,0 +1,49 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + # Documentation: http://robokassa.ru/Doc/En/Interface.aspx + module Robokassa + autoload :Helper, File.dirname(__FILE__) + '/robokassa/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/robokassa/notification.rb' + autoload :Return, File.dirname(__FILE__) + '/robokassa/return.rb' + autoload :Common, File.dirname(__FILE__) + '/robokassa/common.rb' + + # Overwrite this if you want to change the Robokassa test url + mattr_accessor :test_url + self.test_url = 'http://test.robokassa.ru/Index.aspx' + + # Overwrite this if you want to change the Robokassa production url + mattr_accessor :production_url + self.production_url = 'https://merchant.roboxchange.com/Index.aspx' + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'SignatureValue' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + + def self.return(query_string) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/common.rb new file mode 100644 index 000000000..6c8a79146 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/common.rb @@ -0,0 +1,19 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Robokassa + module Common + def generate_signature_string + custom_param_keys = params.keys.select {|key| key =~ /^shp/}.sort + custom_params = custom_param_keys.map {|key| "#{key}=#{params[key]}"} + [main_params, secret, custom_params.compact].flatten.join(':') + end + + def generate_signature + Digest::MD5.hexdigest(generate_signature_string) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/helper.rb new file mode 100644 index 000000000..58102958c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/helper.rb @@ -0,0 +1,50 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Robokassa + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Common + + def initialize(order, account, options = {}) + @md5secret = options.delete(:secret) + super + end + + def form_fields + @fields.merge(ActiveMerchant::Billing::Integrations::Robokassa.signature_parameter_name => generate_signature) + end + + def main_params + [:account, :amount, :order].map {|key| @fields[mappings[key]]} + end + + def params + @fields + end + + def secret + @md5secret + end + + def method_missing(method_id, *args) + method_id = method_id.to_s.gsub(/=$/, '') + + # support for robokassa custom parameters + if method_id =~ /^shp/ + add_field method_id, args.last + end + + super + end + + mapping :account, 'MrchLogin' + mapping :amount, 'OutSum' + mapping :currency, 'IncCurrLabel' + mapping :order, 'InvId' + mapping :description, 'Desc' + mapping :email, 'Email' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/notification.rb new file mode 100644 index 000000000..bc4de6e7f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/notification.rb @@ -0,0 +1,55 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Robokassa + class Notification < ActiveMerchant::Billing::Integrations::Notification + include Common + + def self.recognizes?(params) + params.has_key?('InvId') && params.has_key?('OutSum') + end + + def complete? + true + end + + def amount + BigDecimal.new(gross) + end + + def item_id + params['InvId'] + end + + def security_key + params[ActiveMerchant::Billing::Integrations::Robokassa.signature_parameter_name].to_s.downcase + end + + def gross + params['OutSum'] + end + + def status + 'success' + end + + def secret + @options[:secret] + end + + def main_params + [gross, item_id] + end + + def acknowledge + security_key == generate_signature + end + + def success_response(*args) + "OK#{item_id}" + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/return.rb new file mode 100644 index 000000000..c9321433c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/robokassa/return.rb @@ -0,0 +1,17 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Robokassa + class Return < ActiveMerchant::Billing::Integrations::Return + def item_id + @params['InvId'] + end + + def amount + @params['OutSum'] + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form.rb new file mode 100644 index 000000000..48c092da7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form.rb @@ -0,0 +1,37 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module SagePayForm + autoload :Helper, File.dirname(__FILE__) + '/sage_pay_form/helper.rb' + autoload :Return, File.dirname(__FILE__) + '/sage_pay_form/return.rb' + autoload :Notification, File.dirname(__FILE__) + '/sage_pay_form/notification.rb' + autoload :Encryption, File.dirname(__FILE__) + '/sage_pay_form/encryption.rb' + + mattr_accessor :production_url + mattr_accessor :test_url + mattr_accessor :simulate_url + self.production_url = 'https://live.sagepay.com/gateway/service/vspform-register.vsp' + self.test_url = 'https://test.sagepay.com/gateway/service/vspform-register.vsp' + self.simulate_url = 'https://test.sagepay.com/Simulator/VSPFormGateway.asp' + + def self.return(query_string, options = {}) + Return.new(query_string, options) + end + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + when :simulate + self.simulate_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb new file mode 100644 index 000000000..9c933a427 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb @@ -0,0 +1,33 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module SagePayForm + module Encryption + def sage_encrypt(plaintext, key) + Base64.strict_encode64(sage_encrypt_xor(plaintext, key)) + end + + def sage_decrypt(ciphertext, key) + sage_encrypt_xor(Base64.decode64(ciphertext), key) + end + + def sage_encrypt_salt(min, max) + length = rand(max - min + 1) + min + SecureRandom.base64(length + 4)[0, length] + end + + private + + def sage_encrypt_xor(data, key) + raise 'No key provided' if key.blank? + + key *= (data.bytesize.to_f / key.bytesize.to_f).ceil + key = key[0, data.bytesize] + + data.bytes.zip(key.bytes).map { |b1, b2| (b1 ^ b2).chr }.join + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb new file mode 100644 index 000000000..b0295dbfc --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb @@ -0,0 +1,136 @@ +require 'uri' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module SagePayForm + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Encryption + + mapping :credential2, 'EncryptKey' + + mapping :account, 'Vendor' + mapping :amount, 'Amount' + mapping :currency, 'Currency' + + mapping :order, 'VendorTxCode' + + mapping :customer, + :first_name => 'BillingFirstnames', + :last_name => 'BillingSurname', + :email => 'CustomerEMail', + :phone => 'BillingPhone', + :send_email_confirmation => 'SendEmail' + + mapping :billing_address, + :city => 'BillingCity', + :address1 => 'BillingAddress1', + :address2 => 'BillingAddress2', + :state => 'BillingState', + :zip => 'BillingPostCode', + :country => 'BillingCountry' + + mapping :shipping_address, + :city => 'DeliveryCity', + :address1 => 'DeliveryAddress1', + :address2 => 'DeliveryAddress2', + :state => 'DeliveryState', + :zip => 'DeliveryPostCode', + :country => 'DeliveryCountry' + + mapping :return_url, 'SuccessURL' + mapping :description, 'Description' + + class_attribute :referrer_id + + def shipping_address(params = {}) + @shipping_address_set = true unless params.empty? + + params.each do |k, v| + field = mappings[:shipping_address][k] + add_field(field, v) unless field.nil? + end + end + + def map_billing_address_to_shipping_address + %w(City Address1 Address2 State PostCode Country).each do |field| + fields["Delivery#{field}"] = fields["Billing#{field}"] + end + end + + def form_fields + map_billing_address_to_shipping_address unless @shipping_address_set + + fields['DeliveryFirstnames'] ||= fields['BillingFirstnames'] + fields['DeliverySurname'] ||= fields['BillingSurname'] + + fields['FailureURL'] ||= fields['SuccessURL'] + + fields['BillingPostCode'] ||= "0000" + fields['DeliveryPostCode'] ||= "0000" + + crypt_skip = ['Vendor', 'EncryptKey', 'SendEmail'] + crypt_skip << 'BillingState' unless fields['BillingCountry'] == 'US' + crypt_skip << 'DeliveryState' unless fields['DeliveryCountry'] == 'US' + crypt_skip << 'CustomerEMail' unless fields['SendEmail'] + key = fields['EncryptKey'] + @crypt ||= create_crypt_field(fields.except(*crypt_skip), key) + + result = { + 'VPSProtocol' => '2.23', + 'TxType' => 'PAYMENT', + 'Vendor' => @fields['Vendor'], + 'Crypt' => @crypt + } + result['ReferrerID'] = referrer_id if referrer_id + result + end + + private + + def create_crypt_field(fields, key) + parts = fields.map { |k, v| "#{k}=#{sanitize(k, v)}" unless v.nil? }.compact.shuffle + parts.unshift(sage_encrypt_salt(key.length, key.length * 2)) + sage_encrypt(parts.join('&'), key) + end + + def sanitize(key, value) + reject = exact = nil + + case key + when /URL$/ + # allow all + when 'VendorTxCode' + reject = /[^A-Za-z0-9{}._-]+/ + when /[Nn]ames?$/ + reject = %r{[^[:alpha:] /\\.'-]+} + when /(?:Address[12]|City)$/ + reject = %r{[^[:alnum:] +'/\\:,.\n()-]+} + when /PostCode$/ + reject = /[^A-Za-z0-9 -]+/ + when /Phone$/ + reject = /[^0-9A-Za-z+ ()-]+/ + when 'Currency' + exact = /^[A-Z]{3}$/ + when /State$/ + exact = /^[A-Z]{2}$/ + when 'Description' + value = value[0...100] + else + reject = /&+/ + end + + if exact + raise ArgumentError, "Invalid value for #{key}: #{value.inspect}" unless value =~ exact + value + elsif reject + value.gsub(reject, ' ') + else + value + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb new file mode 100644 index 000000000..f9dc672d7 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb @@ -0,0 +1,210 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module SagePayForm + class Notification < ActiveMerchant::Billing::Integrations::Notification + class CryptError < StandardError; end + + include Encryption + + def initialize(post_data, options) + super + load_crypt_params(params['crypt'], options[:credential2]) + end + + # Was the transaction complete? + def complete? + status_code == 'OK' + end + + # Was the transaction cancelled? + # Unfortunately, we can't distinguish "user abort" from "idle too long". + def cancelled? + status_code == 'ABORT' + end + + # Text version of #complete?, since we don't support Pending. + def status + complete? ? 'Completed' : 'Failed' + end + + # Status of transaction. List of possible values: + # <tt>OK</tt>:: Transaction completed successfully. + # <tt>NOTAUTHED</tt>:: Incorrect card details / insufficient funds. + # <tt>MALFORMED</tt>:: Invalid input data. + # <tt>INVALID</tt>:: Valid input data, but some fields are incorrect. + # <tt>ABORT</tt>:: User hit cancel button or went idle for 15+ minutes. + # <tt>REJECTED</tt>:: Rejected by account fraud screening rules. + # <tt>AUTHENTICATED</tt>:: Authenticated card details secured at SagePay. + # <tt>REGISTERED</tt>:: Non-authenticated card details secured at SagePay. + # <tt>ERROR</tt>:: Problem internal to SagePay. + def status_code + params['Status'] + end + + # Check this if #completed? is false. + def message + params['StatusDetail'] + end + + # Vendor-supplied code (:order mapping). + def item_id + params['VendorTxCode'] + end + + # Internal SagePay code, typically "{LONG-UUID}". + def transaction_id + params['VPSTxId'] + end + + # Authorization number (only if #completed?). + def auth_id + params['TxAuthNo'] + end + + # Total amount (no fees). + def gross + params['Amount'] + end + + # AVS and CV2 check results. Possible values: + # <tt>ALL MATCH</tt>:: + # <tt>SECURITY CODE MATCH ONLY</tt>:: + # <tt>ADDRESS MATCH ONLY</tt>:: + # <tt>NO DATA MATCHES</tt>:: + # <tt>DATA NOT CHECKED</tt>:: + def avs_cv2_result + params['AVSCV2'] + end + + # Numeric address check. Possible values: + # <tt>NOTPROVIDED</tt>:: + # <tt>NOTCHECKED</tt>:: + # <tt>MATCHED</tt>:: + # <tt>NOTMATCHED</tt>:: + def address_result + params['AddressResult'] + end + + # Post code check. Possible values: + # <tt>NOTPROVIDED</tt>:: + # <tt>NOTCHECKED</tt>:: + # <tt>MATCHED</tt>:: + # <tt>NOTMATCHED</tt>:: + def post_code_result + params['PostCodeResult'] + end + + # CV2 code check. Possible values: + # <tt>NOTPROVIDED</tt>:: + # <tt>NOTCHECKED</tt>:: + # <tt>MATCHED</tt>:: + # <tt>NOTMATCHED</tt>:: + def cv2_result + params['CV2Result'] + end + + # Was the Gift Aid box checked? + def gift_aid? + params['GiftAid'] == '1' + end + + # Result of 3D Secure checks. Possible values: + # <tt>OK</tt>:: Authenticated correctly. + # <tt>NOTCHECKED</tt>:: Authentication not performed. + # <tt>NOTAVAILABLE</tt>:: Card not auth-capable, or auth is otherwise impossible. + # <tt>NOTAUTHED</tt>:: User failed authentication. + # <tt>INCOMPLETE</tt>:: Authentication unable to complete. + # <tt>ERROR</tt>:: Unable to attempt authentication due to data / service errors. + def buyer_auth_result + params['3DSecureStatus'] + end + + # Encoded 3D Secure result code. + def buyer_auth_result_code + params['CAVV'] + end + + # Address confirmation status. PayPal only. Possible values: + # <tt>NONE</tt>:: + # <tt>CONFIRMED</tt>:: + # <tt>UNCONFIRMED</tt>:: + def address_status + params['AddressStatus'] + end + + # Payer verification. Undocumented. + def payer_verified? + params['PayerStatus'] == 'VERIFIED' + end + + # Credit card type. Possible values: + # <tt>VISA</tt>:: Visa + # <tt>MC</tt>:: MasterCard + # <tt>DELTA</tt>:: Delta + # <tt>SOLO</tt>:: Solo + # <tt>MAESTRO</tt>:: Maestro (UK and International) + # <tt>UKE</tt>:: Visa Electron + # <tt>AMEX</tt>:: American Express + # <tt>DC</tt>:: Diners Club + # <tt>JCB</tt>:: JCB + # <tt>LASER</tt>:: Laser + # <tt>PAYPAL</tt>:: PayPal + def credit_card_type + params['CardType'] + end + + # Last four digits of credit card. + def credit_card_last_4_digits + params['Last4Digits'] + end + + # Used by composition methods, but not supplied by SagePay. + def currency + nil + end + + def test? + false + end + + def acknowledge + true + end + + private + + def load_crypt_params(crypt, key) + raise MissingCryptData if crypt.blank? + raise MissingCryptKey if key.blank? + + crypt_data = sage_decrypt(crypt.gsub(' ', '+'), key) + raise InvalidCryptData unless crypt_data =~ /(^|&)Status=/ + + params.clear + parse(crypt_data) + end + + class MissingCryptKey < CryptError + def message + 'No merchant decryption key supplied' + end + end + class MissingCryptData < CryptError + def message + 'No data received from SagePay' + end + end + class InvalidCryptData < CryptError + def message + 'Invalid data received from SagePay' + end + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/return.rb new file mode 100644 index 000000000..b2a2432ea --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/sage_pay_form/return.rb @@ -0,0 +1,31 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module SagePayForm + class Return < ActiveMerchant::Billing::Integrations::Return + + def initialize(query_string, options) + begin + @notification = Notification.new(query_string, options) + rescue Notification::CryptError => e + @message = e.message + end + end + + def success? + @notification && @notification.complete? + end + + def cancelled? + @notification && @notification.cancelled? + end + + def message + @message || @notification.message + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout.rb new file mode 100644 index 000000000..e5733aad3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout.rb @@ -0,0 +1,44 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module TwoCheckout + autoload 'Helper', File.dirname(__FILE__) + '/two_checkout/helper' + autoload 'Return', File.dirname(__FILE__) + '/two_checkout/return' + autoload 'Notification', File.dirname(__FILE__) + '/two_checkout/notification' + + mattr_accessor :payment_routine + self.payment_routine = :single_page + + def self.service_url + case self.payment_routine + when :multi_page + 'https://www.2checkout.com/checkout/purchase' + when :single_page + 'https://www.2checkout.com/checkout/spurchase' + else + raise StandardError, "Integration payment routine set to an invalid value: #{self.payment_routine}" + end + end + + def self.service_url=(service_url) + # Note: do not use this method, it is here for backward compatibility + # Use the payment_routine method to change service_url + if service_url =~ /spurchase/ + self.payment_routine = :single_page + else + self.payment_routine = :multi_page + end + end + + + def self.notification(post, options = {}) + Notification.new(post) + end + + def self.return(query_string, options = {}) + Return.new(query_string) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/helper.rb new file mode 100644 index 000000000..077b9ae42 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/helper.rb @@ -0,0 +1,91 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module TwoCheckout + class Helper < ActiveMerchant::Billing::Integrations::Helper + def initialize(order, account, options = {}) + super + add_field('fixed', 'Y') + + if ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] + add_field('demo', 'Y') + end + end + + # The 2checkout vendor account number + mapping :account, 'sid' + + # The total amount to be billed, in decimal form, without a currency symbol. (8 characters, decimal, 2 characters: Example: 99999999.99) + mapping :amount, 'total' + + # Pass your order id if you are using Third Part Cart Parameters. (128 characters max) + mapping :order, 'cart_order_id' + + # Pass your order id if you are using the Pass Through Products Parameters. (50 characters max) + mapping :invoice, 'merchant_order_id' + + # Left here for backward compatibility, do not use. The line_item method will add automatically. + mapping :mode, 'mode' + + mapping :customer, :email => 'email', + :phone => 'phone' + + mapping :billing_address, :city => 'city', + :address1 => 'street_address', + :address2 => 'street_address2', + :state => 'state', + :zip => 'zip', + :country => 'country' + + mapping :shipping_address, :city => 'ship_city', + :address1 => 'ship_street_address', + :state => 'ship_state', + :zip => 'ship_zip', + :country => 'ship_country' + + # Does nothing, since we've disabled the Continue Shopping button by using the fixed = Y field + mapping :return_url, 'return_url' + + # Approved URL path + mapping :notification_url, 'x_receipt_link_url' + + def customer(params = {}) + add_field(mappings[:customer][:email], params[:email]) + add_field(mappings[:customer][:phone], params[:phone]) + add_field('card_holder_name', "#{params[:first_name]} #{params[:last_name]}") + end + + # Uses Pass Through Product Parameters to pass in lineitems. + # (must mark tanigble sales as shipped to settle the transaction) + def line_item(params = {}) + add_field('mode', '2CO') + (max_existing_line_item_id = form_fields.keys.map do |key| + i = key.to_s[/^li_(\d+)_/, 1] + (i && i.to_i) + end.compact.max || 0) + + line_item_id = max_existing_line_item_id + 1 + params.each do |key, value| + add_field("li_#{line_item_id}_#{key}", value) + end + end + + # Uses Third Party Cart parameter set to pass in lineitem details. + # (sales settle automatically) + def auto_settle(params = {}) + add_field('id_type', '1') + (max_existing_line_item_id = form_fields.keys.map do |key| + i = key.to_s[/^c_prod_(\d+)/, 1] + (i && i.to_i) + end.compact.max || 0) + + line_item_id = max_existing_line_item_id + 1 + params.each do |key, value| + add_field("c_#{key}_#{line_item_id}", value) + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/notification.rb new file mode 100644 index 000000000..8ba211b34 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/notification.rb @@ -0,0 +1,139 @@ +require 'net/http' +require 'base64' +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module TwoCheckout + class Notification < ActiveMerchant::Billing::Integrations::Notification + # card_holder_name - Provides the customer’s name. + # city - Provides the customer’s city. + # country - Provides the customer’s country. + # credit_card_processed - This parameter will always be passed back as Y. + # demo - Defines if an order was live, or if the order was a demo order. If the order was a demo, the MD5 hash will fail. + # email - Provides the email address the customer provided when placing the order. + # fixed - This parameter will only be passed back if it was passed into the purchase routine. + # ip_country - Provides the customer’s IP location. + # key - An MD5 hash used to confirm the validity of a sale. + # lang - Customer language + # merchant_order_id - The order ID you had assigned to the order. + # order_number - The 2Checkout order number associated with the order. + # invoice_id - The 2Checkout invoice number. + # pay_method - Provides seller with the customer’s payment method. CC for Credit Card, PPI for PayPal. + # phone - Provides the phone number the customer provided when placing the order. + # ship_name - Provides the ship to name for the order. + # ship_street_address - Provides ship to address. + # ship_street_address2 - Provides more detailed shipping address if this information was provided by the customer. + # ship_city - Provides ship to city. + # ship_state - Provides ship to state. + # ship_zip - Ship Zip + + # Pass Through Products Only + # li_#_name - Name of the corresponding lineitem. + # li_#_quantity - Quantity of the corresponding lineitem. + # li_#_price - Price of the corresponding lineitem. + # li_#_tangible - Specifies if the corresponding li_#_type is a tangible or intangible. ‘Y’ OR ‘N’ + # li_#_product_id - ID of the corresponding lineitem. + # li_#_product_description - Description of the corresponding lineitem. + # li_#_recurrence - # WEEK | MONTH | YEAR – always singular. + # li_#_duration - Forever or # WEEK | MONTH | YEAR – always singular, defaults to Forever. + # li_#_startup_fee - Amount in account pricing currency. + # li_#_option_#_name - Name of option. 64 characters max – cannot include '<' or '>'. + # li_#_option_#_value - Name of option. 64 characters max – cannot include '<' or '>'. + # li_#_option_#_surcharge - Amount in account pricing currency. + + #Third Party Cart Only + # cart_order_id - The order ID you had assigned to the order. + + # Allow seller to define default currency (should match 2Checkout account pricing currency) + def currency + 'USD' + end + + def complete? + status == 'Completed' + end + + # Third Party Cart parameters will return 'card_order_id' + # Pass Through Product parameters will only return 'merchant_order_id' + def item_id + if (params['cart_order_id'].nil?) + params['merchant_order_id'] + else + params['cart_order_id'] + end + end + + # 2Checkout Sale ID + def transaction_id + params['order_number'] + end + + def received_at + params[''] + end + + #Customer Email + def payer_email + params['email'] + end + + def receiver_email + params[''] + end + + # The MD5 Hash + def security_key + params['key'] + end + + # The money amount we received in X.2 decimal. + def gross + params['total'] + end + + # Was this a test transaction? # Use the hash + # Please note 2Checkout forces the order number computed in the hash to '1' on demo sales. + def test? + params['demo'] == 'Y' + end + + # 2Checkout only returns 'Y' for this parameter. If the sale is not authorized, no passback occurs. + def status + case params['credit_card_processed'] + when 'Y' + 'Completed' + else + 'Failed' + end + end + + # Secret Word defined in 2Checkout account + def secret + @options[:credential2] + end + + # Checks against MD5 Hash + def acknowledge + return false if security_key.blank? + + Digest::MD5.hexdigest("#{secret}#{params['sid']}#{transaction_id}#{gross}").upcase == security_key.upcase + end + + private + + # Parses Header Redirect Query String + def parse(post) + @raw = post.to_s + for line in @raw.split('&') + key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten + params[key] = CGI.unescape(value || '') + end + end + + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/return.rb new file mode 100644 index 000000000..327d1a319 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/two_checkout/return.rb @@ -0,0 +1,17 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module TwoCheckout + class Return < ActiveMerchant::Billing::Integrations::Return + def success? + params['credit_card_processed'] == 'Y' + end + + def message + + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor.rb new file mode 100644 index 000000000..20a5a8ca3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor.rb @@ -0,0 +1,33 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Valitor + autoload :Return, 'active_merchant/billing/integrations/valitor/return.rb' + autoload :Helper, 'active_merchant/billing/integrations/valitor/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/valitor/notification.rb' + + mattr_accessor :test_url + self.test_url = 'https://testvefverslun.valitor.is/1_1/' + + mattr_accessor :production_url + self.production_url = 'https://vefverslun.valitor.is/1_1/' + + def self.test? + (ActiveMerchant::Billing::Base.integration_mode == :test) + end + + def self.service_url + (test? ? test_url : production_url) + end + + def self.notification(params, options={}) + Notification.new(params, options.merge(:test => test?)) + end + + def self.return(query_string, options={}) + Return.new(query_string, options.merge(:test => test?)) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/helper.rb new file mode 100644 index 000000000..15630f659 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/helper.rb @@ -0,0 +1,86 @@ +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Valitor + class Helper < ActiveMerchant::Billing::Integrations::Helper + include RequiresParameters + + DEFAULT_SUCCESS_TEXT = "The transaction has been completed." + + def initialize(order, account, options={}) + options[:currency] ||= 'ISK' + super + add_field 'Adeinsheimild', '0' + add_field 'KaupandaUpplysingar', '0' + add_field 'SlokkvaHaus', '0' + @security_number = options[:credential2] + @amount = options[:amount] + @order = order + end + + mapping :account, 'VefverslunID' + mapping :currency, 'Gjaldmidill' + + mapping :order, 'Tilvisunarnumer' + + mapping :notify_url, 'SlodTokstAdGjaldfaeraServerSide' + mapping :return_url, 'SlodTokstAdGjaldfaera' + mapping :cancel_return_url, 'SlodNotandiHaettirVid' + + mapping :success_text, 'SlodTokstAdGjaldfaeraTexti' + + mapping :language, 'Lang' + + def authorize_only + add_field 'Adeinsheimild', '1' + end + + def collect_customer_info + add_field 'KaupandaUpplysingar', '1' + end + + def hide_header + add_field 'SlokkvaHaus', '1' + end + + def product(id, options={}) + raise ArgumentError, "Product id #{id} is not an integer between 1 and 500" unless id.to_i > 0 && id.to_i <= 500 + requires!(options, :amount, :description) + options.assert_valid_keys([:description, :quantity, :amount, :discount]) + + add_field("Vara_#{id}_Verd", format_amount(options[:amount])) + add_field("Vara_#{id}_Fjoldi", options[:quantity] || "1") + + add_field("Vara_#{id}_Lysing", options[:description]) if options[:description] + add_field("Vara_#{id}_Afslattur", options[:discount] || '0') + + @products ||= [] + @products << id.to_i + end + + def signature + raise ArgumentError, "Security number not set" unless @security_number + parts = [@security_number, @fields['Adeinsheimild']] + @products.sort.uniq.each do |id| + parts.concat(["Vara_#{id}_Fjoldi", "Vara_#{id}_Verd", "Vara_#{id}_Afslattur"].collect{|e| @fields[e]}) + end if @products + parts.concat(%w(VefverslunID Tilvisunarnumer SlodTokstAdGjaldfaera SlodTokstAdGjaldfaeraServerSide Gjaldmidill).collect{|e| @fields[e]}) + Digest::MD5.hexdigest(parts.compact.join('')) + end + + def form_fields + product(1, :amount => @amount, :description => @order) if Array(@products).empty? + @fields[mappings[:success_text]] ||= DEFAULT_SUCCESS_TEXT + @fields.merge('RafraenUndirskrift' => signature) + end + + def format_amount(amount) + amount.to_f.round + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/notification.rb new file mode 100644 index 000000000..6aa643941 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/notification.rb @@ -0,0 +1,13 @@ +require 'active_merchant/billing/integrations/valitor/response_fields' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Valitor + class Notification < ActiveMerchant::Billing::Integrations::Notification + include ResponseFields + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/response_fields.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/response_fields.rb new file mode 100644 index 000000000..9894644f5 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/response_fields.rb @@ -0,0 +1,97 @@ +require 'digest/md5' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Valitor + module ResponseFields + def success? + status == 'Completed' + end + alias :complete? :success? + + def test? + @options[:test] + end + + def item_id + params['Tilvisunarnumer'] + end + alias :order :item_id + + def transaction_id + params['VefverslunSalaID'] + end + + def currency + nil + end + + def status + "Completed" if acknowledge + end + + def received_at + Time.parse(params['Dagsetning'].to_s) + end + + def gross + "%0.2f" % params['Upphaed'].to_s + end + + def card_type + params['Kortategund'] + end + + def card_last_four + params['KortnumerSidustu'] + end + + def authorization_number + params['Heimildarnumer'] + end + + def transaction_number + params['Faerslunumer'] + end + + def customer_name + params['Nafn'] + end + + def customer_address + params['Heimilisfang'] + end + + def customer_zip + params['Postnumer'] + end + + def customer_city + params['Stadur'] + end + + def customer_country + params['Land'] + end + + def customer_email + params['Tolvupostfang'] + end + + def customer_comment + params['Athugasemdir'] + end + + def password + @options[:credential2] + end + + def acknowledge + password ? Digest::MD5.hexdigest("#{password}#{order}") == params['RafraenUndirskriftSvar'] : true + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/return.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/return.rb new file mode 100644 index 000000000..b81cdfae2 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/valitor/return.rb @@ -0,0 +1,13 @@ +require 'active_merchant/billing/integrations/valitor/response_fields' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Valitor + class Return < ActiveMerchant::Billing::Integrations::Return + include ResponseFields + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut.rb new file mode 100644 index 000000000..504148e17 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut.rb @@ -0,0 +1,20 @@ +require File.dirname(__FILE__) + '/verkkomaksut/helper.rb' +require File.dirname(__FILE__) + '/verkkomaksut/notification.rb' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + # Usage, see the blog post here: http://blog.kiskolabs.com/post/22374612968/understanding-active-merchant-integrations and E1 API documentation here: http://docs.verkkomaksut.fi/ + module Verkkomaksut + + mattr_accessor :service_url + self.service_url = 'https://payment.verkkomaksut.fi/' + + def self.notification(post) + Notification.new(post) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb new file mode 100644 index 000000000..130290730 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb @@ -0,0 +1,87 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Verkkomaksut + class Helper < ActiveMerchant::Billing::Integrations::Helper + + # Fetches the md5secret and adds MERCHANT_ID and API TYPE to the form + def initialize(order, account, options = {}) + md5secret options.delete(:credential2) + super + add_field("MERCHANT_ID", account) + add_field("TYPE", "E1") + end + + def md5secret(value) + @md5secret = value + end + + # Adds the AUTHCODE to the form + def form_fields + @fields.merge("AUTHCODE" => generate_md5string) + end + + # Calculates the AUTHCODE + def generate_md5string + fields = [@md5secret, @fields["MERCHANT_ID"], @fields["ORDER_NUMBER"], @fields["REFERENCE_NUMBER"], @fields["ORDER_DESCRIPTION"], @fields["CURRENCY"], @fields["RETURN_ADDRESS"], @fields["CANCEL_ADDRESS"], @fields["PENDING_ADDRESS"], + @fields["NOTIFY_ADDRESS"], @fields["TYPE"], @fields["CULTURE"], @fields["PRESELECTED_METHOD"], @fields["MODE"], @fields["VISIBLE_METHODS"], @fields["GROUP"], @fields["CONTACT_TELNO"], @fields["CONTACT_CELLNO"], + @fields["CONTACT_EMAIL"], @fields["CONTACT_FIRSTNAME"], @fields["CONTACT_LASTNAME"], @fields["CONTACT_COMPANY"], @fields["CONTACT_ADDR_STREET"], @fields["CONTACT_ADDR_ZIP"], @fields["CONTACT_ADDR_CITY"], @fields["CONTACT_ADDR_COUNTRY"], @fields["INCLUDE_VAT"], + @fields["ITEMS"]] + + (0..@fields["ITEMS"].to_i-1).each do |i| + fields += [@fields["ITEM_TITLE[#{i}]"], @fields["ITEM_NO[#{i}]"], @fields["ITEM_AMOUNT[#{i}]"], @fields["ITEM_PRICE[#{i}]"], @fields["ITEM_TAX[#{i}]"], @fields["ITEM_DISCOUNT[#{i}]"], @fields["ITEM_TYPE[#{i}]"]] + end + + fields = fields.join("|") + + return Digest::MD5.hexdigest(fields).upcase + end + + # Mappings + mapping :merchant_id, "MERCHANT_ID" + mapping :order, "ORDER_NUMBER" + mapping :reference_number, "REFERENCE_NUMBER" + mapping :customer, :first_name => "CONTACT_FIRSTNAME", + :last_name => "CONTACT_LASTNAME", + :email => "CONTACT_EMAIL", + :phone => "CONTACT_CELLNO", + :tellno => "CONTACT_TELLNO", + :company => "CONTACT_COMPANY" + + + mapping :billing_address, :city => "CONTACT_ADDR_CITY", + :address1 => "CONTACT_ADDR_STREET", + :address2 => "", + :state => "", + :zip => "CONTACT_ADDR_ZIP", + :country => "CONTACT_ADDR_COUNTRY" + + mapping :notify_url, "NOTIFY_ADDRESS" + mapping :currency, "CURRENCY" + mapping :return_url, "RETURN_ADDRESS" + mapping :cancel_return_url, "CANCEL_ADDRESS" + mapping :description, "ORDER_DESCRIPTION" + mapping :tax, "" + mapping :shipping, "" + mapping :include_vat, "INCLUDE_VAT" + mapping :pending_address, "PENDING_ADDRESS" + mapping :culture, "CULTURE" + mapping :items, "ITEMS" + mapping :preselected_method, "PRESELECTED_METHOD" + mapping :mode, "MODE" + mapping :visible_methods, "VISIBLE_METHODS" + mapping :group, "GROUP" + + (0..499.to_i).each do |i| + mapping "item_no_#{i}".to_sym, "ITEM_NO[#{i}]" + mapping "item_amount_#{i}".to_sym, "ITEM_AMOUNT[#{i}]" + mapping "item_price_#{i}".to_sym, "ITEM_PRICE[#{i}]" + mapping "item_tax_#{i}".to_sym, "ITEM_TAX[#{i}]" + mapping "item_discount_#{i}".to_sym, "ITEM_DISCOUNT[#{i}]" + mapping "item_type_#{i}".to_sym, "ITEM_TYPE[#{i}]" + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb new file mode 100644 index 000000000..466a28230 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb @@ -0,0 +1,59 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Verkkomaksut + class Notification < ActiveMerchant::Billing::Integrations::Notification + + # Is the payment complete or not. Verkkomaksut only has two statuses: random string or 0000000000 which means pending + def complete? + params['PAID'] != "0000000000" + end + + # Order id + def order_id + params['ORDER_NUMBER'] + end + + # Payment method used + def method + params['METHOD'] + end + + # When was this payment received by the client. + def received_at + params['TIMESTAMP'] + end + + # Security key got from Verkkomaksut + def security_key + params['RETURN_AUTHCODE'] + end + + # Another way of asking the payment status + def status + if complete? + "PAID" + else + "PENDING" + end + end + + # Acknowldges the payment. If the authcodes match, returns true. + def acknowledge(authcode) + return_authcode = [params["ORDER_NUMBER"], params["TIMESTAMP"], params["PAID"], params["METHOD"], authcode].join("|") + Digest::MD5.hexdigest(return_authcode).upcase == params["RETURN_AUTHCODE"] + end + private + + def parse(post) + post.each do |key, value| + params[key] = value + end + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay.rb new file mode 100644 index 000000000..06aca03c3 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay.rb @@ -0,0 +1,45 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + # Documentation: You will get it after registration steps here: + # http://reg.webpay.by/registration-form.php + module WebPay + autoload :Helper, File.dirname(__FILE__) + '/web_pay/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/web_pay/notification.rb' + autoload :Common, File.dirname(__FILE__) + '/web_pay/common.rb' + + # Overwrite this if you want to change the WebPay sandbox url + mattr_accessor :test_url + self.test_url = 'https://secure.sandbox.webpay.by:8843' + + # Overwrite this if you want to change the WebPay production url + mattr_accessor :production_url + self.production_url = 'https://secure.webpay.by' + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'wsb_signature' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/common.rb new file mode 100644 index 000000000..8a8191f2b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/common.rb @@ -0,0 +1,50 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module WebPay + module Common + def generate_signature(type) + string = case type + when :request + request_signature_string + when :notify + notify_signature_string + end + if type != :notify && @fields[mappings[:version]] == '2' + Digest::SHA1.hexdigest(string) + else + Digest::MD5.hexdigest(string) + end + end + + def request_signature_string + [ + @fields[mappings[:seed]], + @fields[mappings[:account]], + @fields[mappings[:order]], + @fields[mappings[:test]], + @fields[mappings[:currency]], + @fields[mappings[:amount]], + secret + ].join + end + + def notify_signature_string + [ + params['batch_timestamp'], + params['currency_id'], + params['amount'], + params['payment_method'], + params['order_id'], + params['site_order_id'], + params['transaction_id'], + params['payment_type'], + params['rrn'], + secret + ].join + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/helper.rb new file mode 100644 index 000000000..1082f4355 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/helper.rb @@ -0,0 +1,68 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module WebPay + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Common + + def initialize(order, account, options = {}) + @md5secret = options.delete(:secret) + @line_item_count = 0 + super + end + + def form_fields + @fields.merge(ActiveMerchant::Billing::Integrations::WebPay.signature_parameter_name => generate_signature(:request)) + end + + def params + @fields + end + + def secret + @md5secret + end + + def add_line_item(options) + options.each do |key, value| + add_field("wsb_invoice_item_#{key}[#{@line_item_count}]", value) + end + + @line_item_count += 1 + end + + def calculate_total + sum = 0 + + @line_item_count.times do |i| + sum += @fields["wsb_invoice_item_quantity[#{i}]"].to_i * @fields["wsb_invoice_item_price[#{i}]"].to_i + end + + sum + @fields[mappings[:tax]].to_i + @fields[mappings[:shipping_price]].to_i - @fields[mappings[:discount_price]].to_i + end + + mapping :scart, '*scart' + mapping :account, 'wsb_storeid' + mapping :store, 'wsb_store' + mapping :order, 'wsb_order_num' + mapping :currency, 'wsb_currency_id' + mapping :version, 'wsb_version' + mapping :language, 'wsb_language_id' + mapping :seed, 'wsb_seed' + mapping :success_url, 'wsb_return_url' + mapping :cancel_url, 'wsb_cancel_return_url' + mapping :notify_url, 'wsb_notify_url' + mapping :test, 'wsb_test' + mapping :tax, 'wsb_tax' + mapping :shipping_name, 'wsb_shipping_name' + mapping :shipping_price, 'wsb_shipping_price' + mapping :discount_name, 'wsb_discount_name' + mapping :discount_price, 'wsb_discount_price' + mapping :amount, 'wsb_total' + mapping :email, 'wsb_email' + mapping :phone, 'wsb_phone' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/notification.rb new file mode 100644 index 000000000..a0230ed66 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/web_pay/notification.rb @@ -0,0 +1,51 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module WebPay + class Notification < ActiveMerchant::Billing::Integrations::Notification + include Common + + def self.recognizes?(params) + params.has_key?('site_order_id') && params.has_key?('amount') + end + + def complete? + true + end + + def amount + BigDecimal.new(gross) + end + + def item_id + params['site_order_id'] + end + + def security_key + params[ActiveMerchant::Billing::Integrations::WebPay.signature_parameter_name] + end + + def gross + params['amount'] + end + + def status + 'success' + end + + def secret + @options[:secret] + end + + def acknowledge + (security_key == generate_signature(:notify)) + end + + def success_response(*args) + {:nothing => true} + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney.rb new file mode 100644 index 000000000..3b704846d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney.rb @@ -0,0 +1,43 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + # Documentation: + # http://wiki.webmoney.ru/projects/webmoney/wiki/Web_Merchant_Interface + module Webmoney + autoload :Helper, File.dirname(__FILE__) + '/webmoney/helper.rb' + autoload :Notification, File.dirname(__FILE__) + '/webmoney/notification.rb' + autoload :Return, File.dirname(__FILE__) + '/webmoney/return.rb' + autoload :Common, File.dirname(__FILE__) + '/webmoney/common.rb' + + mattr_accessor :test_url + self.test_url = "https://merchant.webmoney.ru/lmi/payment.asp" + + mattr_accessor :production_url + self.production_url = "https://merchant.webmoney.ru/lmi/payment.asp" + + mattr_accessor :signature_parameter_name + self.signature_parameter_name = 'LMI_HASH' + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.helper(order, account, options = {}) + Helper.new(order, account, options) + end + + def self.notification(query_string, options = {}) + Notification.new(query_string, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/common.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/common.rb new file mode 100644 index 000000000..e6bb96593 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/common.rb @@ -0,0 +1,17 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Webmoney + module Common + def generate_signature_string + "#{params['LMI_PAYEE_PURSE']}#{params['LMI_PAYMENT_AMOUNT']}#{params['LMI_PAYMENT_NO']}#{params['LMI_MODE']}#{params['LMI_SYS_INVS_NO']}#{params['LMI_SYS_TRANS_NO']}#{params['LMI_SYS_TRANS_DATE']}#{secret}#{params['LMI_PAYER_PURSE']}#{params['LMI_PAYER_WM']}" + end + + def generate_signature + Digest::MD5.hexdigest(generate_signature_string).upcase + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/helper.rb new file mode 100644 index 000000000..2516d3f4f --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/helper.rb @@ -0,0 +1,39 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Webmoney + class Helper < ActiveMerchant::Billing::Integrations::Helper + include Common + + def initialize(order, account, options = {}) + @webmoney_options = options.dup + options.delete(:description) + options.delete(:fail_url) + options.delete(:success_url) + options.delete(:result_url) + super + @webmoney_options.each do |key, value| + add_field mappings[key], value + end + end + + def form_fields + @fields + end + + def params + @fields + end + + mapping :account, 'LMI_PAYEE_PURSE' + mapping :amount, 'LMI_PAYMENT_AMOUNT' + mapping :order, 'LMI_PAYMENT_NO' + mapping :description, 'LMI_PAYMENT_DESC' + mapping :fail_url, 'LMI_FAIL_URL' + mapping :success_url, 'LMI_SUCCESS_URL' + mapping :result_url, 'LMI_RESULT_URL' + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/notification.rb new file mode 100644 index 000000000..6fa555604 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/webmoney/notification.rb @@ -0,0 +1,43 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Webmoney + class Notification < ActiveMerchant::Billing::Integrations::Notification + include Common + + def recognizes? + (params.has_key?('LMI_PAYMENT_NO') && params.has_key?('LMI_PAYMENT_AMOUNT')) + end + + def amount + BigDecimal.new(gross) + end + + def key_present? + params["LMI_HASH"].present? + end + + def item_id + params['LMI_PAYMENT_NO'] + end + + def gross + params['LMI_PAYMENT_AMOUNT'] + end + + def security_key + params["LMI_HASH"] + end + + def secret + @options[:secret] + end + + def acknowledge + (security_key == generate_signature) + end + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay.rb new file mode 100644 index 000000000..73190d31b --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay.rb @@ -0,0 +1,34 @@ +require File.dirname(__FILE__) + '/world_pay/helper.rb' +require File.dirname(__FILE__) + '/world_pay/notification.rb' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module WorldPay + + mattr_accessor :production_url, :test_url + self.production_url = 'https://secure.worldpay.com/wcc/purchase' + self.test_url = 'https://secure-test.worldpay.com/wcc/purchase' + + def self.service_url + case ActiveMerchant::Billing::Base.integration_mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post, options = {}) + Notification.new(post, options) + end + + def self.return(post, options = {}) + Return.new(post, options) + end + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/helper.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/helper.rb new file mode 100644 index 000000000..cad7fca69 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/helper.rb @@ -0,0 +1,100 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module WorldPay + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'instId' + mapping :amount, 'amount' + mapping :order, 'cartId' + mapping :currency, 'currency' + + mapping :customer, :email => 'email', + :phone => 'tel' + + mapping :billing_address, :zip => 'postcode', + :country => 'country' + + mapping :description, 'desc' + mapping :notify_url, 'MC_callback' + + + # WorldPay supports two different test modes - :always_succeed and :always_fail + def initialize(order, account, options = {}) + super + + if ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] + test_mode = case options[:test] + when :always_fail + 101 + when false + 0 + else + 100 + end + add_field('testMode', test_mode.to_s) + elsif ActiveMerchant::Billing::Base.integration_mode == :always_succeed + add_field('testMode', '100') + elsif ActiveMerchant::Billing::Base.integration_mode == :always_fail + add_field('testMode', '101') + end + end + + # WorldPay only supports a single address field so we + # have to concat together - lines are separated using &#10; + def billing_address(params={}) + add_field(mappings[:billing_address][:zip], params[:zip]) + add_field(mappings[:billing_address][:country], lookup_country_code(params[:country])) + + address = [params[:address1], params[:address2], params[:city], params[:state]].compact + add_field('address', address.join('&#10;')) + end + + # WorldPay only supports a single name field so we have to concat + def customer(params={}) + add_field(mappings[:customer][:email], params[:email]) + add_field(mappings[:customer][:phone], params[:phone]) + add_field('name', "#{params[:first_name]} #{params[:last_name]}") + end + + # Support for a MD5 hash of selected fields to prevent tampering + # For futher information read the tech note at the address below: + # http://support.worldpay.com/kb/integration_guides/junior/integration/help/tech_notes/sjig_tn_009.html + def encrypt(secret, fields = [:amount, :currency, :account, :order]) + signature_fields = fields.collect{ |field| mappings[field] } + add_field('signatureFields', signature_fields.join(':')) + + field_values = fields.collect{ |field| form_fields[mappings[field]] } + signature = "#{secret}:#{field_values.join(':')}" + add_field('signature', Digest::MD5.hexdigest(signature)) + end + + # Add a time window for which the payment can be completed. Read the link below for how they work + # http://support.worldpay.com/kb/integration_guides/junior/integration/help/appendicies/sjig_10100.html + def valid_from(from_time) + add_field('authValidFrom', from_time.to_i.to_s + '000') + end + + def valid_to(to_time) + add_field('authValidTo', to_time.to_i.to_s + '000') + end + + # WorldPay supports the passing of custom parameters prefixed with the following: + # C_ : These parameters can be used in the response pages hosted on WorldPay's site + # M_ : These parameters are passed through to the callback script (if enabled) + # MC_ or CM_ : These parameters are availble both in the response and callback contexts + def response_params(params={}) + params.each{|k,v| add_field("C_#{k}",v)} + end + + def callback_params(params={}) + params.each{|k,v| add_field("M_#{k}",v)} + end + + def combined_params(params={}) + params.each{|k,v| add_field("MC_#{k}",v)} + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/notification.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/notification.rb new file mode 100644 index 000000000..afd682e9d --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/integrations/world_pay/notification.rb @@ -0,0 +1,160 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module WorldPay + class Notification < ActiveMerchant::Billing::Integrations::Notification + def complete? + status == 'Completed' + end + + def account + params['instId'] + end + + def item_id + params['cartId'] + end + + def transaction_id + params['transId'] + end + + # Time this payment was received by the client in UTC time. + def received_at + Time.at(params['transTime'].to_i / 1000).utc + end + + # Callback password set in the WorldPay CMS + def security_key + params['callbackPW'] + end + + # the money amount we received in X.2 decimal. + def gross + params['authAmount'] + end + + def currency + params['authCurrency'] + end + + # Was this a test transaction? + def test? + params.key?('testMode') && params['testMode'] != '0' + end + + def status + params['transStatus'] == 'Y' ? 'Completed' : 'Cancelled' + end + + def name + params['name'] + end + + def address + params['address'] + end + + def postcode + params['postcode'] + end + + def country + params['country'] + end + + def phone_number + params['tel'] + end + + def fax_number + params['fax'] + end + + def email_address + params['email'] + end + + def card_type + params['cardType'] + end + + # WorldPay extended fraud checks returned as a 4 character string + # 1st char: Credit card CVV check + # 2nd char: Postcode AVS check + # 3rd char: Address AVS check + # 4th char: Country comparison check + # Possible values are: + # :not_supported - 0 + # :not_checked - 1 + # :matched - 2 + # :not_matched - 4 + # :partial_match - 8 + def cvv_status + return avs_value_to_symbol(params['AVS'][0].chr) + end + + def postcode_status + return avs_value_to_symbol(params['AVS'][1].chr) + end + + def address_status + return avs_value_to_symbol(params['AVS'][2].chr) + end + + def country_status + return avs_value_to_symbol(params['AVS'][3].chr) + end + + def acknowledge + return true + end + + # WorldPay supports the passing of custom parameters through to the callback script + def custom_params + return @custom_params ||= read_custom_params + end + + + private + + # Take the posted data and move the relevant data into a hash + def parse(post) + @raw = post + for line in post.split('&') + key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten + params[key] = value + end + end + + # Read the custom params into a hash + def read_custom_params + custom = {} + params.each do |key, value| + if /\A(M_|MC_|CM_)/ === key + custom[key.gsub(/\A(M_|MC_|CM_)/, '').to_sym] = value + end + end + custom + end + + # Convert a AVS value to a symbol - see above for more about AVS + def avs_value_to_symbol(value) + case value.to_s + when '8' + :partial_match + when '4' + :no_match + when '2' + :matched + when '1' + :not_checked + else + :not_supported + end + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/response.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/response.rb new file mode 100644 index 000000000..c02a22e7c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/billing/response.rb @@ -0,0 +1,77 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + class Error < ActiveMerchantError #:nodoc: + end + + class Response + attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result + + def success? + @success + end + + def test? + @test + end + + def fraud_review? + @fraud_review + end + + def initialize(success, message, params = {}, options = {}) + @success, @message, @params = success, message, params.stringify_keys + @test = options[:test] || false + @authorization = options[:authorization] + @fraud_review = options[:fraud_review] + + @avs_result = if options[:avs_result].kind_of?(AVSResult) + options[:avs_result].to_hash + else + AVSResult.new(options[:avs_result]).to_hash + end + + @cvv_result = if options[:cvv_result].kind_of?(CVVResult) + options[:cvv_result].to_hash + else + CVVResult.new(options[:cvv_result]).to_hash + end + end + end + + class MultiResponse < Response + def self.run(&block) + new.tap(&block) + end + + attr_reader :responses + + def initialize + @responses = [] + end + + def process + self << yield if(responses.empty? || success?) + end + + def <<(response) + if response.is_a?(MultiResponse) + response.responses.each{|r| @responses << r} + else + @responses << response + end + end + + def success? + @responses.all?{|r| r.success?} + end + + %w(params message test authorization avs_result cvv_result test? fraud_review?).each do |m| + class_eval %( + def #{m} + (@responses.empty? ? nil : @responses.last.#{m}) + end + ) + end + end + end +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/active_merchant/version.rb b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/version.rb new file mode 100644 index 000000000..09d49a725 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/active_merchant/version.rb @@ -0,0 +1,3 @@ +module ActiveMerchant + VERSION = "1.33.0" +end diff --git a/vendor/gems/activemerchant-1.33.0/lib/activemerchant.rb b/vendor/gems/activemerchant-1.33.0/lib/activemerchant.rb new file mode 100644 index 000000000..0a3f08fee --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/activemerchant.rb @@ -0,0 +1 @@ +require 'active_merchant' \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/support/gateway_support.rb b/vendor/gems/activemerchant-1.33.0/lib/support/gateway_support.rb new file mode 100644 index 000000000..7cf3b2a3c --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/support/gateway_support.rb @@ -0,0 +1,65 @@ +require 'rubygems' +require 'active_support' +require 'active_merchant' + + +class GatewaySupport #:nodoc: + ACTIONS = [:purchase, :authorize, :capture, :void, :credit, :recurring] + + include ActiveMerchant::Billing + + attr_reader :gateways + + def initialize + Dir[File.expand_path(File.dirname(__FILE__) + '/../active_merchant/billing/gateways/*.rb')].each do |f| + filename = File.basename(f, '.rb') + gateway_name = filename + '_gateway' + begin + gateway_class = ('ActiveMerchant::Billing::' + gateway_name.camelize).constantize + rescue NameError + puts "Could not load gateway " + gateway_name.camelize + " from " + f + "." + end + end + @gateways = Gateway.implementations.sort_by(&:name) + @gateways.delete(ActiveMerchant::Billing::BogusGateway) + end + + def each_gateway + @gateways.each{|g| yield g } + end + + def features + width = 15 + + print "Name".center(width + 20) + ACTIONS.each{|f| print "#{f.to_s.capitalize.center(width)}" } + puts + + each_gateway do |g| + print "#{g.display_name.ljust(width + 20)}" + ACTIONS.each do |f| + print "#{(g.instance_methods.include?(f.to_s) ? "Y" : "N").center(width)}" + end + puts + end + end + + def to_rdoc + each_gateway do |g| + puts "* {#{g.display_name}}[#{g.homepage_url}] - #{g.supported_countries.join(', ')}" + end + end + + def to_textile + each_gateway do |g| + puts %/ * "#{g.display_name}":#{g.homepage_url} [#{g.supported_countries.join(', ')}]/ + end + end + + def to_s + each_gateway do |g| + puts "#{g.display_name} - #{g.homepage_url} [#{g.supported_countries.join(', ')}]" + end + end +end + diff --git a/vendor/gems/activemerchant-1.33.0/lib/support/outbound_hosts.rb b/vendor/gems/activemerchant-1.33.0/lib/support/outbound_hosts.rb new file mode 100644 index 000000000..bac790662 --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/support/outbound_hosts.rb @@ -0,0 +1,25 @@ +require 'uri' +require 'set' + +class OutboundHosts + def self.list + uris = Set.new + + Dir['lib/**/*.rb'].each do |file| + content = File.read(file) + + content.each_line do |line| + next if line =~ /homepage_url/ + + if line =~ /("|')(https:\/\/.*)("|')/ + uri = URI.parse($2) + uris << [uri.host, uri.port] + end + end + end + + uris.each do |uri| + puts "#{uri.first} #{uri.last}" + end + end +end \ No newline at end of file diff --git a/vendor/gems/activemerchant-1.33.0/lib/support/ssl_verify.rb b/vendor/gems/activemerchant-1.33.0/lib/support/ssl_verify.rb new file mode 100644 index 000000000..1ba28878a --- /dev/null +++ b/vendor/gems/activemerchant-1.33.0/lib/support/ssl_verify.rb @@ -0,0 +1,93 @@ +require 'active_merchant' +require 'support/gateway_support' + +class SSLVerify + + def initialize + @gateways = GatewaySupport.new.gateways + end + + def test_gateways + success, failed, missing, errored, disabled = [], [], [], [], [] + + puts "Verifying #{@gateways.count} SSL certificates\n\n" + + @gateways.each do |g| + if !g.live_url + missing << g unless g.abstract_class + next + end + + if !g.ssl_strict + disabled << g + end + + uri = URI.parse(g.live_url) + result,message = ssl_verify_peer?(uri) + case result + when :success + print "." + success << g + when :fail + print "F" + failed << {:gateway => g, :message => message} + when :error + print "E" + errored << {:gateway => g, :message => message} + end + end + + puts "\n\n\nFailed Gateways:" + failed.each do |f| + puts "#{f[:gateway].name} - #{f[:message]}" + end + + puts "\n\nError Gateways:" + errored.each do |e| + puts "#{e[:gateway].name} - #{e[:message]}" + end + + if missing.size > 0 + puts "\n\nGateways missing live_url:" + missing.each do |m| + puts m.name + end + end + + if disabled.size > 0 + puts "\n\nGateways with ssl_strict=false:" + disabled.each do |d| + puts d.name + end + end + + end + + def try_host(http, path) + http.get(path) + rescue Net::HTTPBadResponse, EOFError, SocketError + http.post(path, "") + end + + def ssl_verify_peer?(uri) + http = Net::HTTP.new(uri.host, uri.port) + http.use_ssl = true + http.ca_file = File.dirname(__FILE__) + '/certs/cacert.pem' + http.verify_mode = OpenSSL::SSL::VERIFY_PEER + http.open_timeout = 60 + http.read_timeout = 60 + + if uri.path.blank? + try_host(http, "/") + else + try_host(http, uri.path) + end + + return :success + rescue OpenSSL::SSL::SSLError => ex + return :fail, ex.inspect + rescue Net::HTTPBadResponse, Errno::ETIMEDOUT, EOFError, SocketError, Errno::ECONNREFUSED, Timeout::Error => ex + return :error, ex.inspect + end + +end