activemerchant 1.11.0 → 1.12.0
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.
- data.tar.gz.sig +3 -1
- data/CHANGELOG +17 -0
- data/CONTRIBUTORS +16 -0
- data/README.rdoc +5 -0
- data/lib/active_merchant.rb +0 -1
- data/lib/active_merchant/billing/gateway.rb +1 -1
- data/lib/active_merchant/billing/gateways/authorize_net.rb +5 -2
- data/lib/active_merchant/billing/gateways/federated_canada.rb +169 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +13 -1
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +4 -4
- data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +8 -8
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +3 -4
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +2 -2
- data/lib/active_merchant/billing/gateways/paypal_express.rb +37 -5
- data/lib/active_merchant/billing/gateways/qbms.rb +290 -0
- data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +25 -21
- data/lib/active_merchant/billing/integrations/moneybookers.rb +23 -0
- data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +33 -0
- data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +101 -0
- data/lib/active_merchant/billing/integrations/valitor/helper.rb +5 -1
- data/lib/active_merchant/billing/integrations/world_pay.rb +34 -0
- data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
- data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +13 -4
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
@@ -1 +1,3 @@
|
|
1
|
-
|
1
|
+
>:v��e̴�T�(&������@#R�ߗ8}����q7��9�2%�#* ����{8�"���
|
2
|
+
(����=y1++�c�rP������>�X��!cADd�1`F@v��w�!�m���pX�b�R�>F�X���jB���P
|
3
|
+
�1ϗ<U�CaT#_����艓�?oOY��a�X-/m��R1|��R���i��6�x�o�I\��@��2MD-�� ���٤c!��.��.��2��ӊYEU
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
|
+
== Version 1.12.0 (Mar 1, 2011)
|
4
|
+
|
5
|
+
* DirecPay: Send phone number as mobile phone by default [Soleone]
|
6
|
+
* Support sending line items for PayPal Express transactions [Jonathan Rudenberg]
|
7
|
+
* Update PayPal Express XML format to latest version [Jonathan Rudenberg]
|
8
|
+
* Fix custom image header for PayPal Express [mwagg]
|
9
|
+
* Add InvoiceID and OrderDescription to PayPal Express Authorize and Capture [cody]
|
10
|
+
* Add Moneybookers integration [Alex Diakov]
|
11
|
+
* Add QBMS (Quickbooks Merchant Services) gateway [ntalbott]
|
12
|
+
* Add NMI gateway [ntalbott]
|
13
|
+
* Make fully compatible with Rails 2 & 3, and Ruby 1.8 & 1.9 [ntalbott]
|
14
|
+
* Authorize.Net: Only return AVS message for AVS-related reason codes. [ntalbott]
|
15
|
+
* Add Federated Canada gateway [ntalbott]
|
16
|
+
* Garanti: Fix text normalization for nil values [Selem Delul]
|
17
|
+
* Valitor: Always send amount without any decimal places [Soleone]
|
18
|
+
* Add WorldPay integration [Soleone]
|
19
|
+
|
3
20
|
== Version 1.11.0 (Feb 11, 2011)
|
4
21
|
|
5
22
|
* Bump dependency for activesupport from 2.3.2 to 2.3.8 [Soleone]
|
data/CONTRIBUTORS
CHANGED
@@ -199,3 +199,19 @@ Barclays ePDQ
|
|
199
199
|
|
200
200
|
* Original code by Rob W (rfwatson)
|
201
201
|
* Refactored by Nathaniel Talbott
|
202
|
+
|
203
|
+
Federated Canada
|
204
|
+
|
205
|
+
* Bob Larrick (deathbob)
|
206
|
+
|
207
|
+
NMI
|
208
|
+
|
209
|
+
* Nathaniel Talbott (ntalbott)
|
210
|
+
|
211
|
+
QBMS
|
212
|
+
|
213
|
+
* Will Glozer (wg)
|
214
|
+
WorldPay (Feb 17, 2011)
|
215
|
+
|
216
|
+
* Original code by Unknown from this patch: https://jadedpixel.lighthouseapp.com/projects/11599/tickets/3-patch-integration-support-for-worldpay-uk
|
217
|
+
* Refactored by Soleone
|
data/README.rdoc
CHANGED
@@ -25,6 +25,7 @@ The {ActiveMerchant Wiki}[http://github.com/Shopify/active_merchant/wikis] conta
|
|
25
25
|
* {ePay}[http://www.epay.dk/] - DK
|
26
26
|
* {eWAY}[http://www.eway.com.au/] - AU
|
27
27
|
* {E-xact}[http://www.e-xact.com] - CA, US
|
28
|
+
* {Federated Canada}[http://www.federatedcanada.com/] - CA
|
28
29
|
* {FirstPay}[http://www.first-pay.com] - US
|
29
30
|
* {Garanti Sanal POS}[https://ccpos.garanti.com.tr/ccRaporlar/garanti/ccReports] - US, TR
|
30
31
|
* {Inspire}[http://www.inspiregateway.com] - US
|
@@ -40,6 +41,7 @@ The {ActiveMerchant Wiki}[http://github.com/Shopify/active_merchant/wikis] conta
|
|
40
41
|
* {NetRegistry}[http://www.netregistry.com.au] - AU
|
41
42
|
* {NELiX TransaX Gateway}[http://www.nelixtransax.com] - US
|
42
43
|
* {NETbilling}[http://www.netbilling.com] - US
|
44
|
+
* {NMI}[http://nmi.com/] - US
|
43
45
|
* {Ogone DirectLink}[http://www.ogone.com] - BE, DE, FR, NL, AT, CH
|
44
46
|
* {PayBox Direct}[http://www.paybox.com] - FR
|
45
47
|
* {PayJunction}[http://www.payjunction.com/] - US
|
@@ -56,6 +58,7 @@ The {ActiveMerchant Wiki}[http://github.com/Shopify/active_merchant/wikis] conta
|
|
56
58
|
* {Psigate}[http://www.psigate.com/] - CA
|
57
59
|
* {PSL Payment Solutions}[http://www.paymentsolutionsltd.com/] - GB
|
58
60
|
* {Quantum}[http://www.quantumgateway.com] - US
|
61
|
+
* {QuickBooks Merchant Services}[http://payments.intuit.com/] - US
|
59
62
|
* {Quickpay}[http://quickpay.dk/] - DK
|
60
63
|
* {Rabobank Nederland}[http://www.rabobank.nl/] - NL
|
61
64
|
* {Realex}[http://www.realexpayments.com/] - IE, GB
|
@@ -80,10 +83,12 @@ The {ActiveMerchant Wiki}[http://github.com/Shopify/active_merchant/wikis] conta
|
|
80
83
|
* {Chronopay}[http://www.chronopay.com]
|
81
84
|
* {DirecPay}[http://www.timesofmoney.com/direcpay/jsp/home.jsp]
|
82
85
|
* {HiTRUST}[http://www.hitrust.com.hk/]
|
86
|
+
* {Moneybookers}[http://www.moneybookers.com]
|
83
87
|
* {Nochex}[http://www.nochex.com]
|
84
88
|
* {PayPal Website Payments Standard}[https://www.paypal.com/cgi-bin/webscr?cmd=_wp-standard-overview-outside]
|
85
89
|
* {SagePay Form}[http://www.sagepay.com/products_services/sage_pay_go/integration/form]
|
86
90
|
* {Valitor}[http://www.valitor.is/] - IS
|
91
|
+
* {WorldPay}[http://www.worldpay.com]
|
87
92
|
|
88
93
|
== Download
|
89
94
|
|
data/lib/active_merchant.rb
CHANGED
@@ -32,7 +32,6 @@ require 'active_support/core_ext/class/attribute_accessors'
|
|
32
32
|
require 'active_support/core_ext/class/delegating_attributes'
|
33
33
|
require 'active_support/core_ext/module/attribute_accessors'
|
34
34
|
require 'active_support/core_ext/kernel/requires'
|
35
|
-
require 'active_support/core_ext/module/deprecation'
|
36
35
|
require 'active_support/base64'
|
37
36
|
require 'active_support/secure_random'
|
38
37
|
|
@@ -48,6 +48,7 @@ module ActiveMerchant #:nodoc:
|
|
48
48
|
|
49
49
|
CARD_CODE_ERRORS = %w( N S )
|
50
50
|
AVS_ERRORS = %w( A E N R W Z )
|
51
|
+
AVS_REASON_CODES = %w(27 45)
|
51
52
|
|
52
53
|
AUTHORIZE_NET_ARB_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'
|
53
54
|
|
@@ -370,10 +371,12 @@ module ActiveMerchant #:nodoc:
|
|
370
371
|
def message_from(results)
|
371
372
|
if results[:response_code] == DECLINED
|
372
373
|
return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
|
373
|
-
|
374
|
+
if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
|
375
|
+
return AVSResult.messages[ results[:avs_result_code] ]
|
376
|
+
end
|
374
377
|
end
|
375
378
|
|
376
|
-
|
379
|
+
(results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '')
|
377
380
|
end
|
378
381
|
|
379
382
|
def expdate(creditcard)
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class FederatedCanadaGateway < Gateway
|
4
|
+
# Same URL for both test and live, testing is done by using the test username (demo) and password (password).
|
5
|
+
URL = 'https://secure.federatedgateway.com/api/transact.php'
|
6
|
+
|
7
|
+
APPROVED, DECLINED, ERROR = 1, 2, 3
|
8
|
+
|
9
|
+
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
10
|
+
self.supported_countries = ['CA']
|
11
|
+
|
12
|
+
self.default_currency = 'CAD'
|
13
|
+
|
14
|
+
# The card types supported by the payment gateway
|
15
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
16
|
+
|
17
|
+
# The homepage URL of the gateway
|
18
|
+
self.homepage_url = 'http://www.federatedcanada.com/'
|
19
|
+
|
20
|
+
# The name of the gateway
|
21
|
+
self.display_name = 'Federated Canada'
|
22
|
+
|
23
|
+
def initialize(options = {})
|
24
|
+
requires!(options, :login, :password)
|
25
|
+
@options = options
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def purchase(money, creditcard, options = {})
|
30
|
+
post = {}
|
31
|
+
add_invoice(post, options)
|
32
|
+
add_creditcard(post, creditcard)
|
33
|
+
add_address(post, options)
|
34
|
+
add_customer_data(post, options)
|
35
|
+
commit('sale', money, post)
|
36
|
+
end
|
37
|
+
|
38
|
+
def authorize(money, creditcard, options = {})
|
39
|
+
post = {}
|
40
|
+
add_invoice(post, options)
|
41
|
+
add_creditcard(post, creditcard)
|
42
|
+
add_address(post, options)
|
43
|
+
add_customer_data(post, options)
|
44
|
+
commit('auth', money, post)
|
45
|
+
end
|
46
|
+
|
47
|
+
def capture(money, authorization, options = {})
|
48
|
+
options[:transactionid] = authorization
|
49
|
+
commit('capture', money, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
def credit(money, identification, options = {}) # also referred to as refund
|
53
|
+
post = { :transactionid => identification}
|
54
|
+
commit('refund', money, post)
|
55
|
+
end
|
56
|
+
|
57
|
+
def void(authorization, options = {})
|
58
|
+
options[:transactionid] = authorization
|
59
|
+
commit('void', nil, options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def refund(money, authorization, options = {})
|
63
|
+
options[:transactionid] = authorization
|
64
|
+
commit('refund', money, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def add_customer_data(post, options)
|
70
|
+
post[:firstname] = options[:first_name]
|
71
|
+
post[:lastname] = options[:last_name]
|
72
|
+
|
73
|
+
post[:email] = options[:email]
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_address(post, options)
|
77
|
+
if address = (options[:billing_address] || options[:address])
|
78
|
+
post[:company] = address[:company]
|
79
|
+
post[:address1] = address[:address1]
|
80
|
+
post[:address2] = address[:address2]
|
81
|
+
post[:city] = address[:city]
|
82
|
+
post[:state] = address[:state]
|
83
|
+
post[:zip] = address[:zip]
|
84
|
+
post[:country] = address[:country]
|
85
|
+
post[:phone] = address[:phone]
|
86
|
+
end
|
87
|
+
if address = options[:shipping_address]
|
88
|
+
post[:shipping_firstname] = address[:first_name]
|
89
|
+
post[:shipping_lastname] = address[:last_name]
|
90
|
+
post[:shipping_company] = address[:company]
|
91
|
+
post[:shipping_address1] = address[:address1]
|
92
|
+
post[:shipping_address2] = address[:address2]
|
93
|
+
post[:shipping_city] = address[:city]
|
94
|
+
post[:shipping_state] = address[:state]
|
95
|
+
post[:shipping_zip] = address[:zip]
|
96
|
+
post[:shipping_country] = address[:country]
|
97
|
+
post[:shipping_email] = address[:email]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_invoice(post, options)
|
102
|
+
post[:orderid] = options[:order_id]
|
103
|
+
post[:orderdescription] = options[:description]
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_creditcard(post, creditcard)
|
107
|
+
post[:ccnumber] = creditcard.number
|
108
|
+
post[:ccexp] = expdate(creditcard)
|
109
|
+
post[:cvv] = creditcard.verification_value
|
110
|
+
end
|
111
|
+
|
112
|
+
def expdate(creditcard)
|
113
|
+
year = sprintf("%.4i", creditcard.year)
|
114
|
+
month = sprintf("%.2i", creditcard.month)
|
115
|
+
"#{month}#{year[-2..-1]}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def parse(body)
|
119
|
+
body.split('&').inject({}) do |memo, x|
|
120
|
+
k, v = x.split('=')
|
121
|
+
memo[k] = v
|
122
|
+
memo
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def commit(action, money, parameters)
|
127
|
+
parameters[:amount] = amount(money)
|
128
|
+
data = ssl_post(URL, post_data(action, parameters))
|
129
|
+
response = parse(data)
|
130
|
+
message = message_from(response)
|
131
|
+
test_mode = test?
|
132
|
+
|
133
|
+
Response.new(success?(response), message, response,
|
134
|
+
:test => test?,
|
135
|
+
:authorization => response['transactionid'],
|
136
|
+
:avs_result => {:code => response['avsresponse']},
|
137
|
+
:cvv_result => response['cvvresponse']
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
def success?(response)
|
142
|
+
response['response'] == '1'
|
143
|
+
end
|
144
|
+
|
145
|
+
def test?
|
146
|
+
(@options[:login].eql?('demo')) && (@options[:password].eql?('password'))
|
147
|
+
end
|
148
|
+
|
149
|
+
def message_from(response)
|
150
|
+
case response['response'].to_i
|
151
|
+
when APPROVED
|
152
|
+
"Transaction Approved"
|
153
|
+
when DECLINED
|
154
|
+
"Transaction Declined"
|
155
|
+
else
|
156
|
+
"Error in transaction data or system error"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def post_data(action, parameters = {})
|
161
|
+
parameters[:type] = action
|
162
|
+
parameters[:username] = @options[:login]
|
163
|
+
parameters[:password] = @options[:password]
|
164
|
+
parameters.map{|k, v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&')
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
@@ -1,3 +1,7 @@
|
|
1
|
+
if RUBY_VERSION < '1.9' && $KCODE == "NONE"
|
2
|
+
$KCODE = 'u'
|
3
|
+
end
|
4
|
+
|
1
5
|
module ActiveMerchant #:nodoc:
|
2
6
|
module Billing #:nodoc:
|
3
7
|
class GarantiGateway < Gateway
|
@@ -193,7 +197,15 @@ module ActiveMerchant #:nodoc:
|
|
193
197
|
end
|
194
198
|
|
195
199
|
def normalize(text)
|
196
|
-
|
200
|
+
return unless text
|
201
|
+
|
202
|
+
if ActiveSupport::Inflector.method(:transliterate).arity == -2
|
203
|
+
ActiveSupport::Inflector.transliterate(text,'')
|
204
|
+
elsif RUBY_VERSION >= '1.9'
|
205
|
+
text.gsub(/[^\x00-\x7F]+/, '')
|
206
|
+
else
|
207
|
+
ActiveSupport::Inflector.transliterate(text).to_s
|
208
|
+
end
|
197
209
|
end
|
198
210
|
|
199
211
|
def add_transaction_data(xml, money, options)
|
@@ -56,20 +56,20 @@ module ActiveMerchant #:nodoc:
|
|
56
56
|
post[:card_id] = card_id
|
57
57
|
commit('X', nil, post)
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def credit(money, creditcard_or_card_id, options = {})
|
61
61
|
post ={}
|
62
62
|
add_payment_source(post, creditcard_or_card_id, options)
|
63
63
|
commit('C', money, post)
|
64
64
|
end
|
65
65
|
|
66
|
-
def void(transaction_id)
|
66
|
+
def void(transaction_id, options = {})
|
67
67
|
post = {}
|
68
68
|
post[:transaction_id] = transaction_id
|
69
69
|
commit('V', nil, post)
|
70
70
|
end
|
71
|
-
|
72
|
-
private
|
71
|
+
|
72
|
+
private
|
73
73
|
|
74
74
|
def add_address(post, options)
|
75
75
|
if address = options[:billing_address] || options[:address]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class NmiGateway < AuthorizeNetGateway
|
4
|
+
self.test_url = 'https://secure.networkmerchants.com/gateway/transact.dll'
|
5
|
+
self.live_url = 'https://secure.networkmerchants.com/gateway/transact.dll'
|
6
|
+
self.homepage_url = 'http://nmi.com/'
|
7
|
+
self.display_name = 'NMI'
|
8
|
+
self.supported_countries = ['US']
|
9
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -101,7 +101,7 @@ module ActiveMerchant #:nodoc:
|
|
101
101
|
|
102
102
|
class_inheritable_accessor :test_url, :live_url
|
103
103
|
|
104
|
-
self.test_url = "https://
|
104
|
+
self.test_url = "https://www.payjunctionlabs.com/quick_link"
|
105
105
|
self.live_url = "https://payjunction.com/quick_link"
|
106
106
|
|
107
107
|
TEST_LOGIN = 'pj-ql-01'
|
@@ -207,22 +207,22 @@ module ActiveMerchant #:nodoc:
|
|
207
207
|
:transaction_amount => amount(money),
|
208
208
|
:transaction_id => authorization
|
209
209
|
}
|
210
|
-
|
210
|
+
|
211
211
|
commit('CREDIT', parameters)
|
212
212
|
end
|
213
|
-
|
213
|
+
|
214
214
|
# Cancel a transaction that has been charged but has not yet made it
|
215
215
|
# through the batch process.
|
216
|
-
def void(
|
216
|
+
def void(authorization, options = {})
|
217
217
|
parameters = {
|
218
218
|
:transaction_id => authorization,
|
219
219
|
:posture => 'void'
|
220
220
|
}
|
221
|
-
|
222
|
-
add_optional_fields(parameters, options)
|
221
|
+
|
222
|
+
add_optional_fields(parameters, options)
|
223
223
|
commit('update', parameters)
|
224
224
|
end
|
225
|
-
|
225
|
+
|
226
226
|
# Set up a sale that will be made on a regular basis for the same amount
|
227
227
|
# (ex. $20 a month for 12 months)
|
228
228
|
#
|
@@ -389,4 +389,4 @@ module ActiveMerchant #:nodoc:
|
|
389
389
|
|
390
390
|
end
|
391
391
|
end
|
392
|
-
end
|
392
|
+
end
|
@@ -3,13 +3,12 @@ require 'iconv'
|
|
3
3
|
module ActiveMerchant #:nodoc:
|
4
4
|
module Billing #:nodoc:
|
5
5
|
class PayboxDirectGateway < Gateway
|
6
|
-
TEST_URL = 'https://ppps.paybox.com/PPPS.php'
|
7
|
-
TEST_URL_BACKUP = 'https://ppps1.paybox.com/PPPS.php'
|
6
|
+
TEST_URL = 'https://preprod-ppps.paybox.com/PPPS.php'
|
8
7
|
LIVE_URL = 'https://ppps.paybox.com/PPPS.php'
|
9
8
|
LIVE_URL_BACKUP = 'https://ppps1.paybox.com/PPPS.php'
|
10
9
|
|
11
10
|
# Payment API Version
|
12
|
-
API_VERSION = '
|
11
|
+
API_VERSION = '00103'
|
13
12
|
|
14
13
|
# Transactions hash
|
15
14
|
TRANSACTIONS = {
|
@@ -142,7 +141,7 @@ module ActiveMerchant #:nodoc:
|
|
142
141
|
parameters[:devise] = CURRENCY_CODES[options[:currency] || currency(money)]
|
143
142
|
request_data = post_data(action,parameters)
|
144
143
|
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request_data))
|
145
|
-
response = parse(ssl_post(
|
144
|
+
response = parse(ssl_post(LIVE_URL_BACKUP, request_data)) if service_unavailable?(response) && !test?
|
146
145
|
Response.new(success?(response), message_from(response), response.merge(
|
147
146
|
:timestamp => parameters[:dateq]),
|
148
147
|
:test => test?,
|
@@ -8,7 +8,7 @@ module ActiveMerchant #:nodoc:
|
|
8
8
|
base.cattr_accessor :signature
|
9
9
|
end
|
10
10
|
|
11
|
-
API_VERSION = '
|
11
|
+
API_VERSION = '62.0'
|
12
12
|
|
13
13
|
URLS = {
|
14
14
|
:test => { :certificate => 'https://api.sandbox.paypal.com/2.0/',
|
@@ -323,4 +323,4 @@ module ActiveMerchant #:nodoc:
|
|
323
323
|
end
|
324
324
|
end
|
325
325
|
end
|
326
|
-
end
|
326
|
+
end
|