an 0.0.1.rc2 → 0.0.1.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README +17 -24
  2. data/an.gemspec +3 -2
  3. data/lib/an.rb +52 -42
  4. data/test/an.rb +43 -26
  5. metadata +18 -7
data/README CHANGED
@@ -13,32 +13,25 @@ USAGE
13
13
 
14
14
  $ gem install an
15
15
 
16
- AN.login_id = ENV["LOGIN_ID"]
17
- AN.transaction_key = ENV["TRANS_KEY"]
18
-
19
- gateway = AN::AIM.test
20
-
21
- customer = AN::Customer.new(first_name: "John",
22
- last_name: "Doe",
23
- zip: "98004",
24
- email: "me@cyrildavid.com")
25
-
26
- invoice = AN::Invoice.new(invoice_num: SecureRandom.hex(20),
27
- amount: "19.99",
28
- description: "Sample Transaction")
29
-
30
- card = AN::CreditCard.new(card_num: "4111111111111111",
31
- card_code: "123",
32
- exp_month: "1", exp_year: "2015")
33
-
34
- begin
35
- gateway.sale(customer, invoice, card)
36
- rescue AN::TransactionFailed => e
37
- puts "%s: %s" % [e.reason_code, e.reason_text]
16
+ $ export AUTHORIZE_NET_URL=https://<login>:<key>@<url>
17
+
18
+ gateway = AN.connect
19
+
20
+ response = gateway.transact(
21
+ card_number: "4111111111111111",
22
+ card_code: "123",
23
+ expiration_date: "2015-01",
24
+ amount: "10.00",
25
+ invoice_number: SecureRandom.hex(10)
26
+ )
27
+
28
+ if resp.success?
29
+ # process the order, possibly storing
30
+ # parts of resp.to_hash
31
+ else
32
+ # display an error.
38
33
  end
39
34
 
40
-
41
35
  TODOS
42
36
 
43
37
  ARB Integration
44
- CIM Integration
data/an.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "an"
3
- s.version = "0.0.1.rc2"
3
+ s.version = "0.0.1.rc3"
4
4
  s.summary = "A thin Authorize.NET client."
5
5
  s.description = "AN is a simplified client for integration with Authorize.NET."
6
6
  s.authors = ["Cyril David"]
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
15
15
  "test/*.*"
16
16
  ]
17
17
 
18
- s.add_dependency "scrivener"
18
+ s.add_dependency "mote"
19
+ s.add_dependency "xml-simple"
19
20
  s.add_development_dependency "cutest"
20
21
  end
data/lib/an.rb CHANGED
@@ -9,14 +9,14 @@ class AN
9
9
  #
10
10
  # AUTHORIZE_NET_URL=https://login:key@api.authorize.net/xml/v1/request.api
11
11
  #
12
- # in the appropriate location (e.g. /etc/profile.d, ~/.bashrc, or
12
+ # in the appropriate location (e.g. /etc/profile.d, ~/.bashrc, or
13
13
  # whatever you're most comfortable with.
14
14
  #
15
15
  # The TEST URL is https://apikey.authorize.net/xml/v1/request.api
16
16
  def self.connect(url = ENV["AUTHORIZE_NET_URL"])
17
17
  new(URI(url))
18
18
  end
19
-
19
+
20
20
  TEMPLATES = File.expand_path("../templates", File.dirname(__FILE__))
21
21
 
22
22
  include Mote::Helpers
@@ -24,7 +24,7 @@ class AN
24
24
  attr :url
25
25
  attr :auth
26
26
  attr :client
27
-
27
+
28
28
  def initialize(uri)
29
29
  @auth = { login: uri.user, transaction_key: uri.password }
30
30
  @client = Client.new(uri)
@@ -41,16 +41,16 @@ class AN
41
41
  def create_payment_profile(params)
42
42
  call("createCustomerPaymentProfileRequest", params)
43
43
  end
44
-
44
+
45
45
  def create_profile_transaction(params)
46
46
  call("createCustomerProfileTransactionRequest", params)
47
47
  end
48
48
 
49
- private
49
+ private
50
50
  def call(api_call, params)
51
51
  Response.new(post(payload(api_call, params)))
52
52
  end
53
-
53
+
54
54
  def post(xml)
55
55
  client.post(xml, "Content-Type" => "text/xml")
56
56
  end
@@ -58,71 +58,81 @@ private
58
58
  def payload(api_call, params)
59
59
  mote(File.join(TEMPLATES, "%s.mote" % api_call), params.merge(auth))
60
60
  end
61
-
61
+
62
62
  class Response
63
- attr :data
64
-
65
63
  OK = "Ok"
66
64
 
67
65
  def initialize(xml)
68
- @data = XmlSimple.xml_in(xml, forcearray: false)
66
+ @data = XmlSimple.xml_in(xml, forcearray: false)
69
67
  end
70
68
 
71
- def success?
72
- data["messages"]["resultCode"] == OK
69
+ def [](key)
70
+ @data[key]
73
71
  end
74
72
 
75
- def transaction_id
76
- data["transactionResponse"]["transId"]
73
+ def success?
74
+ @data["messages"]["resultCode"] == OK
77
75
  end
78
76
 
79
- def reference_id
80
- data["refId"]
77
+ def to_hash
78
+ @data
81
79
  end
82
80
 
83
81
  def profile_id
84
- data["customerProfileId"]
82
+ @data["customerProfileId"]
85
83
  end
86
84
 
87
85
  def payment_profile_id
88
- data["customerPaymentProfileId"]
86
+ @data["customerPaymentProfileId"]
89
87
  end
90
88
 
91
- def validation_response
92
- if resp = data["validationDirectResponse"] || data["directResponse"]
93
- ValidationResponse.new(resp)
94
- end
89
+ def authorization
90
+ response = @data["validationDirectResponse"] || @data["directResponse"]
91
+
92
+ AuthorizationResponse.new(response) if response
95
93
  end
96
94
  end
97
95
 
98
- class ValidationResponse
99
- RESPONSE_FIELDS = %w[code subcode reason_code reason_text
100
- authorization_code avs_response trans_id
101
- invoice_number description amount method
102
- transaction_type customer_id first_name
103
- last_name company address city state zip
104
- country phone fax email
105
- shipping_first_name shipping_last_name
106
- shipping_company shipping_address shipping_city
107
- shipping_state shipping_zip shipping_country
108
- tax duty freight tax_exempt purchase_order_number
109
- md5_hash card_code_response cavv_response
110
- _41 _42 _43 _44 _45 _46 _47 _48 _49 _50
111
- account_number card_type split_tender_id
112
- requested_amount balance_on_card].freeze
113
-
114
- attr :fields
96
+ class AuthorizationResponse
97
+ FIELDS = {
98
+ 1 => "responseCode",
99
+ 3 => "messageCode",
100
+ 4 => "messageDescription",
101
+ 5 => "authCode",
102
+ 6 => "avsResultCode",
103
+ 7 => "transId",
104
+ 38 => "transHash",
105
+ 39 => "cvvResultCode",
106
+ 40 => "cavvResultCode",
107
+ 51 => "accountNumber",
108
+ 52 => "accountType"
109
+ }
115
110
 
116
111
  def initialize(data, delimiter = ",")
117
- @fields = Hash[RESPONSE_FIELDS.zip(data.split(delimiter))]
112
+ @list = data.split(delimiter)
113
+ @data = {}
114
+
115
+ FIELDS.each do |index, field|
116
+ # The FIELDS hash is using a 1-based index in order
117
+ # to match the ordering number in the AIM documentation.
118
+ @data[field] = @list[index - 1]
119
+ end
120
+ end
121
+
122
+ def to_hash
123
+ @data
124
+ end
125
+
126
+ def [](key)
127
+ @data[key]
118
128
  end
119
129
 
120
130
  def success?
121
- fields["code"] == "1" && fields["reason_code"] == "1"
131
+ @data["responseCode"] == "1" && @data["messageCode"] == "1"
122
132
  end
123
133
 
124
134
  def transaction_id
125
- fields["trans_id"]
135
+ @data["transId"]
126
136
  end
127
137
  end
128
138
 
data/test/an.rb CHANGED
@@ -4,22 +4,39 @@ setup do
4
4
  AN.connect
5
5
  end
6
6
 
7
- test "AIM basic transaction" do |gateway|
8
- resp = gateway.transact({
9
- :card_number => "4111111111111111",
10
- :card_code => "123",
11
- :expiration_date => "2015-01",
12
- :amount => "10.00",
13
- :invoice_number => SecureRandom.hex(10),
14
- :description => "Aeutsahoesuhtaeu",
15
- :first_name => "John",
16
- :last_name => "Doe",
17
- :address => "12345 foobar street",
18
- :zip => "90210"
19
- })
7
+ test "AIM most basic transaction" do |gateway|
8
+ resp = gateway.transact(
9
+ card_number: "4111111111111111",
10
+ card_code: "123",
11
+ expiration_date: "2015-01",
12
+ amount: "10.00",
13
+ invoice_number: SecureRandom.hex(10)
14
+ )
20
15
 
21
16
  assert resp.success?
22
- assert resp.transaction_id
17
+ assert resp["transactionResponse"].kind_of?(Hash)
18
+ assert_equal "XXXX1111", resp["transactionResponse"]["accountNumber"]
19
+ assert_equal "Visa", resp["transactionResponse"]["accountType"]
20
+ end
21
+
22
+ test "AIM transaction with billing info" do |gateway|
23
+ resp = gateway.transact(
24
+ card_number: "4111111111111111",
25
+ card_code: "123",
26
+ expiration_date: "2015-01",
27
+ amount: "10.00",
28
+ invoice_number: SecureRandom.hex(10),
29
+ description: "Aeutsahoesuhtaeu",
30
+ first_name: "John",
31
+ last_name: "Doe",
32
+ address: "12345 foobar street",
33
+ zip: "90210"
34
+ )
35
+
36
+ assert resp.success?
37
+ assert resp["transactionResponse"].kind_of?(Hash)
38
+ assert_equal "XXXX1111", resp["transactionResponse"]["accountNumber"]
39
+ assert_equal "Visa", resp["transactionResponse"]["accountType"]
23
40
  end
24
41
 
25
42
  # CIM (Customer Information Manager)
@@ -33,9 +50,9 @@ scope do
33
50
  resp = gateway.create_profile(reference_id: reference_id,
34
51
  customer_id: customer_id,
35
52
  email: "foo@bar.com")
36
-
53
+
37
54
  assert resp.success?
38
- assert_equal reference_id, resp.reference_id
55
+ assert_equal reference_id, resp["refId"]
39
56
  assert resp.profile_id
40
57
 
41
58
  # After a successful response in the background process, you
@@ -64,13 +81,13 @@ scope do
64
81
  # By default the validation method used is liveMode which returns an
65
82
  # AIM-like payment response string related to the credit card details
66
83
  # passed as part of creating the payment profile.
67
- assert resp.success?
84
+ assert resp.success?
68
85
  assert resp.payment_profile_id
69
- assert resp.validation_response.success?
70
-
71
- assert_equal "XXXX1111", resp.validation_response.fields["account_number"]
72
- assert_equal "Visa", resp.validation_response.fields["card_type"]
73
-
86
+ assert resp.authorization.success?
87
+
88
+ assert_equal "XXXX1111", resp.authorization["accountNumber"]
89
+ assert_equal "Visa", resp.authorization["accountType"]
90
+
74
91
  # The payment profile id should then be saved together with the user.
75
92
  # You may also do a one-to-many setup similar to amazon where they can
76
93
  # add multiple credit cards. If that's the case, simply use the
@@ -89,10 +106,10 @@ scope do
89
106
  description: "Jan - Feb",
90
107
  purchase_order_number: "001"
91
108
  })
92
-
109
+
93
110
  assert resp.success?
94
- assert resp.validation_response.success?
95
- assert_equal "XXXX1111", resp.validation_response.fields["account_number"]
96
- assert_equal "Visa", resp.validation_response.fields["card_type"]
111
+ assert resp.authorization.success?
112
+ assert_equal "XXXX1111", resp.authorization["accountNumber"]
113
+ assert_equal "Visa", resp.authorization["accountType"]
97
114
  end
98
115
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: an
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.rc2
4
+ version: 0.0.1.rc3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -12,8 +12,8 @@ cert_chain: []
12
12
  date: 2012-02-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: scrivener
16
- requirement: &2156032980 !ruby/object:Gem::Requirement
15
+ name: mote
16
+ requirement: &2151853740 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,21 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2156032980
24
+ version_requirements: *2151853740
25
+ - !ruby/object:Gem::Dependency
26
+ name: xml-simple
27
+ requirement: &2151853160 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2151853160
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: cutest
27
- requirement: &2155894040 !ruby/object:Gem::Requirement
38
+ requirement: &2151852500 !ruby/object:Gem::Requirement
28
39
  none: false
29
40
  requirements:
30
41
  - - ! '>='
@@ -32,7 +43,7 @@ dependencies:
32
43
  version: '0'
33
44
  type: :development
34
45
  prerelease: false
35
- version_requirements: *2155894040
46
+ version_requirements: *2151852500
36
47
  description: AN is a simplified client for integration with Authorize.NET.
37
48
  email:
38
49
  - me@cyrildavid.com
@@ -66,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
77
  version: 1.3.1
67
78
  requirements: []
68
79
  rubyforge_project:
69
- rubygems_version: 1.8.11
80
+ rubygems_version: 1.8.16
70
81
  signing_key:
71
82
  specification_version: 3
72
83
  summary: A thin Authorize.NET client.