ipay 0.1.1

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.
@@ -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
+