parsbank 0.0.4 → 0.0.8

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.
@@ -1,7 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+
1
7
  module Parsbank
2
8
  class Restfull
3
9
  attr_accessor :connection
4
10
 
11
+ MAX_RETRIES = 3
12
+ RETRY_INTERVAL = 5 # In seconds
13
+
5
14
  def initialize(args = {})
6
15
  @endpoint = args.fetch(:endpoint)
7
16
  @action = args.fetch(:action)
@@ -16,16 +25,14 @@ module Parsbank
16
25
  def call
17
26
  response = send_request
18
27
 
19
- Rails.logger.info("Received response with status: #{response.status}, body: #{response.body.inspect}")
28
+ log_response(response)
20
29
 
21
- if response.success?
22
- response
30
+ if response.is_a?(Net::HTTPSuccess)
31
+ parse_response(response)
23
32
  else
24
33
  log_and_raise_error(response)
25
34
  end
26
- rescue Faraday::ConnectionFailed => e
27
- handle_error("Connection failed: #{e.message}", e)
28
- rescue Faraday::TimeoutError => e
35
+ rescue Timeout::Error => e
29
36
  handle_error("Request timed out: #{e.message}", e)
30
37
  rescue StandardError => e
31
38
  handle_error("An unexpected error occurred: #{e.message}", e)
@@ -33,103 +40,155 @@ module Parsbank
33
40
 
34
41
  private
35
42
 
36
- def webhook(_message)
37
- webhook_url = Parsbank.configuration.webhook
43
+ def setup_connection
44
+ @uri = URI.parse(@endpoint)
45
+ @connection = Net::HTTP.new(@uri.host, @uri.port)
46
+ @connection.use_ssl = @uri.scheme == 'https'
47
+ @connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
48
+ @connection.set_debug_output($stdout) if Parsbank.configuration.debug
49
+ # Setting timeouts
50
+ @connection.open_timeout = 10 # Time to wait for the connection to open
51
+ @connection.read_timeout = 10 # Time to wait for a response
52
+ end
38
53
 
39
- webhook_url.gsub!('MESSAGE', _message) if Parsbank.configuration.webhook_method == :get
40
- webhook_url.gsub!('TITLE', "Webhook of Connection Error at #{Time.now}") if Parsbank.configuration.webhook_method == :get
54
+ def send_request
55
+ retries = 0
56
+ begin
57
+ request = build_request
58
+ @connection.start do
59
+ response = @connection.request(request)
41
60
 
42
- connection = Faraday.new() do |conn|
43
- conn.request :json if @response_type == :json # Automatically converts payload to JSON
44
- conn.response :json if @response_type == :json # Automatically parses JSON response
45
- conn.adapter Faraday.default_adapter
46
- conn.request :retry, max: 3, interval: 0.05,
47
- interval_randomness: 0.5, backoff_factor: 2,
48
- exceptions: [Faraday::TimeoutError, Faraday::ConnectionFailed]
49
- conn.use FaradayMiddleware::FollowRedirects
50
- end
61
+ # Handling redirects manually (max 5 redirects)
62
+ handle_redirects(response)
51
63
 
52
- case Parsbank.configuration.webhook_method
53
- when :post
54
- connection.post('&parsbank') do |req|
55
- req.headers = headers
56
- req.body = {}
64
+ return response
57
65
  end
58
-
59
- when :get
60
- connection.get('&parsbank')
66
+ rescue Timeout::Error => e
67
+ retries += 1
68
+ raise "Request timed out after #{MAX_RETRIES} retries: #{e.message}" unless retries < MAX_RETRIES
69
+
70
+ log_to_rails("Timeout occurred. Retrying... (#{retries}/#{MAX_RETRIES})", :warn)
71
+ sleep(RETRY_INTERVAL)
72
+ retry
73
+ rescue StandardError => e
74
+ log_to_rails("Request failed: #{e.message}", :error)
75
+ raise e
61
76
  end
62
- rescue Faraday::ConnectionFailed => e
63
- Rails.logger.error("Webhook Connection failed: #{e.message}", e)
64
- rescue Faraday::TimeoutError => e
65
- Rails.logger.error("Webhook Request timed out: #{e.message}", e)
66
- rescue StandardError => e
67
- Rails.logger.error("Webhook An unexpected error occurred: #{e.message}", e)
68
77
  end
69
78
 
70
- def setup_connection
71
- @connection = Faraday.new(@endpoint) do |conn|
72
- conn.request :json if @response_type == :json # Automatically converts payload to JSON
73
- conn.response :json if @response_type == :json # Automatically parses JSON response
74
- conn.adapter Faraday.default_adapter
75
- conn.request :retry, max: 3, interval: 0.05,
76
- interval_randomness: 0.5, backoff_factor: 2,
77
- exceptions: [Faraday::TimeoutError, Faraday::ConnectionFailed]
78
- conn.use FaradayMiddleware::FollowRedirects
79
- end
80
- end
81
-
82
- def send_request
83
- headers = default_headers.merge(@headers)
84
-
79
+ def build_request
85
80
  case @http_method
86
81
  when :post
87
- perform_post(headers)
82
+ build_post_request
88
83
  when :get
89
- perform_get(headers)
84
+ build_get_request
90
85
  when :options
91
- perform_options(headers)
86
+ build_options_request
92
87
  else
93
88
  raise ArgumentError, "HTTP Method Not Allowed: #{@http_method}"
94
89
  end
95
90
  end
96
91
 
97
- def perform_post(headers)
98
- @connection.post(@action) do |req|
99
- req.headers = headers
100
- req.body = @request_message
101
- end
92
+ def build_post_request
93
+ request = Net::HTTP::Post.new(@action, default_headers)
94
+ request['Connection'] = 'close' # Avoid HTTP/2 issues
95
+ request.body = JSON.generate(@request_message) if @request_message.any?
96
+ puts "Request Header: #{default_headers}" if Parsbank.configuration.debug
97
+ puts "Request Body: #{request.body}" if Parsbank.configuration.debug
98
+ request
102
99
  end
103
100
 
104
- def perform_get(headers)
105
- @connection.get(@action) do |req|
106
- req.headers = headers
107
- req.params = @request_message
108
- end
101
+ def build_get_request
102
+ request = Net::HTTP::Get.new(@action, default_headers)
103
+ request.set_form_data(@request_message) if @request_message.any?
104
+ request
109
105
  end
110
106
 
111
- def perform_options(headers)
112
- @connection.options(@action) do |req|
113
- req.headers = headers
114
- end
107
+ def build_options_request
108
+ Net::HTTP::Options.new(@action, default_headers)
115
109
  end
116
110
 
117
111
  def default_headers
118
112
  {
119
- 'Content-Type' => 'application/json',
120
- 'Parsbank-RubyGem' => Parsbank::VERSION
121
- }
113
+ 'content-type' => 'application/json',
114
+ 'accept' => 'application/json',
115
+ 'user-agent' => 'ParsBank Ruby Gem',
116
+ 'app-version' => Parsbank::VERSION
117
+ }.merge(@headers)
118
+ end
119
+
120
+ def log_response(response)
121
+ log_to_rails("Received response with status: #{response.code}, body: #{response.body.inspect}", :info)
122
+ end
123
+
124
+ def parse_response(response)
125
+ return response.body if @response_type == :raw
126
+
127
+ case @response_type
128
+ when :json
129
+ JSON.parse(response.body)
130
+ else
131
+ response.body
132
+ end
122
133
  end
123
134
 
124
135
  def log_and_raise_error(response)
125
- Rails.logger.error("Request to #{@endpoint}/#{@action} failed with status: #{response.status}, error: #{response.body.inspect}")
126
- raise "API request failed with status #{response.status}: #{response.body}"
136
+ log_to_rails(
137
+ "Request to #{@endpoint}/#{@action} failed with status: #{response.code}, error: #{response.body.inspect}", :error
138
+ )
139
+ raise "API request failed with status #{response.code}: #{response.body}"
127
140
  end
128
141
 
129
142
  def handle_error(message, exception)
130
- Rails.logger.error(message)
143
+ log_to_rails(message, :error)
131
144
  webhook(message) if Parsbank.configuration.webhook.present?
132
145
  raise exception
133
146
  end
147
+
148
+ def log_to_rails(message, level = :info)
149
+ case level
150
+ when :error
151
+ Rails.logger.error(message) if defined?(Rails)
152
+ when :warn
153
+ Rails.logger.warn(message) if defined?(Rails)
154
+ else
155
+ Rails.logger.info(message) if defined?(Rails)
156
+ end
157
+ end
158
+
159
+ def webhook(message)
160
+ webhook_url = Parsbank.configuration.webhook
161
+ webhook_url.gsub!('MESSAGE', message) if Parsbank.configuration.webhook_method == :get
162
+ if Parsbank.configuration.webhook_method == :get
163
+ webhook_url.gsub!('TITLE',
164
+ "Webhook of Connection Error at #{Time.now}")
165
+ end
166
+
167
+ uri = URI.parse(webhook_url)
168
+ connection = Net::HTTP.new(uri.host, uri.port)
169
+ connection.use_ssl = uri.scheme == 'https'
170
+
171
+ case Parsbank.configuration.webhook_method
172
+ when :post
173
+ request = Net::HTTP::Post.new(uri.path, default_headers)
174
+ request.body = {}.to_json
175
+ connection.request(request)
176
+ when :get
177
+ request = Net::HTTP::Get.new(uri.path, default_headers)
178
+ connection.request(request)
179
+ end
180
+ rescue StandardError => e
181
+ log_to_rails("Webhook Error: #{e.message}", :error)
182
+ end
183
+
184
+ def handle_redirects(response)
185
+ return unless response.is_a?(Net::HTTPRedirection)
186
+
187
+ location = response['Location']
188
+ log_to_rails("Redirecting to: #{location}", :warn)
189
+ redirect_uri = URI.parse(location)
190
+ request = Net::HTTP::Get.new(redirect_uri)
191
+ @connection.request(request)
192
+ end
134
193
  end
135
194
  end
@@ -0,0 +1,106 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'rexml/document'
4
+ require 'logger'
5
+
6
+ module Parsbank
7
+ # SOAP Client Class - Standard SOAP generation with namespaces and headers
8
+ class SOAP
9
+ attr_reader :endpoint, :namespace, :logger
10
+
11
+ # Initialize SOAP Client with endpoint, namespace, and optional logger
12
+ def initialize(endpoint, namespace)
13
+ @endpoint = URI.parse(endpoint)
14
+ @namespace = namespace
15
+ @logger = Logger.new(STDOUT)
16
+ @logger.level = Parsbank.configuration.debug ? Logger::DEBUG : Logger::WARN
17
+ end
18
+
19
+ # Main method to make a SOAP request
20
+ def call(action, body, headers = {})
21
+ log_request(action, body)
22
+
23
+ xml = build_envelope(action, body.map { |k, v| "<s:#{k}>#{v}</#{k}>" }.join(''))
24
+
25
+ http = Net::HTTP.new(@endpoint.host, @endpoint.port)
26
+ http.use_ssl = (@endpoint.scheme == 'https')
27
+
28
+ request = Net::HTTP::Post.new(@endpoint.request_uri)
29
+ request.content_type = 'text/xml; charset=utf-8'
30
+ request['SOAPAction'] = "#{@namespace}/#{action}"
31
+ request.body = xml
32
+
33
+ headers.store('Parsbank-RubyGem', Parsbank::VERSION)
34
+ headers.each { |key, value| request[key] = value }
35
+
36
+ begin
37
+ response = http.request(request)
38
+ log_response(response)
39
+ parse_response(response)
40
+ rescue Timeout::Error => e
41
+ handle_error("Request timed out", e)
42
+ rescue SocketError => e
43
+ handle_error("Network connection failed", e)
44
+ rescue Errno::ECONNREFUSED => e
45
+ handle_error("Connection refused by server", e)
46
+ rescue StandardError => e
47
+ handle_error("Unexpected error: #{e.message}", e)
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ # Build the SOAP XML Envelope
54
+ def build_envelope(action, body)
55
+ <<~XML
56
+ <?xml version="1.0" encoding="UTF-8"?>
57
+ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
58
+ xmlns:s="#{@namespace}">
59
+ <soap:Header/>
60
+ <soap:Body>
61
+ <s:#{action}>
62
+ #{body}
63
+ </s:#{action}>
64
+ </soap:Body>
65
+ </soap:Envelope>
66
+ XML
67
+ end
68
+
69
+ # Parse the XML response body
70
+ def parse_response(response)
71
+ if response.is_a?(Net::HTTPSuccess)
72
+ puts "Response Success"
73
+ puts response.body
74
+ parse_xml(response.body)
75
+ else
76
+ { error: "HTTP Error #{response.code}: #{response.message}" }
77
+ end
78
+ end
79
+
80
+ # Convert XML to Hash
81
+ def parse_xml(xml)
82
+ begin
83
+ doc = REXML::Document.new(xml)
84
+ { success: true, body: doc }
85
+ rescue REXML::ParseException => e
86
+ { success: false, error: "Invalid XML response: #{e.message}" }
87
+ end
88
+ end
89
+
90
+ # Error handling and logging
91
+ def handle_error(message, exception)
92
+ @logger.error("#{message}: #{exception.message}")
93
+ { success: false, error: message }
94
+ end
95
+
96
+ # Log the SOAP request for debugging
97
+ def log_request(action, body)
98
+ @logger.debug("Sending SOAP request: Action = #{action}, Body = #{body}")
99
+ end
100
+
101
+ # Log the SOAP response for debugging
102
+ def log_response(response)
103
+ @logger.debug("Received SOAP response: Status = #{response.code}, Body = #{response.body}")
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,134 @@
1
+ module Parsbank
2
+ class TransactionRequest
3
+ def self.create(args = {})
4
+ bank = fetch_bank(args)
5
+ validate_bank(bank)
6
+
7
+ description = args.fetch(:description)
8
+ callback_url = generate_callback_url(bank, description)
9
+
10
+ crypto_amount, fiat_amount, real_amount = fetch_amounts(args)
11
+ validate_amounts(bank, crypto_amount, fiat_amount, real_amount)
12
+
13
+ transaction = initialize_transaction(args, description, fiat_amount, crypto_amount, bank, callback_url)
14
+ process_gateway(bank, transaction, description, callback_url, crypto_amount, fiat_amount, args)
15
+
16
+ { transaction: transaction, html_form: @result }
17
+ end
18
+
19
+ def self.fetch_bank(args)
20
+ args.fetch(:bank, Parsbank.available_gateways_list.keys.sample)
21
+ end
22
+
23
+ def self.validate_bank(bank)
24
+ selected_bank = Parsbank.available_gateways_list[bank]
25
+ raise "Bank not enabled or not exists in #{Parsbank.configuration.secrets_path}: #{bank}" unless selected_bank
26
+ end
27
+
28
+ def self.generate_callback_url(bank, _description)
29
+ selected_bank = Parsbank.available_gateways_list[bank]
30
+ "#{selected_bank['callback_url'] || Parsbank.configuration.callback_url}&bank_name=#{bank}"
31
+ end
32
+
33
+ def self.fetch_amounts(args)
34
+ [
35
+ args.fetch(:crypto_amount, nil),
36
+ args.fetch(:fiat_amount, nil),
37
+ args.fetch(:real_amount, nil)
38
+ ]
39
+ end
40
+
41
+ def self.validate_amounts(bank, crypto_amount, fiat_amount, real_amount)
42
+ raise 'Amount fields are empty: crypto_amount OR fiat_amount OR real_amount' if [crypto_amount, fiat_amount,
43
+ real_amount].all?(&:nil?)
44
+
45
+ tags = Parsbank.supported_psp[bank]['tags']
46
+ if tags.include?('crypto') && crypto_amount.nil? && real_amount.nil?
47
+ raise "#{bank} needs crypto_amount or real_amount"
48
+ end
49
+
50
+ return unless tags.include?('rial') && fiat_amount.nil? && real_amount.nil?
51
+
52
+ raise "#{bank} needs fiat_amount or real_amount"
53
+ end
54
+
55
+ def self.initialize_transaction(args, description, fiat_amount, crypto_amount, bank, callback_url)
56
+ model_class = Parsbank.configuration.model || 'Transaction'
57
+ @transaction= Object.const_get(model_class).new(
58
+ description: description,
59
+ amount: fiat_amount || crypto_amount,
60
+ gateway: bank,
61
+ callback_url: callback_url,
62
+ status: 'start',
63
+ user_id: args.fetch(:user_id, nil),
64
+ cart_id: args.fetch(:cart_id, nil),
65
+ local_id: args.fetch(:local_id, nil),
66
+ ip: args.fetch(:ip, nil)
67
+ )
68
+ @transaction.save
69
+
70
+ @transaction
71
+ end
72
+
73
+ def self.process_gateway(bank, transaction, description, callback_url, crypto_amount, fiat_amount, args)
74
+ case bank
75
+ when 'mellat'
76
+ process_mellat(transaction, description, callback_url, fiat_amount)
77
+ when 'zarinpal'
78
+ process_zarinpal(transaction, description, callback_url, fiat_amount)
79
+ when 'zibal'
80
+ process_zibal(description, callback_url, fiat_amount)
81
+ when 'bscbitcoin'
82
+ process_bscbitcoin(transaction, description, crypto_amount, args)
83
+ else
84
+ raise "Unsupported gateway: #{bank}"
85
+ end
86
+ end
87
+
88
+ def self.process_mellat(transaction, description, callback_url, fiat_amount)
89
+ mellat = Parsbank::Mellat.new(
90
+ amount: fiat_amount,
91
+ additional_data: description,
92
+ callback_url: callback_url,
93
+ orderId: transaction.id
94
+ )
95
+ mellat.call
96
+ transaction.update!(gateway_response: mellat.response, unit: 'irr')
97
+ @result = mellat.redirect_form
98
+ end
99
+
100
+ def self.process_zarinpal(transaction, description, callback_url, fiat_amount)
101
+ zarinpal = Parsbank::Zarinpal.new(
102
+ amount: fiat_amount,
103
+ additional_data: description,
104
+ callback_url: callback_url
105
+ )
106
+ zarinpal.call
107
+ transaction.update!(
108
+ gateway_response: zarinpal.response,
109
+ track_id: zarinpal.ref_id,
110
+ unit: 'irt'
111
+ )
112
+ @result = zarinpal.redirect_form
113
+ end
114
+
115
+ def self.process_zibal(description, callback_url, fiat_amount)
116
+ zibal = Parsbank::Zibal.new(
117
+ amount: fiat_amount,
118
+ additional_data: description,
119
+ callback_url: callback_url
120
+ )
121
+ zibal.call
122
+ @result = zibal.redirect_form
123
+ end
124
+
125
+ def self.process_bscbitcoin(transaction, description, crypto_amount, args)
126
+ bscbitcoin = Parsbank::BscBitcoin.new(
127
+ additional_data: description
128
+ )
129
+ convert_real_amount_to_assets if crypto_amount.nil? && args.key?(:real_amount)
130
+ @result = bscbitcoin.generate_payment_address(amount: crypto_amount)
131
+ transaction.update!(gateway_response: @result, unit: 'bitcoin')
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parsbank
4
+ class TransactionVerify
5
+ def self.verify(args = {})
6
+ validate_params(args.params)
7
+
8
+ transaction = initialize_transaction(args, description, fiat_amount, crypto_amount, bank, callback_url)
9
+ process_gateway(bank, transaction, description, callback_url, crypto_amount, fiat_amount, args)
10
+
11
+ { transaction: transaction, html_form: @result }
12
+ end
13
+
14
+ def self.validate_params(params)
15
+ model_class = Parsbank.configuration.model || 'Transaction'
16
+ tack_transaction = Object.const_get(model_class).find(params[:transaction_id].to_i)
17
+ { status: 404, message: I18n.t('model.not_found') } unless tack_transaction.present?
18
+ end
19
+
20
+ def self.fetch_bank(args)
21
+ args.fetch(:bank)
22
+ end
23
+
24
+ def self.validate_bank(bank)
25
+ selected_bank = Parsbank.available_gateways_list[bank]
26
+ raise "Bank not enabled or not exists in #{Parsbank.configuration.secrets_path}: #{bank}" unless selected_bank
27
+ end
28
+
29
+ def self.generate_callback_url(bank, _description)
30
+ selected_bank = Parsbank.available_gateways_list[bank]
31
+ "#{selected_bank['callback_url'] || Parsbank.configuration.callback_url}&bank_name=#{bank}"
32
+ end
33
+
34
+ def self.fetch_amounts(args)
35
+ [
36
+ args.fetch(:crypto_amount, nil),
37
+ args.fetch(:fiat_amount, nil),
38
+ args.fetch(:real_amount, nil)
39
+ ]
40
+ end
41
+
42
+ def self.validate_amounts(bank, crypto_amount, fiat_amount, real_amount)
43
+ raise 'Amount fields are empty: crypto_amount OR fiat_amount OR real_amount' if [crypto_amount, fiat_amount,
44
+ real_amount].all?(&:nil?)
45
+
46
+ tags = $SUPPORTED_PSP[bank]['tags']
47
+ if tags.include?('crypto') && crypto_amount.nil? && real_amount.nil?
48
+ raise "#{bank} needs crypto_amount or real_amount"
49
+ end
50
+
51
+ return unless tags.include?('rial') && fiat_amount.nil? && real_amount.nil?
52
+
53
+ raise "#{bank} needs fiat_amount or real_amount"
54
+ end
55
+
56
+ def self.initialize_transaction(args, description, fiat_amount, crypto_amount, bank, callback_url)
57
+ model_class = Parsbank.configuration.model || 'Transaction'
58
+ @transaction = Object.const_get(model_class).new(
59
+ description: description,
60
+ amount: fiat_amount || crypto_amount,
61
+ gateway: bank,
62
+ callback_url: callback_url,
63
+ status: 'start',
64
+ user_id: args.fetch(:user_id, nil),
65
+ cart_id: args.fetch(:cart_id, nil),
66
+ local_id: args.fetch(:local_id, nil),
67
+ ip: args.fetch(:ip, nil)
68
+ )
69
+ @transaction.save
70
+
71
+ @transaction
72
+ end
73
+
74
+ def self.process_gateway(bank, transaction, description, callback_url, crypto_amount, fiat_amount, args)
75
+ case bank
76
+ when 'mellat'
77
+ process_mellat(transaction, description, callback_url, fiat_amount)
78
+ when 'zarinpal'
79
+ process_zarinpal(transaction, description, callback_url, fiat_amount)
80
+ when 'zibal'
81
+ process_zibal(description, callback_url, fiat_amount)
82
+ when 'bscbitcoin'
83
+ process_bscbitcoin(transaction, description, crypto_amount, args)
84
+ else
85
+ raise "Unsupported gateway: #{bank}"
86
+ end
87
+ end
88
+
89
+ def self.process_mellat(transaction, description, callback_url, fiat_amount)
90
+ mellat = Parsbank::Mellat.new(
91
+ amount: fiat_amount,
92
+ additional_data: description,
93
+ callback_url: callback_url,
94
+ orderId: transaction.id
95
+ )
96
+ mellat.call
97
+ transaction.update!(gateway_response: mellat.response, unit: 'irr')
98
+ @result = mellat.redirect_form
99
+ end
100
+
101
+ def self.process_zarinpal(transaction, description, callback_url, fiat_amount)
102
+ zarinpal = Parsbank::Zarinpal.new(
103
+ amount: fiat_amount,
104
+ additional_data: description,
105
+ callback_url: callback_url
106
+ )
107
+ zarinpal.call
108
+ transaction.update!(
109
+ gateway_response: zarinpal.response,
110
+ track_id: zarinpal.ref_id,
111
+ unit: 'irt'
112
+ )
113
+ @result = zarinpal.redirect_form
114
+ end
115
+
116
+ def self.process_zibal(description, callback_url, fiat_amount)
117
+ zibal = Parsbank::Zibal.new(
118
+ amount: fiat_amount,
119
+ additional_data: description,
120
+ callback_url: callback_url
121
+ )
122
+ zibal.call
123
+ @result = zibal.redirect_form
124
+ end
125
+
126
+ def self.process_bscbitcoin(transaction, description, crypto_amount, args)
127
+ bscbitcoin = Parsbank::BscBitcoin.new(
128
+ additional_data: description
129
+ )
130
+ convert_real_amount_to_assets if crypto_amount.nil? && args.key?(:real_amount)
131
+ @result = bscbitcoin.generate_payment_address(amount: crypto_amount)
132
+ transaction.update!(gateway_response: @result, unit: 'bitcoin')
133
+ end
134
+ end
135
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsbank
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.8'
5
5
  end
@@ -1,4 +1,4 @@
1
- <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1575 350">
1
+ <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" viewBox="0 0 1575 350">
2
2
  <defs>
3
3
  <style>
4
4
  .cls-1 {