epay 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.gitignore +15 -0
  2. data/.travis.yml +5 -0
  3. data/CHANGELOG.md +13 -0
  4. data/Gemfile +2 -0
  5. data/Guardfile +10 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.markdown +21 -0
  8. data/Rakefile +8 -0
  9. data/bin/epay-console +8 -0
  10. data/epay.gemspec +55 -0
  11. data/lib/epay.rb +104 -0
  12. data/lib/epay/api.rb +92 -0
  13. data/lib/epay/api/response.rb +29 -0
  14. data/lib/epay/card.rb +23 -0
  15. data/lib/epay/model.rb +23 -0
  16. data/lib/epay/subscription.rb +132 -0
  17. data/lib/epay/transaction.rb +171 -0
  18. data/lib/epay/version.rb +3 -0
  19. data/lib/extensions/hash.rb +4 -0
  20. data/spec/api/response_spec.rb +71 -0
  21. data/spec/api_spec.rb +58 -0
  22. data/spec/card_spec.rb +21 -0
  23. data/spec/fixtures/vcr_cassettes/existing_subscription.yml +75 -0
  24. data/spec/fixtures/vcr_cassettes/existing_transaction.yml +47 -0
  25. data/spec/fixtures/vcr_cassettes/non_existing_transaction.yml +48 -0
  26. data/spec/fixtures/vcr_cassettes/subscription_authorization.yml +95 -0
  27. data/spec/fixtures/vcr_cassettes/subscription_creation.yml +101 -0
  28. data/spec/fixtures/vcr_cassettes/subscription_invalid_creation.yml +47 -0
  29. data/spec/fixtures/vcr_cassettes/subscriptions.yml +87 -0
  30. data/spec/fixtures/vcr_cassettes/transaction_creation.yml +90 -0
  31. data/spec/fixtures/vcr_cassettes/transaction_invalid_creation.yml +47 -0
  32. data/spec/fixtures/vcr_cassettes/transactions.yml +50 -0
  33. data/spec/helpers/http_responses.rb +13 -0
  34. data/spec/model_spec.rb +36 -0
  35. data/spec/spec_helper.rb +20 -0
  36. data/spec/subscription_spec.rb +139 -0
  37. data/spec/transaction_spec.rb +245 -0
  38. metadata +280 -0
@@ -0,0 +1,90 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx
6
+ body: merchantnumber=8887978&cardno=5555555555555000&cvc=999&expmonth=10&expyear=15&amount=6000&currency=208&orderid=TEST-ORDER-12345&accepturl=https%3A%2F%2Fssl.ditonlinebetalingssystem.dk%2Fauth%2Fdefault.aspx%3Faccept%3D1&declineurl=https%3A%2F%2Fssl.ditonlinebetalingssystem.dk%2Fauth%2Fdefault.aspx%3Fdecline%3D1&description=For%20the%20cool%20products&cardholder=Jack%20Jensen&group=Test-transactions&instantcapture=0
7
+ headers:
8
+ Accept:
9
+ - ! '*/*; q=0.5, application/xml'
10
+ Accept-Encoding:
11
+ - gzip, deflate
12
+ Content-Length:
13
+ - '417'
14
+ Content-Type:
15
+ - application/x-www-form-urlencoded
16
+ User-Agent:
17
+ - Ruby
18
+ response:
19
+ status:
20
+ code: 302
21
+ message: Found
22
+ headers:
23
+ Cache-Control:
24
+ - private
25
+ Content-Type:
26
+ - text/html; charset=iso-8859-1
27
+ Location:
28
+ - https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?accept=1&tid=8840215&orderid=TEST-ORDER-12345&amount=6000&cur=208&date=20120214&time=1147&cardnopostfix=5000&tcardno=555555XXXXXX5000&cardid=4&transfee=0
29
+ Set-Cookie:
30
+ - ASP.NET_SessionId=ttcv4fb3oby30sayyisibj55; path=/; HttpOnly
31
+ X-Aspnet-Version:
32
+ - 2.0.50727
33
+ X-Powered-By:
34
+ - ASP.NET
35
+ Date:
36
+ - Tue, 14 Feb 2012 10:46:46 GMT
37
+ Content-Length:
38
+ - '368'
39
+ body: ! "<html><head><title>Object moved</title></head><body>\r\n<h2>Object moved
40
+ to <a href=\"https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?accept=1&amp;tid=8840215&amp;orderid=TEST-ORDER-12345&amp;amount=6000&amp;cur=208&amp;date=20120214&amp;time=1147&amp;cardnopostfix=5000&amp;tcardno=555555XXXXXX5000&amp;cardid=4&amp;transfee=0\">here</a>.</h2>\r\n</body></html>\r\n"
41
+ http_version: !!null
42
+ recorded_at: Tue, 14 Feb 2012 10:47:50 GMT
43
+ - request:
44
+ method: post
45
+ uri: https://ssl.ditonlinebetalingssystem.dk/remote/payment.asmx
46
+ body: ! "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soap:Envelope xmlns:xsi=\"http://schemas.xmlsoap.org/soap/envelope/\"
47
+ xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n
48
+ \ <soap:Body>\n <gettransaction xmlns=\"https://ssl.ditonlinebetalingssystem.dk/remote/payment\">\n
49
+ \ <transactionid>8840215</transactionid>\n <merchantnumber>8887978</merchantnumber>\n
50
+ \ </gettransaction>\n </soap:Body>\n</soap:Envelope>\n"
51
+ headers:
52
+ Accept:
53
+ - ! '*/*; q=0.5, application/xml'
54
+ Accept-Encoding:
55
+ - gzip, deflate
56
+ Content-Type:
57
+ - text/xml; charset=utf-8
58
+ Soapaction:
59
+ - https://ssl.ditonlinebetalingssystem.dk/remote/payment/gettransaction
60
+ Content-Length:
61
+ - '453'
62
+ User-Agent:
63
+ - Ruby
64
+ response:
65
+ status:
66
+ code: 200
67
+ message: OK
68
+ headers:
69
+ Cache-Control:
70
+ - private, max-age=0
71
+ Content-Type:
72
+ - text/xml; charset=utf-8
73
+ X-Aspnet-Version:
74
+ - 2.0.50727
75
+ X-Powered-By:
76
+ - ASP.NET
77
+ Date:
78
+ - Tue, 14 Feb 2012 10:46:46 GMT
79
+ Content-Length:
80
+ - '1836'
81
+ body: <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
82
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><gettransactionResponse
83
+ xmlns="https://ssl.ditonlinebetalingssystem.dk/remote/payment"><gettransactionResult>true</gettransactionResult><transactionInformation><group>Test-transactions</group><authamount>6000</authamount><currency>208</currency><cardtypeid>4</cardtypeid><capturedamount>0</capturedamount><creditedamount>0</creditedamount><orderid>TEST-ORDER-12345</orderid><description>For
84
+ the cool products</description><authdate>2012-02-14T11:47:00</authdate><captureddate>0001-01-01T00:00:00</captureddate><deleteddate>0001-01-01T00:00:00</deleteddate><crediteddate>0001-01-01T00:00:00</crediteddate><status>PAYMENT_NEW</status><history><TransactionHistoryInfo><transactionHistoryID>21568611</transactionHistoryID><logonID>0</logonID><username
85
+ /><eventMsg>Payment moved to group Test-transactions</eventMsg><created>2012-02-14T11:47:00</created></TransactionHistoryInfo><TransactionHistoryInfo><transactionHistoryID>21568610</transactionHistoryID><logonID>0</logonID><username
86
+ /><eventMsg>Payment authorized with amount 60,00 and currency code 208</eventMsg><created>2012-02-14T11:47:00</created></TransactionHistoryInfo></history><transactionid>8840215</transactionid><cardholder>Jack
87
+ Jensen</cardholder><mode>MODE_EPAY</mode><msc>false</msc><fraudStatus>0</fraudStatus><payerCountryCode> </payerCountryCode><issuedCountryCode> </issuedCountryCode><fee>0</fee><splitpayment>false</splitpayment><acquirer>EUROLINE</acquirer><tcardno>555555XXXXXX5000</tcardno><expmonth>10</expmonth><expyear>15</expyear></transactionInformation><epayresponse>-1</epayresponse></gettransactionResponse></soap:Body></soap:Envelope>
88
+ http_version: !!null
89
+ recorded_at: Tue, 14 Feb 2012 10:47:50 GMT
90
+ recorded_with: VCR 2.0.0.rc1
@@ -0,0 +1,47 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx
6
+ body: merchantnumber=8887978&cardno=5555555555555118&cvc=999&expmonth=10&expyear=15&amount=6000&currency=208&orderid=TEST-ORDER-12345&accepturl=https%3A%2F%2Fssl.ditonlinebetalingssystem.dk%2Fauth%2Fdefault.aspx%3Faccept%3D1&declineurl=https%3A%2F%2Fssl.ditonlinebetalingssystem.dk%2Fauth%2Fdefault.aspx%3Fdecline%3D1&description=For%20the%20cool%20products&cardholder=Jack%20Jensen&group=Test-transactions&instantcapture=0
7
+ headers:
8
+ Accept:
9
+ - ! '*/*; q=0.5, application/xml'
10
+ Accept-Encoding:
11
+ - gzip, deflate
12
+ Content-Length:
13
+ - '417'
14
+ Content-Type:
15
+ - application/x-www-form-urlencoded
16
+ User-Agent:
17
+ - Ruby
18
+ response:
19
+ status:
20
+ code: 302
21
+ message: Found
22
+ headers:
23
+ Cache-Control:
24
+ - private
25
+ Content-Type:
26
+ - text/html; charset=iso-8859-1
27
+ Location:
28
+ - https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?decline=1&error=118&orderid=TEST-ORDER-12345&errortext=Betalingen
29
+ blev afvist da det indtastede kortnummer ikke kan findes. Pr%f8v og indtaste
30
+ kortets oplysninger igen eller pr%f8v med et andet betalingskort.
31
+ Set-Cookie:
32
+ - ASP.NET_SessionId=k44l3g55x4sofwm3esjkga45; path=/; HttpOnly
33
+ X-Aspnet-Version:
34
+ - 2.0.50727
35
+ X-Powered-By:
36
+ - ASP.NET
37
+ Date:
38
+ - Tue, 14 Feb 2012 10:47:46 GMT
39
+ Content-Length:
40
+ - '395'
41
+ body: ! "<html><head><title>Object moved</title></head><body>\r\n<h2>Object moved
42
+ to <a href=\"https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?decline=1&amp;error=118&amp;orderid=TEST-ORDER-12345&amp;errortext=Betalingen
43
+ blev afvist da det indtastede kortnummer ikke kan findes. Pr%f8v og indtaste
44
+ kortets oplysninger igen eller pr%f8v med et andet betalingskort.\">here</a>.</h2>\r\n</body></html>\r\n"
45
+ http_version: !!null
46
+ recorded_at: Tue, 14 Feb 2012 10:48:50 GMT
47
+ recorded_with: VCR 2.0.0.rc1
@@ -0,0 +1,50 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://ssl.ditonlinebetalingssystem.dk/remote/payment.asmx
6
+ body: ! "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<soap:Envelope xmlns:xsi=\"http://schemas.xmlsoap.org/soap/envelope/\"
7
+ xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n
8
+ \ <soap:Body>\n <gettransaction xmlns=\"https://ssl.ditonlinebetalingssystem.dk/remote/payment\">\n
9
+ \ <transactionid>8786997</transactionid>\n <merchantnumber>8887978</merchantnumber>\n
10
+ \ </gettransaction>\n </soap:Body>\n</soap:Envelope>\n"
11
+ headers:
12
+ Accept:
13
+ - ! '*/*; q=0.5, application/xml'
14
+ Accept-Encoding:
15
+ - gzip, deflate
16
+ Content-Type:
17
+ - text/xml; charset=utf-8
18
+ Soapaction:
19
+ - https://ssl.ditonlinebetalingssystem.dk/remote/payment/gettransaction
20
+ Content-Length:
21
+ - '453'
22
+ User-Agent:
23
+ - Ruby
24
+ response:
25
+ status:
26
+ code: 200
27
+ message: OK
28
+ headers:
29
+ Cache-Control:
30
+ - private, max-age=0
31
+ Content-Type:
32
+ - text/xml; charset=utf-8
33
+ X-Aspnet-Version:
34
+ - 2.0.50727
35
+ X-Powered-By:
36
+ - ASP.NET
37
+ Date:
38
+ - Mon, 13 Feb 2012 12:38:22 GMT
39
+ Content-Length:
40
+ - '1518'
41
+ body: <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
42
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><gettransactionResponse
43
+ xmlns="https://ssl.ditonlinebetalingssystem.dk/remote/payment"><gettransactionResult>true</gettransactionResult><transactionInformation><group
44
+ /><authamount>7900</authamount><currency>208</currency><cardtypeid>18</cardtypeid><capturedamount>0</capturedamount><creditedamount>0</creditedamount><orderid>orderid</orderid><description
45
+ /><authdate>2012-02-10T11:30:00</authdate><captureddate>0001-01-01T00:00:00</captureddate><deleteddate>0001-01-01T00:00:00</deleteddate><crediteddate>0001-01-01T00:00:00</crediteddate><status>PAYMENT_NEW</status><history><TransactionHistoryInfo><transactionHistoryID>21437164</transactionHistoryID><logonID>-1</logonID><username
46
+ /><eventMsg>Payment authorized with amount 79,00 and currency code 208</eventMsg><created>2012-02-10T11:30:00</created></TransactionHistoryInfo></history><transactionid>8786997</transactionid><cardholder
47
+ /><mode>MODE_EPAY</mode><msc>false</msc><fraudStatus>0</fraudStatus><payerCountryCode> </payerCountryCode><issuedCountryCode> </issuedCountryCode><fee>0</fee><splitpayment>false</splitpayment><acquirer>EUROLINE</acquirer><tcardno>333333XXXXXX3000</tcardno><expmonth>10</expmonth><expyear>12</expyear></transactionInformation><epayresponse>-1</epayresponse></gettransactionResponse></soap:Body></soap:Envelope>
48
+ http_version: !!null
49
+ recorded_at: Mon, 13 Feb 2012 12:39:25 GMT
50
+ recorded_with: VCR 2.0.0.rc1
@@ -0,0 +1,13 @@
1
+ module HttpResponses
2
+ def self.included(base) do
3
+ before do
4
+ stub_request(:post, 'https://ssl.ditonlinebetalingssystem.dk/remote/payment.asmx') { 'lol?' }
5
+ end
6
+ end
7
+
8
+ def stub_soap_request(url, action, parameters)
9
+ Epay::Api.stub(:request).with(url, actions, parameters) do
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ module Epay
4
+ class MockedModel
5
+ include Model
6
+
7
+ def self.inspectable_attributes
8
+ %w(id description another_attribute)
9
+ end
10
+
11
+ def description
12
+ 'Description'
13
+ end
14
+
15
+ def another_attribute
16
+ 'Another'
17
+ end
18
+ end
19
+
20
+ describe 'Model' do
21
+ let(:model) do
22
+ MockedModel.new(42)
23
+ end
24
+
25
+ describe "inspection" do
26
+ it "contains id" do
27
+ model.inspect.to_s.should =~ /id: 42/
28
+ end
29
+
30
+ it "contains attributes" do
31
+ model.inspect.to_s.should =~ /description: "Description"/
32
+ model.inspect.to_s.should =~ /another_attribute: "Another"/
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ require 'vcr'
2
+ require 'webmock/rspec'
3
+
4
+ require 'epay'
5
+
6
+ module Epay
7
+ EXISTING_TRANSACTION_ID = 8786997
8
+ NON_EXISTING_TRANSACTION_ID = 12345678
9
+ end
10
+
11
+ RSpec.configure do |c|
12
+ c.before(:all) do
13
+ Epay.merchant_number = 8887978
14
+ end
15
+ end
16
+
17
+ VCR.configure do |c|
18
+ c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
19
+ c.hook_into :webmock
20
+ end
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+
3
+ module Epay
4
+ describe Subscription do
5
+ let(:subscription) do
6
+ VCR.use_cassette('existing_subscription') do
7
+ Subscription.find(387544)
8
+ end
9
+ end
10
+
11
+ describe "attributes" do
12
+ it "has created_at" do
13
+ subscription.created_at.should == Time.local(2012, 2, 9, 12, 11)
14
+ end
15
+
16
+ it "has description" do
17
+ subscription.description.should == "Test-subscriber"
18
+ end
19
+ end
20
+
21
+ describe "#transactions" do
22
+ it "returns a list of transactions" do
23
+ subscription.transactions.first.should be_a Transaction
24
+ end
25
+
26
+ context "when no transactions has been made" do
27
+ it "returns an empty list" do
28
+ subscription.data.delete('transactionList')
29
+ subscription.transactions.should == []
30
+ end
31
+ end
32
+
33
+ context "when one transaction has been made" do
34
+ it "returns list of transactions" do
35
+ subscription.data['transactionList'] = {"TransactionInformationType"=>{"group"=>nil, "authamount"=>"59000", "currency"=>"208", "cardtypeid"=>"4", "capturedamount"=>"0", "creditedamount"=>"0", "orderid"=>"__dev__-1-10000", "description"=>nil, "authdate"=>"2012-03-12T19:56:00", "captureddate"=>"0001-01-01T00:00:00", "deleteddate"=>"0001-01-01T00:00:00", "crediteddate"=>"0001-01-01T00:00:00", "status"=>"PAYMENT_NEW", "history"=>{"TransactionHistoryInfo"=>{"transactionHistoryID"=>"22572373", "logonID"=>"-1", "username"=>nil, "eventMsg"=>"Payment authorized with amount 590,00 and currency code 208", "created"=>"2012-03-12T19:56:00"}}, "transactionid"=>"9239756", "cardholder"=>nil, "mode"=>"MODE_EPAY", "msc"=>"false", "fraudStatus"=>"0", "payerCountryCode"=>" ", "issuedCountryCode"=>" ", "fee"=>"0", "splitpayment"=>"false", "acquirer"=>"EUROLINE", "tcardno"=>"555555XXXXXX5000", "expmonth"=>"1", "expyear"=>"12"}}
36
+ subscription.transactions.first.should be_a Transaction
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#card" do
42
+ it "returns card" do
43
+ Card.should_receive(:new).with(:exp_year => 12, :exp_month => 10, :kind => :visa, :number => '333333XXXXXX3000')
44
+ subscription.card
45
+ end
46
+
47
+ context "when no transaction has been made" do
48
+ it "returns card with no number" do
49
+ subscription.stub(:transactions) { [] }
50
+ Card.should_receive(:new).with(:exp_year => 12, :exp_month => 10, :kind => :visa, :number => nil)
51
+ subscription.card
52
+ end
53
+ end
54
+ end
55
+
56
+ describe ".all" do
57
+ it "returns a list of subscriptions" do
58
+ VCR.use_cassette('subscriptions') do
59
+ subscriptions = Subscription.all
60
+ subscriptions.should be_a Enumerable
61
+ subscriptions.first.should be_a Subscription
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "#delete" do
67
+ it "requests to api" do
68
+ subscription_id = subscription.id
69
+
70
+ Api.should_receive(:request).with(SUBSCRIPTION_SOAP_URL, 'delete', :subscriptionid => subscription_id) {
71
+ mock(Api::Response, :success? => true)
72
+ }
73
+
74
+ subscription.delete
75
+ end
76
+ end
77
+
78
+ describe ".create" do
79
+ context "when card data is valid" do
80
+ let(:subscription) do
81
+ VCR.use_cassette('subscription_creation') do
82
+ Subscription.create(:card_no => '5555555555555000', :exp_year => '15', :exp_month => '10', :cvc => '999', :description => 'A new subscriber', :currency => :DKK)
83
+ end
84
+ end
85
+
86
+ it "returns subscription" do
87
+ subscription.should be_a Subscription
88
+ subscription.transactions.should be_empty
89
+ end
90
+
91
+ it "is has card with card number" do
92
+ subscription.card_no.should == '555555XXXXXX5000'
93
+ end
94
+ end
95
+
96
+ context "when card data is invalid" do
97
+ describe "the returned subscription" do
98
+ let(:subscription) do
99
+ VCR.use_cassette('subscription_invalid_creation') do
100
+ Subscription.create(:card_no => '5555555555555118', :exp_year => '15', :exp_month => '10', :cvc => '999', :description => 'A new subscriber', :currency => :DKK)
101
+ end
102
+ end
103
+
104
+ it "has error code" do
105
+ subscription.error.should == '118'
106
+ end
107
+
108
+ it "is isn't valid" do
109
+ subscription.should_not be_valid
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "#authorize" do
116
+ it "returns new transaction" do
117
+ VCR.use_cassette('subscription_authorization') do
118
+ transaction = subscription.authorize(:order_no => 'NEW ORDER', :amount => 10.0, :currency => :DKK)
119
+ transaction.should be_a Transaction
120
+ end
121
+ end
122
+
123
+ context "when authorization fails" do
124
+ it "returns transaction with error code etc." do
125
+ subscription
126
+
127
+ response = mock(Api::Response)
128
+ response.stub(:success?) { false }
129
+ response.stub(:data) { {'pbsresponse' => '404'} }
130
+
131
+ Api.stub(:request).with(SUBSCRIPTION_SOAP_URL, 'authorize', anything).and_yield(response)
132
+
133
+ Transaction.should_receive(:new).with(nil, 'error' => '404', 'failed' => true)
134
+ subscription.authorize(:order_no => 'NEW ORDER', :amount => 10.0, :currency => :DKK)
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,245 @@
1
+ require 'spec_helper'
2
+
3
+ module Epay
4
+ describe Transaction do
5
+ let(:transaction) do
6
+ VCR.use_cassette('existing_transaction') do
7
+ Transaction.find(EXISTING_TRANSACTION_ID)
8
+ end
9
+ end
10
+
11
+ describe "attributes" do
12
+ it "has description" do
13
+ transaction.description.should == "Description of transaction"
14
+ end
15
+
16
+ it "has amount" do
17
+ transaction.amount.should == 79.0
18
+ end
19
+
20
+ it "has card" do
21
+ Card.should_receive(:new).with(:number => '333333XXXXXX3000', :exp_year => 12, :exp_month => 10, :kind => :visa)
22
+ transaction.card
23
+ end
24
+
25
+ it "has group" do
26
+ transaction.group.should == 'Group'
27
+ end
28
+
29
+ it "has cardholder" do
30
+ transaction.cardholder.should == 'John Doe'
31
+ end
32
+
33
+ it "has acquirer" do
34
+ transaction.acquirer.should == 'EUROLINE'
35
+ end
36
+
37
+ it "has currency" do
38
+ transaction.currency.should == :DKK
39
+ end
40
+
41
+ it "has order no" do
42
+ transaction.order_no.should == 'MY-ORDER-ID'
43
+ end
44
+
45
+ it "has created_at" do
46
+ transaction.created_at.should == Time.local(2012, 2, 10, 11, 30, 0)
47
+ end
48
+
49
+ it "has error" do
50
+ transaction.data.stub(:[]).with('error') { 404 }
51
+ transaction.error.should == 404
52
+ end
53
+
54
+ it "has credited_amount" do
55
+ transaction.credited_amount == 3
56
+ end
57
+ end
58
+
59
+ describe "#test?" do
60
+ it "is true when mode is EPAY or TEST" do
61
+ transaction.data.stub(:[]).with('mode') { 'MODE_EPAY' }
62
+ transaction.test?.should be_true
63
+
64
+ transaction.data.stub(:[]).with('mode') { 'MODE_TEST' }
65
+ transaction.test?.should be_true
66
+ end
67
+
68
+ it "is false when in production" do
69
+ transaction.data.stub(:[]).with('mode') { 'MODE_PRODUCTION' }
70
+ transaction.test?.should be_false
71
+ end
72
+ end
73
+
74
+ describe "#production?" do
75
+ it "is opposite of test?" do
76
+ transaction.stub(:test?) { false }
77
+ transaction.production?.should be_true
78
+
79
+ transaction.stub(:test?) { true }
80
+ transaction.production?.should be_false
81
+ end
82
+ end
83
+
84
+ describe "#captured?" do
85
+ it "is true when captured_at is set" do
86
+ transaction.stub(:captured_at) { Time.now }
87
+ transaction.captured?.should be_true
88
+ end
89
+
90
+ it "is false when captured_at isn't set" do
91
+ transaction.stub(:captured_at) { nil }
92
+ transaction.captured?.should be_false
93
+ end
94
+ end
95
+
96
+ describe "#failed?" do
97
+ it "is true when 'failed' is set" do
98
+ transaction.should_not be_failed
99
+ transaction.data.stub(:[]).with('failed') { true }
100
+ transaction.should be_failed
101
+ end
102
+ end
103
+
104
+ describe "#success?" do
105
+ it "is true unless failed" do
106
+ transaction.stub(:failed?) { false }
107
+ transaction.success?.should be_true
108
+
109
+ transaction.stub(:failed?) { true }
110
+ transaction.success?.should be_false
111
+ end
112
+ end
113
+
114
+ describe "#permanent_error?" do
115
+ it "is true unless error code is temporary" do
116
+ transaction.stub(:failed?) { true }
117
+ transaction.stub(:temporary_error?) { false }
118
+ transaction.permanent_error?.should be_true
119
+ end
120
+ end
121
+
122
+ describe "#temporary_error?" do
123
+ it "is true if error code is a temporary code" do
124
+ transaction.stub(:failed?) { true }
125
+ transaction.stub(:error) { '915' }
126
+ transaction.temporary_error?.should be_true
127
+ end
128
+ end
129
+
130
+ describe "#capture" do
131
+ it "calls capture action with transaction id and amount in minor" do
132
+ transaction.stub(:amount) { 10 }
133
+ Api.should_receive(:request).with(PAYMENT_SOAP_URL, 'capture', :transactionid => transaction.id, :amount => 1000).and_return(mock('response', :success? => false))
134
+ transaction.capture
135
+ end
136
+
137
+ context "when request is success" do
138
+ it "reloads and returns true" do
139
+ transaction
140
+ Api.stub(:request).with(PAYMENT_SOAP_URL, 'capture', anything).and_return(mock('response', :success? => true))
141
+ transaction.should_receive(:reload)
142
+ transaction.capture.should be_true
143
+ end
144
+ end
145
+
146
+ context "when request fails" do
147
+ it "returns false" do
148
+ transaction
149
+ Epay::Api.stub(:request) { mock('response', :success? => false) }
150
+ transaction.capture.should be_false
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "#credit" do
156
+ context "if amount to be credited is given" do
157
+ it "credits the amount" do
158
+ transaction_id = transaction.id
159
+ Api.should_receive(:request).with(PAYMENT_SOAP_URL, 'credit', :transactionid => transaction_id, :amount => 1000).and_return(mock('response', :success => true))
160
+ transaction.credit(10)
161
+ end
162
+ end
163
+
164
+ context "with no amount given" do
165
+ it "credits full authorization amount" do
166
+ transaction.stub(:credited_amount) { 10 }
167
+ transaction.stub(:amount) { 60 }
168
+ Api.should_receive(:request).with(PAYMENT_SOAP_URL, 'credit', :transactionid => transaction.id, :amount => 5000).and_return(mock('response', :success => true))
169
+ transaction.credit
170
+ end
171
+ end
172
+ end
173
+
174
+ describe ".create" do
175
+ context "with valid card data" do
176
+ it "returns transaction" do
177
+ VCR.use_cassette('transaction_creation') do
178
+ transaction = Transaction.create(
179
+ :card_no => '5555555555555000',
180
+ :exp_year => '15',
181
+ :exp_month => '10',
182
+ :cvc => '999',
183
+ :description => 'For the cool products',
184
+ :currency => :DKK,
185
+ :amount => 60,
186
+ :group => 'Test-transactions',
187
+ :cardholder => 'Jack Jensen',
188
+ :order_no => 'TEST-ORDER-12345'
189
+ )
190
+
191
+ transaction.should be_a Transaction
192
+ transaction.success?.should be_true
193
+ transaction.amount.should == 60
194
+ transaction.cardholder.should == 'Jack Jensen'
195
+ end
196
+ end
197
+ end
198
+
199
+ context "with invalid card data" do
200
+ it "returns failed transaction" do
201
+ VCR.use_cassette('transaction_invalid_creation') do
202
+ transaction = Transaction.create(
203
+ :card_no => '5555555555555118',
204
+ :exp_year => '15',
205
+ :exp_month => '10',
206
+ :cvc => '999',
207
+ :description => 'For the cool products',
208
+ :currency => :DKK,
209
+ :amount => 60,
210
+ :group => 'Test-transactions',
211
+ :cardholder => 'Jack Jensen',
212
+ :order_no => 'TEST-ORDER-12345'
213
+ )
214
+
215
+ transaction.should be_a Transaction
216
+ transaction.success?.should be_false
217
+ transaction.amount.should == 60
218
+ transaction.cardholder.should == 'Jack Jensen'
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ describe ".find" do
225
+ it "returns a transaction" do
226
+ VCR.use_cassette('existing_transaction') do
227
+ Transaction.find(EXISTING_TRANSACTION_ID).should be_a Transaction
228
+ end
229
+ end
230
+
231
+ it "reloads transaction data" do
232
+ Transaction.any_instance.should_receive(:reload)
233
+ Transaction.find(EXISTING_TRANSACTION_ID)
234
+ end
235
+
236
+ context "when transaction doesn't exist" do
237
+ it "raises exception" do
238
+ VCR.use_cassette('non_existing_transaction') do
239
+ lambda { Transaction.find(NON_EXISTING_TRANSACTION_ID) }.should raise_error(TransactionNotFound)
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
245
+ end