PayPal IPN not connecting with canceling recurring billing - ruby-on-rails

I need help to understand how to mark user as cancelled in my database when the user cancels the recurring payment via PayPal.
Notifications controller:
def create
params.permit! # Permit all Paypal input params
#query = params
puts "in method*************************************"
#query[:cmd] = "_notify-validate"
#if params[:txn_type] == 'subscr_cancel'
# user_subscription = Subscription.find_by(paypal_customer_token: params[:payer_id])
# user_subscription.update_column("cancelled",1) if user_subscription.present?
#els
if params[:txn_type] == 'recurring_payment_profile_cancel'
user_subscription = Subscription.find_by(paypal_recurring_profile_token: params[:recurring_payment_id])
user_subscription.update_column("cancelled",1) if user_subscription.present?
end
render :text => 'OK'
end
end

Hm,, I think you have to uncommend the lines you have commented,, somehting like this:
if params[:txn_type] == 'subscr_cancel'
user_subscription = Subscription.find_by(paypal_customer_token: params[:payer_id])
user_subscription.update_column("cancelled",1) if user_subscription.present?
end
I'm using php api and have this 'subscr_cancel' when user cancels subscription

Related

Limit requests that users can send to 3 every 30 days. Ruby on Rails

I am learning to program and I am trying with Ruby on rails. I would like to restrict one functionality that allows users to send me introduction requests (3 introduction request per 30 days). I am not sure if I have to create a method first, for example:
def month
where("created_at <?", Date.today - 30.days))
end
I don't know if that method is correct and if I can integrate it within this piece of code:
def create
#introduction = CompanyIntroduction.create(intro_params)
if current_user #Admin can edit the user name and email
#introduction.user = current_user
#introduction.user_name = current_user.full_name
#introduction.user_email = current_user.email
end
if #introduction.save
flash[:success] = "Thank you. Your request is being reviewed by TechIreland."
else
flash[:error] = #introduction.errors.full_messages
end
redirect_back(fallback_location: user_companies_path)
end
You're close. You have the time comparison backwards though, and the method (assuming it's on your model) should be a class method or a scope.
scope :in_the_last_month, -> { where('created_at > ?', Date.today - 30.days) }
# or more elegantly
scope :in_the_last_month, -> { where(created_at: 30.days.ago..) }
Then in the controller you can check how many requests were made recently.
if CompanyIntroduction.in_the_last_month.count >= 3
# give some error
else
# continue
end
This code is simple enough that you don't actually need to make it into a method, just the code in the controller is probably fine.
if CompanyIntroduction.where(created_at: 30.days.ago..).count >= 3

How to refactor this code to make it more readable and efficient?

I need help refactoring the code.I ve tried by best landed with the following code. Is there anything That I can do
class OrdersController < ApplicationController
before_action :get_cart
before_action :set_credit_details, only: [:create]
# process order
def create
#order = Order.new(order_params)
# Add items from cart to order's ordered_items association
#cart.ordered_items.each do |item|
#order.ordered_items << item
end
# Add shipping and tax to order total
#order.total = case params[:order][:shipping_method]
when 'ground'
(#order.taxed_total).round(2)
when 'two-day'
#order.taxed_total + (15.75).round(2)
when "overnight"
#order.taxed_total + (25).round(2)
end
# Process credit card
# Check if card is valid
if #credit_card.valid?
billing_address = {
name: "#{params[:billing_first_name]} # .
{params[:billing_last_name]}",
address1: params[:billing_address_line_1],
city: params[:billing_city], state: params[:billing_state],
country: 'US',zip: params[:billing_zip],
phone: params[:billing_phone]
}
options = { address: {}, billing_address: billing_address }
# Make the purchase through ActiveMerchant
charge_amount = (#order.total.to_f * 100).to_i
response = ActiveMerchant::Billing::AuthorizeNetGateway.new(
login: ENV["AUTHORIZE_LOGIN"],
password: ENV["AUTHORIZE_PASSWORD"]
).purchase(charge_amount, #credit_card, options)
unless response.success?
#order.errors.add(:error, "We couldn't process your credit
card")
end
else
#order.errors.add(:error, "Your credit card seems to be invalid")
flash[:error] = "There was a problem processing your order. Please try again."
render :new && return
end
#order.order_status = 'processed'
if #order.save
# get rid of cart
Cart.destroy(session[:cart_id])
# send order confirmation email
OrderMailer.order_confirmation(order_params[:billing_email], session[:order_id]).deliver
flash[:success] = "You successfully ordered!"
redirect_to confirmation_orders_path
else
flash[:error] = "There was a problem processing your order. Please try again."
render :new
end
end
private
def order_params
params.require(:order).permit!
end
def get_cart
#cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
end
def set_credit_details
# Get credit card object from ActiveMerchant
#credit_card = ActiveMerchant::Billing::CreditCard.new(
number: params[:card_info][:card_number],
month: params[:card_info][:card_expiration_month],
year: params[:card_info][:card_expiration_year],
verification_value: params[:card_info][:cvv],
first_name: params[:card_info][:card_first_name],
last_name: params[:card_info][:card_last_name],
type: get_card_type # Get the card type
)
end
def get_card_type
length, number = params[:card_info][:card_number].size, params[:card_info][:card_number]
case
when length == 15 && number =~ /^(34|37)/
"AMEX"
when length == 16 && number =~ /^6011/
"Discover"
when length == 16 && number =~ /^5[1-5]/
"MasterCard"
when (length == 13 || length == 16) && number =~ /^4/
"Visa"
else
"Unknown"
end
end
end
Products with a price attribute. We have shopping Carts that have many Products through the OrderedItems join table. An OrderedItem belongs_to a Cart and a Product. It has a quantity attribute to keep track of the number of products ordered.
The OrderedItem also belongs_to an Order
I wanted to know if it can be refactored further.
First of all you should move all that business logic from the controller into models and services (OrderProcessService, PaymentService). All the controller's private methods belong to a PaymentService.
Split the code into smaller methods.
If doing that on the model level some things that come into my mind when reading your code are the following:
#order.add_items_from_cart(#cart)
#order.add_shipping_and_tax(shipping_method)
Orders should be first saved (persisted in DB), then processed (purchased with changing their status).
#order.save might fail after a successful payment, so a client will lose the money and not get their order.
the purchasing is an important and critical process, so you should make sure everything is ready for it (the order is valid and saved)
a client should be able to purchase later or after the payment page is accidentally reloaded without filling the form again
normally when a payment is performed you should send an order ID to the payment system. The payment system will store the ID and you will always know which order the payment belongs to.
There are a lot of other things to consider. You have a lot of work to do.

Callback during sign- in process in order to change boolean to true or false

I'm using the devise gem with my app. Which callback should I use in order to pass a method from my user model during the sign in process??
Warden::Manager.after_set_user ?
before_validation?
before_save?
before_create?
Method details:
I have a boolean column:is_active in the users table.
Each time a user tries to sign in, the braintree code finds if the user has has an active or not subscription thru the braintree api. And if the user has and active or not subscription I'm trying to update the is_active column to true or false.
I'm using this currently, but it's not working:
Warden::Manager.after_set_user :scope => :user do |user, auth, opts|
customer = Braintree::Customer.find('customer_id')
customer_card = customer.payment_methods[0].token
payment_method = Braintree::PaymentMethod.find(customer_card)
sub = payment_method.subscriptions[0]
sub.status
if Braintree::Subscription::Status::Active
obj = User.find_by_id(params[:id])
obj.is_active = true
obj.save!
else
obj = User.find_by_id(params[:id])
obj.is_active = false
obj.save!
end
end
def active_for_authentication?
super && is_active?
end
def inactive_message
"User not active, please subscribe!"
end
Since Braintree::Subscription::Status::Active is merely a constant pointing to a string "Active", it's always "truthy". That means that if Braintree::Subscription::Status::Active will always be true.
You probably want to do this instead:
user.update(is_active: sub.status == Braintree::Subscription::Status::Active)
No need for that conditional or explicitly setting true or false based on the condition of the block, and you already have a User instance passed to the block so you don't need to load one from the database.

How to get multiple values of a record with map

In my application I can have multiple accounts and accounts can have multiple emails. I have a method that counts all the unique email from every account, but that is not what I want however.
Instead I want to return all the unique email from just one account NOT all, as the method is currently doing.
Here is my current method:
class AccountEmails
def self.count
accounts = Account.all
alert = accounts.map do |a|
a.users.first.alert_email.split(",")
end
billing = accounts.map do |a|
a.users.first.billing_email.split(",")
end
user = accounts.map do |a|
a.users.first.email.split(",")
end
snitch = accounts.map do |a|
a.snitches.map { |s| s.alert_email.split(",") }
end
[alert, billing, user, snitch].flatten.uniq.count
end
end
This will return all the email that are unique from all the accounts. I want to return all the unique email for each account, so account 1 could have four unique email and account 2 could have five unique email.
It sounds like you're saying you want a single method that gives you all the unique emails for each account. If I'm understanding you, I would do something like this:
class Account
def all_emails
# I'm assuming here that you actually only want the unique
# emails on the first user for each account
user = self.users.first
[
user.alert_email.split(","),
user.billing_email.split(","),
user.email.split(","),
self.snitches.map{|snitch| snitch.alert_email.split(",") }
].flatten
end
def unique_emails
all_emails.uniq
end
end
class AccountEmails
def self.unique
Account.all.includes(:snitches).map do |account|
account.uniq_emails
end
end
def self.count
uniq.flatten.count
end
end

Rails 3: loops and plucking items out best practices

I am working on a small app that allows for users to add a product (or subscription) to their cart. Upon creating their account, the new user is sent to a "bundle" page where it asks if they would like to add a different subscription to a different product altogether for a bundled price.
Here is where I am stuck: Upon submitting the user's credit card info I get slightly "lost in translation" when trying to setup the bundle pricing to submit to Authorize.net (I understand how to authnet, not the question here).
Here is what I have so far:
current_order.products.includes(:client).each do |product|
transaction = current_order.submit_order_to_authnet(product)
if transaction.result_code == 'Ok'
new_group = Group.create!(:name => "#{current_user.full_name} #{product.title}", :type => 'school', :start_date => Time.now, :status => 'active', :site_id => 1)
primary = session[:primary_product_id].eql?(product.id) ? true : false
# Add subscription to Group
new_group.add_subscription(product, current_order, transaction.subscription_id, 'active', primary)
# Add Subscription to CurrentOrder
current_order.subscriptions << new_group.subscriptions.last
# Add user to NewGroup
current_user.groups << new_group
# Create New Group Admin
new_group.group_admins.create(:user_id => current_user.id)
# Send success email
OrderMailer.checkout_confirmation(current_user).deliver
else
errors << transaction.result_code
end
end
I am trying to figure out the best solution when it comes to looping through each product in the users current_order because the second subscription in the users cart is the subscription that gets the discount applied too. I know I can write something like this:
current_order.products.includes(:client).each do |product|
if current_order.products.many? and product == current_order.products.last
# run discount logic
else
# continue with authnet for single subscription
end
end
But I am just not sure if that is a best practice or not. Thoughts?
So the only subscription that doesn't get discounted is the first one? Why not write it like this:
current_order.products.includes(:client).each do |product|
if product == current_order.products.first
# continue with authnet for single subscription
else
# run discount logic
end
end

Resources