Skip to content

Instantly share code, notes, and snippets.

@wiseleyb
Created February 15, 2011 17:42
Show Gist options
  • Save wiseleyb/827883 to your computer and use it in GitHub Desktop.
Save wiseleyb/827883 to your computer and use it in GitHub Desktop.
Code we use to handle Moneybookers payments
#----------------------------------------------------------------------------------
# CONTROLLER
#----------------------------------------------------------------------------------
class MoneybookersPaymentsController < ApplicationController
layout :false
ssl_required :mbstatus, :mbreturn, :mbcancel if HTTPS
def redirect_to_moneybookers(user, product)
url = MoneybookersPayment.moneybookers_payment_url(user, product)
redirect_to(url) and return
end
# MoneyBookers return URLs
def mbreturn
if logged_in?
logger.info("mbreturn received #{params.to_yaml} from Moneybookers")
ActivityLog.create :user => current_user, :text => "mbreturn received #{params.to_yaml} from Moneybookers"
if current_user.subscription && current_user.subscription.active?
flash[:notice] = "Thank you for purchasing a subscription."
else
flash[:notice] = "Thank you for purchasing a subscription. We are waiting for MoneyBookers to confirm with us your purchase. Once we receive this notification your subscription will be active and you will be notified via email."
end
redirect_to "/mydc"
else
logger.info("mbreturn received #{params.to_yaml} from Moneybookers but user was not logged in")
redirect_to "/"
end
end
def mbcancel
if logged_in?
flash[:notice] = %(You now have a basic account with the username #{self.current_user.login}. You can upgrade your account by clicking the green "Upgrade!" button after logging in)
logger.info("mbcancel received #{params.to_yaml} from Moneybookers")
ActivityLog.create :user => current_user, :text => "mbcancel received #{params.to_yaml} from Moneybookers"
redirect_to "/mydc/subscribe"
else
logger.info("mbcancel received #{params.to_yaml} from Moneybookers but user was not logged in")
redirect_to "/"
end
end
# this controller accepts postbacks from Moneybookers, and handles all the actual billing.
# Posted information is verified by the parameter md5sig, which contains information from the
# "Secret word" configured in the Merchant Tools section of Moneybookers.
def mbstatus
(redirect_to(:controller => :index, :action => :index) and return) unless request.post?
logger.info("mbstatus received #{params.to_yaml} from Moneybookers")
mb = Moneybookers.new
if mb.calculate_md5(params) == params[:md5sig]
logger.info("mbstatus verified the md5 signature!")
else
logger.warn("mbstatus calculated md5 sig of #{mb.calculate_md5(params)}, but received expected value of #{params[:md5sig]}. refusing to carry on.")
render(:text => "ERROR") and return
end
if params[:mb_currency] != 'USD'
logger.warn("mbstatus received a post with currency ne to USD. Currency: #{params[:mb_currency]}")
elsif params[:status] == '2'
product = Product.find params[:product_id]
product = free_flash_festival_product(product) if product && free_flash_festival?
if product.price.to_i > params[:mb_amount].to_i && RAILS_ENV == "production"
logger.warn("Product price (#{product.price.to_s}) is more than the charge amount (#{params[:mb_mount]}), user may have attempted to submit 'custom' values. Not crediting their account.")
render(:text => "ERROR") and return
end
user = User.find params[:user_id]
subscription = Subscription.new_or_existing_for(user,0,product.duration)
mb_payment = MoneybookersPayment.create!(
:subscription => subscription,
:user => user,
:customer_id => params[:customer_id],
:merchant_id => params[:merchant_id],
:payment_type => params[:payment_type],
:product => product,
:pay_from_email => params[:pay_from_email],
:pay_to_email => params[:pay_to_email],
:mb_transaction_key => params[:mb_transaction_id],
:amount => params[:amount],
:mb_amount => params[:mb_amount]
)
subscription.flash_only = false
subscription.save!
user.cim_profile.destroy if user.cim_profile
msg = "Credited user's subscription #{subscription.id} with #{product.duration} months from Moneybookers payment #{mb_payment.id}"
log = ActivityLog.create :user => user, :text => msg
UserNotifier.deliver_moneybookers_payment_notification(user,mb_payment)
else
# Status of the transaction: -2 failed / 2 processed / 0 pending / -1 cancelled
logger.warn("mbstatus received a post with status not equal to '2'/Success. Status: #{params[:status]}")
end
render(:text => "nil") and return
end
end
#----------------------------------------------------------------------------------
# MODEL
#----------------------------------------------------------------------------------
class MoneybookersPayment < ActiveRecord::Base
belongs_to :subscription
belongs_to :user
belongs_to :product
belongs_to :affiliate
validates_presence_of :subscription
validates_presence_of :mb_transaction_key
validates_presence_of :mb_amount
validates_presence_of :pay_from_email
# initiates moneybookers payment, returns url to redirect user to.
def self.moneybookers_payment_url(user, product)
@payment_address = MONEYBOOKERS_PAYMENT_ADDRESS || "test@example.com"
@return_url = "#{BASE_URL}/moneybookers_payments/mbreturn"
@cancel_url = "#{BASE_URL}/moneybookers_payments/mbcancel"
@status_url = "#{BASE_URL}/moneybookers_payments/mbstatus"
if HTTPS
@return_url.gsub!("http:","https:")
@cancel_url.gsub!("http:","https:")
@status_url.gsub!("http:","https:")
end
amount = RAILS_ENV == "production" ? product.price : product.price / 100 #moneybookers doesn't give us much $$$ in our test account.
query_params = {
:pay_to_email => @payment_address,
:recipient_description => "DeucesCracked",
:merchant_fields => "user_id,user_login,product_id",
:user_id => user.id,
:user_login => user.login,
:return_url => @return_url,
:cancel_url => @cancel_url,
:status_url => @status_url,
:language => "EN",
:amount => amount,
:product_id => product.id,
:currency => "USD",
:detail1_description => "#{product.description} subscription",
:detail1_text => "",
:logo_url => "https://www.deucescracked.com/images/logo.png",
:confirmation_note => "Thank you for your payment.<br />Welcome to DeucesCracked!"
}
Moneybookers::PAYMENT_URL + "?" + query_params.to_query
end
end
#----------------------------------------------------------------------------------
# DB
#----------------------------------------------------------------------------------
create_table "moneybookers_payments", :force => true do |t|
t.integer "subscription_id"
t.integer "user_id"
t.integer "customer_id"
t.integer "merchant_id"
t.string "payment_type"
t.string "pay_to_email"
t.string "pay_from_email"
t.integer "product_id"
t.string "mb_transaction_key"
t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0
t.decimal "mb_amount", :precision => 8, :scale => 2, :default => 0.0
t.datetime "created_at"
t.datetime "updated_at"
t.integer "affiliate_id"
end
add_index "moneybookers_payments", ["subscription_id"], :name => "subscription_id"
add_index "moneybookers_payments", ["user_id"], :name => "user_id"
add_index "moneybookers_payments", ["product_id"], :name => "product_id"
add_index "moneybookers_payments", ["affiliate_id"], :name => "affiliate_id"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment