I am following along with this stripe tutorial but the server.rb in the example from Stripe's Github is throwing an error when I run Ruby server.rb
I am very new to ruby so I could be doing things wrong.
What I did was:
Installed Ruby, Rails, Stripe CLI, Sinatra, and dotenv
Downloaded the example from the site by typing Stripe samples create
developer-office-hours
cd'd into the server directory and ran ruby
server.rb
this is the error
1: from server.rb:10:in '<main.'
server.rb:10:in 'join': no implicit conversation of nil into string (TypeError)
here is the server.rb file
require 'stripe'
require 'sinatra'
require 'dotenv'
# Replace if using a different env file or config
Dotenv.load
Stripe.api_key = ENV['STRIPE_SECRET_KEY']
set :static, true
set :public_folder, File.join(File.dirname(__FILE__), ENV['STATIC_DIR'])
set :views, File.join(File.dirname(__FILE__), ENV['STATIC_DIR'])
set :port, 4242
get '/' do
content_type 'text/html'
send_file File.join(settings.public_folder, 'index.html')
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
# Get the type of webhook event sent - used to check the status of PaymentIntents.
event_type = event['type']
data = event['data']
data_object = data['object']
if event_type == 'some.event'
puts "🔔 Webhook received!"
end
content_type 'application/json'
{
status: 'success'
}.to_json
end
stripe login
This is a crucial step.
stripe samples create adding-sales-tax
cd adding-sales-tax/server
bundle install
If you don't have bundler, gem install bundler
bundle exec ruby server.rb
Open http://localhost:4242
Related
So, I've been following this guide: https://docs.github.com/pt/developers/webhooks-and-events/webhooks/creating-webhooks
This is my code:
require 'sinatra'
require 'json'
require 'openssl'
post '/payload' do
request.body.rewind
header_token = request.env["zzzzzzzzzzzzzzzzzzzz"]
payload_body = request.body.read
verify_signature(payload_body)
push = JSON.parse(payload_body)
"I got some JSON: #{push.inspect}"
end
def verify_signature(payload_body)
signature = 'sha256=' + (OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'),
ENV['jksdaskçjdaskçdhaskdhakdhaskdhaskdhaskdaskdasdkh'],
payload_body))
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])
end
When I load http://localhost:4567 i get :
Sinatra doesn’t know this ditty.
If I change Post to Get (trying to see if it is working) :
no implicit conversion of nil into String file: payload.rb location:
hexdigest line: 15
I'm pretty new to this and I'm attempting to create a prestashop module for a payment gateway, but this webhook thing is messing with me.
Im I doing something wrong? Is there a easy way? Is it everything correct?
Thanks
I have a simple ruby script meant to send all received messages as sms messages. However, somehow for some reason it does not execute.
Here is the sample code;
/etc/aliases
motor: "|/home/motorcare/sms_script.rb"
sms_script.rb
#!/usr/bin/env ruby
require "json"
require "httparty"
require 'net/http'
require 'uri'
require "cgi"
require "mail"
# Reading files
mail = Mail.read(ARGV[0])
destination = mail.subject
message = mail.body.decoded
#first_line = lines[0].strip
if destination =~ /^(256)/
send(destination, message)
else
destination = "256#{destination.gsub(/^0+/,"")}"
send(destination, message)
end
# Sending message
def send(destination, message)
url = "http://xxxxxxxxxx.com/messages?token=c19ae2574be1875f0fa09df13b0dde0b&to=#{phone_number}&from=xxxxxx&message=#{CGI.escape(message)}"
5.times do |i|
response = HTTParty.get(url)
body = JSON.parse(response.body)
if body["status"] == "Success"
break
end
end
end
Anyone with a similar script to assist with this one?
You have 2 errors.
1st error is that send is already defined in Ruby. See this SO post What does send() do in Ruby?
see this code
$ cat send.rb
#!/usr/bin/env ruby
puts defined? send
puts send :class
$ ./send.rb
method
Object
2nd error is that you call the method before it's even defined. See this sample code (calling welcome before def welcome)
$ cat welcome.rb
#!/usr/bin/env ruby
welcome('hello from welcome')
def welcome(msg)
puts msg
end
$ ./welcome.rb
./welcome.rb:3:in `<main>': undefined method `welcome' for main:Object (NoMethodError)
Change the method name from send to something else, e.g. send_sms, and put the definition before calling the method
So this should be sth like:
#!/usr/bin/env ruby
require "json"
require "httparty"
require 'net/http'
require 'uri'
require "cgi"
require "mail"
# Sending message
def send_sms(destination, message)
url = "http://xxxxxxxxxx.com/messages?token=c19ae2574be1875f0fa09df13b0dde0b&to=#{phone_number}&from=xxxxxx&message=#{CGI.escape(message)}"
5.times do |i|
response = HTTParty.get(url)
body = JSON.parse(response.body)
if body["status"] == "Success"
break
end
end
end
# Reading files
mail = Mail.read(ARGV[0])
destination = mail.subject
message = mail.body.decoded
#first_line = lines[0].strip
if destination =~ /^(256)/
send_sms(destination, message)
else
destination = "256#{destination.gsub(/^0+/,"")}"
send_sms(destination, message)
end
And also adding logging to the script would give you info about what's going in inside when it's run and pipped. So you can easily debug the beaviour. Logging is the easies approach to DEBUG.
When I run my unit test case (written in ChefSpec) I get the following error:
Chef::Exceptions::CookbookNotFound: Cookbook azuredns not found. If
you're loading azuredns from another cook book, make sure you
configure the dependency in your metadata
Following are my spec file, recipe file and metadata file
azuredns/spec/get_azure_token_spec.rb
require 'chefspec'
require 'rest-client'
describe 'azuredns::get_azure_token' do
let(:chef_run) do
# Step into the provider
runner = ChefSpec::SoloRunner.new(step_into: ['azuredns_token'])
# Read test data from a json file
file_path = File.expand_path('test_data.json', __dir__)
file = File.open(file_path)
contents = file.read
node_attr = JSON.parse(contents)
# Load test data into node object
runner.node.consume_attributes(node_attr)
runner.converge(described_recipe)
end
before(:each) do
# Mock post method of RestClient
allow(RestClient).to receive(:post)
.and_return({ access_token: 'i-am-a-token' }.to_json)
end
it 'retrieves token' do
expect(chef_run).to retrieve_azuredns_token('azure_token')
end
it 'varifies the expected value of azure_rest_token' do
expect(chef_run.node['azure_rest_token']).to eq('Bearer i-am-a-token')
end
it 'does not retrieve token due to incorrect resource name' do
expect(chef_run).to_not retrieve_azuredns_token('azure_token1')
end
it 'raises exception due to error in response' do
# Mock post method of RestClient
allow(RestClient).to receive(:post)
.and_return({ error: 'invalid_grant' }.to_json)
expect { chef_run }.to raise_error(Exception)
end
end
azuredns/recipe/get_azure_token.rb
require 'rest_client'
require 'json'
cloud_name = node['workorder']['cloud']['ciName']
cloud = node['workorder']['services']['dns'][cloud_name]
dns_attributes = cloud['ciAttributes']
# Establish connection and get a security token
token = azuredns_token 'azure_token' do
tenant_id dns_attributes['tenant_id']
client_id dns_attributes['client_id']
client_secret dns_attributes['client_secret']
end
token.run_action(:retrieve)
azuredns/metadata.rb
name 'Azuredns'
maintainer 'Shaffan'
maintainer_email 'shaffan.chaudhry1#gmail.com'
license 'Apache License, Version 2.0'
description 'Installs/Configures Azure DNS'
version '0.1.0'
depends 'azure'
Please help!
Azuredns != azuredns :-)
Fix the name in your metadata. Chef, and pretty much everything from the UNIX world, is case sensitive.
I'm getting the following error message when I try to do an OAuth2 connection to google.
.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/google-api-client-0.7.1/lib/google/api_client/auth/file_storage.rb:49:in `at': can't convert nil into an exact number (TypeError)
Looking at the source this is trying to read a cached credentials file and is failing to parse an attribute called issued_at.
I initially set up my app with the wrong port in the google developer console. Now I've updated the client_secrets.json but I'm continually getting this error.
My code is trying doing the calendar example from the google site, but converted to use the admin directory API, but it isn't getting beyond the auth step.
Where is this cached value coming from?
require 'rubygems'
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/file_storage'
require 'sinatra'
require 'logger'
enable :sessions
CREDENTIAL_STORE_FILE = "client_secrets.json"
def logger; settings.logger end
def api_client; settings.api_client; end
def directory_api; settings.directory; end
def user_credentials
# Build a per-request oauth credential based on token stored in session
# which allows us to use a shared API client.
#authorization ||= (
auth = api_client.authorization.dup
auth.redirect_uri = to('/oauth2callback')
auth.update_token!(session)
auth
)
end
configure do
log_file = File.open('directory.log', 'a+')
log_file.sync = true
logger = Logger.new(log_file)
logger.level = Logger::DEBUG
client = Google::APIClient.new(
:application_name => 'Ruby Directory sample',
:application_version => '1.0.0')
puts "store file : #{CREDENTIAL_STORE_FILE}"
file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
if file_storage.authorization.nil?
client_secrets = Google::APIClient::ClientSecrets.load
client.authorization = client_secrets.to_authorization
client.authorization.scope = 'https://www.googleapis.com/auth/admin.directory.user'
else
client.authorization = file_storage.authorization
end
# Since we're saving the API definition to the settings, we're only retrieving
# it once (on server start) and saving it between requests.
# If this is still an issue, you could serialize the object and load it on
# subsequent runs.
directory = client.discovered_api('admin', "directory_v1")
set :logger, logger
set :api_client, client
set :directory, directory
end
before do
# Ensure user has authorized the app
unless user_credentials.access_token || request.path_info =~ /\A\/oauth2/
redirect to('/oauth2authorize')
end
end
after do
# Serialize the access/refresh token to the session and credential store.
session[:access_token] = user_credentials.access_token
session[:refresh_token] = user_credentials.refresh_token
session[:expires_in] = user_credentials.expires_in
session[:issued_at] = user_credentials.issued_at
file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
file_storage.write_credentials(user_credentials)
end
get '/oauth2authorize' do
# Request authorization
redirect user_credentials.authorization_uri.to_s, 303
end
get '/oauth2callback' do
# Exchange token
user_credentials.code = params[:code] if params[:code]
user_credentials.fetch_access_token!
redirect to('/')
end
get '/' do
result = api_client.execute(:api_method => directory.users.list)
# # Fetch list of events on the user's default calandar
# result = api_client.execute(:api_method => calendar_api.events.list,
# :parameters => {'calendarId' => 'primary'},
# :authorization => user_credentials)
[result.status, {'Content-Type' => 'application/json'}, result.data.to_json]
end
Change the line to CREDENTIAL_STORE_FILE = "#{$0}-oauth2.json" and then rename the json you downloaded from the Google dashboard to client_secrets.json per convention. CREDENTIAL_STORE_FILE is where your OAuth tokens get stored and is created by the FileStorage instance.
I am trying to implement a request-response pattern using the em-zeromq gem, but I can't get the response socket to send a message back to the request socket in its handler. I have written some very simple code to test it:
em_req.rb
require 'em-zeromq'
client_id = ARGV[0] ? ARGV[0].to_i : 1
message = ARGV[1] || "Foo"
Thread.abort_on_exception = true
class ReqHandler
attr_reader :received
def on_readable(socket, messages)
messages.each do |m|
puts "Received message from server: #{m.copy_out_string}"
end
end
end
trap('INT') do
EM.stop
end
ctx = EM::ZeroMQ::Context.new(1)
EM.run do
conn = ctx.connect(ZMQ::REQ, 'tcp://127.0.0.1:9000', ReqHandler.new, identity: "client#{client_id}")
conn.socket.send_string(message)
end
em_rep.rb
require 'em-zeromq'
Thread.abort_on_exception = true
class ResponseHandler
attr_reader :received
def on_readable(socket, messages)
message = messages.first.copy_out_string
puts "Received message from client: #{message}"
socket.send_msg("re: #{message}")
end
end
trap('INT') do
EM.stop
end
ctx = EM::ZeroMQ::Context.new(1)
EM.run do
socket = ctx.bind(ZMQ::REP, 'tcp://127.0.0.1:9000', ResponseHandler.new)
end
I have written similar code using the push-pull pattern and got that to work, but for request-response all I get is the response code printing "Received message from client1: Foo" but the reply never reaches the request code. I suspect it has to do with writing to the socket in the response code's handler, because the same thing happens when I use a request-router pattern. The only time it works is when I send a message from the server without sending a message from the client first (using push-pull).
Any ideas about what might be causing this? The author of the gem isn't maintaining it anymore, but I thought I would post this issue anyway in the hopes of other developers with similar experiences seeing this.
I am using em-zeromq 0.2.2 on Ruby 1.9.2p290.
I commmited a fix in the master branch which should solve your problem, can you give it a try ?
You can use bundler to easily test it:
Create a file called Gemfile in your application folder:
source :rubygems
gem 'em-zeromq', :git => "git://github.com/andrewvc/em-zeromq.git"
And add this on top of your ruby files:
require 'rubygems'
require 'bundler/setup'
And last run this in the application folder ($ is your prompt):
$ bundle
Now you can execute your ruby files they will use the latest code from github
Edit: I am the new maintainer for the em-zeromq gem.