I am trying to implement PaypalExpressCheckout in my e-commerce application which is built on Rails3.
There will be two roles in the application - Seller and Buyer
Seller can create products and he can add his valid Paypal Email address to get amount on behalf of his sold products.
Buyer able to purchase items and can checkout through Paypal, amount shall transfer to the seller account once the user transaction is successful.
The issue I'm facing here, when buyer checking out, the amount is successfully transfer to the seller account but not deducting same from the buyer account.
I configured API credentials from Paypal sandbox and here are the methods I'm using from ActiveMerchant gem:
From Controller:
def checkout
values = {:ip => request.remote_ip,
:return_url => confirm_paypal_url(#payment),
:cancel_return_url => root_url, :shipping => 0,
:handling => 0, :tax => 0,
:items => get_items(session[:cart])}
response = #payment.setup_purchase(values)
redirect_to #payment.redirect_url_for(response.token)
end
## CALL BACK
def paypal
# session[:product_users] = [{:amount => '100', :email => 'xx#x.com'}]
session[:product_users].each do |user|
#payment = if user.last.nil?
#payment.purchase(:token => params[:token], :payer_id => params[:PayerID], :ip => request.remote_ip)
else
#payment.transfer(user[:amount], user[:email])
end
#payment.save
end
redirect_to billing_thank_you_url(#payment)
end
From Model:
def setup_purchase(options)
gateway.setup_purchase(amount * 100, options)
end
def transfer(amount, receiver)
response = gateway.transfer(amount * 100, receiver, :subject => "Payment from XXX")
end
I'd be grateful if anyone help me on this.
Thank You
Related
Using Rails 5.02, Ruby 2.3, with Stripe gem 'stripe'
My code for the deduction of the charge is as:
begin
# Use Stripe's library to make requests...
charge = Stripe::Charge.create(
:customer => 1234,
:amount => 100, ## i.e 1$
:description => "job payment",
:currency => 'usd',
capture: false,
metadata: {'transaction' => transaction_id},
)
if !charge.review
charge.capture
end
if charge.paid?
#job_payment.invoice_id = transaction_id
#job_payment.transaction_date = Time.now
#job_payment.save
#job.update(job_payment_status: 'paid', expiry_date: Time.now + 30.days)
puts 'Job Payment.....'
job_payment_done_email(#job, #job_payment.invoice_id)
end
rescue Stripe::CardError => e
flash[:error] = "Insufficient funds!"
Rails.logger.info '***********Begin Exception*********'
Rails.logger.info e
Rails.logger.info "Amount = " + #amount.to_s
Rails.logger.info '***********End Exception*********'
rescue Stripe::RateLimitError => e
# Too many requests made to the API too quickly
flash[:error] = "Too many requests made to the API too quickly!"
rescue Stripe::InvalidRequestError => e
# Invalid parameters were supplied to Stripe's API
flash[:error] = "Invalid parameters were supplied to payment gateway!"
rescue Stripe::AuthenticationError => e
# Authentication with Stripe's API failed
flash[:error] = "Payment authentication problem!"
rescue Stripe::APIConnectionError => e
# Network communication with Stripe failed
flash[:error] = "Payment can not be completed due to the network problem with payment gateway!"
rescue Stripe::StripeError => e
# Display a very generic error to the user, and maybe send
# yourself an email
flash[:error] = "Something went wrong inside server while payment in stripe!"
rescue => e
# Something else happened, completely unrelated to Stripe
flash[:error] = "Something went wrong inside server while payment!"
end
The transaction get stuck by giving the following error of insuficient balance:
(Status 402) (Request req_QPLfwLnwBf2OeY) Your card has insufficient
funds.
Instead if the amount was less than the desired one, then it should have told that at the js pop up itself, but it is giving this error on the server end, But the card has an amount of Rs 1000 in it already.
I have tried to figure out this response back to PayPal for a while and it drives me nuts. Somewhere I need to send it back to stop PayPal from re-sending the IPN. This is my code for the IPN listener so far, how do I send the IPN response? Just doing ppr.valid? creates a VERIFIED response but the IPN messages keep coming so I guess that doesn't count as an IPN response. The valid? line always fails as well as it can't find the email and seller_id, which I also need to put somewhere (this stuff needs documentation). See gem documentation here: https://github.com/fnando/paypal-recurring
def ipn
subscription = Subscription.where(:email => params[:payer_email], :status => "Active").last
if subscription
ppr = PayPal::Recurring::Notification.new(params)
PaymentsNotification.create!(:params => params.to_json, :status => params[:payment_status], :transaction_id => params[:txn_id])
if ppr.valid? && (ppr.express_checkout? || ppr.recurring_payment?)
#business logic
end
end
I ended up with this code:
def ipn
subscription = Subscription.where(:email => params[:payer_email], :status => "Active").last
if subscription
PaymentsNotification.create!(:params => params.to_json.gsub("\"", "'"), :status => params[:payment_status], :transaction_id => params[:txn_id])
ppr = PayPal::Recurring::Notification.new(params)
ppr.response #send back the response to confirm IPN, stops further IPN notifications from being sent out
if ppr.verified? && ppr.completed?
if ppr.express_checkout? || ppr.recurring_payment?
#do stuff here
end
else
#raise response.errors.inspect
end
end
render :nothing => true
end
We are using Paypal Adaptive Chained payments to allow contributions on a crowd funding website. I've got everything working as far as making the payment and being returned to the 'return_url' after a successful payment (in the sandbox).
Paypals documentation on testing IPN in the Sandbox is sparse. Perhaps I missed a setting somewhere to enable IPN callbacks?
I would like to be able to use the IPN callback to verify a successful payment. I would like to see the callback JSON so I know which field to capture and compare with. I have found sample code, but the IPN callback doesn't seem to be called in the Sandbox. I've tried to output the params like so (also the puts statement isn't called):
****backers_controller.rb
class BackersController < ApplicationController
include ActiveMerchant::Billing::Integrations
def callback_ipn
puts "callback: ipn"
notify = PaypalAdaptivePayment::Notification.new(request.raw_post)
puts notify.to_yaml
end
def callback_return
puts "callback: return"
#backer = Backer.find(params[:id])
#reward = #project.rewards.find_by_id(#backer.reward_id)
#backer.callback
respond_to do |format|
format.html { render :layout => 'application_proj_back_blog' }
format.json { render json: #backer }
end
end
(The 'callback_return' action is working)
****backer.rb
class Backer < ActiveRecord::Base
include ActionDispatch::Routing::UrlFor
include Rails.application.routes.url_helpers
def purchase
project = Project.find(self.project_id)
default_url_options[:host] = 'localhost:3000'
proj_owner_email = User.find(project.user_id).email
recipients = [{:email => PRIMARY_EMAIL,
:amount => total_pledge,
:primary => true},
{:email => project.paypal_email,
:amount => project_owner_cut,
:primary => false}
]
response = GATEWAY.setup_purchase(
:action_type => "PAY_PRIMARY",
:return_url => callback_return_project_backer_url(project, self),
:cancel_url => callback_cancel_project_backer_url(project, self),
:ipn_notification_url => callback_ipn_project_backer_url(project, self),
:currency_code =>"USD",
:receiver_list => recipients
)
puts response.to_yaml
pay_key = response["payKey"]
pledge_transactions.create!(:action => "purchase", :amount => total_pledge, :response => response)
return response["payKey"]
end
Back in backers_controller.rb, 'def purchase' calls the purchase:
****backers_controller.rb
class BackersController < ApplicationController
def purchase
#backer = Backer.find(params[:id])
#backer.purchase
redirect_to (GATEWAY.redirect_url_for(#backer.purchase))
end
It turns out my authentication was preventing paypal from calling my ipn listener.
i want to rebuild an app which is a typical rails 3.2 mvc app into a API + Frontend (Backbone) only. As I have no experience in building APIs in rails including authenticatin:
What's the best way to authenticate with devise using backbone? Using auth_tokens?
How should I make he API? Just printing out JSON or use a gem like Grape?
thanks in advance!
I can explain you the way i do this :
First, i install a standard rails application with devise. After that, i create my own session controller :
class SessionsController < ApplicationController
def authenticate
# this method logs you in and returns you a single_access_token token for authentication.
#user = User.find_for_authentication(:email => params[:user][:email])
if #user && #user.valid_password?(params[:user][:password])
render :json => {:user => {:email => #user.email, :id => #user.id, :firsname => #user.firstname, :lastname => #user.lastname, :team_id => #user.team_id, :singleAccessToken => #user.generate_access_token}}
else
render :json => {:errors => ["Nom d'utilisateur ou mot de passe invalide"]}, :status => 401
end
end
end
As you can see, i send a request to this url with the json looking like :
{
user => {
email => "myemail#toto.com",
password => "monpass"
}
}
And my controller return me the json with user data if every thing is fine, or an error. On json with user, i return an access_token used on next requests to check that the user is allowed to request. I made this filters in my application controller :
class ApplicationController < ActionController::Base
protect_from_forgery
protected
def user_access_token
request.headers["HTTP_X_USER_ACCESS_TOKEN"] || request.headers["HTTP_USER_ACCESS_TOKEN"]
end
def current_user
if token = user_access_token
#user ||= User.find_by_access_token(token)
end
end
def require_user
unless current_user
render :json => {:error => "Invalid Access Token"}, :status => 401
end
end
def require_owner
unless current_user && current_user == object.user
render :json => {:error => "Unauthorized"}
end
end
end
As you can see, on each next request, i will add the access_token in html header on key : HTTP_USER_ACCESS_TOKEN
So, i can check if the user is allowed to make the request.
To make an API, you can use the Rails API gem as see here :
http://railscasts.com/episodes/348-the-rails-api-gem
Good luck.
i am using rails3.0.6 and ruby 1.8.7, i can easily send email from my applications development mode.But last night i saw a new error when i tried to send mail to my customers email which is polymorphic associated with my invoice model. The error is:
Net::SMTPSyntaxError in InvoicesController#email_invoice
501 < #invoice.account.accountable.email >: missing or malformed local part
My code for email.rb file is :
def send_invoice(invoice)
email = '#invoice.account.accountable.email'
mail(:to => email, :from => "support#thenextwave.in", :subject=>"Invoice, check it.")
end
and in my invoice controller i did:
def email_invoice
#company = Company.find(User.find(session[:current_user_id]))
#invoice = Invoice.find(params[:id])
#invoice_line_items = #invoice.invoice_line_items
#receipt_vouchers = #invoice.receipt_vouchers
#email = #invoice.account.accountable.email
Email.send_invoice(#invoice).deliver
redirect_to invoice_path(#invoice)
flash[:success] = 'Email has been sent successfully.'
end
i goggled for this error and find that it causes due to wrong from and to email addresses or wrong SMTP settings, but my SMTP setting is ok since i can send email from my application but has problem with below line:
#invoice.account.accountable.email
any help would be thaknful..
I come up with a solution, I made mistake in email.rb file in my mailer :
def send_invoice(invoice)
email = '#invoice.account.accountable.email'
mail(:to => email, :from => "support#thenextwave.in", :subject=>"Invoice, check it.")
end
it should be:
def send_invoice(invoice)
email = invoice.account.accountable.email
mail(:to => email, :from => "support#thenextwave.in", :subject=>"Invoice, check it.")
end
Now I can send email easily..