I tried to pass total from index page to amount in ruby script instead of hardcoding it,but it didnt work.It just print a bunch of code after I paste "Invoke-WebRequest -Method POST -Uri http://localhost:4242/create-payment-intent -UseBasicParsing " command,In first console it successfuly run command ruby server.rb heres my index.html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Stripe Sample</title>
<meta name="description" content="A demo of Stripe" />
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="css/normalize.css" />
<link rel="stylesheet" href="css/global.css" />
<script src="https://js.stripe.com/v3/"></script>
<script src="./payment.js"></script>
</head>
<body>
<span id="total" class="total-value" style='display: none;'></span>
<div class="sr-root">
<div class="sr-main">
<h1>Pay with a bunch of payment option</h1>
<form id="payment-form" method="POST">
<input type="text" name="email" id="email" placeholder="E-Mail" required>
<input type="text" name="name" id="name" placeholder="Full Name" required>
<div id="payment-element"></div>
<button>Pay</button><!--Make functional-->
<!--Make total price hidden and that total of this is same as in checkout and that its connected to ruby-->
<div id="error-messages"></div>
</form>
</div>
</div>
<script>
// get the value of the "total" parameter from the URL
const urlParams = new URLSearchParams(window.location.search);
const total = urlParams.get("total");
// set the value of the hidden input field to the total value
const totalSpan = document.getElementById("total-input");
totalSpan.value = total;
</script>
</body>
</html>
heres my ruby script :
# frozen_string_literal: true
require 'stripe'
require 'sinatra'
require 'dotenv'
require 'mail'
require 'nokogiri'
require 'open-uri'
enable :sessions
# Replace if using a different env file or config
Dotenv.load
# For sample support and debugging, not required for production:
Stripe.set_app_info(
'stripe-samples/<name-of-sample>/[<name-of-integration-type>]',
version: '0.0.1',
url: 'https://github.com/stripe-samples'
)
Stripe.api_version = '2020-08-27'
Stripe.api_key = ENV['STRIPE_SECRET_KEY']
set :static, true
set :public_folder, File.join(File.dirname(__FILE__), ENV['STATIC_DIR'])
set :port, 4242
# Define a global array to store the products added to cart
$cart_items = []
# Define a route to add products to the cart
post '/cart' do
request.body.rewind
product = JSON.parse(request.body.read)
$cart_items.push(product)
content_type :json
{ cart_size: $cart_items.size }.to_json
end
# Define a route to get the cart items
get '/cart' do
content_type :json
$cart_items.to_json
end
get '/' do
content_type 'text/html'
send_file File.join(settings.public_folder, 'index.html')
end
get '/config' do
content_type 'application/json'
{
publishableKey: ENV['STRIPE_PUBLISHABLE_KEY'],
}.to_json
end
post '/create-payment-intent' do
# Fetch the HTML document and parse it using Nokogiri
doc = Nokogiri::HTML(URI.open("http://localhost:4242"))
# Find the total element containing the total value
total_span = doc.css(".total span-value").first
# Extract the total value from the span element's text content
total = total_span.text.to_i
payment_intent = Stripe::PaymentIntent.create({
amount: total,
currency: 'usd',
automatic_payment_methods: { enabled: true }
})
{ clientSecret: payment_intent.client_secret }.to_json
end
get '/complete' do
# Retrieve the payment intent object from Stripe
payment_intent = Stripe::PaymentIntent.retrieve(params[:payment_intent])
# Check if the payment was successful
if payment_intent.status == "succeeded"
# Redirect to success page (optional)
redirect '/success.html'
else
# Redirect to error page
redirect '/error'
end
end
post '/webhook' do
# You can use webhooks to receive information about asynchronous payment events.
# For more about our webhook events check out https://stripe.com/docs/webhooks.
webhook_secret = ENV['STRIPE_WEBHOOK_SECRET']
payload = request.body.read
if !webhook_secret.empty?
# Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
sig_header = request.env['HTTP_STRIPE_SIGNATURE']
event = nil
begin
event = Stripe::Webhook.construct_event(
payload, sig_header, webhook_secret
)
rescue JSON::ParserError => e
# Invalid payload
status 400
return
rescue Stripe::SignatureVerificationError => e
# Invalid signature
puts '⚠️ Webhook signature verification failed.'
status 400
return
end
else
data = JSON.parse(payload, symbolize_names: true)
event = Stripe::Event.construct_from(data)
end
case event.type
when 'payment_intent.succeeded'
puts ' Payment received!'
end
content_type 'application/json'
{
status: 'success'
}.to_json
end
and heres my javascript code if its needed :
document.addEventListener('DOMContentLoaded', async () => {
// Fetch publishable key from the server
const {publishableKey} = await fetch('/config').then(r => r.json())
const stripe = Stripe(publishableKey)
// Create payment intent on the server
const {clientSecret} = await fetch("/create-payment-intent", {
method: "POST",
headers: {
'Content-Type': 'application/json'
}
}).then(r => r.json())
// Render payment element
const elements = stripe.elements({ clientSecret });
var paymentElement = elements.getElement('payment');
var paymentElement = elements.create('payment', {
fields: {
billingDetails: {
name: 'auto',
email: 'auto',
}
}
});
paymentElement.mount('#payment-element')
const nameInput = document.getElementById('name');
const emailInput = document.getElementById('email');
const form = document.getElementById('payment-form')
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Get the values from the input fields
const name = nameInput.value;
const email = emailInput.value;
// Confirm the payment and redirect to the return URL
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: window.location.origin + '/complete',
payment_method_data: {
billing_details: {
name: name,
email: email,
}
},
},
})
if (error) {
const messages = document.getElementById('error-messages')
messages.innerText = error.message;
}
})
})
heres error that i get
conditions = @conditions
@conditions = []
wrapper = block.arity.zero? ?
proc { |a, _p| unbound_method.bind(a).call } :
proc { |a, p| unbound_method.bind(a).call(*p) }
[pattern, conditions, wrapper]
end
def compile(path, route_mustermann_opts = {})
Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts))
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
block in compile!
pattern = compile(path, route_mustermann_opts)
method_name = "#{verb} #{path}"
unbound_method = generate_method(method_name, &block)
conditions = @conditions
@conditions = []
wrapper = block.arity.zero? ?
proc { |a, _p| unbound_method.bind(a).call } :
proc { |a, p| unbound_method.bind(a).call(*p) }
[pattern, conditions, wrapper]
end
def compile(path, route_mustermann_opts = {})
Mustermann.new(path, **mustermann_opts.merge(route_mustermann_opts))
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
block (3 levels) in route!
routes = base.routes[@request.request_method]
routes&.each do |pattern, conditions, block|
response.delete_header('Content-Type') unless @pinned_response
returned_pass_block = process_route(pattern, conditions) do |*args|
env['sinatra.route'] = "#{@request.request_method} #{pattern}"
route_eval { block[*args] }
end
# don't wipe out pass_block in superclass
pass_block = returned_pass_block if returned_pass_block
end
# Run routes defined in superclass.
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
route_eval
route_eval(&pass_block) if pass_block
route_missing
end
# Run a route block and throw :halt with the result.
def route_eval
throw :halt, yield
end
# If the current request matches pattern and conditions, fill params
# with keys and call the given block.
# Revert params afterwards.
#
# Returns pass block.
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
block (2 levels) in route!
routes = base.routes[@request.request_method]
routes&.each do |pattern, conditions, block|
response.delete_header('Content-Type') unless @pinned_response
returned_pass_block = process_route(pattern, conditions) do |*args|
env['sinatra.route'] = "#{@request.request_method} #{pattern}"
route_eval { block[*args] }
end
# don't wipe out pass_block in superclass
pass_block = returned_pass_block if returned_pass_block
end
# Run routes defined in superclass.
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
block in process_route
@params[:captures] = force_encoding(captures) unless captures.nil? || captures.empty?
else
values += params.values.flatten
end
catch(:pass) do
conditions.each { |c| throw :pass if c.bind(self).call == false }
block ? block[self, values] : yield(self, values)
end
rescue StandardError
@env['sinatra.error.params'] = @params
raise
ensure
params ||= {}
params.each { |k, _| @params.delete(k) } unless @env['sinatra.error.params']
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
catch
captures = pattern.match(route).captures.map { |c| URI_INSTANCE.unescape(c) if c }
values += captures
@params[:captures] = force_encoding(captures) unless captures.nil? || captures.empty?
else
values += params.values.flatten
end
catch(:pass) do
conditions.each { |c| throw :pass if c.bind(self).call == false }
block ? block[self, values] : yield(self, values)
end
rescue StandardError
@env['sinatra.error.params'] = @params
raise
ensure
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
process_route
captures = pattern.match(route).captures.map { |c| URI_INSTANCE.unescape(c) if c }
values += captures
@params[:captures] = force_encoding(captures) unless captures.nil? || captures.empty?
else
values += params.values.flatten
end
catch(:pass) do
conditions.each { |c| throw :pass if c.bind(self).call == false }
block ? block[self, values] : yield(self, values)
end
rescue StandardError
@env['sinatra.error.params'] = @params
raise
ensure
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
block in route!
# Run routes defined on the class and all superclasses.
def route!(base = settings, pass_block = nil)
routes = base.routes[@request.request_method]
routes&.each do |pattern, conditions, block|
response.delete_header('Content-Type') unless @pinned_response
returned_pass_block = process_route(pattern, conditions) do |*args|
env['sinatra.route'] = "#{@request.request_method} #{pattern}"
route_eval { block[*args] }
end
# don't wipe out pass_block in superclass
pass_block = returned_pass_block if returned_pass_block
end
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
each
end
end
# Run routes defined on the class and all superclasses.
def route!(base = settings, pass_block = nil)
routes = base.routes[@request.request_method]
routes&.each do |pattern, conditions, block|
response.delete_header('Content-Type') unless @pinned_response
returned_pass_block = process_route(pattern, conditions) do |*args|
env['sinatra.route'] = "#{@request.request_method} #{pattern}"
route_eval { block[*args] }
end
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
route!
end
end
# Run routes defined on the class and all superclasses.
def route!(base = settings, pass_block = nil)
routes = base.routes[@request.request_method]
routes&.each do |pattern, conditions, block|
response.delete_header('Content-Type') unless @pinned_response
returned_pass_block = process_route(pattern, conditions) do |*args|
env['sinatra.route'] = "#{@request.request_method} #{pattern}"
route_eval { block[*args] }
end
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
block in dispatch!
end
invoke do
static! if settings.static? && (request.get? || request.head?)
filter! :before do
@pinned_response = !response['Content-Type'].nil?
end
route!
end
rescue ::Exception => e
invoke { handle_exception!(e) }
ensure
begin
filter! :after unless env['sinatra.static_file']
rescue ::Exception => e
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
catch
env['sinatra.static_file'] = path
cache_control(*settings.static_cache_control) if settings.static_cache_control?
send_file path, options.merge(disposition: nil)
end
# Run the block with 'throw :halt' support and apply result to the response.
def invoke(&block)
res = catch(:halt, &block)
res = [res] if (Integer === res) || (String === res)
if (Array === res) && (Integer === res.first)
res = res.dup
status(res.shift)
body(res.pop)
headers(*res)
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
invoke
env['sinatra.static_file'] = path
cache_control(*settings.static_cache_control) if settings.static_cache_control?
send_file path, options.merge(disposition: nil)
end
# Run the block with 'throw :halt' support and apply result to the response.
def invoke(&block)
res = catch(:halt, &block)
res = [res] if (Integer === res) || (String === res)
if (Array === res) && (Integer === res.first)
res = res.dup
status(res.shift)
body(res.pop)
headers(*res)
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
dispatch!
@params.merge!(@request.params).each do |key, val|
next unless val.respond_to?(:force_encoding)
val = val.dup if val.frozen?
@params[key] = force_encoding(val)
end
invoke do
static! if settings.static? && (request.get? || request.head?)
filter! :before do
@pinned_response = !response['Content-Type'].nil?
end
route!
end
rescue ::Exception => e
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
block in call!
@env = env
@params = IndifferentHash.new
@request = Request.new(env)
@response = Response.new
@pinned_response = nil
template_cache.clear if settings.reload_templates
invoke { dispatch! }
invoke { error_block!(response.status) } unless @env['sinatra.error']
unless @response['Content-Type']
if Array === body && body[0].respond_to?(:content_type)
content_type body[0].content_type
elsif (default = settings.default_content_type)
content_type default
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
catch
env['sinatra.static_file'] = path
cache_control(*settings.static_cache_control) if settings.static_cache_control?
send_file path, options.merge(disposition: nil)
end
# Run the block with 'throw :halt' support and apply result to the response.
def invoke(&block)
res = catch(:halt, &block)
res = [res] if (Integer === res) || (String === res)
if (Array === res) && (Integer === res.first)
res = res.dup
status(res.shift)
body(res.pop)
headers(*res)
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
invoke
env['sinatra.static_file'] = path
cache_control(*settings.static_cache_control) if settings.static_cache_control?
send_file path, options.merge(disposition: nil)
end
# Run the block with 'throw :halt' support and apply result to the response.
def invoke(&block)
res = catch(:halt, &block)
res = [res] if (Integer === res) || (String === res)
if (Array === res) && (Integer === res.first)
res = res.dup
status(res.shift)
body(res.pop)
headers(*res)
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
call!
@env = env
@params = IndifferentHash.new
@request = Request.new(env)
@response = Response.new
@pinned_response = nil
template_cache.clear if settings.reload_templates
invoke { dispatch! }
invoke { error_block!(response.status) } unless @env['sinatra.error']
unless @response['Content-Type']
if Array === body && body[0].respond_to?(:content_type)
content_type body[0].content_type
elsif (default = settings.default_content_type)
content_type default
C:/web/Ruby31-x64/lib/ruby/gems/3.1.0/gems/sinatra-3.0.5/lib
F;sinatra/base.rb in
call
@template_cache = Tilt::Cache.new
@pinned_response = nil # whether a before! filter pinned the content-type
yield self if block_given?
end
# Rack call interface.
def call(env)
At line:1 char:1
+ Invoke-WebRequest -Method POST -Uri http://localhost:4242/create-paym ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExcepti
on
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand