Repository URL to install this package:
|
Version:
4.0.0.pre.3 ▾
|
module Core
module Utils
# An encapsulation of different payment errors, allowing a JSON output.
class PaymentError < StandardError
attr_reader :message
attr_reader :id
attr_reader :url
attr_reader :http_status
def initialize(message, id, url, http_status)
@message = message
@id = id
@url = url
@http_status = http_status
end
def json_body
{ id: @id, message: @message, url: @url }
end
end
# Payments handling.
class Payments
attr_reader :user, :source
# Create a new Payments object for processing payments.
#
# @param [User] user the user object to work with.
# @param [String/Hash] source a 'Stripe Token' or a Hash of card details.
# @return [Payments] a payment object that can be used to process
# payments for a given user.
def initialize(user, source = nil)
@user = user
@source = source
# configure Stripe
Stripe.api_key = Core.configuration.stripe_token
end
# Store a user's details.
#
# This is intended to be used when a payment isn't processed, but a
# customer should be created.
#
# @return [String] a Stripe customer identifier.
def store_details
update_or_create_customer_id(@user)
end
# Process a payment.
#
# @param [Integer] amount value to charge (in pence).
# @param [String] description explanation which shows up on the user's
# receipt.
# @return [Stripe::Charge] a Stripe charge object representing the new
# charge.
#
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def process(amount, description)
begin
customer_id = update_or_create_customer_id(@user)
charge = Stripe::Charge.create(
amount: amount,
description: description,
currency: 'gbp',
customer: customer_id
)
rescue Stripe::CardError => e
body = e.json_body
err = body[:error]
raise PaymentError.new(err[:message], 'card_error', '', 400)
rescue Stripe::InvalidRequestError => e
body = e.json_body
err = body[:error]
raise PaymentError.new(err[:message], 'invalid_request', '', 400)
rescue Stripe::AuthenticationError => e
body = e.json_body
err = body[:error]
raise PaymentError.new(err[:message], 'authentication_error', '', 500)
rescue Stripe::StripeError => e
body = e.json_body
err = body[:error]
raise PaymentError.new(err[:message], 'stripe_error', '', 500)
rescue => e
body = e.json_body
err = body[:error]
raise PaymentError.new(err[:message], 'unknown_error', '', 500)
end
charge
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
protected
def update_or_create_customer_id(user)
# if we've already got a customer and the source exists
if user.stripe_customer_id?
replace_customer_default_source(user, @source) if @source
else
create_new_customer(user, @source)
end
user.stripe_customer_id
end
def create_new_customer(user, source)
customer = Stripe::Customer.create(
card: source, description: user.id, email: user.email
)
user.stripe_customer_id = customer.id
user.save
customer
end
def replace_customer_default_source(user, new_source)
customer = Stripe::Customer.retrieve(user.stripe_customer_id)
# remove the current, add the new
customer.sources.first.delete
customer.save
new_source[:object] = card if new_source.is_a? Hash
customer.sources.create(source: new_source)
customer.save
customer
end
end
end
end