braspag-pagador 0.9.4 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +164 -162
- data/braspag-pagador.gemspec +3 -3
- data/coverage/.resultset.json +69 -26
- data/coverage/index.html +1431 -1147
- data/lib/{braspag.rb → braspag-pagador.rb} +14 -14
- data/lib/{braspag → braspag-pagador}/core/connection.rb +5 -3
- data/lib/{braspag → braspag-pagador}/core/converter.rb +4 -4
- data/lib/{braspag → braspag-pagador}/core/customer.rb +2 -2
- data/lib/{braspag → braspag-pagador}/core/order.rb +51 -51
- data/lib/{braspag → braspag-pagador}/core/poster.rb +1 -1
- data/lib/{braspag → braspag-pagador}/crypto/no_crypto.rb +2 -2
- data/lib/{braspag → braspag-pagador}/crypto/webservice.rb +10 -10
- data/lib/{braspag → braspag-pagador}/payment/billet.rb +10 -10
- data/lib/{braspag → braspag-pagador}/payment/credit_card.rb +8 -8
- data/lib/{braspag → braspag-pagador}/payment/eft.rb +3 -3
- data/lib/{braspag → braspag-pagador}/payment/recurrency_credit_card.rb +1 -1
- data/lib/{braspag → braspag-pagador}/templates/crypto/decrypt.xml.erb +0 -0
- data/lib/{braspag → braspag-pagador}/templates/crypto/encrypt.xml.erb +0 -0
- data/lib/{braspag → braspag-pagador}/templates/justclick/archive.xml.erb +0 -0
- data/lib/{braspag → braspag-pagador}/templates/justclick/get_recurrency.xml.erb +0 -0
- data/lib/{braspag → braspag-pagador}/templates/justclick/recurrency.xml.erb +0 -0
- data/lib/braspag-pagador/version.rb +3 -0
- data/spec/core/connection_spec.rb +50 -50
- data/spec/core/converter_spec.rb +41 -41
- data/spec/core/customer_spec.rb +2 -2
- data/spec/core/order_spec.rb +78 -78
- data/spec/core/poster_spec.rb +8 -8
- data/spec/crypto/webservice_spec.rb +23 -23
- data/spec/integration/billet_spec.rb +11 -11
- data/spec/payment/billet_spec.rb +48 -48
- data/spec/payment/credit_card_spec.rb +82 -82
- data/spec/payment/eft_spec.rb +25 -25
- data/spec/payment/recurrency_credit_card_spec.rb +11 -11
- data/spec/spec_helper.rb +5 -5
- metadata +20 -20
- data/lib/braspag/version.rb +0 -3
data/spec/core/order_spec.rb
CHANGED
@@ -1,73 +1,73 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
3
3
|
|
4
|
-
describe
|
4
|
+
describe BraspagPagador::Connection do
|
5
5
|
let(:merchant_id) { "{12345678-1234-1234-1234-123456789000}" }
|
6
|
-
let(:connection) {
|
7
|
-
let(:order) {
|
8
|
-
|
6
|
+
let(:connection) { BraspagPagador::Connection.new(:merchant_id => merchant_id, :environment => :homologation)}
|
7
|
+
let(:order) { BraspagPagador::Order.new(:id => "XPTO") }
|
8
|
+
|
9
9
|
describe ".get" do
|
10
10
|
context "when error" do
|
11
11
|
it "should return message for response blank" do
|
12
12
|
connection.stub(:post).and_return({})
|
13
13
|
response = connection.get(order)
|
14
|
-
|
14
|
+
|
15
15
|
response.success?.should eq(false)
|
16
16
|
response.message.should eq('')
|
17
17
|
response.params.should eq({})
|
18
18
|
response.test.should eq(true)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
it "should return message for error code" do
|
22
22
|
order_response = {:error_code => 'bla', :error_message => 'xpto', :status => '223'}
|
23
23
|
connection.stub(:post).and_return(order_response)
|
24
24
|
response = connection.get(order)
|
25
|
-
|
25
|
+
|
26
26
|
response.success?.should eq(false)
|
27
27
|
response.message.should eq(order_response[:error_message])
|
28
28
|
response.params.should eq({"error_code"=>"bla", "error_message"=>"xpto", "status" => '223'})
|
29
29
|
response.test.should eq(true)
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
it "should return message for empty status" do
|
33
33
|
connection.stub(:post).and_return({:error_message => 'bla'})
|
34
34
|
response = connection.get(order)
|
35
|
-
|
35
|
+
|
36
36
|
response.success?.should eq(false)
|
37
37
|
response.message.should eq('bla')
|
38
38
|
response.params.should eq({"error_message"=>"bla"})
|
39
39
|
response.test.should eq(true)
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
it "should return response ok" do
|
44
44
|
connection.stub(:post).and_return({:status => '1'})
|
45
45
|
response = connection.get(order)
|
46
|
-
|
46
|
+
|
47
47
|
response.success?.should eq(true)
|
48
48
|
response.message.should eq('OK')
|
49
49
|
response.params.should eq({"status" => "1"})
|
50
50
|
response.test.should eq(true)
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
it "should get more info for billet" do
|
54
54
|
connection.should_receive(:post).and_return({:status => '1'})
|
55
55
|
connection.should_receive(:post).with(:info_billet, order)
|
56
56
|
order.payment_method = 6 #BILLET BRADESCO
|
57
57
|
response = connection.get(order)
|
58
|
-
|
58
|
+
|
59
59
|
response.success?.should eq(true)
|
60
60
|
response.message.should eq('OK')
|
61
61
|
response.params.should eq({"status" => "1"})
|
62
62
|
response.test.should eq(true)
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
it "should get more info for credit_card" do
|
66
66
|
connection.should_receive(:post).and_return({:status => '1'})
|
67
67
|
connection.should_receive(:post).with(:info_credit_card, order)
|
68
68
|
order.payment_method = 18 #AMEX
|
69
69
|
response = connection.get(order)
|
70
|
-
|
70
|
+
|
71
71
|
response.success?.should eq(true)
|
72
72
|
response.message.should eq('OK')
|
73
73
|
response.params.should eq({"status" => "1"})
|
@@ -76,9 +76,9 @@ describe Braspag::Connection do
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
-
describe
|
79
|
+
describe BraspagPagador::Order do
|
80
80
|
let(:merchant_id) { "{12345678-1234-1234-1234-123456789000}" }
|
81
|
-
let(:connection) {
|
81
|
+
let(:connection) { BraspagPagador::Connection.new(:merchant_id => merchant_id, :environment => :homologation)}
|
82
82
|
|
83
83
|
describe ".payment_method_type?" do
|
84
84
|
it "should return payment method type" do
|
@@ -109,7 +109,7 @@ describe Braspag::Order do
|
|
109
109
|
</DadosPedido>
|
110
110
|
EOXML
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
let(:invalid_xml) do
|
114
114
|
<<-EOXML
|
115
115
|
<?xml version="1.0" encoding="utf-8"?>
|
@@ -119,7 +119,7 @@ describe Braspag::Order do
|
|
119
119
|
xmlns="http://www.pagador.com.br/" />
|
120
120
|
EOXML
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
let(:error_xml) do
|
124
124
|
<<-EOXML
|
125
125
|
<?xml version="1.0" encoding="utf-8"?>
|
@@ -131,38 +131,38 @@ describe Braspag::Order do
|
|
131
131
|
</DadosPedido>
|
132
132
|
EOXML
|
133
133
|
end
|
134
|
-
|
135
|
-
let(:order) {
|
136
|
-
|
134
|
+
|
135
|
+
let(:order) { BraspagPagador::Order.new(:id => "XPTO") }
|
136
|
+
|
137
137
|
it "should convert objects to hash" do
|
138
|
-
|
139
|
-
"loja" => "#{merchant_id}",
|
138
|
+
BraspagPagador::Order.to_info(connection, order).should eq({
|
139
|
+
"loja" => "#{merchant_id}",
|
140
140
|
"numeroPedido" => "#{order.id}"
|
141
141
|
})
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
it "should populate data" do
|
145
|
-
resp =
|
146
|
-
|
145
|
+
resp = BraspagPagador::Order.from_info(connection, order, mock(:body => valid_xml))
|
146
|
+
|
147
147
|
order.authorization.should eq('885796')
|
148
148
|
order.payment_method_name.should eq('American Express 2P')
|
149
149
|
order.payment_method.should eq('18')
|
150
150
|
order.installments.should eq('1')
|
151
151
|
order.status.should eq('3')
|
152
152
|
order.amount.should eq(0.01)
|
153
|
-
order.gateway_cancelled_at.should eq(Time.parse('2011-08-07 13:19:38
|
154
|
-
order.gateway_paid_at.should eq(Time.parse('2011-08-07 13:19:38
|
155
|
-
order.gateway_created_at.should eq(Time.parse('2011-08-07 13:06:06
|
153
|
+
order.gateway_cancelled_at.should eq(Time.parse('2011-08-07 13:19:38'))
|
154
|
+
order.gateway_paid_at.should eq(Time.parse('2011-08-07 13:19:38'))
|
155
|
+
order.gateway_created_at.should eq(Time.parse('2011-08-07 13:06:06'))
|
156
156
|
order.transaction_id.should eq('398591')
|
157
157
|
order.gateway_id.should eq('5a1d4463-1d11-4571-a877-763aba0ef7ff')
|
158
|
-
|
158
|
+
|
159
159
|
resp.should eq({
|
160
160
|
:authorization => "885796",
|
161
161
|
:error_code => nil,
|
162
162
|
:error_message => nil,
|
163
163
|
:payment_method => "18",
|
164
164
|
:payment_method_name => "American Express 2P",
|
165
|
-
:installments => "1",
|
165
|
+
:installments => "1",
|
166
166
|
:status => "3",
|
167
167
|
:amount => "0.01",
|
168
168
|
:cancelled_at => Time.parse('2011-08-07 13:19:38 -0300'),
|
@@ -172,10 +172,10 @@ describe Braspag::Order do
|
|
172
172
|
:tid => "5a1d4463-1d11-4571-a877-763aba0ef7ff"
|
173
173
|
})
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
it "should populate data accepts invalid xml" do
|
177
|
-
resp =
|
178
|
-
|
177
|
+
resp = BraspagPagador::Order.from_info(connection, order, mock(:body => invalid_xml))
|
178
|
+
|
179
179
|
resp.should eq({
|
180
180
|
:authorization => nil,
|
181
181
|
:error_code => nil,
|
@@ -192,10 +192,10 @@ describe Braspag::Order do
|
|
192
192
|
:tid => nil
|
193
193
|
})
|
194
194
|
end
|
195
|
-
|
195
|
+
|
196
196
|
it "should populate data for error" do
|
197
|
-
resp =
|
198
|
-
|
197
|
+
resp = BraspagPagador::Order.from_info(connection, order, mock(:body => error_xml))
|
198
|
+
|
199
199
|
resp.should eq({
|
200
200
|
:authorization => nil,
|
201
201
|
:error_code => "885796",
|
@@ -213,7 +213,7 @@ describe Braspag::Order do
|
|
213
213
|
})
|
214
214
|
end
|
215
215
|
end
|
216
|
-
|
216
|
+
|
217
217
|
context "on info for billet" do
|
218
218
|
let(:valid_xml) do
|
219
219
|
<<-EOXML
|
@@ -238,7 +238,7 @@ describe Braspag::Order do
|
|
238
238
|
</DadosBoleto>
|
239
239
|
EOXML
|
240
240
|
end
|
241
|
-
|
241
|
+
|
242
242
|
let(:invalid_xml) do
|
243
243
|
<<-EOXML
|
244
244
|
<?xml version="1.0" encoding="utf-8"?>
|
@@ -248,29 +248,29 @@ describe Braspag::Order do
|
|
248
248
|
</DadosBoleto>
|
249
249
|
EOXML
|
250
250
|
end
|
251
|
-
|
252
|
-
let(:order) {
|
253
|
-
|
251
|
+
|
252
|
+
let(:order) { BraspagPagador::Order.new(:id => "XPTO") }
|
253
|
+
|
254
254
|
it "should convert objects to hash" do
|
255
|
-
|
256
|
-
"loja" => "#{merchant_id}",
|
255
|
+
BraspagPagador::Order.to_info_billet(connection, order).should eq({
|
256
|
+
"loja" => "#{merchant_id}",
|
257
257
|
"numeroPedido" => "#{order.id}"
|
258
258
|
})
|
259
259
|
end
|
260
|
-
|
260
|
+
|
261
261
|
it "should populate data" do
|
262
|
-
resp =
|
262
|
+
resp = BraspagPagador::Order.from_info_billet(connection, order, mock(:body => valid_xml))
|
263
263
|
|
264
264
|
order.customer.name.should eq('XPTO')
|
265
265
|
|
266
266
|
order.billet.id.should eq('999')
|
267
267
|
order.billet.code.should eq('35690.00361 03962.070003 00000.009993 4 50160000001000')
|
268
|
-
|
268
|
+
|
269
269
|
order.billet.created_at.should eq(Date.parse('2011-06-22'))
|
270
270
|
order.billet.due_date_on.should eq(Date.parse('2011-07-2'))
|
271
|
-
|
271
|
+
|
272
272
|
order.billet.receiver.should eq('Acessoria Empresarial Ltda')
|
273
|
-
|
273
|
+
|
274
274
|
order.billet.bank.should eq('356-5')
|
275
275
|
order.billet.agency.should eq('0003')
|
276
276
|
order.billet.account.should eq('6039620')
|
@@ -296,9 +296,9 @@ describe Braspag::Order do
|
|
296
296
|
:invoice_date=> Date.parse('2011-07-02')
|
297
297
|
})
|
298
298
|
end
|
299
|
-
|
299
|
+
|
300
300
|
it "should not raise error for invalid xml" do
|
301
|
-
resp =
|
301
|
+
resp = BraspagPagador::Order.from_info_billet(connection, order, mock(:body => invalid_xml))
|
302
302
|
|
303
303
|
resp.should eq({
|
304
304
|
:document_number => nil,
|
@@ -336,18 +336,18 @@ describe Braspag::Order do
|
|
336
336
|
</DadosCartao>
|
337
337
|
EOXML
|
338
338
|
end
|
339
|
-
|
340
|
-
let(:order) {
|
341
|
-
|
339
|
+
|
340
|
+
let(:order) { BraspagPagador::Order.new(:id => "XPTO") }
|
341
|
+
|
342
342
|
it "should convert objects to hash" do
|
343
|
-
|
344
|
-
"loja" => "#{merchant_id}",
|
343
|
+
BraspagPagador::Order.to_info_credit_card(connection, order).should eq({
|
344
|
+
"loja" => "#{merchant_id}",
|
345
345
|
"numeroPedido" => "#{order.id}"
|
346
346
|
})
|
347
347
|
end
|
348
|
-
|
348
|
+
|
349
349
|
it "should populate data" do
|
350
|
-
resp =
|
350
|
+
resp = BraspagPagador::Order.from_info_credit_card(connection, order, mock(:body => valid_xml))
|
351
351
|
|
352
352
|
order.credit_card.checking_number.should eq('11111')
|
353
353
|
order.credit_card.avs.should eq('false')
|
@@ -370,7 +370,7 @@ describe Braspag::Order do
|
|
370
370
|
})
|
371
371
|
end
|
372
372
|
end
|
373
|
-
|
373
|
+
|
374
374
|
[:purchase, :generate, :authorize, :capture, :void, :recurrency].each do |context_type|
|
375
375
|
context "on #{context_type}" do
|
376
376
|
it "should validate minimum 1 length of id" do
|
@@ -390,24 +390,24 @@ describe Braspag::Order do
|
|
390
390
|
subject.valid?(context_type)
|
391
391
|
subject.errors.messages[:id].should eq(nil)
|
392
392
|
end
|
393
|
-
|
393
|
+
|
394
394
|
[:cielo_noauth_visa, :cielo_preauth_visa, :cielo_noauth_mastercard, :cielo_preauth_mastercard, :cielo_noauth_elo, :cielo_noauth_diners ].each do |payment_method|
|
395
395
|
context "when has payment method for #{payment_method}" do
|
396
396
|
it "should not allow spaces" do
|
397
|
-
subject.payment_method =
|
397
|
+
subject.payment_method = BraspagPagador::PAYMENT_METHOD[payment_method]
|
398
398
|
subject.id = '123 4'
|
399
399
|
subject.valid?(context_type)
|
400
400
|
subject.errors.messages[:id].should include("is invalid")
|
401
401
|
end
|
402
402
|
it "should not allow characters" do
|
403
|
-
subject.payment_method =
|
403
|
+
subject.payment_method = BraspagPagador::PAYMENT_METHOD[payment_method]
|
404
404
|
subject.id = 'abcd'
|
405
405
|
subject.valid?(context_type)
|
406
406
|
subject.errors.messages[:id].should include("is invalid")
|
407
407
|
end
|
408
408
|
|
409
409
|
it "should not allow special characters" do
|
410
|
-
subject.payment_method =
|
410
|
+
subject.payment_method = BraspagPagador::PAYMENT_METHOD[payment_method]
|
411
411
|
subject.id = '*-[]'
|
412
412
|
subject.valid?(context_type)
|
413
413
|
subject.errors.messages[:id].should include("is invalid")
|
@@ -416,7 +416,7 @@ describe Braspag::Order do
|
|
416
416
|
end
|
417
417
|
end
|
418
418
|
end
|
419
|
-
|
419
|
+
|
420
420
|
[:purchase, :generate, :authorize, :recurrency].each do |context_type|
|
421
421
|
context "on #{context_type}" do
|
422
422
|
it "should not allow blank for payment_method" do
|
@@ -424,19 +424,19 @@ describe Braspag::Order do
|
|
424
424
|
subject.valid?(context_type)
|
425
425
|
subject.errors.messages[:payment_method].should include("can't be blank")
|
426
426
|
end
|
427
|
-
|
427
|
+
|
428
428
|
it "should not allow blank for amount" do
|
429
429
|
subject.amount = ''
|
430
430
|
subject.valid?(context_type)
|
431
431
|
subject.errors.messages[:amount].should include("can't be blank")
|
432
432
|
end
|
433
|
-
|
433
|
+
|
434
434
|
it "should validate minimum 1 of amount" do
|
435
435
|
subject.amount = 0
|
436
436
|
subject.valid?(context_type)
|
437
437
|
subject.errors.messages[:amount].should include("must be greater than 0")
|
438
438
|
end
|
439
|
-
|
439
|
+
|
440
440
|
it "should not allow blank for customer" do
|
441
441
|
subject.customer = ''
|
442
442
|
subject.valid?(context_type)
|
@@ -444,11 +444,11 @@ describe Braspag::Order do
|
|
444
444
|
end
|
445
445
|
|
446
446
|
it "should not allow invalid customer" do
|
447
|
-
subject.customer =
|
447
|
+
subject.customer = BraspagPagador::Customer.new
|
448
448
|
subject.valid?(context_type)
|
449
449
|
subject.errors.messages[:customer].should include("invalid data")
|
450
450
|
end
|
451
|
-
|
451
|
+
|
452
452
|
it "should accept only valid payment method" do
|
453
453
|
subject.payment_method = 0
|
454
454
|
subject.valid?(context_type)
|
@@ -464,36 +464,36 @@ describe Braspag::Order do
|
|
464
464
|
subject.valid?(context_type)
|
465
465
|
subject.errors.messages[:installments].should include("can't be blank")
|
466
466
|
end
|
467
|
-
|
467
|
+
|
468
468
|
it "should validate minimum 1 of installments" do
|
469
469
|
subject.installments = 0
|
470
470
|
subject.valid?(context_type)
|
471
471
|
subject.errors.messages[:installments].should include("must be greater than 0")
|
472
472
|
end
|
473
|
-
|
474
|
-
|
473
|
+
|
474
|
+
|
475
475
|
it "should validate maxium 99 of installments" do
|
476
476
|
subject.installments = 100
|
477
477
|
subject.valid?(context_type)
|
478
478
|
subject.errors.messages[:installments].should include("must be less than 100")
|
479
479
|
end
|
480
|
-
|
480
|
+
|
481
481
|
it "should not allow blank for installments_type" do
|
482
482
|
subject.installments_type = ''
|
483
483
|
subject.valid?(context_type)
|
484
484
|
subject.errors.messages[:installments_type].should include("can't be blank")
|
485
485
|
end
|
486
|
-
|
486
|
+
|
487
487
|
it "should accept only valid installments_type" do
|
488
488
|
subject.installments_type = 100
|
489
489
|
subject.valid?(context_type)
|
490
490
|
subject.errors.messages[:installments_type].should include("invalid installments type")
|
491
491
|
end
|
492
|
-
|
493
|
-
|
492
|
+
|
493
|
+
|
494
494
|
context "when installments_type is NO_INTEREST" do
|
495
495
|
it "should installments is one" do
|
496
|
-
subject.installments_type =
|
496
|
+
subject.installments_type = BraspagPagador::INTEREST[:no]
|
497
497
|
subject.installments = 3
|
498
498
|
subject.valid?(context_type)
|
499
499
|
subject.errors.messages[:installments].should include("is invalid")
|
data/spec/core/poster_spec.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'ostruct'
|
3
3
|
|
4
|
-
describe
|
4
|
+
describe BraspagPagador::Poster do
|
5
5
|
let(:request) { OpenStruct.new(:url => 'http://foo/bar') }
|
6
6
|
let(:response) { mock(:body => 'success') }
|
7
7
|
let(:logger) { mock(:info => nil) }
|
8
8
|
let(:merchant_id) { "{12345678-1234-1234-1234-123456789000}" }
|
9
|
-
let(:connection) {
|
10
|
-
let(:connection_logger) {
|
11
|
-
let(:connection_proxy) {
|
9
|
+
let(:connection) { BraspagPagador::Connection.new(:merchant_id => merchant_id, :environment => :homologation)}
|
10
|
+
let(:connection_logger) { BraspagPagador::Connection.new(:merchant_id => merchant_id, :environment => :homologation, :logger => logger)}
|
11
|
+
let(:connection_proxy) { BraspagPagador::Connection.new(:merchant_id => merchant_id, :environment => :homologation, :proxy_address => 'http://proxy.com')}
|
12
12
|
|
13
13
|
describe "#do_post" do
|
14
14
|
before do
|
@@ -23,18 +23,18 @@ describe Braspag::Poster do
|
|
23
23
|
request.should_not_receive(:proxy=)
|
24
24
|
subject.do_post(:foo, {})
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
it "should not raise an error if logger is not defined" do
|
28
28
|
expect {
|
29
29
|
subject.do_post(:doe, { :foo => :bar, :egg => :span })
|
30
30
|
}.to_not raise_error
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
end
|
34
34
|
|
35
35
|
context "with logger" do
|
36
36
|
subject { described_class.new(connection_logger, 'http://foo/bar') }
|
37
|
-
|
37
|
+
|
38
38
|
it "should log the request info" do
|
39
39
|
logger.should_receive(:info).with('[Braspag] #doe: http://foo/bar, data: {:foo=>:bar, :egg=>:span}')
|
40
40
|
subject.do_post(:doe, { :foo => :bar, :egg => :span })
|
@@ -53,7 +53,7 @@ describe Braspag::Poster do
|
|
53
53
|
|
54
54
|
context "with proxy" do
|
55
55
|
subject { described_class.new(connection_proxy, 'http://foo/bar') }
|
56
|
-
|
56
|
+
|
57
57
|
it "should set the proxy if the proxy_address is set" do
|
58
58
|
request.should_receive(:proxy=).with('http://proxy.com')
|
59
59
|
subject.do_post(:foo, {})
|