johnreitano-activemerchant 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +508 -0
- data/CONTRIBUTORS +134 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +136 -0
- data/gem-public_cert.pem +20 -0
- data/lib/active_merchant/billing/avs_result.rb +98 -0
- data/lib/active_merchant/billing/base.rb +57 -0
- data/lib/active_merchant/billing/check.rb +68 -0
- data/lib/active_merchant/billing/credit_card.rb +159 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/expiry_date.rb +34 -0
- data/lib/active_merchant/billing/gateway.rb +163 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +654 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +736 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +244 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +98 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +594 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +593 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
- data/lib/active_merchant/billing/gateways/eway.rb +277 -0
- data/lib/active_merchant/billing/gateways/exact.rb +222 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +270 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +449 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +279 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
- data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
- data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
- data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +326 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +130 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
- data/lib/active_merchant/billing/gateways/realex.rb +200 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
- data/lib/active_merchant/billing/gateways/sage.rb +146 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +309 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +265 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
- data/lib/active_merchant/billing/gateways/transax.rb +25 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
- data/lib/active_merchant/billing/gateways.rb +18 -0
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
- data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
- data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
- data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
- data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
- data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
- data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
- data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
- data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
- data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
- data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
- data/lib/active_merchant/billing/integrations/helper.rb +93 -0
- data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
- data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
- data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
- data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
- data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
- data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
- data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
- data/lib/active_merchant/billing/integrations/notification.rb +62 -0
- data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
- data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
- data/lib/active_merchant/billing/integrations/quickpay.rb +17 -0
- data/lib/active_merchant/billing/integrations/return.rb +35 -0
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
- data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
- data/lib/active_merchant/billing/integrations.rb +29 -0
- data/lib/active_merchant/billing/response.rb +32 -0
- data/lib/active_merchant/billing.rb +9 -0
- data/lib/active_merchant/lib/connection.rb +170 -0
- data/lib/active_merchant/lib/country.rb +319 -0
- data/lib/active_merchant/lib/error.rb +4 -0
- data/lib/active_merchant/lib/post_data.rb +22 -0
- data/lib/active_merchant/lib/posts_data.rb +47 -0
- data/lib/active_merchant/lib/requires_parameters.rb +16 -0
- data/lib/active_merchant/lib/utils.rb +18 -0
- data/lib/active_merchant/lib/validateable.rb +76 -0
- data/lib/active_merchant.rb +46 -0
- data/lib/certs/cacert.pem +7815 -0
- data/lib/support/gateway_support.rb +58 -0
- metadata +218 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
module Integrations #:nodoc:
|
6
|
+
module Paypal
|
7
|
+
# Parser and handler for incoming Instant payment notifications from paypal.
|
8
|
+
# The Example shows a typical handler in a rails application. Note that this
|
9
|
+
# is an example, please read the Paypal API documentation for all the details
|
10
|
+
# on creating a safe payment controller.
|
11
|
+
#
|
12
|
+
# Example
|
13
|
+
#
|
14
|
+
# class BackendController < ApplicationController
|
15
|
+
# include ActiveMerchant::Billing::Integrations
|
16
|
+
#
|
17
|
+
# def paypal_ipn
|
18
|
+
# notify = Paypal::Notification.new(request.raw_post)
|
19
|
+
#
|
20
|
+
# order = Order.find(notify.item_id)
|
21
|
+
#
|
22
|
+
# if notify.acknowledge
|
23
|
+
# begin
|
24
|
+
#
|
25
|
+
# if notify.complete? and order.total == notify.amount
|
26
|
+
# order.status = 'success'
|
27
|
+
#
|
28
|
+
# shop.ship(order)
|
29
|
+
# else
|
30
|
+
# logger.error("Failed to verify Paypal's notification, please investigate")
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# rescue => e
|
34
|
+
# order.status = 'failed'
|
35
|
+
# raise
|
36
|
+
# ensure
|
37
|
+
# order.save
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# render :nothing
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
45
|
+
include PostsData
|
46
|
+
|
47
|
+
# Was the transaction complete?
|
48
|
+
def complete?
|
49
|
+
status == "Completed"
|
50
|
+
end
|
51
|
+
|
52
|
+
# When was this payment received by the client.
|
53
|
+
# sometimes it can happen that we get the notification much later.
|
54
|
+
# One possible scenario is that our web application was down. In this case paypal tries several
|
55
|
+
# times an hour to inform us about the notification
|
56
|
+
def received_at
|
57
|
+
Time.parse params['payment_date']
|
58
|
+
end
|
59
|
+
|
60
|
+
# Status of transaction. List of possible values:
|
61
|
+
# <tt>Canceled-Reversal</tt>::
|
62
|
+
# <tt>Completed</tt>::
|
63
|
+
# <tt>Denied</tt>::
|
64
|
+
# <tt>Expired</tt>::
|
65
|
+
# <tt>Failed</tt>::
|
66
|
+
# <tt>In-Progress</tt>::
|
67
|
+
# <tt>Partially-Refunded</tt>::
|
68
|
+
# <tt>Pending</tt>::
|
69
|
+
# <tt>Processed</tt>::
|
70
|
+
# <tt>Refunded</tt>::
|
71
|
+
# <tt>Reversed</tt>::
|
72
|
+
# <tt>Voided</tt>::
|
73
|
+
def status
|
74
|
+
params['payment_status']
|
75
|
+
end
|
76
|
+
|
77
|
+
# Id of this transaction (paypal number)
|
78
|
+
def transaction_id
|
79
|
+
params['txn_id']
|
80
|
+
end
|
81
|
+
|
82
|
+
# What type of transaction are we dealing with?
|
83
|
+
# "cart" "send_money" "web_accept" are possible here.
|
84
|
+
def type
|
85
|
+
params['txn_type']
|
86
|
+
end
|
87
|
+
|
88
|
+
# the money amount we received in X.2 decimal.
|
89
|
+
def gross
|
90
|
+
params['mc_gross']
|
91
|
+
end
|
92
|
+
|
93
|
+
# the markup paypal charges for the transaction
|
94
|
+
def fee
|
95
|
+
params['mc_fee']
|
96
|
+
end
|
97
|
+
|
98
|
+
# What currency have we been dealing with
|
99
|
+
def currency
|
100
|
+
params['mc_currency']
|
101
|
+
end
|
102
|
+
|
103
|
+
# This is the item number which we submitted to paypal
|
104
|
+
# The custom field is also mapped to item_id because PayPal
|
105
|
+
# doesn't return item_number in dispute notifications
|
106
|
+
def item_id
|
107
|
+
params['item_number'] || params['custom']
|
108
|
+
end
|
109
|
+
|
110
|
+
# This is the invoice which you passed to paypal
|
111
|
+
def invoice
|
112
|
+
params['invoice']
|
113
|
+
end
|
114
|
+
|
115
|
+
# Was this a test transaction?
|
116
|
+
def test?
|
117
|
+
params['test_ipn'] == '1'
|
118
|
+
end
|
119
|
+
|
120
|
+
def account
|
121
|
+
params['business'] || params['receiver_email']
|
122
|
+
end
|
123
|
+
|
124
|
+
# Acknowledge the transaction to paypal. This method has to be called after a new
|
125
|
+
# ipn arrives. Paypal will verify that all the information we received are correct and will return a
|
126
|
+
# ok or a fail.
|
127
|
+
#
|
128
|
+
# Example:
|
129
|
+
#
|
130
|
+
# def paypal_ipn
|
131
|
+
# notify = PaypalNotification.new(request.raw_post)
|
132
|
+
#
|
133
|
+
# if notify.acknowledge
|
134
|
+
# ... process order ... if notify.complete?
|
135
|
+
# else
|
136
|
+
# ... log possible hacking attempt ...
|
137
|
+
# end
|
138
|
+
def acknowledge
|
139
|
+
payload = raw
|
140
|
+
|
141
|
+
response = ssl_post(Paypal.service_url + '?cmd=_notify-validate', payload,
|
142
|
+
'Content-Length' => "#{payload.size}",
|
143
|
+
'User-Agent' => "Active Merchant -- http://activemerchant.org"
|
144
|
+
)
|
145
|
+
|
146
|
+
raise StandardError.new("Faulty paypal result: #{response}") unless ["VERIFIED", "INVALID"].include?(response)
|
147
|
+
|
148
|
+
response == "VERIFIED"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module Paypal
|
5
|
+
autoload :Return, 'active_merchant/billing/integrations/paypal/return.rb'
|
6
|
+
autoload :Helper, 'active_merchant/billing/integrations/paypal/helper.rb'
|
7
|
+
autoload :Notification, 'active_merchant/billing/integrations/paypal/notification.rb'
|
8
|
+
|
9
|
+
# Overwrite this if you want to change the Paypal test url
|
10
|
+
mattr_accessor :test_url
|
11
|
+
self.test_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'
|
12
|
+
|
13
|
+
# Overwrite this if you want to change the Paypal production url
|
14
|
+
mattr_accessor :production_url
|
15
|
+
self.production_url = 'https://www.paypal.com/cgi-bin/webscr'
|
16
|
+
|
17
|
+
def self.service_url
|
18
|
+
mode = ActiveMerchant::Billing::Base.integration_mode
|
19
|
+
case mode
|
20
|
+
when :production
|
21
|
+
self.production_url
|
22
|
+
when :test
|
23
|
+
self.test_url
|
24
|
+
else
|
25
|
+
raise StandardError, "Integration mode set to an invalid value: #{mode}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.notification(post)
|
30
|
+
Notification.new(post)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.return(query_string)
|
34
|
+
Return.new(query_string)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module Quickpay
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper
|
6
|
+
|
7
|
+
def initialize(order, account, options = {})
|
8
|
+
super
|
9
|
+
add_field('protocol', '3')
|
10
|
+
add_field('msgtype', 'authorize')
|
11
|
+
add_field('language', 'da')
|
12
|
+
add_field('autocapture', 0)
|
13
|
+
add_field('testmode', 0)
|
14
|
+
add_field('ordernumber', format_order_number(order))
|
15
|
+
end
|
16
|
+
|
17
|
+
def md5secret(value)
|
18
|
+
@md5secret = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def form_fields
|
22
|
+
@fields.merge('md5check' => generate_md5check)
|
23
|
+
end
|
24
|
+
|
25
|
+
def generate_md5string
|
26
|
+
MD5_CHECK_FIELDS.map {|key| @fields[key.to_s]} * "" + @md5secret
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate_md5check
|
30
|
+
Digest::MD5.hexdigest(generate_md5string)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Limited to 20 digits max
|
34
|
+
def format_order_number(number)
|
35
|
+
number.to_s.gsub(/[^\w_]/, '').rjust(4, "0")[0...20]
|
36
|
+
end
|
37
|
+
|
38
|
+
MD5_CHECK_FIELDS = [
|
39
|
+
:protocol, :msgtype, :merchant, :language, :ordernumber,
|
40
|
+
:amount, :currency, :continueurl, :cancelurl, :callbackurl,
|
41
|
+
:autocapture, :cardtypelock, :description, :ipaddress, :testmode
|
42
|
+
]
|
43
|
+
|
44
|
+
mapping :protocol, 'protocol'
|
45
|
+
mapping :msgtype, 'msgtype'
|
46
|
+
mapping :account, 'merchant'
|
47
|
+
mapping :language, 'language'
|
48
|
+
mapping :amount, 'amount'
|
49
|
+
mapping :currency, 'currency'
|
50
|
+
|
51
|
+
mapping :return_url, 'continueurl'
|
52
|
+
mapping :cancel_return_url, 'cancelurl'
|
53
|
+
mapping :notify_url, 'callbackurl'
|
54
|
+
|
55
|
+
mapping :autocapture, 'autocapture'
|
56
|
+
mapping :cardtypelock, 'cardtypelock'
|
57
|
+
|
58
|
+
mapping :description, 'description'
|
59
|
+
mapping :ipaddress, 'ipaddress'
|
60
|
+
mapping :testmode, 'testmode'
|
61
|
+
|
62
|
+
mapping :md5secret, 'md5secret'
|
63
|
+
|
64
|
+
mapping :customer, ''
|
65
|
+
mapping :billing_address, {}
|
66
|
+
mapping :tax, ''
|
67
|
+
mapping :shipping, ''
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
module Integrations #:nodoc:
|
6
|
+
module Quickpay
|
7
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
8
|
+
def complete?
|
9
|
+
status == '000'
|
10
|
+
end
|
11
|
+
|
12
|
+
def item_id
|
13
|
+
params['ordernumber']
|
14
|
+
end
|
15
|
+
|
16
|
+
def transaction_id
|
17
|
+
params['transaction']
|
18
|
+
end
|
19
|
+
|
20
|
+
def received_at
|
21
|
+
Time.local(*params['time'].scan(/../))
|
22
|
+
end
|
23
|
+
|
24
|
+
def gross
|
25
|
+
"%.2f" % (gross_cents / 100.0)
|
26
|
+
end
|
27
|
+
|
28
|
+
def gross_cents
|
29
|
+
params['amount'].to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
def test?
|
33
|
+
params['testmode'] == 'Yes'
|
34
|
+
end
|
35
|
+
|
36
|
+
def status
|
37
|
+
params['qpstat']
|
38
|
+
end
|
39
|
+
|
40
|
+
def currency
|
41
|
+
params['currency']
|
42
|
+
end
|
43
|
+
|
44
|
+
# Provide access to raw fields from quickpay
|
45
|
+
%w(msgtype ordernumber state chstat chstatmsg qpstat qpstatmsg merchant merchantemail cardtype cardnumber).each do |attr|
|
46
|
+
define_method(attr) do
|
47
|
+
params[attr]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
MD5_CHECK_FIELDS = [
|
52
|
+
:msgtype, :ordernumber, :amount, :currency, :time, :state,
|
53
|
+
:chstat, :chstatmsg, :qpstat, :qpstatmsg, :merchant, :merchantemail,
|
54
|
+
:transaction, :cardtype, :cardnumber, :testmode
|
55
|
+
]
|
56
|
+
|
57
|
+
def generate_md5string
|
58
|
+
MD5_CHECK_FIELDS.map { |key| params[key.to_s] } * "" + @options[:md5secret]
|
59
|
+
end
|
60
|
+
|
61
|
+
def generate_md5check
|
62
|
+
Digest::MD5.hexdigest(generate_md5string)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Quickpay doesn't do acknowledgements of callback notifications
|
66
|
+
# Instead it uses and MD5 hash of all parameters
|
67
|
+
def acknowledge
|
68
|
+
generate_md5check == params['md5check']
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module Quickpay
|
5
|
+
autoload :Helper, File.dirname(__FILE__) + '/quickpay/helper.rb'
|
6
|
+
autoload :Notification, File.dirname(__FILE__) + '/quickpay/notification.rb'
|
7
|
+
|
8
|
+
mattr_accessor :service_url
|
9
|
+
self.service_url = 'https://secure.quickpay.dk/form/'
|
10
|
+
|
11
|
+
def self.notification(post)
|
12
|
+
Notification.new(post)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
class Return
|
5
|
+
attr_accessor :params
|
6
|
+
|
7
|
+
def initialize(query_string)
|
8
|
+
@params = parse(query_string)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Successful by default. Overridden in the child class
|
12
|
+
def success?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def message
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse(query_string)
|
21
|
+
return {} if query_string.blank?
|
22
|
+
|
23
|
+
query_string.split('&').inject({}) do |memo, chunk|
|
24
|
+
next if chunk.empty?
|
25
|
+
key, value = chunk.split('=', 2)
|
26
|
+
next if key.empty?
|
27
|
+
value = value.nil? ? nil : CGI.unescape(value)
|
28
|
+
memo[CGI.unescape(key)] = value
|
29
|
+
memo
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module TwoCheckout
|
5
|
+
class Helper < ActiveMerchant::Billing::Integrations::Helper
|
6
|
+
def initialize(order, account, options = {})
|
7
|
+
super
|
8
|
+
add_field('fixed', 'Y')
|
9
|
+
|
10
|
+
if ActiveMerchant::Billing::Base.integration_mode == :test || options[:test]
|
11
|
+
add_field('demo', 'Y')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# The 2checkout vendor account number
|
16
|
+
mapping :account, 'sid'
|
17
|
+
|
18
|
+
# he total amount to be billed, in decimal form, without a currency symbol. (8 characters, decimal, 2 characters: Example: 99999999.99)
|
19
|
+
mapping :amount, 'total'
|
20
|
+
|
21
|
+
# a unique order id from your program. (128 characters max)
|
22
|
+
mapping :order, 'cart_order_id'
|
23
|
+
|
24
|
+
|
25
|
+
mapping :customer, :email => 'email',
|
26
|
+
:phone => 'phone'
|
27
|
+
|
28
|
+
mapping :billing_address, :city => 'city',
|
29
|
+
:address1 => 'street_address',
|
30
|
+
:address2 => 'street_address2',
|
31
|
+
:state => 'state',
|
32
|
+
:zip => 'zip',
|
33
|
+
:country => 'country'
|
34
|
+
|
35
|
+
mapping :shipping_address, :city => 'ship_city',
|
36
|
+
:address1 => 'ship_street_address',
|
37
|
+
:state => 'ship_state',
|
38
|
+
:zip => 'ship_zip',
|
39
|
+
:country => 'ship_country'
|
40
|
+
|
41
|
+
mapping :invoice, 'merchant_order_id'
|
42
|
+
|
43
|
+
# Does nothing, since we've disabled the Continue Shopping button by using the fixed = Y field
|
44
|
+
mapping :return_url, 'return_url'
|
45
|
+
|
46
|
+
#mapping :description, ''
|
47
|
+
#mapping :tax, ''
|
48
|
+
#mapping :shipping, ''
|
49
|
+
|
50
|
+
def customer(params = {})
|
51
|
+
add_field(mappings[:customer][:email], params[:email])
|
52
|
+
add_field(mappings[:customer][:phone], params[:phone])
|
53
|
+
add_field('card_holder_name', "#{params[:first_name]} #{params[:last_name]}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'base64'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module ActiveMerchant #:nodoc:
|
6
|
+
module Billing #:nodoc:
|
7
|
+
module Integrations #:nodoc:
|
8
|
+
module TwoCheckout
|
9
|
+
class Notification < ActiveMerchant::Billing::Integrations::Notification
|
10
|
+
# order_number 2Checkout.com order number
|
11
|
+
# card_holder_name Card holder's name
|
12
|
+
# street_address Card holder's address
|
13
|
+
# city Card holder's city
|
14
|
+
# state Card holder's state
|
15
|
+
# zip Card holder's zip
|
16
|
+
# country Card holder's country
|
17
|
+
# email Card holder's email
|
18
|
+
# phone Card holder's phone
|
19
|
+
# credit_card_processed Y if successful, K if waiting for approval
|
20
|
+
# total Total purchase amount
|
21
|
+
# ship_name Shipping information
|
22
|
+
# ship_street_address Shipping information
|
23
|
+
# ship_city Shipping information
|
24
|
+
# ship_state Shipping information
|
25
|
+
# ship_zip Shipping information
|
26
|
+
# ship_country Shipping information
|
27
|
+
# product_id 2Checkout product ID for purchased items will append a number if more than one item.
|
28
|
+
# ex. product_id,product_id1,product_id2
|
29
|
+
# quantity quantity of corresponding product will append a number if more than one item.
|
30
|
+
# ex. quantity,quantity1,quantity2
|
31
|
+
# merchant_product_id your product ID for purchased items will append a number if more than one item.
|
32
|
+
# ex. merchant_product_id,merchant_product_id1,merchant_product_id2
|
33
|
+
# product_description your description for purchased items will append a number if more than one item.
|
34
|
+
# ex. product_description,product_description1,product_description2
|
35
|
+
|
36
|
+
def currency
|
37
|
+
'USD'
|
38
|
+
end
|
39
|
+
|
40
|
+
def complete?
|
41
|
+
status == 'Completed'
|
42
|
+
end
|
43
|
+
|
44
|
+
def item_id
|
45
|
+
params['cart_order_id']
|
46
|
+
end
|
47
|
+
|
48
|
+
def transaction_id
|
49
|
+
params['order_number']
|
50
|
+
end
|
51
|
+
|
52
|
+
def received_at
|
53
|
+
params['']
|
54
|
+
end
|
55
|
+
|
56
|
+
def payer_email
|
57
|
+
params['email']
|
58
|
+
end
|
59
|
+
|
60
|
+
def receiver_email
|
61
|
+
params['']
|
62
|
+
end
|
63
|
+
|
64
|
+
# The MD5 Hash
|
65
|
+
def security_key
|
66
|
+
params['key']
|
67
|
+
end
|
68
|
+
|
69
|
+
# the money amount we received in X.2 decimal.
|
70
|
+
def gross
|
71
|
+
params['total']
|
72
|
+
end
|
73
|
+
|
74
|
+
# Was this a test transaction? # Use the hash
|
75
|
+
def test?
|
76
|
+
params['demo'] == 'Y'
|
77
|
+
end
|
78
|
+
|
79
|
+
def status
|
80
|
+
case params['credit_card_processed']
|
81
|
+
when 'Y'
|
82
|
+
'Completed'
|
83
|
+
when 'K'
|
84
|
+
'Pending'
|
85
|
+
else
|
86
|
+
'Failed'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def verify(secret)
|
91
|
+
return false if security_key.blank?
|
92
|
+
|
93
|
+
Digest::MD5.hexdigest("#{secret}#{params['sid']}#{transaction_id}#{gross}").upcase == security_key.upcase
|
94
|
+
end
|
95
|
+
|
96
|
+
def acknowledge
|
97
|
+
true
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def parse(post)
|
103
|
+
@raw = post.to_s
|
104
|
+
for line in @raw.split('&')
|
105
|
+
key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
|
106
|
+
params[key] = CGI.unescape(value || '')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
module Integrations #:nodoc:
|
4
|
+
module TwoCheckout
|
5
|
+
class Return < ActiveMerchant::Billing::Integrations::Return
|
6
|
+
def success?
|
7
|
+
params['credit_card_processed'] == 'Y'
|
8
|
+
end
|
9
|
+
|
10
|
+
def message
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module ActiveMerchant #:nodoc:
|
3
|
+
module Billing #:nodoc:
|
4
|
+
module Integrations #:nodoc:
|
5
|
+
module TwoCheckout
|
6
|
+
autoload 'Helper', File.dirname(__FILE__) + '/two_checkout/helper'
|
7
|
+
autoload 'Return', File.dirname(__FILE__) + '/two_checkout/return'
|
8
|
+
autoload 'Notification', File.dirname(__FILE__) + '/two_checkout/notification'
|
9
|
+
|
10
|
+
mattr_accessor :service_url
|
11
|
+
self.service_url = 'https://www.2checkout.com/2co/buyer/purchase'
|
12
|
+
|
13
|
+
def self.notification(post)
|
14
|
+
Notification.new(post)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.return(query_string)
|
18
|
+
Return.new(query_string)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
# make the bogus gateway be classified correctly by the inflector
|
3
|
+
if defined?(ActiveSupport::Inflector)
|
4
|
+
ActiveSupport::Inflector.inflections do |inflect|
|
5
|
+
inflect.uncountable 'bogus'
|
6
|
+
end
|
7
|
+
else
|
8
|
+
Inflector.inflections do |inflect|
|
9
|
+
inflect.uncountable 'bogus'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ActiveMerchant
|
14
|
+
module Billing
|
15
|
+
module Integrations
|
16
|
+
|
17
|
+
Dir[File.dirname(__FILE__) + '/integrations/*.rb'].each do |f|
|
18
|
+
|
19
|
+
# Get camelized class name
|
20
|
+
filename = File.basename(f, '.rb')
|
21
|
+
# Camelize the string to get the class name
|
22
|
+
gateway_class = filename.camelize.to_sym
|
23
|
+
|
24
|
+
# Register for autoloading
|
25
|
+
autoload gateway_class, f
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
|
4
|
+
class Error < ActiveMerchantError #:nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class Response
|
8
|
+
attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result
|
9
|
+
|
10
|
+
def success?
|
11
|
+
@success
|
12
|
+
end
|
13
|
+
|
14
|
+
def test?
|
15
|
+
@test
|
16
|
+
end
|
17
|
+
|
18
|
+
def fraud_review?
|
19
|
+
@fraud_review
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(success, message, params = {}, options = {})
|
23
|
+
@success, @message, @params = success, message, params.stringify_keys
|
24
|
+
@test = options[:test] || false
|
25
|
+
@authorization = options[:authorization]
|
26
|
+
@fraud_review = options[:fraud_review]
|
27
|
+
@avs_result = AVSResult.new(options[:avs_result]).to_hash
|
28
|
+
@cvv_result = CVVResult.new(options[:cvv_result]).to_hash
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|