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 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,4 @@
1
+ module UnifiedPayment
2
+ class TransactionsController < ActionController::Base
3
+ end
4
+ end
@@ -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,5 @@
1
+ # Set up gems listed in the Gemfile.
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
5
+ $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)
@@ -0,0 +1,5 @@
1
+ # Load the Rails application.
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the Rails application.
5
+ UnifiedPayment::Application.initialize!
@@ -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,4 @@
1
+ Rails.application.routes.draw do
2
+ get '/unified_transactions', :to => 'transactions#index'
3
+ # mount UnifiedPayment::Engine => "/unified_payment"
4
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate unified_payment Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -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,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :unified_payment do
3
+ # # Task goes here
4
+ # 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,7 @@
1
+ module UnifiedPayment
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace UnifiedPayment
4
+
5
+ config.autoload_paths += %W(#{config.root}/lib)
6
+ end
7
+ 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,3 @@
1
+ module UnifiedPayment
2
+ VERSION = "1.0.0"
3
+ 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
@@ -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