Uninitialized constant ActiveMerchant - ruby-on-rails

In rails i'm getting the error uninitialized constant CartController::EXPRESS_CHECKOUT while i'm calling the method express_checkout of the controller CartController, i think that the problem is in config/environments/development.rb file, because i defined
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :test
paypal_options = {
login: "<mail>",
password: "<pass>",
signature: "<sig>"
}
::EXPRESS_GATEWAY =
ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end
But even if i tried to change something in this file, i can't fix this error.
This is the code of cart_controller.rb
def express_checkout
response = EXPRESS_GATEWAY.setup_purchase(params[:amount], ip: request.remote_ip, return_url: "http://localhost:8080/checkout_details", cancel_return_url: "http://localhost:8080", currency: "EUR", allow_guest_checkout: true, items: [{name: "Order", description: "Order description", quantity: "1", amount: params[:amount]}]
)
redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end
def checkout_details
#token = params[:token]
#payer_id = params[:PayerID]
#details = EXPRESS_GATEWAY.details_for(#token)
end
def purchase
#t = params[:token]
#p = params[:PayerID]
#result = EXPRESS_GATEWAY.purchase(params[:amount], {:token => #t, :payer_id => #p, :currency => "EUR"})
end
I checked the version of the gem activemerchant and is version 1.66.0, so the version of this gem is not a problem.
Anyone knows something about this?

As Tobias suggested me, i corrected the mistake in CartController.rb, modifying EXPRESS_GATEWAY in ::EXPRESS_GATEWAY. After this change, i restarted the rails server and everything works perfectly!

Related

Rails class gives NoMethodError undefined method `each'

I'm working with redmine and I've installed a plugin for managing mails.
When I try to send a mail I obtain the following error
[ActiveJob] [ActionMailer::DeliveryJob] [uuid] Error performing ActionMailer::DeliveryJob (Job ID: uuid) from Async(mailers) in 41.81ms: NoMethodError (undefined method `each' for #<User:id>):
This is the file that gives me the error
module EncryptMails
def self.included(base) # :nodoc:
base.send(:include, InstanceMethods)
base.class_eval do
alias_method :mail_without_relocation, :mail
alias_method :mail, :mail_with_relocation
end
end
module InstanceMethods
# action names to be processed by this plugin
def actions
[
'attachments_added',
'document_added',
'issue_add',
'issue_edit',
'message_posted',
'news_added',
'news_comment_added',
'wiki_content_added',
'wiki_content_updated'
]
end
# dispatched mail method
def mail_with_relocation(headers={}, &block)
# pass unchanged, if action does not match or plugin is inactive
act = Setting.plugin_openpgp['activation']
return mail_without_relocation(headers, &block) if
act == 'none' or not actions.include? #_action_name or
(act == 'project' and not project.try('module_enabled?', 'openpgp'))
# relocate recipients
recipients = relocate_recipients(headers)
header = #_message.header.to_s
# render and deliver encrypted mail
reset(header)
m = mail_without_relocation prepare_headers(
headers, recipients[:encrypted], encrypt = true, sign = true
) do |format|
format.text
end
m.deliver
# render and deliver filtered mail
reset(header)
tpl = #_action_name + '.filtered'
m = mail_without_relocation prepare_headers(
headers, recipients[:filtered], encrypt = false, sign = true
) do |format|
format.text { render tpl }
format.html { render tpl } unless Setting.plain_text_mail?
end
m.deliver
# render unchanged mail (deliverd by calling method)
reset(header)
m = mail_without_relocation prepare_headers(
headers, recipients[:unchanged], encrypt = false, sign = false
) do |format|
format.text
format.html unless Setting.plain_text_mail?
end
m
end
# get project dependent on action and object
def project
case #_action_name
when 'attachments_added'
#attachments.first.project
when 'document_added'
#document.project
when 'issue_add', 'issue_edit'
#issue.project
when 'message_posted'
#message.project
when 'news_added', 'news_comment_added'
#news.project
when 'wiki_content_added', 'wiki_content_updated'
#wiki_content.project
else
nil
end
end
# relocates reciepients (to, cc) of message
def relocate_recipients(headers)
# hash to be returned
recipients = {
:encrypted => {:to => [], :cc => []},
:blocked => {:to => [], :cc => []},
:filtered => {:to => [], :cc => []},
:unchanged => {:to => [], :cc => []},
:lost => {:to => [], :cc => []}
}
# relocation of reciepients
[:to, :cc].each do |field|
headers[field].each do |user|
# encrypted
unless Pgpkey.find_by(user_id: user.id).nil?
recipients[:encrypted][field].push user and next
end
# unencrypted
case Setting.plugin_openpgp['unencrypted_mails']
when 'blocked'
recipients[:blocked][field].push user
when 'filtered'
recipients[:filtered][field].push user
when 'unchanged'
recipients[:unchanged][field].push user
else
recipients[:lost][field].push user
end
end unless headers[field].blank?
end
recipients
end
# resets the mail for sending mails multiple times
def reset(header)
#_mail_was_called = false
#_message = Mail.new
#_message.header header
end
# prepares the headers for different configurations
def prepare_headers(headers, recipients, encrypt, sign)
h = headers.deep_dup
# headers for recipients
h[:to] = recipients[:to]
h[:cc] = recipients[:cc]
# headers for gpg
h[:gpg] = {
encrypt: false,
sign: false
}
# headers for encryption
if encrypt
h[:gpg][:encrypt] = true
# add pgp keys for emails
h[:gpg][:keys] = {}
[:to, :cc].each do |field|
h[field].each do |user|
user_key = Pgpkey.find_by user_id: user.id
unless user_key.nil?
h[:gpg][:keys][user.mail] = user_key.fpr
end
end unless h[field].blank?
end
end
# headers for signature
if sign
server_key = Pgpkey.find_by(:user_id => 0)
unless server_key.nil?
h[:gpg][:sign] = true
h[:gpg][:sign_as] = Setting['mail_from']
h[:gpg][:password] = server_key.secret
end
end
h
end
end
end
The stack of the log tells me that the error is in row 109
# relocation of reciepients
[:to, :cc].each do |field|
I'm not an expert of ruby and rails but I've seen that each is a method of a Ruby array, not a custom one, so I don't understand why I obtain the error.
What I am doing wrong and how can I fix this error?
Are you sure the problem isn't on this line?
h[field].each do |user|
The field there would be :to or :cc so h[field] could be a User instance.
If you want to allow h[:to] or h[:cc] to be a single User or an array of Users, then wrap it in Array():
# relocation of reciepients
[:to, :cc].each do |field|
Array(headers[field]).each do |user|
#^^^^
I'd also move that trailing unless so it doesn't get missed, maybe something like this:
%i[to cc].select { |field| headers[field].present? }.each do |field|
Array(headers[filed]).each do |user|
#...
end
end

WebMock stub data from Aws CognitoIdentityProvider

I have the following module in a Rails controller concern:
module AwsAuth
extend ActiveSupport::Concern
require 'aws-sdk'
def get_cognito_user(token)
cognitoidentityprovider = Aws::CognitoIdentityProvider::Client.new(region: ENV['AWS_REGION'])
begin
cognito_user = cognitoidentityprovider.get_user({ access_token: token })
puts cognito_user
return {"email" => cognito_user.username}
rescue StandardError => msg
puts "ERROR!"
puts msg
return {"error" => msg}
end
end
end
At the moment, puts cognito_user returns:
#<Aws::CognitoIdentityProvider::Types::GetUserResponse:0x7fe51b0013a8
mfa_options = nil,
user_attributes = nil,
username = nil
>
How can I stud the response in Rspec so that username and user_attributes are not nil ?
after playing around with yzalavin's suggestion... the following works for me...
allow_any_instance_of( AwsAuth )
.to receive(:get_cognito_user)
.and_return( JSON[ {email: "testy#example.com"}.to_json ] )

Active Merchant paypal recurring payments

I am using Active Merchant gem to handle payments through the site. But now i want to make these payments recurring, on a monthly basis. Is there a way using active merchant or?
subscription_controller.rb
class SubscriptionsController < ApplicationController
def new
#home_page = true
#white = true
#subscription = Subscription.new(token: params[:token])
if !logged_in?
redirect_to signup_url
end
end
def create
#subscription = Subscription.new(subscription_params)
#subscription.remote_ip = request.remote_ip
#subscription.user_id = current_user.id
if #subscription.save
if #subscription.purchase
#subscription.send_thank_you_email
redirect_to thankyou_path
else
raise ActiveRecord::Rollback
flash[:notice] = "It seems something went wrong with the paypal transaction. Please check that your credit card is valid and has credit in it and try again."
redirect_to :back
end
else
flash[:notice] = "Something went wrong with marking your purchase as complete. Please contact support to check it out."
redirect_to :back
end
end
def purchase
response = GATEWAY.setup_purchase(999,
ip: request.remote_ip,
return_url: new_subscription_url,
cancel_return_url: root_url,
currency: "USD",
items: [{name: "Order", description: "Recurring payment for ******", quantity: "1", amount: 999}]
)
redirect_to GATEWAY.redirect_url_for(response.token)
end
def thank_you
#home_page = true
#white = true
end
private
def subscription_params
params.require(:subscription).permit(:token)
end
end
subscription.rb model
def purchase
response = GATEWAY.purchase(999, express_purchase_options)
response.success?
end
def token=(token)
self[:token] = token
if new_record? && !token.blank?
# you can dump details var if you need more info from buyer
details = GATEWAY.details_for(token)
puts details.params["PayerInfo"]["PayerName"].inspect
self.payer_id = details.payer_id
self.first_name = details.params["PayerInfo"]["PayerName"]["FirstName"]
self.last_name = details.params["PayerInfo"]["PayerName"]["LastName"]
end
end
# send thank you email
def send_thank_you_email
UserMailer.thank_you(self).deliver_now
end
private
def express_purchase_options
{
:ip => remote_ip,
:token => token,
:payer_id => payer_id
}
end
production.rb environment
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :production
::GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(
:login => ENV['PAYPAL_LOGIN'],
:password => ENV['PAYPAL_PASSWORD'],
:signature => ENV['PAYPAL_SIGNATURE']
)
end
I think ActiveMerchant used to have something like this:
subscription = PAYPAL_EXPRESS_GATEWAY.recurring(#subscription.price_in_cents, nil,
:description => 'blah',
:start_date => Date.tomorrow,
:period => 'Year',
:frequency => 1,
:amount => price,
:currency => 'USD'
)
See this answer Does ActiveMerchant support Subscription Based transaction
Also see this: https://github.com/activemerchant/active_merchant/blob/master/lib/active_merchant/billing/gateways/paypal_express.rb
https://github.com/activemerchant/active_merchant/blob/master/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb

How to send email to user after payment is done with paypal

I want to sent email to user after transcation done. now paypal is working fine for me, but user is not getting mail notification after transcation done? how to get email notification for user .
Here is my code
This is my controller code
This is my paypal function
def pay
if #order.update order_params
#order.update_attributes(:invoice_id => rand.to_s[2..11])
if current_user.billing_address.blank?
current_user.create_billing_address(#order.billing_address.dup.attributes)
end
if current_user.shipping_address.blank?
current_user.create_shipping_address(#order.shipping_address.dup.attributes)
end
# #cart.calculate_shipping
if #order.total == 0
return redirect_to checkout_thank_you_path
end
# if !params['payment'].present?
# return redirect_to :back, notice: 'Select Payment Gateway!'
# end
# if params['payment']=='paypal'
#order.order_statuses.create(status_type: 1)
item_details=[]
#order.line_items.each do |item|
item_details << {:name => item.title, :quantity => item.quantity, :amount => item.amount.fractional}
end
logger.info item_details.inspect
response = EXPRESS_GATEWAY.setup_purchase(#cart.total.fractional,
:ip => request.remote_ip,
:currency =>"USD",
:items => item_details,
:order_id => #order.invoice_id,
:return_url => checkout_thank_you_url,
:cancel_return_url => cart_url
)
return redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
# else
# return redirect_to 'https://www.payumoney.com/'
# end
else
flash[:alert] = 'Billing and shipping address fields are required!'
render :addresses
end
end
This is my thank function for paypal
def thank_you
#order = Order.find(session[:order_id])
details = EXPRESS_GATEWAY.details_for(params[:token])
response = EXPRESS_GATEWAY.purchase(#cart.total.fractional, {
ip: request.remote_ip,
token: params[:token],
payer_id: details.payer_id,
items: #order.line_items.map{|l| {name: l.title, quantity: l.quantity, amount: l.amount.fractional}}
})
if response.success?
# logger.info payment_params.inspect
payment_params = {gateway: 'PayPal Express Checkout', transaction_id: response.params['token'], ip: request.remote_ip, amount: response.params['gross_amount']}
#cart.order.created_at = DateTime.now
#cart.order.status = 'Paid'
#cart.order.save
session.delete :order_id
# OrderMailer.order_confirmation(#order).deliver
# OrderMailer.admin_receipt(#order).deliver
else
redirect_to :cart_checkout, alert: 'Something went wrong. Please try again. If the problem persists, please contact us.'
end
#cart = Cart.new current_or_null_user.id, session[:order_id], session[:currency] # Start a new cart
end
Any help is appreciatable

Solution to AbstractController::DoubleRenderError

I've built a volunteer tracking application with a phone-text user interface using the Twilio API. I don't need a view so my controller contains this code:
class TwilioController < ApplicationController
include TwilioHelper
def sms_receive
user = User.find_or_create_by(phone_number: params[:From])
text = Text.create(user_id: user.id, body: params[:Body].capitalize, date: DateTime.now)
activity_log = ActivityLog.new(user_id: user.id, phone_number: "xxx-xxx-#{user.last_four_digits}", text_id: text.id)
args = {user: user, text: text, activity_log: activity_log, options: params}
volunteer_manager = VolunteerHandler.new(args)
replies = volunteer_manager.process
replies.each {|reply| text_response(reply, args[:options])}
end
def text_response(reply, args)
account_sid = ENV['ACCOUNT_SID']
auth_token = ENV['AUTH_TOKEN']
client = Twilio::REST::Client.new account_sid, auth_token
client.account.messages.create(:body => reply, :to => args[:From], :from => args[:To])
render nothing: true and return
end
end
A user will send a multi command string (i.e. 'In with American Red Cross'). In this case two commands will execute 'In' and 'with American Red Cross'. These commands return an array of strings such as ['Thank you for volunteering', 'Would you like the American Red Cross to keep in contact with you for future volunteering opportunities?']. This array is what local variable replies points to.
If I take off the render nothing:true and return code then I get the error: ActionView::MissingTemplate Missing template twilio/sms_receive
I can create the unnecessary view and solve my problem, but this doesn't seem like the best solution.
Any and all help is greatly appreciated. Thank you.
As replies is an array which is iterating over text_response its executing render nothing: true and return multiple times, which is cause of error you are facing.
Try getting render statement out of the loop.
class TwilioController < ApplicationController
include TwilioHelper
def sms_receive
user = User.find_or_create_by(phone_number: params[:From])
text = Text.create(user_id: user.id, body: params[:Body].capitalize, date: DateTime.now)
activity_log = ActivityLog.new(user_id: user.id, phone_number: "xxx-xxx-#{user.last_four_digits}", text_id: text.id)
args = {user: user, text: text, activity_log: activity_log, options: params}
volunteer_manager = VolunteerHandler.new(args)
replies = volunteer_manager.process
replies.each {|reply| text_response(reply, args[:options])}
render nothing: true and return
end
def text_response(reply, args)
account_sid = ENV['ACCOUNT_SID']
auth_token = ENV['AUTH_TOKEN']
client = Twilio::REST::Client.new account_sid, auth_token
client.account.messages.create(:body => reply, :to => args[:From], :from => args[:To])
end
end

Resources