payzilla 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +23 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +23 -0
  5. data/README.md +82 -0
  6. data/Rakefile +4 -0
  7. data/init.rb +1 -0
  8. data/lib/encoding/converter.rb +5 -0
  9. data/lib/payzilla/config.rb +224 -0
  10. data/lib/payzilla/gateways/akado.rb +59 -0
  11. data/lib/payzilla/gateways/beeline.rb +205 -0
  12. data/lib/payzilla/gateways/cyberplat.rb +97 -0
  13. data/lib/payzilla/gateways/dummy.rb +72 -0
  14. data/lib/payzilla/gateways/gorod.rb +80 -0
  15. data/lib/payzilla/gateways/mailru.rb +56 -0
  16. data/lib/payzilla/gateways/matrix.rb +66 -0
  17. data/lib/payzilla/gateways/megafon.rb +120 -0
  18. data/lib/payzilla/gateways/mts.rb +200 -0
  19. data/lib/payzilla/gateways/osmp.rb +85 -0
  20. data/lib/payzilla/gateways/rapida.rb +127 -0
  21. data/lib/payzilla/gateways/skylink.rb +105 -0
  22. data/lib/payzilla/gateways/webmoney.rb +102 -0
  23. data/lib/payzilla/gateways/yamoney.rb +93 -0
  24. data/lib/payzilla/gateways/yota.rb +63 -0
  25. data/lib/payzilla/gateways.rb +173 -0
  26. data/lib/payzilla/payment.rb +161 -0
  27. data/lib/payzilla/revision.rb +18 -0
  28. data/lib/payzilla/transports/http.rb +62 -0
  29. data/lib/payzilla/utils/string_file.rb +14 -0
  30. data/lib/payzilla/version.rb +3 -0
  31. data/lib/payzilla.rb +19 -0
  32. data/lib/string.rb +12 -0
  33. data/payzilla.gemspec +33 -0
  34. data/schemas/.gitkeep +0 -0
  35. data/schemas/beeline.wsdl +538 -0
  36. data/spec/lib/payzilla/gateways/akado_spec.rb +31 -0
  37. data/spec/lib/payzilla/gateways/beeline_spec.rb +52 -0
  38. data/spec/lib/payzilla/gateways/cyberplat_spec.rb +44 -0
  39. data/spec/lib/payzilla/gateways/gorod_spec.rb +36 -0
  40. data/spec/lib/payzilla/gateways/mailru_spec.rb +24 -0
  41. data/spec/lib/payzilla/gateways/matrix_spec.rb +35 -0
  42. data/spec/lib/payzilla/gateways/megafon_spec.rb +45 -0
  43. data/spec/lib/payzilla/gateways/mts_spec.rb +55 -0
  44. data/spec/lib/payzilla/gateways/osmp_spec.rb +30 -0
  45. data/spec/lib/payzilla/gateways/rapida_spec.rb +48 -0
  46. data/spec/lib/payzilla/gateways/skylink_spec.rb +39 -0
  47. data/spec/lib/payzilla/gateways/webmoney_spec.rb +38 -0
  48. data/spec/lib/payzilla/gateways/yamoney_spec.rb +31 -0
  49. data/spec/lib/payzilla/gateways/yota_spec.rb +30 -0
  50. data/spec/spec_helper.rb +9 -0
  51. data/spec/support/config_stub.rb +7 -0
  52. metadata +236 -0
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rbx
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ .DS_Store
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ certificates/*.*
21
+ log/*.*
22
+ *.swp
23
+ *~
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --tty
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in payzilla.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2012 Round Lake, inc.,
4
+ Boris Staal <boris@roundlake.ru>,
5
+ Vasilij Melnychuck <v.melnychuck@roundlake.ru>.
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Payzilla
2
+
3
+ This gem is a set of gateways, that allows you easily send payments to carriers.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'payzilla'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install payzilla
18
+
19
+ ## Usage
20
+
21
+ To use Payzilla, you should have config, payment and gateway instances. Config can be defined with YAML, or just by passing arguments to the contructor. Payment, which you need to send, can be defined only by passing arguments to the constructor. Sending payment should comprise two steps: check and pay, and the second one should be sent only after successfull check.
22
+
23
+ ```ruby
24
+ # Create config instance
25
+ config = Payzilla::Config.new("dummy", File.new("config.yaml"))
26
+
27
+ # Load attachments
28
+ config.attachment_cert = File.new("certificates/dummy.cer")
29
+ config.attachment_key = File.new("certificates/dummy.key")
30
+
31
+ # Define payment, that you need to send
32
+ payment = Payzilla::Payment.new(
33
+ :id => 1,
34
+ :accound => 111111111,
35
+ :enrolled_amound => 100
36
+ )
37
+
38
+ # Check'n'Pay
39
+ transport = Payzilla::Gateways::Dummy.new(config, './log/dummy.log')
40
+ if transport.check(payment)[:success]
41
+ transport.pay(payment)
42
+ end
43
+ ```
44
+
45
+ ```yaml
46
+ # config.yaml
47
+ dummy:
48
+ setting_url: "https://dummy.com/gateway"
49
+ setting_client: "JDoe"
50
+ setting_contract: "123456789"
51
+ setting_password: "1234"
52
+ ```
53
+
54
+ ## Gateways status
55
+ * Akado _working_
56
+ * Beeline _testing_
57
+ * Cyberplat _testing_
58
+ * Mailru _testing_
59
+ * Matrix _testing_
60
+ * Megafon _working_
61
+ * MTS _testing_
62
+ * Rapida _MRI only_
63
+ * Skylink _testing_
64
+ * Webmoney _not working_
65
+ * Yamoney _testing_
66
+ * Yota _not working_
67
+
68
+ ## Credits
69
+
70
+ <img src="http://roundlake.ru/assets/logo.png" align="right" />
71
+
72
+ * Boris Staal ([@_inossidabile](http://twitter.com/#!/_inossidabile))
73
+ * Vasilij Melnychuk ([@sqrel](http://twitter.com/#!/sqrel))
74
+
75
+ ## Contributors
76
+
77
+ * Byteg ([@bypeg](https://github.com/byteg))
78
+ * Alexander Pavlenko ([@AlexanderPavlenko](https://github.com/AlexanderPavlenko))
79
+
80
+ ## LICENSE
81
+
82
+ It is free software, and may be redistributed under the terms of MIT license.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'payzilla'
@@ -0,0 +1,5 @@
1
+ Encoding::Converter.instance_eval do
2
+ def search_convpath(from, to, options={})
3
+ new(from, to, options).convpath
4
+ end
5
+ end
@@ -0,0 +1,224 @@
1
+ require 'yaml'
2
+
3
+ module Payzilla
4
+ class Config
5
+
6
+ # @!attribute setting_bank
7
+ # Bank identifier
8
+ # Used by:
9
+ # * Akado
10
+ #
11
+ # @!attribute setting_key_password
12
+ # Password, that is needed for decrypt encrypted key
13
+ # Used by:
14
+ # * Akado
15
+ # * Cyberplat
16
+ # * Matrix
17
+ # * MTS
18
+ # * Rapida
19
+ # * Webmoney
20
+ #
21
+ # @!attribute setting_partner_id
22
+ # Partner identifier
23
+ # Used by:
24
+ # * Beeline
25
+ #
26
+ # @!attribute setting_payment_point_id
27
+ # Accepting payments point identifier
28
+ # Used by:
29
+ # * Beeline
30
+ #
31
+ # @!attribute setting_url
32
+ # Carrier server URL where data will be sent
33
+ # Used by:
34
+ # * Beeline
35
+ # * Matrix
36
+ # * MTS
37
+ # * Rapida
38
+ # * Skylink
39
+ # * Webmoney
40
+ # * Yota
41
+ #
42
+ # @!attribute host
43
+ # Carrier server URL where data will be sent
44
+ # Used by:
45
+ # * Cyberplat
46
+ #
47
+ # @!attribute setting_operator
48
+ # Acceptance point operator identifier
49
+ # Used by:
50
+ # * Ceberplat
51
+ #
52
+ # @!attribute setting_point
53
+ # Acceptance point identifier
54
+ # Used by:
55
+ # * Cyberplat
56
+ # @!attribute setting_dealer
57
+ # Dealer identifier
58
+ # Used by:
59
+ # * Cyberplat
60
+ #
61
+ # @!attribute setting_key
62
+ # Key
63
+ # Used by:
64
+ # * Mailru
65
+ #
66
+ # @!attribute setting_dealer_id
67
+ # Dealer identifier
68
+ # Used by:
69
+ # * Matrix
70
+ #
71
+ # @!attribute setting_domain
72
+ # Carrier server URL where data will be sent
73
+ # Used by:
74
+ # * Megafon
75
+ # * OSMP
76
+ #
77
+ # @!attribute setting_client
78
+ # Client identifier. To get this, speak with carrier support.
79
+ # Used by:
80
+ # * Megafon
81
+ # * OSMP
82
+ # * Skylink
83
+ #
84
+ # @!attribute setting_password
85
+ # Password, that will be sent with payment
86
+ # Used by:
87
+ # * Megafon
88
+ # * OSMP
89
+ # * Yamoney
90
+ #
91
+ # @!attribute setting_agent
92
+ # Agent identifier
93
+ # _Get this info from carrier_
94
+ # Used by:
95
+ # * MTS
96
+ #
97
+ # @!attribute setting_contract
98
+ # Contract identifier
99
+ # _Get this info from carrier_
100
+ # Used by:
101
+ # * MTS
102
+ #
103
+ # @!attribute setting_signature_key_password
104
+ # Password, that is neede to decrypt encrypted signature key
105
+ # _Get this info from carrier_
106
+ # Used by:
107
+ # * MTS
108
+ # * Yota
109
+ #
110
+ # @!attribute setting_terminal_prefix
111
+ # Some prefix, that would be added to your current kiosk name
112
+ # Used by:
113
+ # * MTS
114
+ #
115
+ # @!attribute setting_terminal
116
+ # Terminal identifier
117
+ # Used by:
118
+ # * OSMP
119
+ #
120
+ # @!attribute setting_wmid
121
+ # WebMoney identifier
122
+ # Used by:
123
+ # * Webmoney
124
+ #
125
+ # @!attribute setting_kiosk_id
126
+ # Kiosk identifier
127
+ # Used by:
128
+ # * Webmoney
129
+ #
130
+ # @!attribute setting_currency
131
+ # Carrier's currency code
132
+ # Used by:
133
+ # * Yamoney
134
+ #
135
+ # @!attribute setting_gpg_key
136
+ # GPG key
137
+ # Used by:
138
+ # * Yamoney
139
+ attr_accessor :setting_url, :setting_bank, :setting_key_password,
140
+ :setting_partner_id, :setting_payment_poind_id,
141
+ :setting_host, :setting_operator, :setting_poing,
142
+ :setting_dealer, :setting_key, :setting_dealer_id,
143
+ :setting_domain, :setting_client, :setting_password,
144
+ :setting_agent, :setting_contract, :setting_signature_key_password,
145
+ :setting_terminal_prefix, :setting_terminal, :setting_wmid,
146
+ :setting_kiosk_id, :setting_currency, :setting_gpg_key
147
+
148
+ # @!attribute attachment_cert
149
+ # File, that contains X509 certificate
150
+ # Used by:
151
+ # * Akado
152
+ # * Beeline
153
+ # * Matrix
154
+ # * Megafon
155
+ # * Rapida
156
+ # * Webmoney
157
+ # * Yota
158
+ #
159
+ # @!attribute attachment_wsdl
160
+ # WSDL file
161
+ # Used by:
162
+ # * Beeline
163
+ #
164
+ # @!attribute attachment_private_key
165
+ # Private key file
166
+ # Used by:
167
+ # * Cyberplat
168
+ # * Rapida
169
+ #
170
+ # @!attribute attachment_public_key
171
+ # Public key file
172
+ # Used by:
173
+ # * Cyberplat
174
+ # * Yamoney
175
+ #
176
+ # @!attribute attachment_key
177
+ # File with keypair
178
+ # Used by:
179
+ # * Matrix
180
+ # * Megafon
181
+ # * Webmoney
182
+ # * Yota
183
+ #
184
+ # @!attribute attachment_ca
185
+ # Certificate autority file
186
+ # * Matrix
187
+ # * Yota
188
+ #
189
+ # @!attribute attachment_signature_key
190
+ # File with keypair, that is needed to generate signature
191
+ # Used by:
192
+ # * MTS
193
+ #
194
+ # @!attribute attachment_secret_key
195
+ # Secret key file
196
+ # Used by:
197
+ # * Yamoney
198
+ attr_accessor :attachment_cert, :attachment_key, :attachment_ca,
199
+ :attachment_wsdl, :attachment_private_key,
200
+ :attachment_public_key, :attachment_signature_key,
201
+ :attachment_secret_key
202
+
203
+ # @!attribute switch_test_mode
204
+ # Switch to the testing mode
205
+ # Used by:
206
+ # * Webmoney
207
+ attr_accessor :switch_test_mode
208
+
209
+ def initialize(carrier, config={})
210
+ config = if config.kind_of?(Hash)
211
+ {carrier => config}
212
+ else
213
+ ::YAML.load_file(config)
214
+ end
215
+
216
+ begin
217
+ config[carrier].each{|k,v| send "#{k}=", v}
218
+ rescue NoMethodError => e
219
+ puts "No such carrier in yaml config file"
220
+ puts e
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,59 @@
1
+ # coding: utf-8
2
+
3
+ require 'cgi'
4
+
5
+ module Payzilla
6
+ module Gateways
7
+ class Akado < Gateway
8
+ include Payzilla::Transports::HTTP
9
+ register_settings %w(key_password bank)
10
+ register_attachments %w(cert key ca)
11
+
12
+ def check(payment)
13
+ begin
14
+ result = request 'check_pay',
15
+ :numabo => payment.account
16
+
17
+ return retval(result)
18
+ rescue Errno::ECONNRESET
19
+ return retval(-1000)
20
+ end
21
+ end
22
+
23
+ def pay(payment)
24
+ begin
25
+ result = request 'pay',
26
+ :date => payment.created_at,
27
+ :id => payment.id,
28
+ :numabo => payment.account,
29
+ :summ => "%.2f" % payment.enrolled_amount
30
+
31
+ return retval(result)
32
+ rescue Errno::ECONNRESET
33
+ return retval(-1000)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def retval(code)
40
+ {:success => (code == "0"), :error => code}
41
+ end
42
+
43
+ def request(operation, params)
44
+ params[:type] = operation
45
+
46
+ request = send :get, "https://payment.comcor-tv.ru/#{@config.setting_bank}/payorder.php", params,
47
+ ssl(
48
+ @config.attachment_cert,
49
+ @config.attachment_key,
50
+ @config.setting_key_password,
51
+ @config.attachment_ca
52
+ )
53
+
54
+ return CGI.parse(request)["code"].first
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,205 @@
1
+ require 'savon'
2
+ require 'json'
3
+ require 'gyoku'
4
+
5
+ module Payzilla
6
+ module Gateways
7
+ class Beeline < Gateway
8
+ requires_revision
9
+ register_settings %w(url partner_id payment_point_id)
10
+ register_attachments %w(wsdl cert ca)
11
+
12
+ def check(payment)
13
+ begin
14
+ result = request :create_payment,
15
+ {
16
+ :partnerId => @config.setting_partner_id,
17
+ :paymentPointId => @config.setting_payment_point_id,
18
+ :money => "",
19
+ :phone => payment.account,
20
+ :amountAll => "",
21
+ :attributes! => {
22
+ :money => {
23
+ :amount => payment.enrolled_amount,
24
+ :code => 'RUR'
25
+ },
26
+ :amountAll => {
27
+ :amount => payment.paid_amount,
28
+ :code => 'RUR'
29
+ }
30
+ }
31
+ }, payment
32
+
33
+ return retval(result.to_hash[:paymentResponse][:error][:error])
34
+ rescue Errno::ECONNRESET
35
+ return retval(-1000)
36
+ end
37
+ end
38
+
39
+ def pay(payment)
40
+ return retval(-1001) if settings_miss?
41
+
42
+ begin
43
+ result = request :immediate_payment,
44
+ {
45
+ :partnerId => @config.setting_partner_id,
46
+ :subagentId => payment.subagent_id,
47
+ :paymentPointId => @config.setting_payment_point_id,
48
+ :money => "",
49
+ :phone => payment.account,
50
+ :discountCardNumber => payment.discount_card,
51
+
52
+ :attributes! => {
53
+ :money => {
54
+ :amount => payment.enrolled_amount,
55
+ :code => 'RUR'
56
+ }
57
+ }
58
+ }, payment
59
+
60
+ return retval(result.to_hash[:paymentResponse][:error][:error])
61
+ rescue Errno::ECONNRESET
62
+ return retval(-1000)
63
+ end
64
+ end
65
+
66
+ def generate_revision(revision)
67
+ return retval(-1001) if settings_miss?
68
+
69
+ builder = []
70
+ paginate_payments(revision.payments, builder) do |slice,buidler|
71
+ generate_revision_page(slice, builder)
72
+ end
73
+ data = {
74
+ :partnerId => @config.setting_partner_id,
75
+ :paymentsList => builder,
76
+
77
+ :attributes! => {
78
+ :partnerId => { :xmlns => "http://payment.beepayxp.jetinfosoft.ru/PaymentTypes.xsd" },
79
+ :paymentsList => { :xmlns => "http://payment.beepayxp.jetinfosoft.ru/PaymentTypes.xsd" }
80
+ }
81
+ }
82
+ [:xml, data]
83
+ end
84
+
85
+ def send_revision(revision)
86
+ return retval(-1001) if settings_miss?
87
+ opts = {
88
+ :method => "reconciliation",
89
+ :startTime => revision.date.to_date.to_datetime.strftime("%Y-%m-%dT%H:%M:%SZ%:z"),
90
+ :endTime => DateTime.new(
91
+ revision.date.year,
92
+ revision.date.month,
93
+ revision.date.day,
94
+ 23,
95
+ 59,
96
+ 59
97
+ ).strftime("%Y-%m-%dT%H:%M:%SZ%:z")
98
+ }
99
+ revision = generate_revision(revision)[1]
100
+
101
+ begin
102
+ result = request :register_transfer, revision, opts
103
+ return retval(result.to_hash[:reconciliationResponse][:error][:error])
104
+ rescue Errno::ECONNRESET
105
+ return retval(-1000)
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ def generate_revision_page(payments, builder)
112
+ payments.each do |p|
113
+ builder << {
114
+ :reconciliationPayment => {
115
+ :subagentId => p.subagent_id,
116
+ :paymentPointId => @config.setting_payment_point_id,
117
+ :money => "",
118
+ :phone => p.account,
119
+
120
+ :attributes! => {
121
+ :money => {
122
+ :amount => p.enrolled_amount,
123
+ :code => 'RUR'
124
+ }
125
+ }
126
+ },
127
+
128
+ :attributes! => {
129
+ :reconciliationPayment => {
130
+ :paymentTime => p.created_at.strftime("%Y-%m-%dT%H:%M:%SZ%:z"),
131
+ :externalId => p.id,
132
+ :registeredId => p.id
133
+ }
134
+ }
135
+ }
136
+ end
137
+ end
138
+
139
+ def settings_miss?
140
+ @config.setting_partner_id.blank? ||
141
+ @config.setting_payment_point_id.blank? ||
142
+ @config.attachment_cert.blank? ||
143
+ @config.attachment_wsdl.blank?
144
+ end
145
+
146
+ def retval(code)
147
+ {:success => (code.to_s == "0"), :error => code}
148
+ end
149
+
150
+ def sign_request(text)
151
+ cryptcp = "#{Dir.pwd}/bin/cryptcp"
152
+ out_txt = "#{Dir.pwd}/certificates/beeline_out.txt"
153
+ out_msg = "#{Dir.pwd}/certificates/beeline_out.msg"
154
+
155
+ begin
156
+ system("#{cryptcp} -sign -f #{@config.attachment_cert.path} \
157
+ -nochain #{out_txt} \
158
+ #{out_msg}")
159
+ signature = File.read(out_txt)
160
+ ensure
161
+ raise "cryptcp failed while doing something" if $? != 0
162
+ end
163
+
164
+ signature
165
+ end
166
+
167
+ def request(method, params, opts)
168
+ Savon.config.env_namespace = :soap
169
+ client = Savon.client @config.attachment_wsdl.path
170
+ client.wsdl.endpoint = @config.setting_url
171
+
172
+ client.request(method) do
173
+ config.logger = logger
174
+
175
+ http.auth.ssl.verify_mode = :none
176
+ soap.element_form_default = :unqualified
177
+ soap.namespaces.delete("xmlns:pt")
178
+ soap.input = ["#{opts.kind_of?(Hash) ? opts[:method] : method.to_s.lower_camelcase}Request"]
179
+ soap.input << if method == :register_transfer
180
+ {
181
+ :startTime => opts[:startTime],
182
+ :endTime => opts[:endTime],
183
+ :xmlns => "http://payment.beepayxp.jetinfosoft.ru"
184
+ }
185
+ else
186
+ {
187
+ :paymentTime => opts.created_at.strftime("%Y-%m-%dT%H:%M:%SZ%:z"),
188
+ :externalId => opts.id,
189
+ :xmlns => "http://payment.beepayxp.jetinfosoft.ru"
190
+ }
191
+ end
192
+ soap.body = params
193
+ soap.header = {
194
+ :digitalSignature => {
195
+ :signature => sign_request(soap.send :body_to_xml)
196
+ },
197
+ :attributes! => {
198
+ :digitalSignature => {:xmlns => "http://payment.beepayxp.jetinfosoft.ru"}
199
+ }
200
+ }
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end