mpay_gateway 0.41
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +68 -0
- data/app/controllers/mpay_callbacks_controller.rb +14 -0
- data/app/controllers/mpay_confirmation_controller.rb +84 -0
- data/app/helpers/admin/payments_helper.rb +21 -0
- data/app/helpers/mpay_helper.rb +19 -0
- data/app/models/billing_integration/mpay.rb +191 -0
- data/app/models/m_pay_source.rb +9 -0
- data/app/views/admin/payments/_list.html.erb +30 -0
- data/app/views/admin/payments/show.html.erb +18 -0
- data/app/views/admin/payments/source_forms/_mpay.html.erb +1 -0
- data/app/views/admin/payments/source_views/_mpay.html.erb +0 -0
- data/app/views/checkout/payment/_mpay.html.erb +6 -0
- data/app/views/shared/_mpay_confirm.html.erb +8 -0
- data/app/views/shared/_mpay_success.html.erb +3 -0
- data/config/locales/de.yml +7 -0
- data/config/locales/en.yml +7 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20101010085758_create_m_pay_sources.rb +16 -0
- data/db/seeds.rb +2 -0
- data/lib/active_merchant/billing/gateways/mpay.rb +93 -0
- data/lib/mpay_gateway.rb +24 -0
- data/lib/tasks/install.rake +25 -0
- data/lib/tasks/mpay_gateway.rake +1 -0
- metadata +101 -0
data/README.markdown
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
Mpay Gateway
|
2
|
+
============
|
3
|
+
|
4
|
+
This integrates the [mPAY24](https://www.mpay24.com/web/en/mpay24-payment-platform.html)
|
5
|
+
payment gateway into Spree. mPAY24 is an European credit card and mobile phone payment
|
6
|
+
processing gateway.
|
7
|
+
|
8
|
+
The plugin takes care of basic security:
|
9
|
+
|
10
|
+
* transferred data is secured by a salt
|
11
|
+
* no credit card data is stored within the spree web shop
|
12
|
+
* the identity of the confirmation callback is verified
|
13
|
+
|
14
|
+
The plugin was tested with multiple web shops implemented by [we](http://wwww.starseeders.net).
|
15
|
+
|
16
|
+
Installation
|
17
|
+
============
|
18
|
+
|
19
|
+
This plugin has been tested with Spree 0.11.2 and Spree 0.40.3.
|
20
|
+
|
21
|
+
Spree 0.11
|
22
|
+
----------
|
23
|
+
|
24
|
+
Install it as a git submodule. To do this execute the following within your application
|
25
|
+
directory:
|
26
|
+
|
27
|
+
<blockquote>
|
28
|
+
git clone git://github.com/andreashappe/spree-mpay24 vendor/extensions/mpay_gateway
|
29
|
+
cd vendor/extensions/mpay_gateway
|
30
|
+
git checkout spree-0.11
|
31
|
+
</blockquote>
|
32
|
+
|
33
|
+
Spree 0.40
|
34
|
+
----------
|
35
|
+
|
36
|
+
This plugin will be released as a "real" gem soon.
|
37
|
+
|
38
|
+
Configuration
|
39
|
+
=============
|
40
|
+
|
41
|
+
Add a payment method of provider type BillingIntegration:Mpay. The
|
42
|
+
payment method comes with a configuration pane which allows setting
|
43
|
+
of basic options as:
|
44
|
+
|
45
|
+
* merchant id (for both testing as well as production mpay mode)
|
46
|
+
* shared secret (which is used as salt to secure the communication)
|
47
|
+
* base url (the URL of your website, this is needed for the confirmation callback from mPAY24)
|
48
|
+
|
49
|
+
License stuff
|
50
|
+
=============
|
51
|
+
|
52
|
+
Copyright © 2010 Andreas Happe <andreashappe@starseeders.net>
|
53
|
+
|
54
|
+
This plugin is free software; you can redistribute it and/or
|
55
|
+
modify it either under the terms of the GNU Lesser General Public
|
56
|
+
License version 2.1 as published by the Free Software Foundation
|
57
|
+
(the "LGPL") or, at your option, under the terms of the Mozilla
|
58
|
+
Public License Version 1.1 (the "MPL"). If you do not alter this
|
59
|
+
notice, a recipient may use your version of this file under either
|
60
|
+
the MPL or the LGPL.
|
61
|
+
|
62
|
+
You should have received a copy of the LGPL along with this library
|
63
|
+
in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
64
|
+
Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
65
|
+
|
66
|
+
This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
67
|
+
OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
68
|
+
the specific language governing rights and limitations.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class MpayCallbacksController < Spree::BaseController
|
2
|
+
def index
|
3
|
+
|
4
|
+
@order = BillingIntegration::Mpay.current.find_order(params["TID"])
|
5
|
+
|
6
|
+
order_params = {:checkout_complete => true}
|
7
|
+
session[:order_id] = nil
|
8
|
+
flash[:commerce_tracking] = "Track Me in GA"
|
9
|
+
|
10
|
+
# TODO: this should not be rendered into the IFRAME but in the surrounding page
|
11
|
+
# redirect_to order_url(@order, {:checkout_complete => true, :order_token => @order.token})
|
12
|
+
render :partial => "shared/mpay_success", :locals => { :final_url => order_url(@order, {:checkout_complete => true, :order_token => @order.token})}
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
class MpayConfirmationController < Spree::BaseController
|
2
|
+
|
3
|
+
# possible transaction states
|
4
|
+
TRANSACTION_STATES = ["ERROR", "RESERVED", "BILLED", "REVERSED", "CREDITED", "SUSPENDED"]
|
5
|
+
|
6
|
+
# Confirmation interface is a GET request
|
7
|
+
def show
|
8
|
+
|
9
|
+
BillingIntegration::Mpay.current.verify_ip(request)
|
10
|
+
|
11
|
+
check_operation(params["OPERATION"])
|
12
|
+
check_status(params["STATUS"])
|
13
|
+
|
14
|
+
# get the order
|
15
|
+
order = BillingIntegration::Mpay.current.find_order(params["TID"])
|
16
|
+
|
17
|
+
case params["STATUS"]
|
18
|
+
when "BILLED"
|
19
|
+
# check if the retrieved order is the same as the outgoing one
|
20
|
+
if verify_currency(order, params["CURRENCY"])
|
21
|
+
|
22
|
+
# create new payment object
|
23
|
+
payment_details = MPaySource.create ({
|
24
|
+
:p_type => params["P_TYPE"],
|
25
|
+
:brand => params["BRAND"],
|
26
|
+
:mpayid => params["MPAYTID"]
|
27
|
+
})
|
28
|
+
|
29
|
+
payment_details.save!
|
30
|
+
|
31
|
+
payment_method = PaymentMethod.where(:type => "BillingIntegration::Mpay").where(:environment => RAILS_ENV.to_s).first
|
32
|
+
|
33
|
+
# TODO log the payment
|
34
|
+
order.checkout.payments.create({
|
35
|
+
:amount => params["PRICE"],
|
36
|
+
:payment_method_id => payment_method,
|
37
|
+
:source => payment_details
|
38
|
+
})
|
39
|
+
|
40
|
+
# TODO: create this before (when sending the request?)
|
41
|
+
# TODO: but do we even want this?
|
42
|
+
payment.started_processing!
|
43
|
+
payment.complete!
|
44
|
+
payment.save!
|
45
|
+
|
46
|
+
payment_details.payment = payment
|
47
|
+
payment_details.save!
|
48
|
+
order.update!
|
49
|
+
end
|
50
|
+
when "RESERVED"
|
51
|
+
raise "send the confirmation request out".inspect
|
52
|
+
else
|
53
|
+
raise "what is going on?".inspect
|
54
|
+
end
|
55
|
+
|
56
|
+
render :text => "OK", :status => 200
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def check_operation(operation)
|
62
|
+
if operation != "CONFIRMATION"
|
63
|
+
raise "unknown operation: #{operation}".inspect
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def check_status(status)
|
68
|
+
if !TRANSACTION_STATES.include?(status)
|
69
|
+
raise "unknown status: #{status}".inspect
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_order(tid)
|
74
|
+
if (order = Order.find(tid)).nil?
|
75
|
+
raise "could not find order: #{tid}".inspect
|
76
|
+
end
|
77
|
+
|
78
|
+
return order
|
79
|
+
end
|
80
|
+
|
81
|
+
def verify_currency(order, currency)
|
82
|
+
"EUR" == currency
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Admin::PaymentsHelper
|
2
|
+
def payment_method_name(payment)
|
3
|
+
# hack to allow us to retrieve the name of a "deleted" payment method
|
4
|
+
id = payment.payment_method_id
|
5
|
+
# hack because the payment method is not set in the mpay confirmation controller. fix it
|
6
|
+
if id == nil then
|
7
|
+
PaymentMethod.find_by_id(842616224).name
|
8
|
+
else
|
9
|
+
|
10
|
+
# TODO: include destroyed payment methods
|
11
|
+
method = PaymentMethod.find_by_id(id)
|
12
|
+
|
13
|
+
# somehow we've got invalid payment methods in our system
|
14
|
+
if method.nil?
|
15
|
+
PaymentMethod.find_by_id(842616224).name
|
16
|
+
else
|
17
|
+
method.name
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module MpayHelper
|
2
|
+
def humanize_p_type(p_type)
|
3
|
+
case p_type
|
4
|
+
when "CC"
|
5
|
+
t('CC')
|
6
|
+
else
|
7
|
+
t('Uknown')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def payment_method(order)
|
12
|
+
return "" unless order
|
13
|
+
return "" if order.checkout.payments.empty?
|
14
|
+
return "" if order.checkout.payment.source.nil?
|
15
|
+
return "" unless order.checkout.payment.source.is_a?(MPaySource)
|
16
|
+
|
17
|
+
"#{humanize_p_type(order.checkout.payment.source.p_type)}: #{order.checkout.payment.source.brand}"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'net/https'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
# Integrate our payment gateway with spree. This is needed
|
5
|
+
# to allow configuration through spree's web interface, etc.
|
6
|
+
class BillingIntegration::Mpay < BillingIntegration
|
7
|
+
|
8
|
+
preference :production_merchant_id, :string
|
9
|
+
preference :test_merchant_id, :string
|
10
|
+
preference :url, :string, :default => 'http://trageboutiquedev.com/'
|
11
|
+
preference :secret_phrase, :string
|
12
|
+
|
13
|
+
TEST_REDIRECT_URL = 'https://test.mPAY24.com/app/bin/etpv5'
|
14
|
+
PRODUCTION_REDIRECT_URL = 'https://www.mpay24.com/app/bin/etpv5'
|
15
|
+
MPAY24_IP = "213.164.25.245"
|
16
|
+
MPAY24_TEST_IP = "213.164.23.169"
|
17
|
+
|
18
|
+
def provider_class
|
19
|
+
ActiveMerchant::Billing::MpayGateway
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.current
|
23
|
+
# I'm not sure why I'm needing RAILS_ENV.to_s. It looks like a string
|
24
|
+
# but cannot otherwise be compared to another string
|
25
|
+
BillingIntegration::Mpay.where(:active => true).where(:environment => RAILS_ENV.to_s).first
|
26
|
+
end
|
27
|
+
|
28
|
+
def verify_ip(request)
|
29
|
+
if request.env['REMOTE_ADDR'] != mpay24_ip
|
30
|
+
if request.env['REMOTE_ADDR'] == "127.0.0.1"
|
31
|
+
#maybe we've gotten forwarded by the nginx reverse proxy
|
32
|
+
if request.env.include?('HTTP_X_FORWARDED_FOR')
|
33
|
+
ips = request.env['HTTP_X_FORWARDED_FOR'].split(',').map(&:strip)
|
34
|
+
if ips[1] != mpay24_ip
|
35
|
+
raise "invalid forwarded originator IP of x#{ips[1]}x vs #{mpay24_ip}".inspect
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise request.env.inspect
|
39
|
+
end
|
40
|
+
else
|
41
|
+
raise "invalid originator IP of #{request.env['REMOTE_ADDR']} vs #{mpay24_ip}".inspect
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_order(tid)
|
47
|
+
if prefers_secret_phrase?
|
48
|
+
if tid.starts_with?(preferred_secret_phrase)
|
49
|
+
tid = tid.gsub(/^#{preferred_secret_phrase}_/, "")
|
50
|
+
else
|
51
|
+
raise "unknown secret phrase: #{tid}".inspect
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Order.find(:first, :conditions => { :id => tid })
|
56
|
+
end
|
57
|
+
|
58
|
+
def gateway_url
|
59
|
+
prefers_test_mode? ? TEST_REDIRECT_URL : PRODUCTION_REDIRECT_URL
|
60
|
+
end
|
61
|
+
|
62
|
+
def mpay24_ip
|
63
|
+
prefers_test_mode? ? MPAY24_TEST_IP : MPAY24_IP
|
64
|
+
end
|
65
|
+
|
66
|
+
def merchant_id
|
67
|
+
prefers_test_mode? ? preferred_test_merchant_id : preferred_production_merchant_id
|
68
|
+
end
|
69
|
+
|
70
|
+
# generate the iframe URL
|
71
|
+
def generate_url(order)
|
72
|
+
|
73
|
+
cmd = generate_mdxi(order)
|
74
|
+
|
75
|
+
# send the HTTP request
|
76
|
+
response = send_request(merchant_id, cmd)
|
77
|
+
|
78
|
+
result = parse_result(response)
|
79
|
+
|
80
|
+
# if everything did work out: return the link url. Otherwise
|
81
|
+
# output an ugly exception (at least we will get notified)
|
82
|
+
if result["STATUS"] == "OK" && result["RETURNCODE"] == "REDIRECT"
|
83
|
+
order.created_at = Time.now
|
84
|
+
order.save!
|
85
|
+
return result["LOCATION"].chomp
|
86
|
+
else
|
87
|
+
raise response.body.inspect
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def parse_result(response)
|
94
|
+
result = {}
|
95
|
+
|
96
|
+
response.body.split('&').each do |part|
|
97
|
+
key, value = part.split("=")
|
98
|
+
result[key] = CGI.unescape(value)
|
99
|
+
end
|
100
|
+
|
101
|
+
result
|
102
|
+
end
|
103
|
+
|
104
|
+
def generate_tid(order_id)
|
105
|
+
if prefers_secret_phrase?
|
106
|
+
"#{preferred_secret_phrase}_#{order_id}"
|
107
|
+
else
|
108
|
+
order_id
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def send_request(merchant_id, cmd)
|
113
|
+
url = URI.parse(gateway_url)
|
114
|
+
request = Net::HTTP::Post.new(url.path,{"Content-Type"=>"text/xml"})
|
115
|
+
http = Net::HTTP.new(url.host, url.port)
|
116
|
+
|
117
|
+
# verify through SSL
|
118
|
+
http.use_ssl = true
|
119
|
+
http.ca_path = "/etc/ssl/certs/"
|
120
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
121
|
+
http.verify_depth = 5
|
122
|
+
|
123
|
+
request = Net::HTTP::Post.new(url.request_uri)
|
124
|
+
request.set_form_data({
|
125
|
+
'OPERATION' => 'SELECTPAYMENT',
|
126
|
+
'MERCHANTID' => merchant_id,
|
127
|
+
'MDXI' => cmd
|
128
|
+
})
|
129
|
+
|
130
|
+
http.request(request)
|
131
|
+
end
|
132
|
+
|
133
|
+
def generate_mdxi(order)
|
134
|
+
xml = Builder::XmlMarkup.new
|
135
|
+
xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
136
|
+
xml.tag! 'Order' do
|
137
|
+
xml.tag! 'Tid', generate_tid(order.id)
|
138
|
+
xml.tag! 'ShoppingCart' do
|
139
|
+
xml.tag! 'Description', order.number
|
140
|
+
|
141
|
+
order.line_items.each do |li|
|
142
|
+
xml.tag! 'Item' do
|
143
|
+
xml.tag! 'Description', li.variant.product.name
|
144
|
+
xml.tag! 'Quantity', li.quantity
|
145
|
+
xml.tag! 'ItemPrice', sprintf("%.2f", li.price)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
order.update_totals
|
150
|
+
|
151
|
+
xml.tag! 'Tax', sprintf("%.2f", order.tax_total)
|
152
|
+
|
153
|
+
# TODO is this the same as order.credit_total?
|
154
|
+
discounts = order.adjustment_total
|
155
|
+
xml.tag! 'Discount', sprintf("%.2f", discounts)
|
156
|
+
|
157
|
+
xml.tag! 'ShippingCosts', sprintf("%.2f", order.ship_total)
|
158
|
+
end
|
159
|
+
|
160
|
+
xml.tag! 'Price', sprintf("%.2f", order.total)
|
161
|
+
|
162
|
+
xml.tag! 'BillingAddr', :Mode => 'ReadWrite' do
|
163
|
+
xml.tag! 'Name', "#{order.ship_address.firstname} #{order.ship_address.lastname}"
|
164
|
+
xml.tag! 'Street', order.bill_address.address1
|
165
|
+
xml.tag! 'Street2', order.bill_address.address2
|
166
|
+
xml.tag! 'Zip', order.bill_address.zipcode
|
167
|
+
xml.tag! 'City', order.bill_address.city
|
168
|
+
xml.tag! 'State', order.bill_address.state_name
|
169
|
+
xml.tag! 'Country', order.bill_address.country.name
|
170
|
+
xml.tag! 'Email', order.email
|
171
|
+
end
|
172
|
+
|
173
|
+
xml.tag! 'ShippingAddr', :Mode => 'ReadOnly' do
|
174
|
+
xml.tag! 'Name', "#{order.ship_address.firstname} #{order.ship_address.lastname}"
|
175
|
+
xml.tag! 'Street', order.ship_address.address1
|
176
|
+
xml.tag! 'Street2', order.ship_address.address2
|
177
|
+
xml.tag! 'Zip', order.ship_address.zipcode
|
178
|
+
xml.tag! 'City', order.ship_address.city
|
179
|
+
xml.tag! 'State', order.ship_address.state_name
|
180
|
+
xml.tag! 'Country', order.ship_address.country.name
|
181
|
+
xml.tag! 'Email', order.email
|
182
|
+
end
|
183
|
+
xml.tag! 'URL' do
|
184
|
+
xml.tag! 'Success', "#{preferred_url}/mpay_callbacks"
|
185
|
+
xml.tag! 'Confirmation', "#{preferred_url}/mpay_confirmation"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
xml.target!
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<table class="index">
|
2
|
+
<tr>
|
3
|
+
<th><%= "#{t('spree.date')}/#{t('spree.time')}" %></th>
|
4
|
+
<th><%= t("amount") %></th>
|
5
|
+
<th><%= t("payment_method") %></th>
|
6
|
+
<th></th>
|
7
|
+
</tr>
|
8
|
+
<% payments.each do |payment| %>
|
9
|
+
<tr>
|
10
|
+
<td><%= payment.created_at.to_s(:date_time24) %></td>
|
11
|
+
<td>
|
12
|
+
<% if payment.source_type == 'MPaySource' %>
|
13
|
+
<%= number_to_currency(payment.amount/100) %>
|
14
|
+
<% else %>
|
15
|
+
<%= number_to_currency(payment.amount) %>
|
16
|
+
<% end %>
|
17
|
+
</td>
|
18
|
+
<td><%= payment_method_name payment %></td>
|
19
|
+
<td>
|
20
|
+
<%= link_to t('show'), admin_order_payment_path(@order, payment) %>
|
21
|
+
<% payment.actions.each do |action| %>
|
22
|
+
<%= link_to t(action), fire_admin_order_payment_path(@order, payment, :e => action), :method => :put, :confirm => t('are_you_sure') %>
|
23
|
+
<% end %>
|
24
|
+
<% if payment.actions.empty? and !payment.finalized? %>
|
25
|
+
<%= link_to t(:finalize), finalize_admin_order_payment_path(@order, payment), :method => :put, :confirm => t('are_you_sure') %>
|
26
|
+
<% end %>
|
27
|
+
</td>
|
28
|
+
</tr>
|
29
|
+
<% end %>
|
30
|
+
</table>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= render :partial => 'admin/shared/order_tabs', :locals => {:current => "Payments"} %>
|
2
|
+
|
3
|
+
<h2><%= t("activerecord.models.#{@object.class.to_s.underscore}.one") %></h2>
|
4
|
+
|
5
|
+
<p>
|
6
|
+
<label><%= t("amount") %>:</label></td>
|
7
|
+
<% if @payment.source_type == 'MPaySource' %>
|
8
|
+
<%= object.amount/100 %>
|
9
|
+
<% else %>
|
10
|
+
<%= object.amount %>
|
11
|
+
<% end %>
|
12
|
+
</p>
|
13
|
+
|
14
|
+
<% if @payment.payment_method.nil? %>
|
15
|
+
<%= render "admin/payments/source_views/#{PaymentMethod.find_by_id(842616224).method_type}", :payment => object %>
|
16
|
+
<% else %>
|
17
|
+
<%= render "admin/payments/source_views/#{@payment.payment_method.method_type}", :payment => object %>
|
18
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>What do you wnat?</h1>
|
File without changes
|
@@ -0,0 +1,7 @@
|
|
1
|
+
de:
|
2
|
+
test_merchant_id: Merchant ID (Testmodus)
|
3
|
+
production_merchant_id: Merchant ID (Production)
|
4
|
+
url: Basis-URL
|
5
|
+
secret_phrase: this is added to the sent TID. As long as all communication is done through SSL/TLS encryption this prevents injection attacks.
|
6
|
+
CC: "Kreditkarte"
|
7
|
+
Unknown: "Unbekannt"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateMPaySources < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :m_pay_sources do |t|
|
4
|
+
t.string :mpayid
|
5
|
+
t.string :brand
|
6
|
+
t.string :p_type
|
7
|
+
t.integer :payment_id
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :m_pay_sources
|
15
|
+
end
|
16
|
+
end
|
data/db/seeds.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module ActiveMerchant
|
5
|
+
module Billing
|
6
|
+
class MPayGateway < Gateway
|
7
|
+
|
8
|
+
self.test_mode = true
|
9
|
+
self.test_redirect_url = 'https://test.mPAY24.com/app/bin/etpv5';
|
10
|
+
self.test_merchant_id = '92035'
|
11
|
+
self.production_merchant_id = '72035'
|
12
|
+
self.production_redirect_url = 'https://www.mpay24.com/app/bin/etpv5';
|
13
|
+
|
14
|
+
# move this to the other thing?
|
15
|
+
def gateway_url
|
16
|
+
self.test_mode == true ? self.test_redirect_url : self.production_redirect_url
|
17
|
+
end
|
18
|
+
|
19
|
+
def merchant_id
|
20
|
+
self.test_mode == true ? self.test_merchant_id : self.production_merchant_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup_authorization(money, options = {})
|
24
|
+
# TODO: howto use the options infrastructure
|
25
|
+
merchant_id = merchant_id
|
26
|
+
operation = 'SELECTPAYMENT'
|
27
|
+
|
28
|
+
# TODO: merge options
|
29
|
+
|
30
|
+
# build MDXI XML Block
|
31
|
+
xml = Bulder::XmlMarkup.new
|
32
|
+
xml.tag! 'order' do
|
33
|
+
xml.tag! 'Tid', 'some order identifier'
|
34
|
+
xml.tag! 'ShoppingCart' do
|
35
|
+
xml.tag! 'Description', 'some description'
|
36
|
+
end
|
37
|
+
|
38
|
+
xml.tag! 'price', amount(money)
|
39
|
+
xml.tag! 'BillingAddr', :mode => 'ReadWrite' do
|
40
|
+
xml.tag! 'Name', options[:shipping_address][:name]
|
41
|
+
xml.tag! 'City', options[:shipping_address][:city]
|
42
|
+
xml.tag! 'Street', options[:shipping_address][:street]
|
43
|
+
#TODO: add more address stuff from options hash
|
44
|
+
end
|
45
|
+
|
46
|
+
xml.tag! 'URL' do
|
47
|
+
xml.tag! 'Confirmation', 'some-confirmation-url'
|
48
|
+
xml.tag! 'Notifcation', mpay_callbacks_url
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
cmd = xml.build!
|
53
|
+
|
54
|
+
# build and send the command
|
55
|
+
res = Net::HTTP.post_form(URI.parse(self.test_redirect_url),
|
56
|
+
{
|
57
|
+
'operation' => operation,
|
58
|
+
'merchant_id' => merchant_id,
|
59
|
+
'MDXI' => cmd
|
60
|
+
})
|
61
|
+
|
62
|
+
# extract information
|
63
|
+
raise res.inspect
|
64
|
+
|
65
|
+
#3: Detailed control
|
66
|
+
#url = URI.parse('http://www.example.com/todo.cgi')
|
67
|
+
#req = Net::HTTP::Post.new(url.path)
|
68
|
+
#req.basic_auth 'jack', 'pass'
|
69
|
+
#req.set_form_data({'from'=>'2005-01-01', 'to'=>'2005-03-31'}, ';')
|
70
|
+
#res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
|
71
|
+
#case res
|
72
|
+
#when Net::HTTPSuccess, Net::HTTPRedirection
|
73
|
+
# OK
|
74
|
+
#else
|
75
|
+
# res.error!
|
76
|
+
#end
|
77
|
+
|
78
|
+
# render the corresponding URL in an IFRAME
|
79
|
+
render :partial => 'shared/mpay_confirm',
|
80
|
+
:locals => { :iframe_url => "fubar" },
|
81
|
+
:layout => true
|
82
|
+
end
|
83
|
+
|
84
|
+
def authorize(money, options={})
|
85
|
+
raise "mpaygateway.authorize called".inspect
|
86
|
+
end
|
87
|
+
|
88
|
+
def purchase(money, options={})
|
89
|
+
raise "mpaygateway.purchase called".inspect
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/mpay_gateway.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spree_core'
|
2
|
+
|
3
|
+
class MpayGateway < Rails::Engine
|
4
|
+
|
5
|
+
config.autoload_paths += %W(#{config.root}/lib)
|
6
|
+
|
7
|
+
def self.activate
|
8
|
+
|
9
|
+
Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
|
10
|
+
Rails.env.production? ? require(c) : load(c)
|
11
|
+
end
|
12
|
+
|
13
|
+
# load billing stuff
|
14
|
+
BillingIntegration::Mpay.register
|
15
|
+
|
16
|
+
# integrate our god-frickin' view helper
|
17
|
+
Spree::BaseController.class_eval do
|
18
|
+
helper MpayHelper
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
config.to_prepare &method(:activate).to_proc
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
namespace :mpay_gateway do
|
2
|
+
desc "Copies all migrations and assets (NOTE: This will be obsolete with Rails 3.1)"
|
3
|
+
task :install do
|
4
|
+
Rake::Task['mpay_gateway:install:migrations'].invoke
|
5
|
+
Rake::Task['mpay_gateway:install:assets'].invoke
|
6
|
+
end
|
7
|
+
|
8
|
+
namespace :install do
|
9
|
+
desc "Copies all migrations (NOTE: This will be obsolete with Rails 3.1)"
|
10
|
+
task :migrations do
|
11
|
+
source = File.join(File.dirname(__FILE__), '..', '..', 'db')
|
12
|
+
destination = File.join(Rails.root, 'db')
|
13
|
+
Spree::FileUtilz.mirror_files(source, destination)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Copies all assets (NOTE: This will be obsolete with Rails 3.1)"
|
17
|
+
task :assets do
|
18
|
+
source = File.join(File.dirname(__FILE__), '..', '..', 'public')
|
19
|
+
destination = File.join(Rails.root, 'public')
|
20
|
+
puts "INFO: Mirroring assets from #{source} to #{destination}"
|
21
|
+
Spree::FileUtilz.mirror_files(source, destination)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# add custom rake tasks here
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mpay_gateway
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 41
|
8
|
+
version: "0.41"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Andreas Happe
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2011-03-05 00:00:00 +01:00
|
17
|
+
default_executable:
|
18
|
+
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: spree_core
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 40
|
30
|
+
- 3
|
31
|
+
version: 0.40.3
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Integrates the mpay24 credit card and online payment processing system into the spree web shop
|
35
|
+
email: andreashappe@starseeders.net
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- README.markdown
|
44
|
+
- lib/active_merchant/billing/gateways/mpay.rb
|
45
|
+
- lib/mpay_gateway.rb
|
46
|
+
- lib/tasks/install.rake
|
47
|
+
- lib/tasks/mpay_gateway.rake
|
48
|
+
- app/controllers/mpay_callbacks_controller.rb
|
49
|
+
- app/controllers/mpay_confirmation_controller.rb
|
50
|
+
- app/helpers/admin/payments_helper.rb
|
51
|
+
- app/helpers/mpay_helper.rb
|
52
|
+
- app/models/billing_integration/mpay.rb
|
53
|
+
- app/models/m_pay_source.rb
|
54
|
+
- app/views/admin/payments/_list.html.erb
|
55
|
+
- app/views/admin/payments/show.html.erb
|
56
|
+
- app/views/admin/payments/source_forms/_mpay.html.erb
|
57
|
+
- app/views/admin/payments/source_views/_mpay.html.erb
|
58
|
+
- app/views/checkout/payment/_mpay.html.erb
|
59
|
+
- app/views/shared/_mpay_confirm.html.erb
|
60
|
+
- app/views/shared/_mpay_success.html.erb
|
61
|
+
- config/locales/de.yml
|
62
|
+
- config/locales/en.yml
|
63
|
+
- config/routes.rb
|
64
|
+
- db/migrate/20101010085758_create_m_pay_sources.rb
|
65
|
+
- db/seeds.rb
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://github.com/andreashappe/spree-mpay24
|
68
|
+
licenses: []
|
69
|
+
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 1
|
82
|
+
- 8
|
83
|
+
- 7
|
84
|
+
version: 1.8.7
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
requirements:
|
94
|
+
- none
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.3.7
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: MPay24 Payment gateway for Spree 0.40+
|
100
|
+
test_files: []
|
101
|
+
|