ipay 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,76 @@
1
+ iPay
2
+ ======
3
+
4
+ Ruby gem for interfacing with the iPay XML API
5
+
6
+ Changelog
7
+ ---------
8
+
9
+ **v0.1.1**
10
+
11
+ - Added certification mode
12
+
13
+ **v0.1.0**
14
+
15
+ - CC (credit/debit) and Wallet (client/account) requests
16
+ - Tests
17
+
18
+ **v0.0.1**
19
+
20
+ - Initial commit
21
+
22
+ Dependencies
23
+ ----
24
+
25
+ - libxml-ruby for processing xml responses
26
+
27
+ Setup
28
+ -----
29
+
30
+ Create a configuration file 'ipay.yml' and place it in your apps config/ folder. The configuration file is automatically loaded for you and values are accessible via iPay::config struct.
31
+
32
+ Example configuration:
33
+
34
+ :url: "https://uap.txngw.com/"
35
+ :company_key: 6990
36
+ :terminal_id: 6177
37
+ :pin: 1234
38
+
39
+ You can also configure IPay via a block:
40
+
41
+ IPay::config do |c|
42
+ c.url = 'https://uap.txngw.com/'
43
+ c.company_key = 6990
44
+ c.terminal_id = 6177
45
+ c.pin = 1234
46
+ end
47
+
48
+ Usage
49
+ ----
50
+ require 'ipay'
51
+ resp = IPay::CC::Debit.sale(
52
+ :amount => '4.99',
53
+ :account_number => '4000009999999991',
54
+ :cvv => 123,
55
+ :expiration => '0614',
56
+ :first_name => 'nick',
57
+ :last_name => 'wilson',
58
+ :address => '123 fake st',
59
+ :city => 'sometown',
60
+ :state => 'NY',
61
+ :postal_code => '90210',
62
+ :country => IPay::Countries::USA
63
+ )
64
+
65
+ if resp.success?
66
+ puts resp.data[:transaction_id]
67
+ end
68
+
69
+ Certification
70
+ ----
71
+
72
+ IPay requires that test accounts submit an xml file of compiled responses before allowing an account to be used in production mode. The IPay gem has a certification mode that will compile all responses into the appropriate file/format for you automatically:
73
+
74
+ IPay::Certification.capture do
75
+ # ... all responses for api requests are now logged and saved when the block ends
76
+ end
@@ -0,0 +1,13 @@
1
+ require 'rake/testtask'
2
+
3
+ task :default => [:test]
4
+
5
+ task :console do
6
+ sh 'irb --simple-prompt -rubygems -I lib -r console.rb'
7
+ end
8
+
9
+ Rake::TestTask.new('test') do |t|
10
+ t.libs << 'test'
11
+ t.test_files = FileList['test/test*.rb']
12
+ t.verbose = true
13
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
3
+
4
+ require 'ipay'
5
+ require 'pp'
6
+
7
+ CC_EXP = "#{Date.today.month.to_s.rjust(2,'0')}#{Date.today.year.to_s[2..-1]}"
8
+
9
+ IPay::log = STDOUT
10
+
11
+ IPay::config do |c|
12
+ c.url = 'https://uap.txngw.com/'
13
+ c.company_key = 6990
14
+ c.terminal_id = 6177
15
+ c.pin = 1234
16
+ end
17
+
18
+ IPay::Certification.capture do
19
+
20
+ resp = IPay::CC::Debit.sale(
21
+ :amount => '4.99',
22
+ :account_number => '4000009999999991', :cvv => 123, :expiration => CC_EXP,
23
+ :first_name => 'nick', :last_name => 'wilson', :address => '123 fake st', :city => 'sometown', :state => 'NY', :postal_code => '90210', :country => IPay::Countries::USA
24
+ )
25
+
26
+ resp = IPay::CC::Debit.sale(
27
+ :amount => '59.99',
28
+ :account_number => '4000009999999991', :cvv => 123, :expiration => CC_EXP,
29
+ :first_name => 'nick', :last_name => 'wilson', :address => '123 fake st', :city => 'sometown', :state => 'NY', :postal_code => '90210', :country => IPay::Countries::USA
30
+ )
31
+ end
@@ -0,0 +1,2 @@
1
+ require 'ipay'
2
+ IPay::log = STDOUT
@@ -0,0 +1,42 @@
1
+ module IPay
2
+ ENV = ENV['RAILS_ENV'] || ENV['IPAY_ENV'] || 'development'
3
+ ROOT = ENV['RAILS_ROOT'] || ENV['IPAY_ROOT'] || '.'
4
+ CONFIG_NAME = 'ipay.yml'
5
+ LOG_NAME = 'ipay.log'
6
+
7
+ EM_SWIPED = 1
8
+ EM_MANUAL_PRESENT = 2
9
+ EM_MANUAL_NOT_PRESENT = 3
10
+
11
+ GOODS_DIGITAL = 'D'
12
+ GOODS_PHYSICAL = 'P'
13
+
14
+ CUR_DOMESTIC = 0
15
+ CUR_MCP = 1
16
+ CUR_PYC = 2
17
+
18
+ TXN_VIA_MAIL = 'M'
19
+ TXN_VIA_POS = 'P'
20
+ TXN_VIA_PHONE = 'T'
21
+ TXN_VIA_RECUR = 2
22
+ TXN_AUTHENTICATED = 5
23
+ TXN_AUTH_FAILED = 6
24
+ TXN_VIA_HTTPS = 7
25
+
26
+ ApiError = Class.new(RuntimeError)
27
+ RequestError = Class.new(ApiError)
28
+ RequestTimeout = Class.new(RequestError)
29
+ ResponseError = Class.new(ApiError)
30
+
31
+
32
+ autoload :CC, 'ipay/cc'
33
+ autoload :Wallet, 'ipay/wallet'
34
+ autoload :Network, 'ipay/network'
35
+
36
+ autoload :Certification, 'ipay/certification'
37
+ end
38
+
39
+ $:.unshift(File.dirname(__FILE__))
40
+ %w[ version config log countries ].each do |file|
41
+ require "ipay/#{file}"
42
+ end
@@ -0,0 +1,43 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require 'yaml'
4
+
5
+ require 'ipay/xml_request'
6
+ require 'ipay/response'
7
+
8
+ module IPay
9
+ class ApiRequest
10
+
11
+ DEFAULT_SERVICE_FORMAT = '0000'
12
+
13
+ def self.service_format
14
+ @@service_format ||= DEFAULT_SERVICE_FORMAT
15
+ end
16
+
17
+ def self.service_format=(val)
18
+ @@service_format = val
19
+ end
20
+
21
+ def self.service
22
+ self.name.split('::')[1] rescue nil
23
+ end
24
+
25
+ def self.service_type
26
+ self.name.split('::')[2] rescue nil
27
+ end
28
+
29
+ def self.send_request(data = {}, service_subtype = nil)
30
+ data[:service] = self.service.upcase
31
+ data[:service_type] = self.service_type.upcase
32
+ data[:service_subtype] = service_subtype.nil? ? caller[0][/`.*'/][1..-2].upcase : service_subtype.to_s.upcase
33
+ data[:service_format] ||= self.service_format
34
+
35
+ m = eval("#{self.service}")
36
+ data = m::default_values(data) if m::respond_to?(:default_values)
37
+
38
+ request = XmlRequest.new(data)
39
+ Response.new request.send
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,49 @@
1
+ require 'ipay/api_request'
2
+
3
+ module IPay
4
+ module CC
5
+
6
+ def self.default_values(data)
7
+ data[:currency_code] ||= 840 # USD
8
+ data[:currency_indicator] ||= CUR_DOMESTIC
9
+ data[:transaction_indicator] ||= TXN_VIA_HTTPS
10
+ data
11
+ end
12
+
13
+ class Credit < ApiRequest
14
+ self.service_format = '1010'
15
+
16
+ def self.refund(data)
17
+ self.send_request(data)
18
+ end
19
+
20
+ def self.void(data)
21
+ self.send_request(data)
22
+ end
23
+ end
24
+
25
+ class Debit < ApiRequest
26
+ self.service_format = '1010'
27
+
28
+ def self.auth(data)
29
+ data[:goods_indicator] ||= GOODS_DIGITAL
30
+ self.send_request(data)
31
+ end
32
+
33
+ def self.capture(data)
34
+ self.send_request(data)
35
+ end
36
+
37
+ def self.sale(data)
38
+ data[:goods_indicator] ||= GOODS_DIGITAL
39
+ data[:entry_mode] ||= EM_MANUAL_NOT_PRESENT
40
+ self.send_request(data)
41
+ end
42
+
43
+ def self.void(data)
44
+ self.send_request(data)
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,35 @@
1
+ require 'date'
2
+
3
+ module IPay
4
+ module Certification
5
+
6
+ def self.log(parsed_xml)
7
+ @@responses ||= ''
8
+ @@responses << parsed_xml.to_s.split("\n")[2...-1].join("\n") + "\n"
9
+ end
10
+
11
+ def self.capture(output_path = './')
12
+ IPay::config do |c|
13
+ c.certification = true
14
+ end
15
+
16
+ yield
17
+
18
+ self.save(output_path)
19
+
20
+ IPay::config do |c|
21
+ c.certification = false
22
+ end
23
+ end
24
+
25
+ def self.save(path)
26
+ raise 'Certification mode is not activated' unless IPay::config.certification
27
+
28
+ file_name = File.join(path, "#{IPay::config.operator}_#{Date.today.to_s.split('-').join}#{Random.new.rand(1..99).to_s.rjust(2, '0')}.xml")
29
+ file = File.open(file_name, 'w')
30
+ raise "Failed to open certification file '#{file_name}' for writing" unless file
31
+ file.write("<RESPONSES>\n#{@@responses}</RESPONSES>")
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require 'yaml'
2
+ require 'ostruct'
3
+
4
+ module IPay
5
+
6
+ def self.config_file
7
+ File.expand_path(File.join(ROOT, 'config', CONFIG_NAME))
8
+ end
9
+
10
+ def self.load_config_file
11
+ path = File.expand_path(config_file)
12
+
13
+ if File.readable?(path)
14
+ IPay::log.debug "Using configuration file '#{path}'"
15
+ @config = OpenStruct.new(YAML.load_file(path)) unless @config
16
+ else
17
+ @config = OpenStruct.new
18
+ IPay::log.warn "Failed to locate configuration file '#{CONFIG_NAME}', place in 'config/'"
19
+ end
20
+
21
+ set_defaults(@config)
22
+ end
23
+
24
+ def self.set_defaults(config)
25
+ config.dry_run ||= false
26
+ config.certification ||= false
27
+ config
28
+ end
29
+
30
+ def self.config
31
+ @config ||= load_config_file
32
+ yield @config if block_given?
33
+ @config
34
+ end
35
+ end
@@ -0,0 +1,7 @@
1
+ module IPay
2
+ module Countries
3
+
4
+ USA = 826
5
+
6
+ end
7
+ end
@@ -0,0 +1,28 @@
1
+ require 'logger'
2
+ module IPay
3
+ class Log < Logger
4
+ def format_message(severity, timestamp, progname, msg)
5
+ "#{timestamp} #{severity} -- #{msg}\n"
6
+ end
7
+ end
8
+
9
+ def self.log_file
10
+ path = File.join(ROOT, 'log')
11
+ path = '.' unless File.directory?(path)
12
+ File.expand_path(File.join(path, LOG_NAME))
13
+ end
14
+
15
+ def self.init_log(log = nil)
16
+ @log = Log.new(log||log_file)
17
+ @log.level = Logger::WARN if ENV == 'production'
18
+ @log
19
+ end
20
+
21
+ def self.log
22
+ @log ||= init_log
23
+ end
24
+
25
+ def self.log=(log)
26
+ init_log log
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ require 'ipay/api_request'
2
+
3
+ module IPay
4
+ module Network
5
+
6
+ class Status < ApiRequest
7
+ def self.query
8
+ self.send_request
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,67 @@
1
+ require 'xml'
2
+ require 'date'
3
+ require 'ipay/util'
4
+
5
+ module IPay
6
+ class Response
7
+
8
+ PARSER_OPT = XML::Parser::Options::NOBLANKS | XML::Parser::Options::NOERROR | XML::Parser::Options::RECOVER | XML::Parser::Options::NOWARNING
9
+
10
+ attr_reader :status, :server_time, :data, :raw_xml
11
+
12
+ def initialize(xml)
13
+ if IPay::config.dry_run
14
+ @status = {:arc => '00', :mrc => '00', :description => 'Dry Run, no response processed'}
15
+ else
16
+ @raw_xml = xml
17
+ parse_response @raw_xml
18
+ end
19
+ end
20
+
21
+ def success?
22
+ @status[:arc] == '00' && @status[:mrc] == '00'
23
+ end
24
+
25
+ def error?
26
+ not success?
27
+ end
28
+
29
+ private
30
+
31
+ def parse_response(xml)
32
+ IPay::log.debug 'Parsing response xml...'
33
+ parser = XML::Parser.string xml
34
+ parser.context.options = PARSER_OPT
35
+ parsed = parser.parse
36
+
37
+ IPay::Certification.log(parsed) if IPay::config.certification
38
+
39
+ response = xml_node_to_hash(parsed.find('//RESPONSE/RESPONSE/FIELDS')[0])
40
+ raise ResponseError.new 'Invalid response from server' unless response and response.include? :arc
41
+
42
+ d = response.delete(:local_date).match(/([0-9]{2})([0-9]{2})([0-9]{4})/)
43
+ t = response.delete(:local_time).match(/([0-9]{2})([0-9]{2})([0-9]{2})/)
44
+
45
+ @server_time = DateTime.parse("#{d[3]}-#{d[1]}-#{d[2]}T#{t[1]}:#{t[2]}:#{t[3]}") rescue DateTime.now
46
+ @status = { :arc => response.delete(:arc), :mrc => response.delete(:mrc), :description => response.delete(:response_text) }
47
+ @data = response
48
+
49
+ IPay::log.info "ARC=#{@status[:arc]}, MRC=#{@status[:mrc]}, RESPONSE_TEXT=#{@status[:description]}"
50
+ IPay::log.debug response
51
+ raise RequestTimeout.new(@status[:description]) if @status[:arc] == 'TO'
52
+ end
53
+
54
+ def xml_node_to_hash(node)
55
+ result = {}
56
+ if node.element? && node.children? && node.children[0].element?
57
+ node.children.each do |child|
58
+ result[child.name.downcase.to_sym] = xml_node_to_hash(child)
59
+ end
60
+ result
61
+ else
62
+ Util.unescape(node.content.strip)
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,29 @@
1
+ module IPay
2
+ module Util
3
+
4
+ ESCAPE_CHARS = { '&' => '&amp;', '"' => '&quot;', '<' => '&lt;', '>' => '&gt;', "'" => '&apos;' }
5
+
6
+ def self.escape(string)
7
+ string.to_s.gsub(Regexp.new(ESCAPE_CHARS.keys.join('|')), ESCAPE_CHARS)
8
+ end
9
+
10
+ def self.unescape(string)
11
+ string.gsub(Regexp.new(ESCAPE_CHARS.values.join('|')), ESCAPE_CHARS.invert)
12
+ end
13
+
14
+ def self.hash_to_xml(h, l=0)
15
+ return h.to_s unless h.is_a? Hash
16
+ xml = ''
17
+ h.each do |k,v|
18
+ k = k.to_s.upcase
19
+ xml << if v.kind_of? Enumerable
20
+ (v.is_a?(Array) ? v : Array[v]).collect { |group| "#{"\t"*l}<#{k}>\n#{hash_to_xml(group, l+1)}#{"\t"*l}</#{k}>\n"}.join
21
+ else
22
+ "#{"\t"*l}<#{k}>#{self.escape(v)}</#{k}>\n"
23
+ end
24
+ end
25
+ xml
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module IPay
2
+ VERSION = '0.1.1'
3
+ end
@@ -0,0 +1,44 @@
1
+ require 'ipay/api_request'
2
+
3
+ module IPay
4
+ module Wallet
5
+
6
+ def self.default_values(data)
7
+ data[:transaction_indicator] ||= TXN_VIA_HTTPS
8
+ data
9
+ end
10
+
11
+ class Client < ApiRequest
12
+ self.service_format = '1010'
13
+
14
+ def self.insert(data)
15
+ self.send_request(data)
16
+ end
17
+
18
+ def self.modify(data)
19
+ self.send_request(data)
20
+ end
21
+
22
+ def self.delete(data)
23
+ self.send_request(data)
24
+ end
25
+ end
26
+
27
+ class Account < ApiRequest
28
+ self.service_format = '1010'
29
+
30
+ def self.insert(data)
31
+ self.send_request(data)
32
+ end
33
+
34
+ def self.modify(data)
35
+ self.send_request(data)
36
+ end
37
+
38
+ def self.delete(data)
39
+ self.send_request(data)
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,69 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require 'yaml'
4
+ require 'ipay/util'
5
+
6
+ module IPay
7
+ class XmlRequest
8
+
9
+ CONFIG_GLOBALS = [:operator, :terminal_id, :pin, :verbose_response]
10
+
11
+ def initialize(data = {})
12
+ @data = data
13
+ IPay::log.debug "Request Args: #{(@data.collect { |k, v| "#{k}=#{v}" }.join(','))}"
14
+
15
+ CONFIG_GLOBALS.each do |key|
16
+ next if @data.include?(key)
17
+ @data[key] = IPay::config.send(key) if IPay::config.respond_to?(key)
18
+ end
19
+
20
+ @xml = build_xml Util::hash_to_xml(@data)
21
+ IPay::log.debug @xml
22
+ end
23
+
24
+ def to_s
25
+ @xml
26
+ end
27
+
28
+ def send
29
+ do_post(IPay::config.url, @xml)
30
+ end
31
+
32
+ private
33
+
34
+ def do_post(api_url, data)
35
+ IPay::log.debug "POST to #{api_url}"
36
+
37
+ if IPay::config.dry_run
38
+ IPay::log.info 'Dry run enabled, not sending to API'
39
+ return
40
+ end
41
+
42
+ url = URI.parse(api_url)
43
+ http = Net::HTTP.new(url.host, url.port)
44
+ http.use_ssl = true
45
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
46
+ store = OpenSSL::X509::Store.new
47
+ store.set_default_paths
48
+ http.cert_store = store
49
+
50
+ req = Net::HTTP::Post.new(url.path)
51
+ req.body = data
52
+
53
+ res = http.start { |http| http.request(req) }
54
+ res.body
55
+
56
+ rescue EOFError
57
+ raise RequestError.new('Unable to send your request or the request was rejected by the server.')
58
+ end
59
+
60
+ def build_xml(fields_xml)
61
+ "<REQUEST KEY=\"#{IPay::config.company_key}\" PROTOCOL=\"1\" FMT=\"1\" ENCODING=\"0\">
62
+ <TRANSACTION>
63
+ <FIELDS>#{fields_xml}</FIELDS>
64
+ </TRANSACTION>
65
+ </REQUEST>"
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,13 @@
1
+ require 'ipay'
2
+ require 'test/unit'
3
+ require 'date'
4
+
5
+ class Test::Unit::TestCase
6
+ def self.test(string, &block)
7
+ define_method("test:#{string}", &block)
8
+ end
9
+
10
+ def assert_not(expression)
11
+ assert_block("Expected <#{expression}> to be false!") { not expression }
12
+ end
13
+ end
@@ -0,0 +1,126 @@
1
+ require 'helper'
2
+
3
+ class TestCC < Test::Unit::TestCase
4
+ CC_EXP = "#{Date.today.month.to_s.rjust(2,'0')}#{Date.today.year.to_s[2..-1]}"
5
+
6
+ test 'debit sale' do
7
+ resp = IPay::CC::Debit.sale(
8
+ :amount => '4.99',
9
+ :account_number => '4000009999999991',
10
+ :cvv => 123,
11
+ :expiration => CC_EXP,
12
+ :first_name => 'nick',
13
+ :last_name => 'wilson',
14
+ :address => '123 fake st',
15
+ :city => 'sometown',
16
+ :state => 'NY',
17
+ :postal_code => '90210',
18
+ :country => IPay::Countries::USA
19
+ )
20
+
21
+ assert resp.success?
22
+ assert resp.data.include?(:transaction_id)
23
+ end
24
+
25
+ test 'debit capture and auth' do
26
+ resp = IPay::CC::Debit.auth(
27
+ :amount => '4.99',
28
+ :account_number => '4000009999999991',
29
+ :cvv => 123,
30
+ :expiration => CC_EXP,
31
+ :first_name => 'nick',
32
+ :last_name => 'wilson',
33
+ :address => '123 fake st',
34
+ :city => 'sometown',
35
+ :state => 'NY',
36
+ :postal_code => '90210',
37
+ :country => IPay::Countries::USA
38
+ )
39
+
40
+ assert resp.success?
41
+ assert resp.data.include?(:transaction_id)
42
+
43
+ sleep(3)
44
+
45
+ resp = IPay::CC::Debit.capture(
46
+ :amount => '4.99',
47
+ :transaction_id => resp.data[:transaction_id]
48
+ )
49
+
50
+ assert resp.success?
51
+ end
52
+
53
+ test 'debit void' do
54
+ resp = IPay::CC::Debit.sale(
55
+ :amount => '4.99',
56
+ :account_number => '4000009999999991',
57
+ :cvv => 123,
58
+ :expiration => CC_EXP,
59
+ :first_name => 'nick',
60
+ :last_name => 'wilson',
61
+ :address => '123 fake st',
62
+ :city => 'sometown',
63
+ :state => 'NY',
64
+ :postal_code => '90210',
65
+ :country => IPay::Countries::USA
66
+ )
67
+
68
+ assert resp.success?
69
+ assert resp.data.include?(:transaction_id)
70
+
71
+ sleep(3)
72
+
73
+ resp = IPay::CC::Debit.void(
74
+ :transaction_id => resp.data[:transaction_id]
75
+ )
76
+
77
+ assert resp.success?
78
+ end
79
+
80
+ test 'credit refund' do
81
+ resp = IPay::CC::Credit.refund(
82
+ :amount => '4.99',
83
+ :account_number => '4000009999999991',
84
+ :cvv => 123,
85
+ :expiration => CC_EXP,
86
+ :first_name => 'nick',
87
+ :last_name => 'wilson',
88
+ :address => '123 fake st',
89
+ :city => 'sometown',
90
+ :state => 'NY',
91
+ :postal_code => '90210',
92
+ :country => IPay::Countries::USA
93
+ )
94
+
95
+ assert resp.success?
96
+ assert resp.data.include?(:transaction_id)
97
+ end
98
+
99
+ test 'credit void' do
100
+ resp = IPay::CC::Credit.refund(
101
+ :amount => '4.99',
102
+ :account_number => '4000009999999991',
103
+ :cvv => 123,
104
+ :expiration => CC_EXP,
105
+ :first_name => 'nick',
106
+ :last_name => 'wilson',
107
+ :address => '123 fake st',
108
+ :city => 'sometown',
109
+ :state => 'NY',
110
+ :postal_code => '90210',
111
+ :country => IPay::Countries::USA
112
+ )
113
+
114
+ assert resp.success?
115
+ assert resp.data.include?(:transaction_id)
116
+
117
+ sleep(3)
118
+
119
+ resp = IPay::CC::Credit.void(
120
+ :transaction_id => resp.data[:transaction_id]
121
+ )
122
+
123
+ assert resp.success?
124
+ end
125
+
126
+ end
@@ -0,0 +1,47 @@
1
+ require 'helper'
2
+
3
+ class TestErrors < Test::Unit::TestCase
4
+ CC_EXP = "#{Date.today.month.to_s.rjust(2,'0')}#{Date.today.year.to_s[2..-1]}"
5
+
6
+ test 'sale declined' do
7
+
8
+ resp = IPay::CC::Debit.sale(
9
+ :amount => '1.05',
10
+ :account_number => '4000009999999991',
11
+ :cvv => 123,
12
+ :expiration => CC_EXP,
13
+ :first_name => 'nick',
14
+ :last_name => 'wilson',
15
+ :address => '123 fake st',
16
+ :city => 'sometown',
17
+ :state => 'NY',
18
+ :postal_code => '90210',
19
+ :country => IPay::Countries::USA
20
+ )
21
+
22
+ assert resp.error?
23
+ assert resp.status[:arc] == '05'
24
+
25
+ end
26
+
27
+ test 'request timeout' do
28
+
29
+ assert_raise IPay::RequestTimeout do
30
+ resp = IPay::CC::Debit.sale(
31
+ :amount => '1.57',
32
+ :account_number => '4000009999999991',
33
+ :cvv => 123,
34
+ :expiration => CC_EXP,
35
+ :first_name => 'nick',
36
+ :last_name => 'wilson',
37
+ :address => '123 fake st',
38
+ :city => 'sometown',
39
+ :state => 'NY',
40
+ :postal_code => '90210',
41
+ :country => IPay::Countries::USA
42
+ )
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,199 @@
1
+ require 'helper'
2
+
3
+ class TestWallet < Test::Unit::TestCase
4
+ CC_EXP = "#{Date.today.month.to_s.rjust(2,'0')}#{Date.today.year.to_s[2..-1]}"
5
+
6
+ test 'client insert' do
7
+ resp = IPay::Wallet::Client.insert(
8
+ :account => 'CC',
9
+ :billing_transaction => 2,
10
+ :account_number => '4000009999999991',
11
+ :cvv => 123,
12
+ :expiration => CC_EXP,
13
+ :first_name => 'nick',
14
+ :last_name => 'wilson',
15
+ :address => '123 fake st',
16
+ :city => 'sometown',
17
+ :state => 'NY',
18
+ :postal_code => '90210',
19
+ :country => IPay::Countries::USA
20
+ )
21
+
22
+ assert resp.success?
23
+ assert resp.data.include?(:transaction_id)
24
+ assert resp.data.include?(:client_id)
25
+ end
26
+
27
+ test 'client modify' do
28
+
29
+ resp = IPay::Wallet::Client.insert(
30
+ :account => 'CC',
31
+ :billing_transaction => 2,
32
+ :account_number => '4000009999999991',
33
+ :cvv => 123,
34
+ :expiration => CC_EXP,
35
+ :first_name => 'nick',
36
+ :last_name => 'wilson',
37
+ :address => '123 fake st',
38
+ :city => 'sometown',
39
+ :state => 'NY',
40
+ :postal_code => '90210',
41
+ :country => IPay::Countries::USA
42
+ )
43
+
44
+ assert resp.success?
45
+ assert resp.data.include?(:transaction_id)
46
+ assert resp.data.include?(:client_id)
47
+
48
+ sleep(3)
49
+
50
+ resp = IPay::Wallet::Client.modify(
51
+ :client_id => resp.data[:client_id],
52
+ :first_name => 'gregory washington'
53
+ )
54
+
55
+ assert resp.success?
56
+ assert resp.data.include?(:transaction_id)
57
+ end
58
+
59
+ test 'client delete' do
60
+ resp = IPay::Wallet::Client.insert(
61
+ :account => 'CC',
62
+ :billing_transaction => 2,
63
+ :account_number => '4000009999999991',
64
+ :cvv => 123,
65
+ :expiration => CC_EXP,
66
+ :first_name => 'nick',
67
+ :last_name => 'wilson',
68
+ :address => '123 fake st',
69
+ :city => 'sometown',
70
+ :state => 'NY',
71
+ :postal_code => '90210',
72
+ :country => IPay::Countries::USA
73
+ )
74
+
75
+ assert resp.success?
76
+ assert resp.data.include?(:transaction_id)
77
+ assert resp.data.include?(:client_id)
78
+
79
+ sleep(3)
80
+
81
+ resp = IPay::Wallet::Client.delete(
82
+ :client_id => resp.data[:client_id]
83
+ )
84
+
85
+ assert resp.success?
86
+ assert resp.data.include?(:transaction_id)
87
+ assert resp.data.include?(:client_id)
88
+ end
89
+
90
+ test 'account insert' do
91
+ resp = IPay::Wallet::Client.insert(
92
+ :account => 'CC',
93
+ :billing_transaction => 2,
94
+ :account_number => '4000009999999991',
95
+ :cvv => 123,
96
+ :expiration => CC_EXP,
97
+ :first_name => 'nick',
98
+ :last_name => 'wilson',
99
+ :address => '123 fake st',
100
+ :city => 'sometown',
101
+ :state => 'NY',
102
+ :postal_code => '90210',
103
+ :country => IPay::Countries::USA
104
+ )
105
+
106
+ assert resp.success?
107
+ assert resp.data.include?(:transaction_id)
108
+ assert resp.data.include?(:client_id)
109
+
110
+ sleep(3)
111
+
112
+ resp = IPay::Wallet::Account.insert(
113
+ :account => 'CC',
114
+ :billing_transaction => 2,
115
+ :account_number => '4000009999999991',
116
+ :cvv => 123,
117
+ :expiration => '0512',
118
+ :client_id => resp.data[:client_id]
119
+ )
120
+ assert resp.success?
121
+ assert resp.data.include?(:transaction_id)
122
+ end
123
+
124
+ test 'account modify' do
125
+ resp = IPay::Wallet::Client.insert(
126
+ :account => 'CC',
127
+ :billing_transaction => 2,
128
+ :account_number => '4000009999999991',
129
+ :cvv => 123,
130
+ :expiration => CC_EXP,
131
+ :first_name => 'nick',
132
+ :last_name => 'wilson',
133
+ :address => '123 fake st',
134
+ :city => 'sometown',
135
+ :state => 'NY',
136
+ :postal_code => '90210',
137
+ :country => IPay::Countries::USA
138
+ )
139
+
140
+ assert resp.success?
141
+ assert resp.data.include?(:transaction_id)
142
+ assert resp.data.include?(:client_id)
143
+
144
+ sleep(3)
145
+
146
+ resp = IPay::Wallet::Account.modify(
147
+ :account_id => resp.data[:account_id],
148
+ :billing_transaction => 2,
149
+ :account_number => '5100009999999997',
150
+ :cvv => 456,
151
+ :expiration => CC_EXP
152
+ )
153
+
154
+ assert resp.success?
155
+ assert resp.data.include?(:transaction_id)
156
+ end
157
+
158
+ test 'account delete' do
159
+ resp = IPay::Wallet::Client.insert(
160
+ :account => 'CC',
161
+ :billing_transaction => 2,
162
+ :account_number => '4000009999999991',
163
+ :cvv => 123,
164
+ :expiration => CC_EXP,
165
+ :first_name => 'nick',
166
+ :last_name => 'wilson',
167
+ :address => '123 fake st',
168
+ :city => 'sometown',
169
+ :state => 'NY',
170
+ :postal_code => '90210',
171
+ :country => IPay::Countries::USA
172
+ )
173
+
174
+ assert resp.success?
175
+ assert resp.data.include?(:transaction_id)
176
+ assert resp.data.include?(:client_id)
177
+
178
+ sleep(3)
179
+
180
+ resp = IPay::Wallet::Account.insert(
181
+ :account => 'CC',
182
+ :billing_transaction => 2,
183
+ :account_number => '4000009999999991',
184
+ :cvv => 123,
185
+ :expiration => '0512',
186
+ :client_id => resp.data[:client_id]
187
+ )
188
+ assert resp.success?
189
+ assert resp.data.include?(:transaction_id)
190
+
191
+ sleep(3)
192
+
193
+ resp = IPay::Wallet::Account.delete(
194
+ :account_id => resp.data[:account_id]
195
+ )
196
+ assert resp.success?
197
+ assert resp.data.include?(:transaction_id)
198
+ end
199
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ipay
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.1
6
+ platform: ruby
7
+ authors:
8
+ - Nick Wilson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-16 00:00:00 -04:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: libxml-ruby
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: iPay is a simple library for interfacing with Planet Payments payment solutions API, iPay. For more information visit http://www.ipay.com
28
+ email: wilson.nick@gmail.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files: []
34
+
35
+ files:
36
+ - lib/console.rb
37
+ - lib/ipay/api_request.rb
38
+ - lib/ipay/cc.rb
39
+ - lib/ipay/certification.rb
40
+ - lib/ipay/config.rb
41
+ - lib/ipay/countries.rb
42
+ - lib/ipay/log.rb
43
+ - lib/ipay/network.rb
44
+ - lib/ipay/response.rb
45
+ - lib/ipay/util.rb
46
+ - lib/ipay/version.rb
47
+ - lib/ipay/wallet.rb
48
+ - lib/ipay/xml_request.rb
49
+ - lib/ipay.rb
50
+ - test/helper.rb
51
+ - test/test_cc.rb
52
+ - test/test_errors.rb
53
+ - test/test_wallet.rb
54
+ - example/certification.rb
55
+ - README.md
56
+ - Rakefile
57
+ has_rdoc: true
58
+ homepage: https://github.com/AudioAddict/ipay
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.6.2
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: library for interfacing with iPay xml API
85
+ test_files: []
86
+