spree_unified_payment 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/.travis.yml +6 -0
- data/Gemfile +20 -0
- data/LICENSE +26 -0
- data/README.md +61 -0
- data/Versionfile +12 -0
- data/app/assets/javascripts/admin/spree_unified_payment.js +39 -0
- data/app/assets/stylesheets/store/spree_unified_payment.css +7 -0
- data/app/controllers/application_controller.rb +2 -0
- data/app/controllers/spree/admin/unified_payments_controller.rb +34 -0
- data/app/controllers/spree/checkout_controller_decorator.rb +19 -0
- data/app/controllers/spree/unified_payments_controller.rb +151 -0
- data/app/helpers/transaction_notification_mail_helper.rb +12 -0
- data/app/helpers/unified_transaction_helper.rb +18 -0
- data/app/mailers/spree/transaction_notification_mailer.rb +16 -0
- data/app/models/spree/order_decorator.rb +67 -0
- data/app/models/spree/payment_method/unified_payment_method.rb +34 -0
- data/app/models/spree/store_credit_decorator.rb +4 -0
- data/app/models/spree/user_decorator.rb +7 -0
- data/app/models/unified_payment/transaction_decorator.rb +102 -0
- data/app/overrides/add_unified_tabs_to_admin_menu.rb +6 -0
- data/app/views/spree/admin/unified_payments/index.html.erb +98 -0
- data/app/views/spree/admin/unified_payments/query_gateway.js.erb +10 -0
- data/app/views/spree/admin/unified_payments/receipt.html.erb +20 -0
- data/app/views/spree/checkout/payment/_unifiedpaymentmethod.html.erb +24 -0
- data/app/views/spree/transaction_notification_mailer/send_mail.html.erb +20 -0
- data/app/views/spree/unified_payments/approved.html.erb +25 -0
- data/app/views/spree/unified_payments/canceled.html.erb +1 -0
- data/app/views/spree/unified_payments/create.html.erb +8 -0
- data/app/views/spree/unified_payments/create.js.erb +3 -0
- data/app/views/spree/unified_payments/declined.html.erb +4 -0
- data/app/views/spree/unified_payments/index.html.erb +28 -0
- data/app/views/spree/unified_payments/new.html.erb +35 -0
- data/app/views/spree/unified_payments/new.js.erb +3 -0
- data/config/initializers/constants.rb +8 -0
- data/config/routes.rb +15 -0
- data/db/migrate/20140120075553_add_transaction_fields_to_unified_payment_transactions.rb +14 -0
- data/db/migrate/20140120081453_add_unified_transaction_id_to_spree_store_credits.rb +6 -0
- data/lib/generators/spree_unified_payment/install/install_generator.rb +27 -0
- data/lib/spree_unified_payment/engine.rb +26 -0
- data/lib/spree_unified_payment.rb +2 -0
- data/lib/transaction_expiration.rb +9 -0
- data/spec/constants_spec.rb +11 -0
- data/spec/controllers/spree/admin/unified_payments_controller_spec.rb +155 -0
- data/spec/controllers/spree/checkout_controller_decorator_spec.rb +114 -0
- data/spec/controllers/spree/unified_payments_controller_spec.rb +509 -0
- data/spec/mailers/transaction_notification_mailer_spec.rb +48 -0
- data/spec/models/spree/order_decorator_spec.rb +206 -0
- data/spec/models/spree/payment_method/unified_payment_spec.rb +25 -0
- data/spec/models/spree/store_credit_decorator_spec.rb +11 -0
- data/spec/models/spree/user_decorator_spec.rb +12 -0
- data/spec/models/unified_payment/transaction_decorator_spec.rb +483 -0
- data/spec/spec_helper.rb +66 -0
- data/spree_unified_payment.gemspec +23 -0
- metadata +184 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
gem 'rails', '3.2.16'
|
3
|
+
gem 'mysql2'
|
4
|
+
|
5
|
+
|
6
|
+
gem 'spree', :git => 'git://github.com/spree/spree.git', :tag => 'v2.0.3'
|
7
|
+
gem 'spree_wallet', :git => 'git://github.com/vinsol/spree_wallet.git'
|
8
|
+
gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '2-0-stable'
|
9
|
+
|
10
|
+
gem 'unified_payment', :git => "git@github.com:vinsol/Unified-Payments.git", :branch => 'master', :ref => '4ced91335fec2cf186c30b593d9a1f6083028748'
|
11
|
+
gem 'delayed_job_active_record', :tag => 'v4.0.0'
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem 'rspec-rails', '~> 2.10'
|
15
|
+
gem 'shoulda-matchers', '2.2.0'
|
16
|
+
gem 'simplecov', :require => false
|
17
|
+
gem 'database_cleaner'
|
18
|
+
gem 'rspec-html-matchers'
|
19
|
+
end
|
20
|
+
gemspec
|
data/LICENSE
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Copyright (c) 2014 vinsol.com
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
* Neither the name Spree nor the names of its contributors may be used to
|
13
|
+
endorse or promote products derived from this software without specific
|
14
|
+
prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
17
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
18
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
19
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
20
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
21
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
22
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
23
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
24
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
25
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
26
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
Spree-Unified-Payments [![Code Climate](https://codeclimate.com/github/vinsol/Spree-Unified-Payments.png)](https://codeclimate.com/github/vinsol/Spree-Unified-Payments)
|
2
|
+
================
|
3
|
+
Enable spree store to allow payment via UnifiedPayment
|
4
|
+
|
5
|
+
Dependencies
|
6
|
+
================
|
7
|
+
|
8
|
+
1) gem unified_payment
|
9
|
+
```ruby
|
10
|
+
gem 'unified_payment'
|
11
|
+
```
|
12
|
+
2) delayed_job
|
13
|
+
```ruby
|
14
|
+
gem 'delayed_job_active_record'
|
15
|
+
```
|
16
|
+
3) spree_wallet
|
17
|
+
```ruby
|
18
|
+
gem 'spree_wallet'
|
19
|
+
```
|
20
|
+
|
21
|
+
Set Up
|
22
|
+
================
|
23
|
+
|
24
|
+
Add To Gemfile:
|
25
|
+
```ruby
|
26
|
+
gem 'spree_unified_payment'
|
27
|
+
```
|
28
|
+
|
29
|
+
And run below command
|
30
|
+
```ruby
|
31
|
+
bundle exec rails g spree_unified_payment:install
|
32
|
+
```
|
33
|
+
Usage
|
34
|
+
---------
|
35
|
+
Customer :
|
36
|
+
|
37
|
+
Customer can pay via Unified Payment payment method at Checkout and can also see the list of Unified Payment Transactions initiated by them.
|
38
|
+
|
39
|
+
If a transaction is completed but the order fails to complete, the amount paid by the customer is added to the customer's account which he can use in future so that the user does not get stuck while making the payment.
|
40
|
+
|
41
|
+
Admin :
|
42
|
+
|
43
|
+
Admin can see the list of Unified Payment Transactions initiated by customers under admin section.
|
44
|
+
|
45
|
+
Admin can also ping Unified Payment gateway for an updated status of a transaction and the transaction is then updated accordingly.
|
46
|
+
|
47
|
+
Testing
|
48
|
+
---------
|
49
|
+
Be sure to bundle your dependencies and then create a dummy test app for the specs to run against.
|
50
|
+
```ruby
|
51
|
+
bundle
|
52
|
+
bundle exec rake test_app
|
53
|
+
bundle exec rspec spec
|
54
|
+
```
|
55
|
+
|
56
|
+
Credits
|
57
|
+
-------
|
58
|
+
|
59
|
+
[![vinsol.com: Ruby on Rails, iOS and Android developers](http://vinsol.com/vin_logo.png "Ruby on Rails, iOS and Android developers")](http://vinsol.com)
|
60
|
+
|
61
|
+
Copyright (c) 2014 [vinsol.com](http://vinsol.com "Ruby on Rails, iOS and Android developers"), released under the New MIT License
|
data/Versionfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# This file is used to designate compatibilty with different versions of Spree
|
2
|
+
# Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
|
3
|
+
|
4
|
+
# Examples
|
5
|
+
#
|
6
|
+
# '1.2.x' => { :branch => 'master' }
|
7
|
+
# '1.1.x' => { :branch => '1-1-stable' }
|
8
|
+
# '1.0.x' => { :branch => '1-0-stable' }
|
9
|
+
# '0.70.x' => { :branch => '0-70-stable' }
|
10
|
+
# '0.40.x' => { :tag => 'v1.0.0', :version => '1.0.0' }
|
11
|
+
|
12
|
+
"1.0.x" => { :branch => '2-0-stable' }
|
@@ -0,0 +1,39 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
click_on_overlay = function(pop_up_div) {
|
3
|
+
$('div.ui-widget-overlay').on('click', function(){
|
4
|
+
$('div.ui-widget-overlay').remove();
|
5
|
+
pop_up_div.dialog("close");
|
6
|
+
});
|
7
|
+
}
|
8
|
+
|
9
|
+
ModalPopUp = function(pop_up_div) {
|
10
|
+
var self = {
|
11
|
+
init: function() {
|
12
|
+
pop_up_div.dialog({
|
13
|
+
autoOpen: false,
|
14
|
+
modal: true,
|
15
|
+
width:700,
|
16
|
+
closeText: "X",
|
17
|
+
dialogClass:"quick_view_container",
|
18
|
+
close: function(event, ui) {
|
19
|
+
pop_up_div.remove();
|
20
|
+
$('#easy_zoom').remove();
|
21
|
+
}
|
22
|
+
});
|
23
|
+
},
|
24
|
+
show: function() {
|
25
|
+
pop_up_div.dialog("open");
|
26
|
+
click_on_overlay(pop_up_div);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
self.init();
|
30
|
+
return self;
|
31
|
+
}
|
32
|
+
|
33
|
+
$('#reveal_xml').click(function() {
|
34
|
+
ct_id = $(this).attr('data-ct-id');
|
35
|
+
var quick_view = new ModalPopUp($("<div></div>").attr('id', 'quick_view_popup').html($("#xml_response_" + ct_id).clone()));
|
36
|
+
$('#quick_view_popup .xml_response').removeClass('hidden');
|
37
|
+
quick_view.show();
|
38
|
+
})
|
39
|
+
});
|
@@ -0,0 +1,7 @@
|
|
1
|
+
#approved_notice { font-family:Georgia, 'Times New Roman', Times, serif; letter-spacing:2px; font-size:12px; text-transform:uppercase; padding:20px; border:solid 1px #3333ff; background:#dedeff; color:#3333ff }
|
2
|
+
#unified_payments_approved_info { width:100%; border:0px; cellspacing: 15; cellpadding: 0; }
|
3
|
+
#unified_payments_approved_info td.info_attr { color:#000; font-family:Georgia, 'Times New Roman', Times, serif; letter-spacing:2px; font-size:12px; text-transform:uppercase; }
|
4
|
+
#unified_payments_approved_info td.info_val { font-family:Arial, Helvetica, sans-serif; font-size:12px; color:#666; }
|
5
|
+
#unified_payment_detail_link_container { display:block; padding:10px 0; font-family:Arial, Helvetica, sans-serif; font-size:14px; font-weight:bold; }
|
6
|
+
#unified_payment_detail_link_container a { text-decoration:underline; color:#09F; }
|
7
|
+
#approved_fail_notice { color:#EC1B23; border:solid 1px #EC1B23; font-family:Georgia, 'Times New Roman', Times, serif; letter-spacing:2px; font-size:12px; text-transform:uppercase; text-align:center; padding:20px 0; background:#ffe0e0; }
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Spree
|
2
|
+
module Admin
|
3
|
+
class UnifiedPaymentsController < Spree::Admin::BaseController
|
4
|
+
helper 'transaction_notification_mail'
|
5
|
+
|
6
|
+
before_filter :load_transactions, :only => [:query_gateway, :receipt]
|
7
|
+
|
8
|
+
def index
|
9
|
+
params[:q] ||= {}
|
10
|
+
@search = UnifiedPayment::Transaction.order('updated_at desc').ransack(params[:q])
|
11
|
+
@card_transactions = @search.result.page(params[:page]).per(20)
|
12
|
+
end
|
13
|
+
|
14
|
+
def receipt
|
15
|
+
@order = @card_transaction.order
|
16
|
+
doc = Nokogiri::XML(@card_transaction.xml_response)
|
17
|
+
@message = Hash.from_xml(doc.to_xml)['Message']
|
18
|
+
render :layout => false
|
19
|
+
end
|
20
|
+
|
21
|
+
def query_gateway
|
22
|
+
response = UnifiedPayment::Client.get_order_status(@card_transaction.gateway_order_id, @card_transaction.gateway_session_id)
|
23
|
+
@card_transaction.update_transaction_on_query(response["orderStatus"])
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def load_transactions
|
29
|
+
@card_transaction = UnifiedPayment::Transaction.where(:payment_transaction_id => params[:transaction_id]).first
|
30
|
+
render js: "alert('Could not find transaction')" unless @card_transaction
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Spree::CheckoutController.class_eval do
|
2
|
+
before_filter :redirect_for_card_payment, :only => :update, :if => :payment_state?
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
def payment_state?
|
7
|
+
params[:state] == 'payment'
|
8
|
+
end
|
9
|
+
|
10
|
+
def redirect_for_card_payment
|
11
|
+
payment_method_id = params[:order][:payments_attributes][0][:payment_method_id] if params[:order] && params[:order][:payments_attributes]
|
12
|
+
payment_method = Spree::PaymentMethod.where(:id => payment_method_id).first
|
13
|
+
|
14
|
+
if payment_method.is_a?(Spree::PaymentMethod::UnifiedPaymentMethod)
|
15
|
+
@order.update_attributes(object_params)
|
16
|
+
redirect_to new_unified_transaction_path
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module Spree
|
2
|
+
#
|
3
|
+
# UnifiedPaymentsController controls payment via UnifiedPayment
|
4
|
+
# and has routes via methods : create, declined, canceled, approved
|
5
|
+
#
|
6
|
+
|
7
|
+
class UnifiedPaymentsController < StoreController
|
8
|
+
include UnifiedTransactionHelper
|
9
|
+
|
10
|
+
before_filter :ensure_valid_order, :only => [:new, :create]
|
11
|
+
skip_before_filter :verify_authenticity_token, :only => [:approved, :declined, :canceled]
|
12
|
+
|
13
|
+
before_filter :load_info_on_return, :only => [:declined, :canceled, :approved]
|
14
|
+
before_filter :ensure_session_transaction_id, :abort_pending_transactions, :only => :create
|
15
|
+
|
16
|
+
def index
|
17
|
+
@card_transactions = spree_current_user.unified_payments.order('updated_at desc').page(params[:page]).per(20)
|
18
|
+
end
|
19
|
+
|
20
|
+
def new
|
21
|
+
session[:transaction_id] = generate_transaction_id
|
22
|
+
end
|
23
|
+
|
24
|
+
def create
|
25
|
+
# We also can extract these options is a method.
|
26
|
+
#[MK] it was decided not giving any options since we want the requested to be redirected defined methods only
|
27
|
+
response = UnifiedPayment::Transaction.create_order_at_unified(@order.total, { :approve_url => approved_unified_payments_url, :cancel_url => canceled_unified_payments_url, :decline_url => declined_unified_payments_url, :description => "Purchasing items from #{Spree::Config[:site_name]}" })
|
28
|
+
if response
|
29
|
+
@payment_url = UnifiedPayment::Transaction.extract_url_for_unified_payment(response)
|
30
|
+
tasks_on_gateway_create_response(response, session[:transaction_id])
|
31
|
+
else
|
32
|
+
@error_message = "Could not create payment at unified, please pay by other methods or try again later."
|
33
|
+
end
|
34
|
+
|
35
|
+
render js: "$('#confirm_payment').hide();top.location.href = '#{@payment_url}'" if @payment_url
|
36
|
+
end
|
37
|
+
|
38
|
+
def declined
|
39
|
+
transaction_unsuccesful_with_message("Payment declined")
|
40
|
+
end
|
41
|
+
|
42
|
+
def canceled
|
43
|
+
transaction_unsuccesful_with_message("Successfully Canceled payment")
|
44
|
+
end
|
45
|
+
|
46
|
+
def approved
|
47
|
+
@transaction_expired = @card_transaction.expired_at?
|
48
|
+
@card_transaction.xml_response = params[:xmlmsg]
|
49
|
+
|
50
|
+
@payment_made = @gateway_message_hash['PurchaseAmountScr'].to_f
|
51
|
+
if @card_transaction.approved_at_gateway?
|
52
|
+
if @card_transaction.amount != @payment_made
|
53
|
+
process_unsuccessful_transaction
|
54
|
+
else
|
55
|
+
process_successful_transaction
|
56
|
+
end
|
57
|
+
else
|
58
|
+
add_error("Not Approved At Gateway")
|
59
|
+
end
|
60
|
+
|
61
|
+
@card_transaction.save(:validate => false)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def process_unsuccessful_transaction
|
67
|
+
add_error("Payment made was not same as requested to gateway. Please contact administrator for queries.")
|
68
|
+
@card_transaction.status = 'unsuccessful'
|
69
|
+
end
|
70
|
+
|
71
|
+
def process_successful_transaction
|
72
|
+
@card_transaction.status = 'successful'
|
73
|
+
|
74
|
+
if @transaction_expired
|
75
|
+
add_error("Payment was successful but transaction has expired. The payment made has been walleted in your account. Please contact administrator to help you further.")
|
76
|
+
elsif @order.paid? || @order.completed?
|
77
|
+
add_error("Order Already Paid Or Completed")
|
78
|
+
elsif @order.total != @payment_made
|
79
|
+
add_error("Payment made is different from order total. Payment made has been walleted to your account.")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def abort_pending_transactions
|
84
|
+
pending_card_transaction = @order.pending_card_transaction
|
85
|
+
pending_card_transaction.abort! if pending_card_transaction
|
86
|
+
end
|
87
|
+
|
88
|
+
def transaction_unsuccesful_with_message(message)
|
89
|
+
@card_transaction.assign_attributes(:status => 'unsuccessful', :xml_response => params[:xmlmsg])
|
90
|
+
@card_transaction.save(:validate => false)
|
91
|
+
flash[:error] = message
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_error(message)
|
95
|
+
flash[:error] = flash[:error] ? [flash[:error], message].join('. ') : message
|
96
|
+
end
|
97
|
+
|
98
|
+
def order_invalid_with_message
|
99
|
+
if current_order
|
100
|
+
current_order.reason_if_cant_pay_by_card
|
101
|
+
else
|
102
|
+
'Order not found'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def ensure_valid_order
|
107
|
+
if @invalid_order_message = order_invalid_with_message
|
108
|
+
flash[:error] = @invalid_order_message
|
109
|
+
|
110
|
+
redirect_to cart_path
|
111
|
+
else
|
112
|
+
load_order
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def load_order
|
117
|
+
@order = current_order
|
118
|
+
end
|
119
|
+
|
120
|
+
def load_info_on_return
|
121
|
+
@gateway_message_hash = Hash.from_xml(params[:xmlmsg])['Message']
|
122
|
+
if @card_transaction = UnifiedPayment::Transaction.where(:gateway_order_id => @gateway_message_hash['OrderID']).first
|
123
|
+
@order = @card_transaction.order
|
124
|
+
else
|
125
|
+
flash[:error] = 'No transaction. Please contact our support team.'
|
126
|
+
redirect_to root_path
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def tasks_on_gateway_create_response(response, transaction_id)
|
131
|
+
response_order = response['Order']
|
132
|
+
|
133
|
+
#[TODO_CR] Make required attributes protected and save them with without protection in the place where protection is not necessary.
|
134
|
+
#[MK] Please look into this change. Could not find a good way to implement it without much hastle.
|
135
|
+
gateway_transaction = UnifiedPayment::Transaction.where(:gateway_session_id => response_order['SessionID'], :gateway_order_id => response_order['OrderID'], :url => response_order['URL']).first
|
136
|
+
gateway_transaction.assign_attributes({:user_id => @order.user.try(:id), :payment_transaction_id => transaction_id, :order_id => @order.id, :gateway_order_status => 'CREATED', :amount => @order.total, :currency => Spree::Config[:currency], :response_status => response["Status"], :status => 'pending'}, :without_protection => true)
|
137
|
+
gateway_transaction.save!
|
138
|
+
|
139
|
+
@order.reserve_stock
|
140
|
+
@order.next if @order.state == 'payment'
|
141
|
+
session[:transaction_id] = nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def ensure_session_transaction_id
|
145
|
+
unless session[:transaction_id]
|
146
|
+
flash[:error] = "No transaction id found, please try again"
|
147
|
+
render js: "top.location.href = '#{checkout_state_url('payment')}'"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module TransactionNotificationMailHelper
|
2
|
+
def mail_content_hash_for_unified(info_hash, card_transaction)
|
3
|
+
send_info = {}
|
4
|
+
|
5
|
+
UNIFIED_XML_CONTENT_MAPPING.each_pair { |key, value| send_info[key] = info_hash[value] }
|
6
|
+
|
7
|
+
send_info[:transaction_reference] = card_transaction.payment_transaction_id
|
8
|
+
send_info[:merchants_name] = MERCHANT_NAME
|
9
|
+
send_info[:merchants_url] = MERCHANT_URL
|
10
|
+
send_info
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module UnifiedTransactionHelper
|
2
|
+
def naira_to_kobo(amount)
|
3
|
+
(amount.to_f)*100
|
4
|
+
end
|
5
|
+
|
6
|
+
def generate_transaction_id
|
7
|
+
begin
|
8
|
+
payment_transaction_id = generate_id_using_timestamp
|
9
|
+
end while UnifiedPayment::Transaction.exists?(payment_transaction_id: payment_transaction_id)
|
10
|
+
payment_transaction_id
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def generate_id_using_timestamp(length = 14)
|
16
|
+
(Time.current.to_i.to_s + [*(0..9)].sample(4).join.to_s)[0,length]
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Spree
|
2
|
+
class TransactionNotificationMailer < ActionMailer::Base
|
3
|
+
helper 'transaction_notification_mail'
|
4
|
+
# helper 'application'
|
5
|
+
default :from => ADMIN_EMAIL
|
6
|
+
|
7
|
+
def send_mail(card_transaction)
|
8
|
+
@card_transaction = card_transaction
|
9
|
+
@message = @card_transaction.xml_response.include?('<Message') ? Hash.from_xml(@card_transaction.xml_response)['Message'] : {}
|
10
|
+
mail(
|
11
|
+
:to => @card_transaction.user.email,
|
12
|
+
:subject => "#{Spree::Config[:site_name]} - Unified Payment Transaction #{@card_transaction.status} notification"
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|