PayPal IPN Send Email - ruby-on-rails

I have a controller that handles PayPal's IPN callback. I want to mark an attendee as 'paid' and send them a confirmation email if they've successfully paid.
The mark paid action is working but the email is not sending.
Here's my controller:
class PaymentNotificationsController < ApplicationController
protect_from_forgery :except => [:create]
def create
PaymentNotification.create!(:params => params, :attendee_id => params[:invoice], :status => params[:payment_status], :transaction_id => params[:txn_id])
if params[:payment_status] == 'Complete'
#attendee = Attendee.find(params[:invoice])
## Working
#attendee.update_attribute(:paid, Time.now)
## Not Working
UserMailer.welcome_email(#attendee).deliver
end
render nothing: true
end
end
Here's my user_mailer file:
class UserMailer < ActionMailer::Base
default from: 'example#email.com'
def welcome_email(user)
#user = user
email_with_name = "#{#user.first_name} #{#user.last_name} <#{#user.email}>"
#url = 'http://example.com'
mail(
to: email_with_name,
subject: 'Welcome to Yadda Yadda'
)
end
end
Here's the weird thing, in another controller that doesn't have PayPal the mailer works:
class VendorsController < ApplicationController
def create
#vendor = Vendor.new(vendor_params)
if #vendor.save
UserMailer.welcome_email(#vendor).deliver
redirect_to vendor_success_path
else
render 'new'
end
end
end

I am pulling your answer out of your question and posting it here for future reference.
This takes two actions (mark paid and send mail). It has been moved to the model as an after_create method.
Here's the model:
class PaymentNotification < ActiveRecord::Base
...
after_create :mark_attendee_paid
private
def mark_attendee_paid
if status == 'Completed'
attendee.update_attribute(:paid, Time.now)
UserMailer.welcome_email(attendee).deliver
end
end
end

Related

rails email notification- mailer

I'am new to rails. Users need to receive the email notification after few days only if they haven't read the notification yet. I've created the email notification with Action Mailer but it's not working after added the time format. The email still not deliver to the users after 5 days.
class NotificationsController < ApplicationController
def show
#notification = current_user.notifications.find_by_id(params[:id])
if current_user.notifications.unread > 5.days.ago
UserMailer.try_notif(#notification, #post, #user).deliver
end
end
def update
#notification = current_user.notifications.find_by_id(params[:id])
#notification.update(read: true)
redirect_to post_path(#notification.post)
end
def read_all
current_user.notifications.unread.update_all(read: true)
end
end
user_mailer.rb
class UserMailer < ApplicationMailer
def try_notif(notification, post, user)
#notification = notification
#post = post
#user = user
mail(to: #post.user.email, subject: 'New Notification')
end
end
i think correct code would be like this:
Need to check each notification with current time
if current_user.notifications.unread
current_user.notifications.each do |notification|
if Time.current - notification.created_at > 120 #just checking in hours
#send reminder
end
end
end
or can try other way
#notifications = Notification.where(created_at: 5.days.ago..Time.current, unread: true)
if #notifications
#notifications.each do |notification|
#send notification
end
end

Can't get users to create a custom message with devise invitable

I have 2 user-like models in my app: 'Participant' and 'Member'.
I'm trying to allow them to include a custom message when they invite other members/participants through Devise Invitable. However, I can't make it work.
I'm following this official tutorial so I've made the following changes to override Devise Invitable Controller but when using pry it seems that this custom controller goes untouched when sending an invite. What am I doing wrong:
controllers/participants/invitations_controller.rb
class Participants::InvitationsController < Devise::InvitationsController
before_action :update_sanitized_params, only: :update
def create
binding.pry
#from = params[:from]
#subject = params[:invite_subject]
#content = params[:invite_content]
#participant = Participant.invite!(params[:user], current_member) do |u| #XXX Check if :user should be changed
u.skip_invitation = true
end
ParticipantInvitationNotificationMailer.invite_message(#participant, #from, #subject, #content).deliver if #participant.errors.empty?
#participant.invitation_sent_at = Time.now.utc # mark invitation as delivered
if #participant.errors.empty?
flash[:notice] = "successfully sent invite to #{#participant.email}"
respond_with #participant, :location => root_path
else
render :new
end
end
def update
respond_to do |format|
format.js do
invitation_token = Devise.token_generator.digest(resource_class, :invitation_token, update_resource_params[:invitation_token])
self.resource = resource_class.where(invitation_token: invitation_token).first
resource.skip_password = true
resource.update_attributes update_resource_params.except(:invitation_token)
end
format.html do
super
end
end
end
protected
def update_sanitized_params
devise_parameter_sanitizer.permit(:accept_invitation, keys: [:password, :password_confirmation, :invitation_token, :username])
end
end
config/routes.rb
Rails.application.routes.draw do
devise_for :members, controllers: { invitations: "members/invitations" }
devise_for :participants, controllers: { invitations: "participants/invitations" }
end
models/participant.rb
class Participant < ApplicationRecord
attr_reader :raw_invitation_token
end
mailers/notification_mailer.rb
class NotificationMailer < ApplicationMailer
def invite_message(user, from, subject, content)
#user = user
#token = user.raw_invitation_token
invitation_link = accept_user_invitation_url(:invitation_token => #token)
mail(:from => from, :bcc => from, :to => #user.email, :subject => subject) do |format|
content = content.gsub '{{first_name}}', user.first_name
content = content.gsub '{{last_name}}', user.last_name
content = content.gsub '{{full_name}}', user.full_name
content = content.gsub('{{invitation_link}}', invitation_link)
format.text do
render :text => content
end
end
end
end
If I send an invitation:with Participant.invite!({:email => 'example#email.com'}, Member.first) the invitation is sent through the default mailer as shown in the console but not through my new mailer. why?
Rendering /Users/andres/.rvm/gems/ruby-2.4.0#pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb
Rendered /Users/andres/.rvm/gems/ruby-2.4.0#pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.html.erb (0.6ms)
Rendering /Users/andres/.rvm/gems/ruby-2.4.0#pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb
Rendered /Users/andres/.rvm/gems/ruby-2.4.0#pixiebob/gems/devise_invitable-1.7.1/app/views/devise/mailer/invitation_instructions.text.erb (0.8ms)
Finally, I could solve this issue.
It ended up being a rookie mistake I was thinking that calling the invite! method would have anything to do with the custom create method in the custom invitations controller.
I had of course to reach the create method through the specified route and within that method prevent the invite! method to send the email through the default mailer using code below (as established clearly in the Devise Invitable Documentation):
#participant = Participant.invite!({:email => #invitation_draft.email}, current_member) do |u|
u.skip_invitation = true
end
After this we can call any custom mailer in the create method.

Cart Checkout >> Send an Email with Cart Items included

I have an "Add To Cart" function working fine based on Sessions so no user is currently logged in.
Here's the Model
class Cart < ActiveRecord::Base
has_many :tutors
def add_tutor(tutor_id)
tutor = Tutor.find(tutor_id)
if tutor
self.tutors << tutor
end
save
end
end
Here's the Controller
class CartsController < ApplicationController
def show
#cart = current_cart
end
def add_to_cart
current_cart.add_tutor(params[:tutor_id])
redirect_to tutors_path
end
end
What i would like to do is when the user checkouts, they will be redirected to a page with a simple form requesting for their name/email/phone-number, and when that email is sent to me, it includes the items in their cart.
I am currently using gem 'mail_form' and this is what i have set-up so far.
Model checkout.rb
class Checkout < MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute :hp, :validate => true
def headers
{
:subject => "Tutor Checkout",
:to => "xxx#xxx.com"
}
end
end
Controller checkouts_controller.rb
class CheckoutsController < ApplicationController
def new
#checkout = Checkout.new
end
def create
#checkout = Checkout.new(params[:checkout])
#checkout.request = request
if #checkout.deliver
flash[:notice] = 'Thank you! We will be in touch with you shortly!'
else
flash[:error] = 'There was an error in sending your message!'
render :new
end
end
end
and under views/checkouts/new.html.erb its just a form requesting for their information.
What i really have no idea on where to start is creating the association between Carts and Checkouts and how do i even include the items in the cart to be sent along with the email?
Any help or advice would be greatly appreciated! Thank you!

Unable to access controller variables in model

I have following controller
class PaypalOrdersController < Spree::BaseController
def new
#paypal_order = PaypalOrder.new
end
def create
#order1 = current_order
#paypal_order = PaypalOrder.new(params[:paypal_order])
if #paypal_order.save
if #paypal_order.purchase
render :action => "success"
else
render :action => "failure"
end
else
render :action => "new"
end
end
end
and the corresponding model is:
class PaypalOrder < ActiveRecord::Base
require 'paypal_payment'
belongs_to :order
attr_accessor :card_number, :card_verification
validate :validate_card, :on => :create
def purchase
orderHash = #order1.clone
paypalHash = #paypal_order.clone
PaypalPayment.new(orderHash, paypalHash)
end
private
def validate_card
#some code
end
def credit_card
#some code
end
end
When the purchase method is triggered I'm getting the error cannot clone nil class. On debugging I found that #order1 and #paypal_order both are nil in the purchase method. I am not sure why this is happening. Please can someone explain.
Thanks
controller:
PaypalOrder.purchase #order1, #paypal_order
model:
def self.purchase order, paypal_order
orderHash = order.clone
paypalHash = paypal_order.clone
PaypalPayment.new(orderHash, paypalHash)
end
edit:
How do you pass data from a controller to a model with Ruby on Rails?
Try this
controller
if #paypal_order.purchase #order1
model
def purchase order1
orderHash = order1.clone
paypalHash = self.clone
PaypalPayment.new(orderHash, paypalHash)
end

REST API Help in Rails

I am trying to get some information posted using our accountancy package (FreeAgentCentral) using their API via a GEM.
http://github.com/aaronrussell/freeagent_api/
I have the following code to get it working (supposedly):
Kase Controller
def create
#kase = Kase.new(params[:kase])
#company = Company.find(params[:kase][:company_id])
#kase = #company.kases.create!(params[:kase])
respond_to do |format|
if #kase.save
UserMailer.deliver_makeakase("dropbox#12808311.macandco.highrisehq.com", "Highrise", #kase)
#kase.create_freeagent_project(current_user)
#flash[:notice] = 'Case was successfully created.'
flash[:notice] = fading_flash_message("Case was successfully created & sent to Highrise.", 5)
format.html { redirect_to(#kase) }
format.xml { render :xml => #kase, :status => :created, :location => #kase }
else
format.html { render :action => "new" }
format.xml { render :xml => #kase.errors, :status => :unprocessable_entity }
end
end
end
To save you looking through, the important part is:
#kase.create_freeagent_project(current_user)
Kase Model
# FreeAgent API Project Create
# Required attribues
# :contact_id
# :name
# :payment_term_in_days
# :billing_basis # must be 1, 7, 7.5, or 8
# :budget_units # must be Hours, Days, or Monetary
# :status # must be Active or Completed
def create_freeagent_project(current_user)
p = Freeagent::Project.create(
:contact_id => 0,
:name => "#{jobno} - #{highrisesubject}",
:payment_terms_in_days => 5,
:billing_basis => 1,
:budget_units => 'Hours',
:status => 'Active'
)
user = Freeagent::User.find_by_email(current_user.email)
Freeagent::Timeslip.create(
:project_id => p.id,
:user_id => user.id,
:hours => 1,
:new_task => 'Setup',
:dated_on => Time.now
)
end
lib/freeagent_api.rb
require 'rubygems'
gem 'activeresource', '< 3.0.0.beta1'
require 'active_resource'
module Freeagent
class << self
def authenticate(options)
Base.authenticate(options)
end
end
class Error < StandardError; end
class Base < ActiveResource::Base
def self.authenticate(options)
self.site = "https://#{options[:domain]}"
self.user = options[:username]
self.password = options[:password]
end
end
# Company
class Company
def self.invoice_timeline
InvoiceTimeline.find :all, :from => '/company/invoice_timeline.xml'
end
def self.tax_timeline
TaxTimeline.find :all, :from => '/company/tax_timeline.xml'
end
end
class InvoiceTimeline < Base
self.prefix = '/company/'
end
class TaxTimeline < Base
self.prefix = '/company/'
end
# Contacts
class Contact < Base
end
# Projects
class Project < Base
def invoices
Invoice.find :all, :from => "/projects/#{id}/invoices.xml"
end
def timeslips
Timeslip.find :all, :from => "/projects/#{id}/timeslips.xml"
end
end
# Tasks - Complete
class Task < Base
self.prefix = '/projects/:project_id/'
end
# Invoices - Complete
class Invoice < Base
def mark_as_draft
connection.put("/invoices/#{id}/mark_as_draft.xml", encode, self.class.headers).tap do |response|
load_attributes_from_response(response)
end
end
def mark_as_sent
connection.put("/invoices/#{id}/mark_as_sent.xml", encode, self.class.headers).tap do |response|
load_attributes_from_response(response)
end
end
def mark_as_cancelled
connection.put("/invoices/#{id}/mark_as_cancelled.xml", encode, self.class.headers).tap do |response|
load_attributes_from_response(response)
end
end
end
# Invoice items - Complete
class InvoiceItem < Base
self.prefix = '/invoices/:invoice_id/'
end
# Timeslips
class Timeslip < Base
def self.find(*arguments)
scope = arguments.slice!(0)
options = arguments.slice!(0) || {}
if options[:params] && options[:params][:from] && options[:params][:to]
options[:params][:view] = options[:params][:from]+'_'+options[:params][:to]
options[:params].delete(:from)
options[:params].delete(:to)
end
case scope
when :all then find_every(options)
when :first then find_every(options).first
when :last then find_every(options).last
when :one then find_one(options)
else find_single(scope, options)
end
end
end
# Users
class User < Base
self.prefix = '/company/'
def self.find_by_email(email)
users = User.find :all
users.each do |u|
u.email == email ? (return u) : next
end
raise Error, "No user matches that email!"
end
end
end
config/initializers/freeagent.rb
Freeagent.authenticate({
:domain => 'XXXXX.freeagentcentral.com',
:username => 'XXXX#XXXXXXX.co.uk',
:password => 'XXXXXX'
})
The above render the following error when trying to create a new Case and send the details to FreeAgent:
ActiveResource::ResourceNotFound in KasesController#create
Failed with 404 Not Found
and
ActiveResource::ResourceNotFound (Failed with 404 Not Found):
app/models/kase.rb:56:in `create_freeagent_project'
app/controllers/kases_controller.rb:96:in `create'
app/controllers/kases_controller.rb:93:in `create'
Rendered rescues/_trace (176.5ms)
Rendered rescues/_request_and_response (1.1ms)
Rendering rescues/layout (internal_server_error)
If anyone can shed any light on this problem it would be greatly appreciated!
Thanks,
Danny
How are you calling create? With a normal restful create action it would be with a POST from a form or something, but 404s are generally rendered from a failed GET action, where an ActiveRecord find fails to locate a record with a specific id. My best guess is that you're calling create with a GET, and that the line
user = Freeagent::User.find_by_email(current_user.email)
simply cannot locate a user with that email, and so is throwing the ResourceNotFound exception.
Additionally, this bit of code is confusing to me:
#kase = Kase.new(params[:kase])
#company = Company.find(params[:kase][:company_id])
#kase = #company.kases.create!(params[:kase])
respond_to do |format|
if #kase.save
Why are you creating #kase twice here, once with Kase.new and once with kases.create? Also, note that the line:
if #kase.save
will always evaluate true, because the line:
#company.kases.create!(params[:kase])
would have thrown an exception if it were false, which is another way of saying that #kase.save is redundant because create! would have already persisted the new Kase record.
EDIT: What I think you meant to do was:
# this line can go #kase = Kase.new(params[:kase])
#company = Company.find(params[:kase][:company_id])
#kase = #company.kases.build(params[:kase])
EDIT: You probably want a new action like this:
def new
#kase = Kase.new # no params here
end
The 'new' erb template will have a form_for something like:
<% form_for #kase do |k| %>
etc. That form will by default post the params from the form to the create action, assuming you've set up something like resources :kase in your routes. That should get you started. Follow the standard tutorials like you're doing and things should get simpler as you go.

Resources