pg_recurrence 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +33 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +65 -0
- data/VERSION +1 -0
- data/lib/pg_recurrence.rb +10 -0
- data/lib/ruby_psigate/account.rb +178 -0
- data/lib/ruby_psigate/charge.rb +227 -0
- data/lib/ruby_psigate/credential.rb +20 -0
- data/lib/ruby_psigate/request.rb +54 -0
- data/lib/ruby_psigate/response.rb +99 -0
- data/test/helper.rb +70 -0
- data/test/remote/test_account_remote.rb +104 -0
- data/test/remote/test_charge_remote.rb +92 -0
- data/test/remote/test_request_remote.rb +36 -0
- data/test/unit/test_account.rb +220 -0
- data/test/unit/test_charge.rb +15 -0
- data/test/unit/test_request.rb +50 -0
- data/test/unit/test_response.rb +55 -0
- metadata +200 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module RubyPsigate
|
2
|
+
class Credential
|
3
|
+
|
4
|
+
attr_reader :cid, :userid, :password, :mode, :endpoint
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@cid = options[:CID]
|
8
|
+
@userid = options[:UserID]
|
9
|
+
@password = options[:password]
|
10
|
+
@mode = options[:mode] || :test
|
11
|
+
|
12
|
+
if @mode == :test
|
13
|
+
@endpoint = "https://dev.psigate.com:8645/Messenger/AMMessenger"
|
14
|
+
else
|
15
|
+
@endpoint = "https://dev.psigate.com:8645/Messenger/AMMessenger"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module RubyPsigate
|
2
|
+
class Request
|
3
|
+
|
4
|
+
attr_reader :params
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def credential
|
8
|
+
@@credential
|
9
|
+
end
|
10
|
+
|
11
|
+
def credential=(x)
|
12
|
+
raise ArgumentError unless x.is_a?(Credential)
|
13
|
+
@@credential = x
|
14
|
+
end
|
15
|
+
|
16
|
+
def storeid
|
17
|
+
@@storeid
|
18
|
+
end
|
19
|
+
|
20
|
+
def storeid=(x)
|
21
|
+
@@storeid = x
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(attributes={})
|
26
|
+
@request = {}
|
27
|
+
@request[:Request] = {}
|
28
|
+
|
29
|
+
# Add credentials
|
30
|
+
%w( CID UserID Password ).each do |c|
|
31
|
+
@request[:Request][c.to_sym] = self.class.credential.send((c.downcase).to_sym)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def params=(hash)
|
36
|
+
raise ArgumentError unless hash.is_a?(Hash)
|
37
|
+
@params = hash
|
38
|
+
end
|
39
|
+
|
40
|
+
def post
|
41
|
+
begin
|
42
|
+
parameters = RubyPsigate::Serializer.new(params, :header => true).to_xml
|
43
|
+
connection = RubyPsigate::Connection.new(self.class.credential.endpoint)
|
44
|
+
response = connection.post(parameters)
|
45
|
+
response = Response.new(response)
|
46
|
+
rescue ConnectionError => e
|
47
|
+
response = nil
|
48
|
+
end
|
49
|
+
response
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module RubyPsigate
|
2
|
+
class Response
|
3
|
+
|
4
|
+
ACCOUNT_SUCCESS_CODES = %w(
|
5
|
+
RPA-0000
|
6
|
+
RPA-0001
|
7
|
+
RPA-0010
|
8
|
+
RPA-0015
|
9
|
+
RPA-0020
|
10
|
+
RPA-0022
|
11
|
+
RPA-0025
|
12
|
+
RPA-0040
|
13
|
+
RPA-0042
|
14
|
+
RPA-0046
|
15
|
+
RPA-0048
|
16
|
+
RPA-0058
|
17
|
+
PSI-0000
|
18
|
+
RRC-0000
|
19
|
+
RRC-0005
|
20
|
+
RRC-0050
|
21
|
+
RRC-0060
|
22
|
+
RRC-0065
|
23
|
+
RRC-0072
|
24
|
+
RRC-0075
|
25
|
+
RRC-0082
|
26
|
+
RRC-0090
|
27
|
+
RRC-0092
|
28
|
+
RRC-0095
|
29
|
+
RRC-0098
|
30
|
+
RRC-0190
|
31
|
+
CTL-0000
|
32
|
+
CTL-0005
|
33
|
+
CTL-0050
|
34
|
+
CTL-0060
|
35
|
+
CTL-0065
|
36
|
+
CTL-0072
|
37
|
+
CTL-0075
|
38
|
+
CTL-0082
|
39
|
+
CTL-0090
|
40
|
+
CTL-0092
|
41
|
+
CTL-0098
|
42
|
+
CTL-0190
|
43
|
+
CTL-0192
|
44
|
+
RIV-0050
|
45
|
+
RIV-0060
|
46
|
+
RIV-0072
|
47
|
+
RIV-0090
|
48
|
+
RIV-0190
|
49
|
+
RIV-0197
|
50
|
+
RIV-0198
|
51
|
+
EMR-0000
|
52
|
+
EMR-0005
|
53
|
+
EMR-0050
|
54
|
+
EMR-0060
|
55
|
+
EMR-0072
|
56
|
+
EMR-0082
|
57
|
+
EMR-0090
|
58
|
+
EMR-0190
|
59
|
+
)
|
60
|
+
|
61
|
+
def initialize(xml_response)
|
62
|
+
@xml_response = Crack::XML.parse(xml_response)
|
63
|
+
end
|
64
|
+
|
65
|
+
def response
|
66
|
+
@xml_response["Response"]
|
67
|
+
end
|
68
|
+
|
69
|
+
def success?
|
70
|
+
return false unless @xml_response
|
71
|
+
ACCOUNT_SUCCESS_CODES.include?(self.returncode)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def method_missing(name, *args, &block)
|
77
|
+
@result = nil
|
78
|
+
name = name.downcase.to_sym
|
79
|
+
@result = find_value_in_hash(name, response)
|
80
|
+
@result
|
81
|
+
end
|
82
|
+
|
83
|
+
def find_value_in_hash(input_key, hash)
|
84
|
+
result = nil
|
85
|
+
hash.each_pair do |key, value|
|
86
|
+
if value.is_a? Hash
|
87
|
+
result = find_value_in_hash(input_key, value)
|
88
|
+
else
|
89
|
+
key = key.downcase.to_sym
|
90
|
+
result = value if input_key == key
|
91
|
+
end
|
92
|
+
|
93
|
+
break unless result.nil?
|
94
|
+
end
|
95
|
+
result
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
require 'test/unit'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
require 'pg_recurrence'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
|
19
|
+
# Helpers
|
20
|
+
def credential
|
21
|
+
@credential = RubyPsigate::Credential.new(:CID => "1000001", :UserID => "teststore", :password => "testpass")
|
22
|
+
end
|
23
|
+
|
24
|
+
def credit_card
|
25
|
+
@credit_card = PgCreditcard.new(
|
26
|
+
:name => "Homer Simpsons",
|
27
|
+
:number => "4111111111111111",
|
28
|
+
:month => "03",
|
29
|
+
:year => "20",
|
30
|
+
:cvv => "123"
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid_account_attributes
|
35
|
+
{
|
36
|
+
:name => "Homer Simpson",
|
37
|
+
:email => "homer@simpsons.com",
|
38
|
+
:address1 => "1234 Evergrove Drive",
|
39
|
+
:address2 => nil,
|
40
|
+
:city => "Toronto",
|
41
|
+
:province => "ON",
|
42
|
+
:postal_code => "M2N3A3",
|
43
|
+
:country => "CA",
|
44
|
+
:phone => "416-111-1111",
|
45
|
+
:credit_card => credit_card
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_account
|
50
|
+
@account = RubyPsigate::Account.new(
|
51
|
+
:name => "Homer Simpson",
|
52
|
+
:email => "homer@simpsons.com",
|
53
|
+
:address1 => "1234 Evergrove Drive",
|
54
|
+
:address2 => nil,
|
55
|
+
:city => "Toronto",
|
56
|
+
:province => "ON",
|
57
|
+
:postal_code => "M2N3A3",
|
58
|
+
:country => "CA",
|
59
|
+
:phone => "416-111-1111",
|
60
|
+
:credit_card => credit_card
|
61
|
+
)
|
62
|
+
|
63
|
+
@account.save
|
64
|
+
@account
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
require 'mocha'
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module RubyPsigate
|
4
|
+
class TestAccountRemote < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
Request.credential = credential
|
8
|
+
@comparison = create_account
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_add_account
|
12
|
+
@account = Account.new(valid_account_attributes)
|
13
|
+
@account.save
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_saving_account_assigns_accountid
|
17
|
+
@account = Account.new(valid_account_attributes)
|
18
|
+
assert_nil @account.accountid
|
19
|
+
@account.save
|
20
|
+
assert_not_nil @account.accountid
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_returns_false_to_new_record_after_save
|
24
|
+
@account = Account.new(valid_account_attributes)
|
25
|
+
assert @account.new_record?
|
26
|
+
@account.save
|
27
|
+
@account = Account.find(@account.accountid)
|
28
|
+
assert !@account.new_record?
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_failure_adding_account
|
32
|
+
@account = Account.new(:accountid => @comparison.accountid)
|
33
|
+
assert !@account.save
|
34
|
+
assert_not_nil @account.error
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_find_account
|
38
|
+
accountid = @comparison.accountid
|
39
|
+
@account = Account.find(accountid)
|
40
|
+
assert_equal @comparison.accountid, @account.accountid
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_cannot_find_account
|
44
|
+
accountid = "somefakeaccountid"
|
45
|
+
@account = Account.find(accountid)
|
46
|
+
assert_nil @account
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_disables_account
|
50
|
+
assert Account.disable(@comparison.accountid)
|
51
|
+
|
52
|
+
# Tests
|
53
|
+
@account = Account.find(@comparison.accountid)
|
54
|
+
assert_equal "N", @account.status
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_enable_account
|
58
|
+
Account.disable(@comparison.accountid)
|
59
|
+
assert Account.enable(@comparison.accountid)
|
60
|
+
|
61
|
+
# Tests
|
62
|
+
@account = Account.find(@comparison.accountid)
|
63
|
+
assert_equal "A", @account.status
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_update_attributes
|
67
|
+
@account = @comparison
|
68
|
+
assert @account.attributes = {
|
69
|
+
:name => "Marge Simpson",
|
70
|
+
:company => "NBC Corp",
|
71
|
+
:address1 => "577 Street",
|
72
|
+
:address2 => "Apt 888",
|
73
|
+
:city => "Ottawa",
|
74
|
+
:province => "ON",
|
75
|
+
:country => "Canada",
|
76
|
+
:postalcode => "A1A1A1",
|
77
|
+
:phone => "1234567890",
|
78
|
+
:fax => "1234567890",
|
79
|
+
:email => "marge@nbc.com",
|
80
|
+
:comments => "Some comment"
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_update_record
|
85
|
+
@account = Account.find(@comparison.accountid)
|
86
|
+
@account.attributes = {
|
87
|
+
:name => "Marge Simpson",
|
88
|
+
:company => "NBC Corp",
|
89
|
+
:address1 => "577 Street",
|
90
|
+
:address2 => "Apt 888",
|
91
|
+
:city => "Ottawa",
|
92
|
+
:province => "ON",
|
93
|
+
:country => "Canada",
|
94
|
+
:postalcode => "A1A1A1",
|
95
|
+
:phone => "1234567890",
|
96
|
+
:fax => "1234567890",
|
97
|
+
:email => "marge@nbc.com",
|
98
|
+
:comments => "Some comment"
|
99
|
+
}
|
100
|
+
assert @account.save
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module RubyPsigate
|
4
|
+
class TestChargeRemote < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
Request.credential = credential
|
8
|
+
Request.storeid = "teststore"
|
9
|
+
Charge.serialno = "1"
|
10
|
+
@account = create_account
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_add_charge
|
14
|
+
@charge = Charge.new(:accountid => @account.accountid, :interval => "M", :rbtrigger => "15", :starttime => "2010.12.25", :endtime => "2011.12.25", :productid => "123456789", :quantity => "1", :price => "99.00")
|
15
|
+
assert @charge.save
|
16
|
+
|
17
|
+
# Example of return response
|
18
|
+
# RuntimeError: #<RubyPsigate::Response:0x00000102858ee8 @xml_response={"Response"=>{"CID"=>"1000001", "Action"=>"REGISTER NEW CHARGE(S)", "ReturnCode"=>"RRC-0000", "ReturnMessage"=>"Register Recurring Charges completed successfully.", "Charge"=>{"ReturnCode"=>"RRC-0050", "ReturnMessage"=>"Register Recurring Charge completed successfully.", "RBCID"=>"2010120512535613602", "StoreID"=>"teststore", "RBName"=>nil, "AccountID"=>"2010120518622", "SerialNo"=>"1", "Status"=>"A", "Interval"=>"M", "Trigger"=>"15", "ProcessType"=>"A", "InstallmentNo"=>"0", "StartDate"=>"2010.12.25", "EndDate"=>"2011.12.25", "ItemInfo"=>{"Status"=>"A", "ItemSerialNo"=>"1", "ProductID"=>"123456789", "Description"=>nil, "Quantity"=>"1.00", "Price"=>"99.00", "Tax1"=>"0.00", "Tax2"=>"0.00", "Cost"=>"0.00", "SubTotal"=>"99.00"}}}}>
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_assigns_rbcid_after_save
|
22
|
+
@charge = Charge.new(:accountid => @account.accountid, :interval => "M", :rbtrigger => "15", :starttime => "2010.12.25", :endtime => "2011.12.25", :productid => "123456789", :quantity => "1", :price => "99.00")
|
23
|
+
@charge.save
|
24
|
+
assert_not_nil @charge.rbcid
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_find_charge
|
28
|
+
@test_charge = Charge.new(:accountid => @account.accountid, :interval => "M", :rbtrigger => "15", :starttime => "2010.12.25", :endtime => "2011.12.25", :productid => "123456789", :quantity => "1", :price => "99.00")
|
29
|
+
@test_charge.save
|
30
|
+
|
31
|
+
@charge = Charge.find(@test_charge.rbcid)
|
32
|
+
assert_not_nil @charge
|
33
|
+
|
34
|
+
# Example of return response
|
35
|
+
# RuntimeError: #<RubyPsigate::Response:0x00000101218188 @xml_response={"Response"=>{"CID"=>"1000001", "Action"=>"RETRIEVE A SUMMARY OF CHARGES", "ReturnCode"=>"RRC-0060", "ReturnMessage"=>"Retrive Recurring Charges Information completed successfully.", "Condition"=>{"RBCID"=>"2010120514303113630"}, "Charge"=>{"RBCID"=>"2010120514303113630", "StoreID"=>"teststore", "RBName"=>nil, "AccountID"=>"2010120518769", "SerialNo"=>"1", "Status"=>"A", "Interval"=>"M", "Trigger"=>"15", "ProcessType"=>"A", "InstallmentNo"=>"1", "StartDate"=>"2010.12.25", "EndDate"=>"2011.12.25"}}}>
|
36
|
+
end
|
37
|
+
|
38
|
+
# Psigate only allows the changing of certain charge elements
|
39
|
+
# SerialNo (payment method)
|
40
|
+
# Interval
|
41
|
+
# RbTrigger
|
42
|
+
# Starttime
|
43
|
+
# Endtime
|
44
|
+
def test_update_charge
|
45
|
+
@test_charge = Charge.new(:accountid => @account.accountid, :interval => "M", :rbtrigger => "15", :starttime => "2010.12.25", :endtime => "2011.12.25", :productid => "123456789", :quantity => "1", :price => "99.00")
|
46
|
+
@test_charge.save
|
47
|
+
|
48
|
+
assert = Charge.update(
|
49
|
+
:rbcid => @test_charge.rbcid,
|
50
|
+
:rbname => "New Name",
|
51
|
+
:serialno => "2",
|
52
|
+
:interval => "A",
|
53
|
+
:RBTrigger => "10",
|
54
|
+
:StartTime => "2010.12.30",
|
55
|
+
:EndTime => "2011.12.30"
|
56
|
+
)
|
57
|
+
|
58
|
+
# Example of return response
|
59
|
+
# RuntimeError: #<RubyPsigate::Response:0x00000100944098 @xml_response={"Response"=>{"CID"=>"1000001", "Action"=>"UPDATE A CHARGE", "ReturnCode"=>"RRC-0072", "ReturnMessage"=>"Update Recurring Charge Information completed successfully.", "Condition"=>{"RBCID"=>"2010120522260613649"}, "Update"=>{"Interval"=>"A", "SerialNo"=>"2", "RBName"=>"New Name"}}}>
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_enable_charge
|
63
|
+
@test_charge = Charge.new(:accountid => @account.accountid, :interval => "M", :rbtrigger => "15", :starttime => "2010.12.25", :endtime => "2011.12.25", :productid => "123456789", :quantity => "1", :price => "99.00")
|
64
|
+
@test_charge.save
|
65
|
+
|
66
|
+
assert Charge.enable(@test_charge.rbcid)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_disable_charge
|
70
|
+
@test_charge = Charge.new(:accountid => @account.accountid, :interval => "M", :rbtrigger => "15", :starttime => "2010.12.25", :endtime => "2011.12.25", :productid => "123456789", :quantity => "1", :price => "99.00")
|
71
|
+
@test_charge.save
|
72
|
+
|
73
|
+
assert Charge.disable(@test_charge.rbcid)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_immediate_charge
|
77
|
+
charge = Charge.new(:accountid => @account.accountid, :productid => "123456", :quantity => "1", :price => "10")
|
78
|
+
assert charge.immediately
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_response
|
82
|
+
charge = Charge.new(:accountid => @account.accountid, :productid => "123456", :quantity => "1", :price => "10")
|
83
|
+
charge.immediately
|
84
|
+
response = charge.response
|
85
|
+
assert response.is_a?(RubyPsigate::Response)
|
86
|
+
|
87
|
+
# Example of return response
|
88
|
+
#RuntimeError: #<RubyPsigate::Response:0x00000101455130 @xml_response={"Response"=>{"CID"=>"1000001", "Action"=>"REGISTER AN IMMEDIATE CHARGE", "ReturnCode"=>"PSI-0000", "ReturnMessage"=>"The transaction completed successfully.", "Invoice"=>{"StoreID"=>"teststore", "PayerName"=>"Homer Simpsons", "Status"=>"Paid", "InvoiceNo"=>"030705", "ReturnCode"=>"Y:123456:0abcdef:M:X:NNN", "ErrMsg"=>nil, "InvoiceDate"=>"2010.12.05", "ExecDate"=>"2010.12.05", "RBCID"=>"2010120511081813577", "AccountID"=>"2010120518355", "SerialNo"=>"1", "CardNumber"=>"411111...1111", "CardExpMonth"=>"03", "CardExpYear"=>"20", "CardType"=>"VISA", "InvoiceTotal"=>"10.00", "ItemInfo"=>{"ItemSerialNo"=>"1", "ProductID"=>"123456", "Description"=>nil, "Quantity"=>"1.00", "Price"=>"10.00", "Tax1"=>"0.00", "Tax2"=>"0.00", "Cost"=>"0.00", "SubTotal"=>"10.00"}}}}>
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module RubyPsigate
|
4
|
+
class TestRequestRemote < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
Request.credential = credential
|
8
|
+
|
9
|
+
@params = {
|
10
|
+
:Request => {
|
11
|
+
:CID => "1000001",
|
12
|
+
:UserID => "teststore",
|
13
|
+
:Password => "testpass",
|
14
|
+
:Action => "AMA00",
|
15
|
+
:Condition => {
|
16
|
+
:AccountID => "000000000000000911"
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
@request = Request.new
|
22
|
+
@request.params = @params
|
23
|
+
@response = @request.post
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_retrieves_remote_information_with_post
|
27
|
+
assert @response.success?
|
28
|
+
assert_equal "RPA-0020", @response.returncode
|
29
|
+
assert_equal "Retrive Payment Accounts Information completed successfully.", @response.returnmessage
|
30
|
+
assert_equal "Earl Grey", @response.name
|
31
|
+
assert_equal "A", @response.status
|
32
|
+
assert_equal "000000000000000911", @response.accountid
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|