Skip to content

Instantly share code, notes, and snippets.

Created August 4, 2013 14:12
Show Gist options
  • Save anonymous/6150447 to your computer and use it in GitHub Desktop.
Save anonymous/6150447 to your computer and use it in GitHub Desktop.
Bips.me Payment and IPN handler for Ruby on Rails (3.2.11) Modify to your own needs. Functionality is tested. I ripped some application specific stuff out and put some stuff back in. So expect some no_method errors
def change
create_table :payments do |t|
t.integer :order_id
t.string :token
t.string :ip_address
t.string :bitcoin_address
t.integer :bitcoin_amount_satoshi
t.integer :euro_amount_ct
t.text :payment_notification_request
t.datetime :payment_completed
t.timestamps
end
add_index :payments, :token, :unique => true
add_index :payments, :order_id
end
gem "rest-client", "~> 1.6.7"
class Order < ActiveRecord::Base
has_many :payments
end
class Payment < ActiveRecord::Base
belongs_to :order
serialize :payment_notification_request
before_create :generate_token
after_save :set_order_payed
def set_order_payed
order.update_attribute(:payed, payment_completed) if payment_completed
end
def generate_token
self.token = loop do
random_token = SecureRandom.uuid
break random_token unless Payment.where(token: random_token).exists?
end
end
end
class PaymentsController < ApplicationController
# GET /payment/new
# Routes: payment
def new
@order = Order.find(params[:order_id])
redirect_to @order, :notice => 'invalid order!' and return if not @order
redirect_to @order, :notice => 'Order already payed!' and return if @order.payed
@payment = @order.payments.build
end
# POST /payment
# POST /payment.json
# Routes: payments, direct_payment
def create
@order = Order.find(payment_params[:order_id])
@payment = @order.payments.build(payment_params)
# set price in cents
@payment.euro_amount_ct = @order.price_in_cents
@payment.ip_address = request.remote_ip.to_s
if @payment.save
redirect_to get_bitcoin_redirect(@payment)
else
render action: "new"
end
end
# POST /payments/confirm/bitcoin
def bitcoin_notification
# set/change secret on https://bips.me/merchant
secret = "mioEJcyTgj0BeYbMVA5XphdZOFzNuKvUHtrxQwnGkPsfaLRIDq"
hash = Digest::SHA512.hexdigest(params[:transaction][:hash] + secret)
@payment = Payment.find_by_token(params[:custom][:payment_token])
if @payment && (hash == params[:hash]) && (params[:status] == "1")
@payment.payment_notification_request = params # store complete request in DB for future reference
@payment.bitcoin_address = params[:transaction][:address] # Bitcoin address of sender
@payment.bitcoin_amount_satoshi = (params[:btc][:amount].to_f * 100000000).to_i # Store recieved bitcoin amount as satoshi integer
@payment.payment_completed = Time.now # set payment completed
@payment.save
#
# Here goes the stuf to do when payment is succesfull
# Send email, change order status etcetera.
# You might want to do that in a background job.
# Maybe use the awesome Spawnling gem?!
#
head :ok
else
head :not_acceptable
end
end
def finish
@payment = Payment.where(:token => params[:payment_token]).first
# do some finish stuff
# BEWARE: payment process not completed / recieved until an IPN is sent to your server.
# Wait with sending payment confirmations until IPN is recieved.
end
def cancel
@payment = Payment.where(:token => params[:payment_token]).first
# do some cancel stuff
# maybe display page to try again
end
private
def get_bitcoin_redirect(payment)
# set/change Api Key on https://bips.me/merchant
api_key = "MySecretApiKey"
# Log RestClient requests to the standard Rails logger
RestClient.log =
Object.new.tap do |proxy|
def proxy.<<(message)
Rails.logger.info message
end
end
base_url = "https://bips.me"
uri = "#{base_url}/api/v1/invoice"
custom_parameters = { "payment_token" => payment.token,
"returnurl" => finish_payment_url(:payment_token => payment.token),
"cancelurl" => cancel_payment_url(:payment_token => payment.token)
}.to_json
parameters = { "price" => payment.euro_amount_ct/100.0,
"currency" => 'EUR',
"item" => "Order #{payment.order.id}",
"custom" => custom_parameters
}
resource = RestClient::Resource.new( uri, { :user => api_key })
response = resource.post parameters
return response.to_str
end
end
resources :payments do
collection do
post 'confirm/bitcoin' => 'payments#bitcoin_notification'
post 'finish/:payment_token' => 'payments#finish'
post 'cancel/:payment_token' => 'payments#cancel'
end
end
@NovapaX
Copy link

NovapaX commented Aug 4, 2013

Forgot to login before placing this Gist.
This comment serves as a find-back-post.

I used this code on www.udid-registration.net to make bitcoin payments available.

I thought this might be helpful to others since documentation from Bips.me is a little lacking.

Oh, and yes: I changed my secret on bips.me quickly after realizing I forgot to take it out of my code :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment