Ticket Dispenser : Array in memory? - ruby-on-rails

I have a ticket dispenser.
It is non efficient. 3300 ms response.
It was previously implemented with a ticker (counter.increment!) which brought problems dealing with concurrency.
It is currently implemented as array.shift.
ticket_roll = [1, 2, 3, 4, 5]
ticket = ticket_roll.shift
Any user can grab a ticket.
The first one to hit the array gets the ticket.
controller
def create
#movie = Movie.find_by(movie: params[:movie])
ticket_roll = TicketRoll.find(1).ticket_roll
#ticket = ticket_roll.shift
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:card => params[:stripeToken],
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => 1500,
)
if charge["paid"]
#movie.update_attributes(status: "sold", email: params[:stripeEmail],
first_name: params[:first_name], last_name: params[:last_name])
Pusher['the_channel'].trigger('the_event', {message: ticket_roll[0]})
else
ticket_roll.unshift(#ticket)
end
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
Can I store the ticket_roll array in memory/cache so that each user does not = a full DB query ?

As you already mentioned having all the tickets in the memory is inefficient and simply using increment! poses concurrency issues. One basic solution to that is to use locks when updating a record.
An example from the guide:
Item.transaction do
i = Item.lock.first
i.name = 'Jones'
i.save
end
In your case you only need to have the number of latest ticket in DB. Before giving out a new ticket number you should lock the record, increment the value and release the lock.

Related

Braintree—how do I get the last_4 credit card details from a transaction OR subscription

From the result of a Transaction.sale() OR a Subscription.create(), how do I access the credit card details in the payment?
I have the following methods:
def bt_make_customer(donation, nonce)
result = Braintree::Customer.create(
first_name: donation.user.first_name,
last_name: donation.user.last_name,
email: donation.user.email,
payment_method_nonce: nonce
)
end
def bt_make_payment(donation, customer, nonce)
if donation.type == "ReoccurringDonation"
result = Braintree::Subscription.create(
payment_method_token: customer.payment_methods[0].token,
price: donation.amount,
plan_id: "pay-monthly"
)
elsif donation.type == "SingleDonation"
result = Braintree::Transaction.sale(
:amount => donation.amount,
:payment_method_nonce => nonce,
:options => {:submit_for_settlement => true}
)
end
end
As you can see, the program accepts one-time donations, or monthly subscriptions. When either is made, I want to get the credit card details such as last_4 to display in a custom receipt.
You can call
result.last_4
for getting The last 4 digits of the credit card number.
For more help visit here
To access the credit card fields, you need to type
result.transaction.credit_card_details.{field you want}
You can pause the program with byebug after the transaction, and type result.inspect in your console to see what fields the result contains.

Rails - Stripe::InvalidRequestError (Must provide source or customer.)

I'm building an application (based in online resource). You can sign up or login with devise. Then, you can buy a product. Or make your own list and sell your products.
I'm integrating Stripe. When I create the Charge, I get this error in the console: Stripe::InvalidRequestError (Must provide source or customer.).
Here is the code of the orders_controller.rb for the charge action:
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
begin
charge = Stripe::Charge.create(
:amount => (#listing.price * 100).floor,
:currency => "usd",
:card => token
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
Of course I'm taking a look in the Stripe API Documentation here: Charge documentation example and here: Charge full API Reference
I'm not sure how to handle the :resource or customer. I saw in other materials in the web that some people create a customer. In other sites it says that the :card is deprecated, so I'm a little confused.
I will leave the github repository of my project, and feel free to take a look. I'm trying to deal with Transfers and Recipients too. Project Repository
Thanks.
As mentioned in the docs, stripe expects either customer or source to be mentioned while creating a charge. So, you either need to
Create a customer on stripe(if you want to charge that customer in future too) from the token you received, and mention that customer while creating a charge,
customer = Stripe::Customer.create(source: params[:stripeToken])
charge = Stripe::Charge.create({
:amount => 400,
:currency => "usd",
:customer => customer.id,
:description => "Charge for test#example.com"
})
Or, if you don't want to create a customer, then directly mention received token as a source,
Stripe::Charge.create({
:amount => 400,
:currency => "usd",
:source => params[:stripeToken],
:description => "Charge for test#example.com"
})
For anyone going through the Stripe docs, you may have something like this (using an existing account)
account_links = Stripe::AccountLink.create({
account: 'acct_1032D82eZvKYlo2C',
refresh_url: 'https://example.com/reauth',
return_url: 'https://example.com/return',
type: 'account_onboarding',
})
if so, just change it to look like this (i.e. include the actual account.id you created in the previous step):
account_links = Stripe::AccountLink.create({
account: account.id,
refresh_url: 'https://example.com/reauth',
return_url: 'https://example.com/return',
type: 'account_onboarding',
})

Rails & Stripe - Stock shipping address in a var, in the ChargesController

with Stripe on Rails 4, I want to stock the shipping address of my customer in a variable #testvar, in my ChargesController, so I can :
- Display it in the charges#create page, as a "Here is where we will deliver"
- Send an email to the admin with this info.
Here is my ChargesController : (UPDATED 3rd April)
class ChargesController < ApplicationController
def new
end
def create
admin = Admin.last
customer = Stripe::Customer.create(
email: params[:stripeEmail],
card: params[:stripeToken],
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:currency => 'eur',
:receipt_email => params[:stripeEmail],
)
customer_name = charge["name"]
AdminMailer.outfit_ordered(admin, customer_name).deliver_now
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to :back
end
end
UPDATE 3rd April
I've added a mailer, hence the two following line
customer_name = charge["name"]
AdminMailer.outfit_ordered(admin, customer_name).deliver_now
I've found the following part in another aswer, but I can't get it to work.
stripe_customer_params = JSON.parse customer.to_s
#testvar = stripe_customer_params['cards']['data'].first['shipping_address']
Furthermore, when I assign a random value to my #testvar (like #testvar = "test") and display it in my charges#create view, it works... But #testvar keeps this value with the other tests I run after that.
I am stuck with this problem and can't find anything that helps me in the Stripe's API documentation.
Thanks for your help.

Stripe charge and Subscription

I have a rails 4 app that I'm using Stripe checkout. I've followed their tutorial, and my controller looks like:
def create
s = Subscription.new
s.user_id = current_user.id
s.plan_id = params[:plan_id]
s.stripe_token = params[:stripeToken]
s.save
# Amount in cents
#amount = 699
customer = Stripe::Customer.create(
:email => current_user.email,
:card => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'Sitekite Pro',
:currency => 'usd'
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
I looked at a couple other tutorials, looking for help with creating a subscription with Stripe checkout. Some of them dont have the Stripe::Charge part. Is the Stripe::Charge part only for single charges? How do I sign the user up for a monthly subscription with the same #amount?
The Stripe::Charge is indeed for single charges. The Customer create is what you need, but when you create the customer you specify a plan (plans are defined in your Stripe dashboard). The plan will specify the amount to charge and how often to charge it.
When the charge is actually made, which might be the same day or might be several days later depending on whether your plan provides, say, some free access time... the Stripe service can send the charge to a webhook... which is to say a route in your project for the dedicated use of the Stripe service.
Stripe will post charges (and failures) to your webhook, and you can handle them appropriately (logging the payments and maybe restricting the user if his card becomes expired or a regular payment fails for some other reason)

Rails 4 - ActiveMerchant Paypal Express Checkout Issue with Passing Item Quantity

I have a weird issue with the PayPal express checkout. When I pass in an options[:item][:quantity], I get an error code from PayPal that the transaction in invalid.
#controllers/orders_controller.rb
def express
options = {
:ip => request.remote_ip,
:return_url => new_order_url,
:cancel_return_url => products_url,
:items => current_cart.line_items_hash
}
response = EXPRESS_GATEWAY.setup_purchase(current_cart.build_order.price_in_cents,
options)
redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end
# models/cart.rb
def line_items_hash
self.line_items.map do |line_item|
{
:name => Product.find(line_item.product_id).name
# :quantity => line_item.quantity,
:description => line_item.product.description,
:amount => line_item.gross_price_in_cents}
end
end
So this works fine. The problem is that the correct quantity is not shown on the PayPal order confirmation page. However, if I uncomment the quantity variable in the line_items_hash function the whole thing breaks and I get "invalid transaction from paypal". Any ideas?
Silly old me. Paypal keeps invalidating my transaction because I'm passing bad information. I was setting the amount to line_item total which is already the total of quantity * product.price. So the information that Paypal was receiving is quantity * (quantity * product.price).
Silly little mistake but I managed to catch it in the end.
# models/cart.rb
def line_items_hash
self.line_items.map do |line_item|
{
:name => Product.find(line_item.product_id).name
:quantity => line_item.quantity,
:description => line_item.product.description,
:amount => line_item.price.in_cents}
end
end

Resources