unified_payment 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +34 -0
- data/app/controllers/unified_payment/transactions_controller.rb +4 -0
- data/app/models/unified_payment/transaction.rb +24 -0
- data/app/views/unified_payment/transactions/index.html.erb +20 -0
- data/config/boot.rb +5 -0
- data/config/environment.rb +5 -0
- data/config/locales/en.yml +23 -0
- data/config/routes.rb +4 -0
- data/lib/generators/unified_payment/USAGE +8 -0
- data/lib/generators/unified_payment/install_generator.rb +26 -0
- data/lib/generators/unified_payment/templates/migrations/20131101092408_add_unified_payment_transactions.rb +23 -0
- data/lib/tasks/unified_payment_tasks.rake +4 -0
- data/lib/unified_payment.rb +27 -0
- data/lib/unified_payment/client.rb +148 -0
- data/lib/unified_payment/engine.rb +7 -0
- data/lib/unified_payment/utility.rb +13 -0
- data/lib/unified_payment/version.rb +3 -0
- data/spec/Libraries/client_spec.rb +152 -0
- data/spec/models/unified_payment/transaction_spec.rb +121 -0
- data/spec/spec_helper.rb +45 -0
- metadata +102 -0
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'UnifiedPayment'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
# APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
# load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module UnifiedPayment
|
2
|
+
class Transaction < ActiveRecord::Base
|
3
|
+
include Utility
|
4
|
+
self.table_name = "unified_payment_transactions"
|
5
|
+
attr_accessible :amount, :gateway_session_id, :gateway_order_id, :url, :merchant_id, :approval_code, :xml_response, :pan, :response_description, :response_status, :order_description, :currency, :gateway_order_status
|
6
|
+
|
7
|
+
def self.create_order_at_unified(amount, options)
|
8
|
+
3.times do |attempt|
|
9
|
+
begin
|
10
|
+
@response = Client.create_order((amount.to_f)*100, options)
|
11
|
+
create(:url => @response['url'], :gateway_order_id => @response['orderId'], :gateway_session_id => @response['sessionId'], :xml_response => @response['xml_response'].to_s)
|
12
|
+
break
|
13
|
+
rescue
|
14
|
+
@response = false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@response
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.extract_url_for_unified_payment(response)
|
21
|
+
response['url'] + '?' + 'ORDERID=' + response['orderId'] + '&' + 'SESSIONID=' + response['sessionId']
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<table>
|
2
|
+
<thead>
|
3
|
+
<tr>
|
4
|
+
<th>Gateway Session Id</th>
|
5
|
+
<th>Gateway Order Id</th>
|
6
|
+
<th>Url</th>
|
7
|
+
<th>Merchant Id</th>
|
8
|
+
<th>Approval Code</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<% UnifiedPayment::Transaction.all.each do |transaction| %>
|
12
|
+
<tr>
|
13
|
+
<td><%= transaction.gateway_session_id %></td>
|
14
|
+
<td><%= transaction.gateway_order_id %></td>
|
15
|
+
<td><%= transaction.url %></td>
|
16
|
+
<td><%= transaction.merchant_id %></td>
|
17
|
+
<td><%= transaction.approval_code %></td>
|
18
|
+
</tr>
|
19
|
+
<% end %>
|
20
|
+
</table>
|
data/config/boot.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Files in the config/locales directory are used for internationalization
|
2
|
+
# and are automatically loaded by Rails. If you want to use locales other
|
3
|
+
# than English, add the necessary files in this directory.
|
4
|
+
#
|
5
|
+
# To use the locales, use `I18n.t`:
|
6
|
+
#
|
7
|
+
# I18n.t 'hello'
|
8
|
+
#
|
9
|
+
# In views, this is aliased to just `t`:
|
10
|
+
#
|
11
|
+
# <%= t('hello') %>
|
12
|
+
#
|
13
|
+
# To use a different locale, set it with `I18n.locale`:
|
14
|
+
#
|
15
|
+
# I18n.locale = :es
|
16
|
+
#
|
17
|
+
# This would use the information in config/locales/es.yml.
|
18
|
+
#
|
19
|
+
# To learn more, please read the Rails Internationalization guide
|
20
|
+
# available at http://guides.rubyonrails.org/i18n.html.
|
21
|
+
|
22
|
+
en:
|
23
|
+
hello: "Hello world"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
module UnifiedPayment
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "Some description of my generator here"
|
5
|
+
|
6
|
+
# Commandline options can be defined here using Thor-like options:
|
7
|
+
class_option :my_opt, :type => :boolean, :default => false, :desc => "My Option"
|
8
|
+
|
9
|
+
# I can later access that option using:
|
10
|
+
# options[:my_opt]
|
11
|
+
|
12
|
+
|
13
|
+
def self.source_root
|
14
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
15
|
+
end
|
16
|
+
|
17
|
+
# Generator Code. Remember this is just suped-up Thor so methods are executed in order
|
18
|
+
def create_migrations
|
19
|
+
Dir["#{self.class.source_root}/migrations/*.rb"].sort.each do |filepath|
|
20
|
+
name = File.basename(filepath)
|
21
|
+
template "migrations/#{name}", "db/migrate/#{name}"
|
22
|
+
sleep 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class AddUnifiedPaymentTransactions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :unified_payment_transactions do |t|
|
4
|
+
t.integer :gateway_order_id
|
5
|
+
t.string :gateway_order_status
|
6
|
+
t.string :amount
|
7
|
+
t.string :gateway_session_id
|
8
|
+
t.string :url
|
9
|
+
t.string :merchant_id
|
10
|
+
t.string :currency
|
11
|
+
t.string :order_description
|
12
|
+
t.string :response_status
|
13
|
+
t.string :response_description
|
14
|
+
t.string :pan
|
15
|
+
t.string :approval_code
|
16
|
+
t.text :xml_response
|
17
|
+
t.timestamps
|
18
|
+
end
|
19
|
+
|
20
|
+
add_index :unified_payment_transactions, [:gateway_order_id, :gateway_session_id], name: :order_session_index
|
21
|
+
add_index :unified_payment_transactions, :response_status
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module UnifiedPayment
|
2
|
+
@config = {
|
3
|
+
:merchant_name => "verbose",
|
4
|
+
:base_uri => 'http://127.0.0.1:5555'
|
5
|
+
}
|
6
|
+
|
7
|
+
@valid_config_keys = @config.keys
|
8
|
+
|
9
|
+
# Configure through hash
|
10
|
+
def self.configure(opts = {})
|
11
|
+
opts.each {|k,v| @config[k.to_sym] = v if @valid_config_keys.include? k.to_sym}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Configure through yaml file
|
15
|
+
def self.configure_with(path_to_yaml_file)
|
16
|
+
config = YAML::load(IO.read(path_to_yaml_file))
|
17
|
+
global_config = config.select { |key, value| value.class != Hash } || {}
|
18
|
+
env_config = config[Rails.env] || {}
|
19
|
+
config = global_config.merge(env_config)
|
20
|
+
configure(config)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.config
|
24
|
+
@config
|
25
|
+
end
|
26
|
+
end
|
27
|
+
require "unified_payment/engine"
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'builder'
|
3
|
+
module UnifiedPayment
|
4
|
+
# This is the usual error raised on any UnifiedPayment related Errors
|
5
|
+
class Error < RuntimeError
|
6
|
+
|
7
|
+
attr_accessor :http_response, :error, :user_error
|
8
|
+
|
9
|
+
def initialize(error, xml_response=nil, user_error=nil)
|
10
|
+
@error = error
|
11
|
+
@xml_response = xml_response
|
12
|
+
@user_error = user_error
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
return "#{ user_error } (#{ error })" if user_error
|
17
|
+
"#{ error }"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class Client
|
23
|
+
|
24
|
+
MERCHANT_NAME = UnifiedPayment.config[:merchant_name]
|
25
|
+
|
26
|
+
include HTTParty
|
27
|
+
format :xml
|
28
|
+
base_uri UnifiedPayment.config[:base_uri]
|
29
|
+
|
30
|
+
# debug_output
|
31
|
+
follow_redirects(50)
|
32
|
+
|
33
|
+
def success?
|
34
|
+
self["orderId"]
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.build_xml_for_create(amount, options)
|
38
|
+
xml_builder = ::Builder::XmlMarkup.new
|
39
|
+
xml_builder.instruct!
|
40
|
+
xml_builder.TKKPG { |tkkpg|
|
41
|
+
tkkpg.Request { |request|
|
42
|
+
request.Operation("CreateOrder")
|
43
|
+
request.Language(options[:language] || "EN")
|
44
|
+
request.Order { |order|
|
45
|
+
order.Merchant(MERCHANT_NAME)
|
46
|
+
order.Amount(amount)
|
47
|
+
order.Currency(options[:currency] || "566")
|
48
|
+
order.Description(options[:description] || "Test Order")
|
49
|
+
order.ApproveURL(options[:approve_url])
|
50
|
+
order.CancelURL(options[:cancel_url])
|
51
|
+
order.DeclineURL(options[:decline_url])
|
52
|
+
if params_to_add = options[:add_params]
|
53
|
+
order.AddParams do |add_param|
|
54
|
+
add_param.email(params_to_add[:email]) if params_to_add[:email]
|
55
|
+
add_param.phone(params_to_add[:phone]) if params_to_add[:phone]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
xml_builder
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.ping_gateway_for(operation, xml_request)
|
65
|
+
begin
|
66
|
+
response = post('/Exec', :body => xml_request.target! )
|
67
|
+
rescue => exception
|
68
|
+
raise Error.new("################### Unable to send " + operation + " request to Unified Payments Ltd " + exception.message)
|
69
|
+
end
|
70
|
+
response
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.send_request_for_create(amount, options)
|
74
|
+
xml_builder = build_xml_for_create(amount, options)
|
75
|
+
ping_gateway_for('CreateOrder', xml_builder)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.create_order(amount, options={})
|
79
|
+
xml_response = send_request_for_create(amount, options)
|
80
|
+
response = xml_response["TKKPG"]["Response"]
|
81
|
+
if response["Status"] == "00"
|
82
|
+
response_order_details = response["Order"]
|
83
|
+
|
84
|
+
return { "url" => response_order_details["URL"],
|
85
|
+
"sessionId" => response_order_details["SessionID"],
|
86
|
+
"orderId" => response_order_details["OrderID"],
|
87
|
+
"Order" => response_order_details,
|
88
|
+
"Status" => response["Status"],
|
89
|
+
"xml_response" => xml_response
|
90
|
+
}
|
91
|
+
else
|
92
|
+
raise Error.new("CreateOrder Failed", response)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.build_xml_for(operation, order_id, session_id)
|
97
|
+
xml_builder = Builder::XmlMarkup.new
|
98
|
+
xml_builder.instruct!
|
99
|
+
xml_builder.TKKPG { |tkkpg|
|
100
|
+
tkkpg.Request { |request|
|
101
|
+
request.Operation(operation)
|
102
|
+
request.Language("EN")
|
103
|
+
request.Order { |order|
|
104
|
+
order.Merchant(MERCHANT_NAME)
|
105
|
+
order.OrderID(order_id) }
|
106
|
+
request.SessionID(session_id)
|
107
|
+
}
|
108
|
+
}
|
109
|
+
xml_builder
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.send_request_for(operation, order_id, session_id)
|
113
|
+
xml_request = build_xml_for(operation, order_id, session_id)
|
114
|
+
ping_gateway_for(operation, xml_request)
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.get_order_status(order_id, session_id)
|
118
|
+
xml_response = send_request_for("GetOrderStatus", order_id, session_id)
|
119
|
+
response = xml_response["TKKPG"]["Response"]
|
120
|
+
|
121
|
+
if response["Status"] == "00"
|
122
|
+
response_order_details = response["Order"]
|
123
|
+
|
124
|
+
return { "orderStatus" => response_order_details["OrderStatus"],
|
125
|
+
"orderId" => response_order_details["OrderID"],
|
126
|
+
"xml_response" => xml_response }
|
127
|
+
else
|
128
|
+
raise Error.new("GetOrderStatus Failed", xml_response)
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.reverse(order_id, session_id)
|
134
|
+
xml_response = send_request_for("Reverse", order_id, session_id)
|
135
|
+
response = xml_response["TKKPG"]["Response"]
|
136
|
+
if response["Status"] == "00"
|
137
|
+
response_order_id, response_reversal_details = response["Order"]["OrderID"], response["Reversal"]
|
138
|
+
|
139
|
+
return { "orderId" => response_order_id,
|
140
|
+
"respCode" => response_reversal_details["RespCode"],
|
141
|
+
"respMessage" => response_reversal_details["RespMessage"],
|
142
|
+
"xml_response" => xml_response }
|
143
|
+
else
|
144
|
+
raise Error.new("Reverse Request Failed", xml_response)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module UnifiedPayment
|
2
|
+
module Utility
|
3
|
+
def approved_at_gateway?
|
4
|
+
get_unified_order_status == 'APPROVED'
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
def get_unified_order_status
|
9
|
+
response = Client.get_order_status(gateway_order_id, gateway_session_id)
|
10
|
+
response['orderStatus']
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UnifiedPayment::Client do
|
4
|
+
describe '#create_order' do
|
5
|
+
before do
|
6
|
+
@xml_builder = Builder::XmlMarkup.new
|
7
|
+
Builder::XmlMarkup.stub(:new).and_return(@xml_builder)
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'not able to reach gateway' do
|
11
|
+
it { expect { UnifiedPayment::Client.create_order(200)}.to raise_error(UnifiedPayment::Error, "################### Unable to send CreateOrder request to Unified Payments Ltd Connection refused - connect(2)") }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'response status is not 00' do
|
15
|
+
before do
|
16
|
+
my_response = { "TKKPG" => { "Response" => { "Operation"=>"CreateOrder", "Status"=>"01", "Order"=>{"OrderID"=>"1086880", "SessionID"=>"740A7AB7EB527908EB9507154CFAD389", "URL"=> "https://mpi.valucardnigeria.com:443/index.jsp"}}}}
|
17
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
18
|
+
end
|
19
|
+
|
20
|
+
it { expect { UnifiedPayment::Client.create_order(200)}.to raise_error(UnifiedPayment::Error, "CreateOrder Failed") }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'response status is 00' do
|
24
|
+
before do
|
25
|
+
my_response = { "TKKPG" => { "Response" => { "Operation"=>"CreateOrder", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "SessionID"=>"740A7AB7EB527908EB9507154CFAD389", "URL"=> "https://mpi.valucardnigeria.com:443/index.jsp"}}}}
|
26
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
27
|
+
end
|
28
|
+
|
29
|
+
it { expect { UnifiedPayment::Client.create_order(200)}.not_to raise_error() }
|
30
|
+
it { UnifiedPayment::Client.create_order(200).should eq({"url"=>"https://mpi.valucardnigeria.com:443/index.jsp", "sessionId"=>"740A7AB7EB527908EB9507154CFAD389", "orderId"=>"1086880", "Order"=>{"OrderID"=>"1086880", "SessionID"=>"740A7AB7EB527908EB9507154CFAD389", "URL"=> "https://mpi.valucardnigeria.com:443/index.jsp"}, "Status"=>"00", "xml_response"=>{"TKKPG"=>{"Response"=>{"Operation"=>"CreateOrder", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "SessionID"=>"740A7AB7EB527908EB9507154CFAD389", "URL"=>"https://mpi.valucardnigeria.com:443/index.jsp"}}}}}) }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'method calls' do
|
34
|
+
before do
|
35
|
+
my_response = { "TKKPG" => { "Response" => { "Operation"=>"CreateOrder", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "SessionID"=>"740A7AB7EB527908EB9507154CFAD389", "URL"=> "https://mpi.valucardnigeria.com:443/index.jsp"}}}}
|
36
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
37
|
+
end
|
38
|
+
|
39
|
+
it { Builder::XmlMarkup.should_receive(:new).and_return(@xml_builder) }
|
40
|
+
it { @xml_builder.should_receive(:instruct!).and_return(true) }
|
41
|
+
|
42
|
+
after { UnifiedPayment::Client.create_order(200) }
|
43
|
+
end
|
44
|
+
|
45
|
+
describe 'sends request along options' do
|
46
|
+
before do
|
47
|
+
my_response = { "TKKPG" => { "Response" => { "Operation"=>"CreateOrder", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "SessionID"=>"740A7AB7EB527908EB9507154CFAD389", "URL"=> "https://mpi.valucardnigeria.com:443/index.jsp"}}}}
|
48
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'default options' do
|
52
|
+
before do
|
53
|
+
UnifiedPayment::Client.create_order(200, :approve_url => 'approve-url', :decline_url => 'decline-url', :cancel_url => 'cancel-url')
|
54
|
+
end
|
55
|
+
|
56
|
+
it { @xml_builder.inspect.should eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><TKKPG><Request><Operation>CreateOrder</Operation><Language>EN</Language><Order><Merchant>verbose</Merchant><Amount>200</Amount><Currency>566</Currency><Description>Test Order</Description><ApproveURL>approve-url</ApproveURL><CancelURL>cancel-url</CancelURL><DeclineURL>decline-url</DeclineURL></Order></Request></TKKPG><inspect/>")}
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'Currency, Description and Language' do
|
60
|
+
before do
|
61
|
+
UnifiedPayment::Client.create_order(200,:currency => '444', :description => 'unified-payment-order', :language => 'HIN', :approve_url => 'approve-url', :decline_url => 'decline-url', :cancel_url => 'cancel-url')
|
62
|
+
end
|
63
|
+
|
64
|
+
it { @xml_builder.inspect.should eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><TKKPG><Request><Operation>CreateOrder</Operation><Language>HIN</Language><Order><Merchant>verbose</Merchant><Amount>200</Amount><Currency>444</Currency><Description>unified-payment-order</Description><ApproveURL>approve-url</ApproveURL><CancelURL>cancel-url</CancelURL><DeclineURL>decline-url</DeclineURL></Order></Request></TKKPG><inspect/>")}
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with email and phone' do
|
68
|
+
before do
|
69
|
+
UnifiedPayment::Client.create_order(200, :add_params => { :email => 'test-email@test.com', :phone => '07123456789' }, :currency => '444', :description => 'unified-payment-order', :language => 'HIN', :approve_url => 'approve-url', :decline_url => 'decline-url', :cancel_url => 'cancel-url')
|
70
|
+
end
|
71
|
+
|
72
|
+
it { @xml_builder.inspect.should eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><TKKPG><Request><Operation>CreateOrder</Operation><Language>HIN</Language><Order><Merchant>verbose</Merchant><Amount>200</Amount><Currency>444</Currency><Description>unified-payment-order</Description><ApproveURL>approve-url</ApproveURL><CancelURL>cancel-url</CancelURL><DeclineURL>decline-url</DeclineURL><AddParams><email>test-email@test.com</email><phone>07123456789</phone></AddParams></Order></Request></TKKPG><inspect/>")}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '.get_order_status' do
|
78
|
+
before do
|
79
|
+
@xml_builder = Builder::XmlMarkup.new
|
80
|
+
Builder::XmlMarkup.stub(:new).and_return(@xml_builder)
|
81
|
+
end
|
82
|
+
|
83
|
+
it { expect { UnifiedPayment::Client.get_order_status(1086880, '740A7AB7EB527908EB9507154CFAD389') }.to raise_error(UnifiedPayment::Error, '################### Unable to send GetOrderStatus request to Unified Payments Ltd Connection refused - connect(2)')}
|
84
|
+
|
85
|
+
context 'response status is not 00' do
|
86
|
+
before do
|
87
|
+
my_response = {"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"01", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}}}}
|
88
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
89
|
+
end
|
90
|
+
|
91
|
+
it { expect { UnifiedPayment::Client.get_order_status(1086880, '740A7AB7EB527908EB9507154CFAD389') }.to raise_error(UnifiedPayment::Error, 'GetOrderStatus Failed') }
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'response status is 00' do
|
95
|
+
before do
|
96
|
+
my_response = {"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}}}}
|
97
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
98
|
+
end
|
99
|
+
|
100
|
+
it { expect { UnifiedPayment::Client.get_order_status(1086880, '740A7AB7EB527908EB9507154CFAD389') }.not_to raise_error() }
|
101
|
+
it { UnifiedPayment::Client.get_order_status(1086880, '740A7AB7EB527908EB9507154CFAD389').should eq({"orderStatus"=>"CREATED", "orderId"=>"1086880", "xml_response"=>{"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}}}}}) }
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'sends request along options' do
|
105
|
+
before do
|
106
|
+
my_response = {"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}}}}
|
107
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
108
|
+
UnifiedPayment::Client.get_order_status(1086880, '740A7AB7EB527908EB9507154CFAD389')
|
109
|
+
end
|
110
|
+
|
111
|
+
it { @xml_builder.inspect.should eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><TKKPG><Request><Operation>GetOrderStatus</Operation><Language>EN</Language><Order><Merchant>verbose</Merchant><OrderID>1086880</OrderID></Order><SessionID>740A7AB7EB527908EB9507154CFAD389</SessionID></Request></TKKPG><inspect/>") }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '.reverse' do
|
116
|
+
before do
|
117
|
+
@xml_builder = Builder::XmlMarkup.new
|
118
|
+
Builder::XmlMarkup.stub(:new).and_return(@xml_builder)
|
119
|
+
end
|
120
|
+
|
121
|
+
it { expect { UnifiedPayment::Client.reverse(1086880, '740A7AB7EB527908EB9507154CFAD389') }.to raise_error(UnifiedPayment::Error, '################### Unable to send Reverse request to Unified Payments Ltd Connection refused - connect(2)')}
|
122
|
+
|
123
|
+
context 'response status is not 00' do
|
124
|
+
before do
|
125
|
+
my_response = {"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"01", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}, "Reversal" => {'RespCode' => '876', 'RespMessage' => 'resp-message' }}}}
|
126
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
127
|
+
end
|
128
|
+
|
129
|
+
it { expect { UnifiedPayment::Client.reverse(1086880, '740A7AB7EB527908EB9507154CFAD389') }.to raise_error(UnifiedPayment::Error, 'Reverse Request Failed') }
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'response status is 00' do
|
133
|
+
before do
|
134
|
+
my_response = {"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}, "Reversal" => {'RespCode' => '876', 'RespMessage' => 'resp-message' }}}}
|
135
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
136
|
+
end
|
137
|
+
|
138
|
+
it { expect { UnifiedPayment::Client.reverse(1086880, '740A7AB7EB527908EB9507154CFAD389') }.not_to raise_error() }
|
139
|
+
it { UnifiedPayment::Client.reverse(1086880, '740A7AB7EB527908EB9507154CFAD389').should eq({"orderId"=>"1086880", "respCode"=>"876", "respMessage"=>"resp-message", "xml_response"=>{"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}, "Reversal"=>{"RespCode"=>"876", "RespMessage"=>"resp-message"}}}}}) }
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'sends request along options' do
|
143
|
+
before do
|
144
|
+
my_response = {"TKKPG"=>{"Response"=>{"Operation"=>"GetOrderStatus", "Status"=>"00", "Order"=>{"OrderID"=>"1086880", "OrderStatus"=>"CREATED"}, "Reversal" => {'RespCode' => '876', 'RespMessage' => 'resp-message' }}}}
|
145
|
+
UnifiedPayment::Client.stub(:post).with('/Exec', :body => @xml_builder.target!).and_return(my_response)
|
146
|
+
UnifiedPayment::Client.reverse(1086880, '740A7AB7EB527908EB9507154CFAD389')
|
147
|
+
end
|
148
|
+
|
149
|
+
it { @xml_builder.inspect.should eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?><TKKPG><Request><Operation>Reverse</Operation><Language>EN</Language><Order><Merchant>verbose</Merchant><OrderID>1086880</OrderID></Order><SessionID>740A7AB7EB527908EB9507154CFAD389</SessionID></Request></TKKPG><inspect/>") }
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UnifiedPayment::Transaction do
|
4
|
+
it { UnifiedPayment::Transaction.table_name.should eq('unified_payment_transactions') }
|
5
|
+
[:gateway_session_id, :gateway_order_id, :url, :merchant_id, :approval_code].each do |attribute|
|
6
|
+
it { should allow_mass_assignment_of attribute }
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:unified_payment) { UnifiedPayment::Transaction.new }
|
10
|
+
context 'utility methods' do
|
11
|
+
describe '#create_order_at_unified' do
|
12
|
+
context 'attempt fails' do
|
13
|
+
context 'never' do
|
14
|
+
before do
|
15
|
+
UnifiedPayment::Client.stub(:create_order).and_return({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'calls to client only once with no error raised' do
|
19
|
+
UnifiedPayment::Client.should_receive(:create_order).and_return({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
20
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {})
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'creates a unified transaction entry' do
|
24
|
+
UnifiedPayment::Transaction.should_receive(:create).with({ :url => 'https://mpi.valucardnigeria.com:443/index.jsp', :gateway_order_id => '12345', :gateway_session_id => '040C78AA2FACF4B1164EDAA27BB281A7', :xml_response => ""})
|
25
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {})
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'sets response' do
|
29
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {}).should eq({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'once' do
|
34
|
+
before do
|
35
|
+
UnifiedPayment::Client.stub(:create_order).once.and_raise(UnifiedPayment::Error.new("Unable to send create order request to Unified Payments Ltd. ERROR: Connection refused - connect(2)") )
|
36
|
+
UnifiedPayment::Client.stub(:create_order).once.and_return({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'calls to client twice with error raise once' do
|
40
|
+
UnifiedPayment::Client.should_receive(:create_order).once.and_raise(UnifiedPayment::Error.new("Unable to send create order request to Unified Payments Ltd. ERROR: Connection refused - connect(2)") )
|
41
|
+
UnifiedPayment::Client.should_receive(:create_order).once.and_return({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
42
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {})
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'sets response' do
|
46
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {}).should eq({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'twice' do
|
51
|
+
before do
|
52
|
+
UnifiedPayment::Client.stub(:create_order).twice.and_raise(UnifiedPayment::Error.new("Unable to send create order request to Unified Payments Ltd. ERROR: Connection refused - connect(2)") )
|
53
|
+
UnifiedPayment::Client.stub(:create_order).once.and_return({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'calls to client thrice with error raise twice' do
|
57
|
+
UnifiedPayment::Client.should_receive(:create_order).twice.and_raise(UnifiedPayment::Error.new("Unable to send create order request to Unified Payments Ltd. ERROR: Connection refused - connect(2)") )
|
58
|
+
UnifiedPayment::Client.should_receive(:create_order).once.and_return({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
59
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {})
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'sets response' do
|
63
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {}).should eq({ 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'thrice' do
|
68
|
+
before do
|
69
|
+
UnifiedPayment::Client.stub(:create_order).and_raise(UnifiedPayment::Error.new("Unable to send create order request to Unified Payments Ltd. ERROR: Connection refused - connect(2)"))
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'calls to client thrice with error raised thrice' do
|
73
|
+
UnifiedPayment::Client.should_receive(:create_order).exactly(3).times.and_raise(UnifiedPayment::Error.new("Unable to send create order request to Unified Payments Ltd. ERROR: Connection refused - connect(2)"))
|
74
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {})
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'sets response false' do
|
78
|
+
UnifiedPayment::Transaction.create_order_at_unified(200, {}).should be_false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#extract_url_for_unified_payment' do
|
85
|
+
before do
|
86
|
+
@response = { 'url' => 'https://mpi.valucardnigeria.com:443/index.jsp', 'orderId' => '12345', 'sessionId' => '040C78AA2FACF4B1164EDAA27BB281A7'}
|
87
|
+
end
|
88
|
+
|
89
|
+
it { UnifiedPayment::Transaction.extract_url_for_unified_payment(@response).should eq('https://mpi.valucardnigeria.com:443/index.jsp?ORDERID=12345&SESSIONID=040C78AA2FACF4B1164EDAA27BB281A7') }
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#approved_at_gateway?' do
|
93
|
+
context 'when approved' do
|
94
|
+
before { unified_payment.stub(:get_unified_order_status).and_return('APPROVED') }
|
95
|
+
|
96
|
+
it { unified_payment.should be_approved_at_gateway }
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when not approved' do
|
100
|
+
before { unified_payment.stub(:get_unified_order_status).and_return('NOT-APPROVED') }
|
101
|
+
|
102
|
+
it { unified_payment.should_not be_approved_at_gateway }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#get_unified_order_status' do
|
107
|
+
before do
|
108
|
+
unified_payment.stub(:gateway_order_id).and_return('12345')
|
109
|
+
unified_payment.stub(:gateway_session_id).and_return('040C78AA2FACF4B1164EDAA27BB281A7')
|
110
|
+
UnifiedPayment::Client.stub(:get_order_status).with(unified_payment.gateway_order_id, unified_payment.gateway_session_id).and_return('orderStatus' => 'APPROVED')
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'calls client' do
|
114
|
+
UnifiedPayment::Client.should_receive(:get_order_status).with(unified_payment.gateway_order_id, unified_payment.gateway_session_id).and_return('orderStatus' => 'APPROVED')
|
115
|
+
unified_payment.send(:get_unified_order_status)
|
116
|
+
end
|
117
|
+
|
118
|
+
it { unified_payment.send(:get_unified_order_status).should eq('APPROVED')}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
+
ENV["RAILS_ENV"] ||= 'test'
|
3
|
+
require File.expand_path("../../config/environment", __FILE__)
|
4
|
+
# require 'rspec/rails'
|
5
|
+
# require 'rspec/autorun'
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'bundler/setup'
|
9
|
+
require 'unified_payment'
|
10
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
11
|
+
# in spec/support/ and its subdirectories.
|
12
|
+
# Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
13
|
+
|
14
|
+
# Checks for pending migrations before tests are run.
|
15
|
+
# If you are not using ActiveRecord, you can remove this line.
|
16
|
+
# ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
# ## Mock Framework
|
20
|
+
#
|
21
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
22
|
+
#
|
23
|
+
# config.mock_with :mocha
|
24
|
+
# config.mock_with :flexmock
|
25
|
+
# config.mock_with :rr
|
26
|
+
|
27
|
+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
28
|
+
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
29
|
+
|
30
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
31
|
+
# examples within a transaction, remove the following line or assign false
|
32
|
+
# instead of true.
|
33
|
+
# config.use_transactional_fixtures = true
|
34
|
+
|
35
|
+
# If true, the base class of anonymous controllers will be inferred
|
36
|
+
# automatically. This will be the default behavior in future versions of
|
37
|
+
# rspec-rails.
|
38
|
+
# config.infer_base_class_for_anonymous_controllers = false
|
39
|
+
|
40
|
+
# Run specs in random order to surface order dependencies. If you find an
|
41
|
+
# order dependency and want to debug it, you can fix the order by providing
|
42
|
+
# the seed, which is printed after each run.
|
43
|
+
# --seed 1234
|
44
|
+
config.order = "random"
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: unified_payment
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Manish Kangia
|
14
|
+
- Sushant Mittal
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2014-02-27 00:00:00 Z
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rails
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
version: "3.0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
description: Interface to handle payments via UnifiedPayment for rails app.
|
37
|
+
email:
|
38
|
+
- info@vinsol.com
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- app/controllers/unified_payment/transactions_controller.rb
|
47
|
+
- app/models/unified_payment/transaction.rb
|
48
|
+
- app/views/unified_payment/transactions/index.html.erb
|
49
|
+
- config/boot.rb
|
50
|
+
- config/environment.rb
|
51
|
+
- config/locales/en.yml
|
52
|
+
- config/routes.rb
|
53
|
+
- lib/generators/unified_payment/install_generator.rb
|
54
|
+
- lib/generators/unified_payment/templates/migrations/20131101092408_add_unified_payment_transactions.rb
|
55
|
+
- lib/generators/unified_payment/USAGE
|
56
|
+
- lib/tasks/unified_payment_tasks.rake
|
57
|
+
- lib/unified_payment/client.rb
|
58
|
+
- lib/unified_payment/engine.rb
|
59
|
+
- lib/unified_payment/utility.rb
|
60
|
+
- lib/unified_payment/version.rb
|
61
|
+
- lib/unified_payment.rb
|
62
|
+
- Rakefile
|
63
|
+
- spec/Libraries/client_spec.rb
|
64
|
+
- spec/models/unified_payment/transaction_spec.rb
|
65
|
+
- spec/spec_helper.rb
|
66
|
+
homepage: http://vinsol.com
|
67
|
+
licenses:
|
68
|
+
- MIT
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.8.24
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Interface to handle payments via UnifiedPayment for rails app.
|
99
|
+
test_files:
|
100
|
+
- spec/Libraries/client_spec.rb
|
101
|
+
- spec/models/unified_payment/transaction_spec.rb
|
102
|
+
- spec/spec_helper.rb
|