mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-19 13:54:25 +01:00
WIP: refactor the price computation system
This commit is contained in:
parent
26dfbef5e1
commit
e456ddc7c9
@ -19,13 +19,19 @@ class API::PayzenController < API::PaymentsController
|
||||
|
||||
def create_payment
|
||||
amount = card_amount
|
||||
@id = PayZen::Helper.generate_ref(cart_items_params, params[:customer])
|
||||
@id = PayZen::Helper.generate_ref(cart_items_params, params[:customer_id])
|
||||
|
||||
client = PayZen::Charge.new
|
||||
@result = client.create_payment(amount: amount[:amount],
|
||||
order_id: @id,
|
||||
customer: PayZen::Helper.generate_customer(params[:customer_id]))
|
||||
@result
|
||||
end
|
||||
|
||||
def create_token
|
||||
@id = PayZen::Helper.generate_ref(cart_items_params, params[:customer_id])
|
||||
client = PayZen::Charge.new
|
||||
@result = client.create_token(order_id: @id,
|
||||
customer: PayZen::Helper.generate_customer(params[:customer_id]))
|
||||
end
|
||||
|
||||
def check_hash
|
||||
|
@ -7,22 +7,27 @@ import { CheckHashResponse, ConfirmPaymentResponse, CreatePaymentResponse, SdkTe
|
||||
export default class PayzenAPI {
|
||||
|
||||
static async chargeSDKTest(baseURL: string, username: string, password: string): Promise<SdkTestResponse> {
|
||||
const res: AxiosResponse = await apiClient.post('/api/payzen/sdk_test', { base_url: baseURL, username, password });
|
||||
const res: AxiosResponse<SdkTestResponse> = await apiClient.post('/api/payzen/sdk_test', { base_url: baseURL, username, password });
|
||||
return res?.data;
|
||||
}
|
||||
|
||||
static async chargeCreatePayment(cartItems: CartItems, customer: User): Promise<CreatePaymentResponse> {
|
||||
const res: AxiosResponse = await apiClient.post('/api/payzen/create_payment', { cart_items: cartItems, customer_id: customer.id });
|
||||
const res: AxiosResponse<CreatePaymentResponse> = await apiClient.post('/api/payzen/create_payment', { cart_items: cartItems, customer_id: customer.id });
|
||||
return res?.data;
|
||||
}
|
||||
|
||||
static async chargeCreateToken(cartItems: CartItems, customer: User): Promise<any> {
|
||||
const res: AxiosResponse = await apiClient.post('/api/payzen/create_token', { cart_items: cartItems, customer_id: customer.id });
|
||||
return res?.data;
|
||||
}
|
||||
|
||||
static async checkHash(algorithm: string, hashKey: string, hash: string, data: string): Promise<CheckHashResponse> {
|
||||
const res: AxiosResponse = await apiClient.post('/api/payzen/check_hash', { algorithm, hash_key: hashKey, hash, data });
|
||||
const res: AxiosResponse<CheckHashResponse> = await apiClient.post('/api/payzen/check_hash', { algorithm, hash_key: hashKey, hash, data });
|
||||
return res?.data;
|
||||
}
|
||||
|
||||
static async confirm(orderId: string, cartItems: CartItems): Promise<ConfirmPaymentResponse> {
|
||||
const res: AxiosResponse = await apiClient.post('/api/payzen/confirm_payment', { cart_items: cartItems, order_id: orderId });
|
||||
const res: AxiosResponse<ConfirmPaymentResponse> = await apiClient.post('/api/payzen/confirm_payment', { cart_items: cartItems, order_id: orderId });
|
||||
return res?.data;
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,17 @@ export interface IntentConfirmation {
|
||||
}
|
||||
|
||||
export enum PaymentMethod {
|
||||
Stripe = 'stripe',
|
||||
Card = 'card',
|
||||
Other = ''
|
||||
}
|
||||
|
||||
export interface CartItems {
|
||||
customer_id: number,
|
||||
reservation?: Reservation,
|
||||
subscription?: SubscriptionRequest,
|
||||
coupon_code?: string
|
||||
coupon_code?: string,
|
||||
payment_schedule?: boolean,
|
||||
payment_method: PaymentMethod
|
||||
}
|
||||
|
||||
export interface UpdateCardResponse {
|
||||
|
@ -7,13 +7,10 @@ export interface ReservationSlot {
|
||||
}
|
||||
|
||||
export interface Reservation {
|
||||
user_id: number,
|
||||
reservable_id: number,
|
||||
reservable_type: string,
|
||||
slots_attributes: Array<ReservationSlot>,
|
||||
plan_id?: number,
|
||||
nb_reserve_places?: number,
|
||||
payment_schedule?: boolean,
|
||||
tickets_attributes?: {
|
||||
event_price_category_id: number,
|
||||
booked: boolean,
|
||||
|
@ -11,8 +11,5 @@ export interface Subscription {
|
||||
}
|
||||
|
||||
export interface SubscriptionRequest {
|
||||
plan_id: number,
|
||||
user_id: number,
|
||||
payment_schedule: boolean,
|
||||
payment_method: PaymentMethod
|
||||
plan_id: number
|
||||
}
|
||||
|
13
app/models/cart_item/base_item.rb
Normal file
13
app/models/cart_item/base_item.rb
Normal file
@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Items that can be added to the shopping cart
|
||||
module CartItem; end
|
||||
|
||||
# This is an abstract class implemented by classes that can be added to the shopping cart
|
||||
class CartItem::BaseItem
|
||||
self.abstract_class = true
|
||||
|
||||
def price
|
||||
{ elements: {}, amount: 0 }
|
||||
end
|
||||
end
|
26
app/models/cart_item/coupon.rb
Normal file
26
app/models/cart_item/coupon.rb
Normal file
@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# A discount coupon applied to the whole shopping cart
|
||||
class CartItem::Coupon
|
||||
|
||||
# @param coupon {String|Coupon} may be nil or empty string if no coupons are applied
|
||||
def initialize(customer, operator, coupon)
|
||||
@customer = customer
|
||||
@operator = operator
|
||||
@coupon = coupon
|
||||
end
|
||||
|
||||
def coupon
|
||||
cs = CouponService.new
|
||||
cs.validate(@coupon, @customer.id)
|
||||
end
|
||||
|
||||
def price(cart_total = 0)
|
||||
cs = CouponService.new
|
||||
new_total = cs.apply(cart_total, coupon)
|
||||
|
||||
amount = new_total - cart_total
|
||||
|
||||
{ amount: amount, total_with_coupon: new_total, total_without_coupon: cart_total }
|
||||
end
|
||||
end
|
36
app/models/cart_item/event_reservation.rb
Normal file
36
app/models/cart_item/event_reservation.rb
Normal file
@ -0,0 +1,36 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# An event reservation added to the shopping cart
|
||||
class CartItem::EventReservation < CartItem::Reservation
|
||||
# @param normal_tickets {Number} number of tickets at the normal price
|
||||
# @param other_tickets {Array<{booked: Number, event_price_category_id: Number}>}
|
||||
def initialize(customer, operator, event, slots, normal_tickets: 0, other_tickets: [])
|
||||
raise TypeError unless event.class == Event
|
||||
|
||||
super(customer, operator, event, slots)
|
||||
@normal_tickets = normal_tickets
|
||||
@other_tickets = other_tickets
|
||||
end
|
||||
|
||||
def price
|
||||
amount = @reservable.amount * @normal_tickets
|
||||
is_privileged = @operator.admin? || (@operator.manager? && @operator.id != @customer.id)
|
||||
|
||||
@other_tickets.each do |ticket|
|
||||
amount += ticket[:booked] * EventPriceCategory.find(ticket[:event_price_category_id]).amount
|
||||
end
|
||||
|
||||
elements = { slots: [] }
|
||||
|
||||
@slots.each do |slot|
|
||||
amount += get_slot_price(amount,
|
||||
slot,
|
||||
is_privileged,
|
||||
elements: elements,
|
||||
is_division: false)
|
||||
end
|
||||
|
||||
{ elements: elements, amount: amount }
|
||||
end
|
||||
|
||||
end
|
23
app/models/cart_item/machine_reservation.rb
Normal file
23
app/models/cart_item/machine_reservation.rb
Normal file
@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# A machine reservation added to the shopping cart
|
||||
class CartItem::MachineReservation < CartItem::Reservation
|
||||
# @param plan {Plan} a subscription bought at the same time of the reservation OR an already running subscription
|
||||
# @param new_subscription {Boolean} true is new subscription is being bought at the same time of the reservation
|
||||
def initialize(customer, operator, machine, slots, plan: nil, new_subscription: false)
|
||||
raise TypeError unless machine.class == Machine
|
||||
|
||||
super(customer, operator, machine, slots)
|
||||
@plan = plan
|
||||
@new_subscription = new_subscription
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
return 0 if @plan.nil?
|
||||
|
||||
machine_credit = @plan.machine_credits.find { |credit| credit.creditable_id == @reservable.id }
|
||||
credits_hours(machine_credit, @new_subscription)
|
||||
end
|
||||
end
|
28
app/models/cart_item/payment_schedule.rb
Normal file
28
app/models/cart_item/payment_schedule.rb
Normal file
@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# A payment schedule applied to plan in the shopping cart
|
||||
class CartItem::PaymentSchedule
|
||||
def initialize(plan, coupon, requested)
|
||||
raise TypeError unless coupon.class == CartItem::Coupon
|
||||
|
||||
@plan = plan
|
||||
@coupon = coupon
|
||||
@requested = requested
|
||||
end
|
||||
|
||||
def schedule(total, total_without_coupon)
|
||||
schedule = if @requested && @plan.monthly_payment
|
||||
PaymentScheduleService.new.compute(@plan, total_without_coupon, coupon: @coupon.coupon)
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
total_amount = if schedule
|
||||
schedule[:items][0].amount
|
||||
else
|
||||
total
|
||||
end
|
||||
|
||||
{ schedule: schedule, total: total_amount }
|
||||
end
|
||||
end
|
81
app/models/cart_item/reservation.rb
Normal file
81
app/models/cart_item/reservation.rb
Normal file
@ -0,0 +1,81 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
MINUTES_PER_HOUR = 60.0
|
||||
SECONDS_PER_MINUTE = 60.0
|
||||
|
||||
GET_SLOT_PRICE_DEFAULT_OPTS = { has_credits: false, elements: nil, is_division: true }.freeze
|
||||
|
||||
# A generic reservation added to the shopping cart
|
||||
class CartItem::Reservation < CartItem::BaseItem
|
||||
def initialize(customer, operator, reservable, slots)
|
||||
@customer = customer
|
||||
@operator = operator
|
||||
@reservable = reservable
|
||||
@slots = slots
|
||||
end
|
||||
|
||||
def price
|
||||
base_amount = @reservable.prices.find_by(group_id: @customer.group_id, plan_id: @plan.try(:id)).amount
|
||||
is_privileged = @operator.admin? || (@operator.manager? && @operator.id != @customer.id)
|
||||
|
||||
elements = { slots: [] }
|
||||
amount = 0
|
||||
|
||||
hours_available = credits
|
||||
@slots.each_with_index do |slot, index|
|
||||
amount += get_slot_price(base_amount, slot, is_privileged, elements: elements, has_credits: (index < hours_available))
|
||||
end
|
||||
|
||||
{ elements: elements, amount: amount }
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
0
|
||||
end
|
||||
|
||||
##
|
||||
# Compute the price of a single slot, according to the base price and the ability for an admin
|
||||
# to offer the slot.
|
||||
# @param hourly_rate {Number} base price of a slot
|
||||
# @param slot {Hash} Slot object
|
||||
# @param is_privileged {Boolean} true if the current user has a privileged role (admin or manager)
|
||||
# @param [options] {Hash} optional parameters, allowing the following options:
|
||||
# - elements {Array} if provided the resulting price will be append into elements.slots
|
||||
# - has_credits {Boolean} true if the user still has credits for the given slot, false if not provided
|
||||
# - is_division {boolean} false if the slot covers a full availability, true if it is a subdivision (default)
|
||||
# @return {Number} price of the slot
|
||||
##
|
||||
def get_slot_price(hourly_rate, slot, is_privileged, options = {})
|
||||
options = GET_SLOT_PRICE_DEFAULT_OPTS.merge(options)
|
||||
|
||||
slot_rate = options[:has_credits] || (slot[:offered] && is_privileged) ? 0 : hourly_rate
|
||||
real_price = if options[:is_division]
|
||||
(slot_rate / MINUTES_PER_HOUR) * ((slot[:end_at].to_time - slot[:start_at].to_time) / SECONDS_PER_MINUTE)
|
||||
else
|
||||
slot_rate
|
||||
end
|
||||
|
||||
unless options[:elements].nil?
|
||||
options[:elements][:slots].push(
|
||||
start_at: slot[:start_at],
|
||||
price: real_price,
|
||||
promo: (slot_rate != hourly_rate)
|
||||
)
|
||||
end
|
||||
real_price
|
||||
end
|
||||
|
||||
##
|
||||
# Compute the number of remaining hours in the users current credits (for machine or space)
|
||||
##
|
||||
def credits_hours(credits, new_plan_being_bought = false)
|
||||
hours_available = credits.hours
|
||||
unless new_plan_being_bought
|
||||
user_credit = @customer.users_credits.find_by(credit_id: credits.id)
|
||||
hours_available = credits.hours - user_credit.hours_used if user_credit
|
||||
end
|
||||
hours_available
|
||||
end
|
||||
end
|
23
app/models/cart_item/space_reservation.rb
Normal file
23
app/models/cart_item/space_reservation.rb
Normal file
@ -0,0 +1,23 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# A space reservation added to the shopping cart
|
||||
class CartItem::SpaceReservation < CartItem::Reservation
|
||||
# @param plan {Plan} a subscription bought at the same time of the reservation OR an already running subscription
|
||||
# @param new_subscription {Boolean} true is new subscription is being bought at the same time of the reservation
|
||||
def initialize(customer, operator, space, slots, plan: nil, new_subscription: false)
|
||||
raise TypeError unless space.class == Space
|
||||
|
||||
super(customer, operator, space, slots)
|
||||
@plan = plan
|
||||
@new_subscription = new_subscription
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
return 0 if @plan.nil?
|
||||
|
||||
space_credit = @plan.space_credits.find { |credit| credit.creditable_id == @reservable.id }
|
||||
credits_hours(space_credit, @new_subscription)
|
||||
end
|
||||
end
|
17
app/models/cart_item/subscription.rb
Normal file
17
app/models/cart_item/subscription.rb
Normal file
@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# A subscription added to the shopping cart
|
||||
class CartItem::Subscription < CartItem::BaseItem
|
||||
def initialize(plan)
|
||||
raise TypeError unless plan.class == Plan
|
||||
|
||||
@plan = plan
|
||||
end
|
||||
|
||||
def price
|
||||
amount = @plan.amount
|
||||
elements = { plan: amount }
|
||||
|
||||
{ elements: elements, amount: amount }
|
||||
end
|
||||
end
|
43
app/models/cart_item/training_reservation.rb
Normal file
43
app/models/cart_item/training_reservation.rb
Normal file
@ -0,0 +1,43 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# A training reservation added to the shopping cart
|
||||
class CartItem::TrainingReservation < CartItem::Reservation
|
||||
# @param plan {Plan} a subscription bought at the same time of the reservation OR an already running subscription
|
||||
# @param new_subscription {Boolean} true is new subscription is being bought at the same time of the reservation
|
||||
def initialize(customer, operator, training, slots, plan: nil, new_subscription: false)
|
||||
raise TypeError unless training.class == Training
|
||||
|
||||
super(customer, operator, training, slots)
|
||||
@plan = plan
|
||||
@new_subscription = new_subscription
|
||||
end
|
||||
|
||||
def price
|
||||
base_amount = @reservable.amount_by_group(@customer.group_id, plan_id: @plan.try(:id)).amount
|
||||
is_privileged = @operator.admin? || (@operator.manager? && @operator.id != @customer.id)
|
||||
|
||||
elements = { slots: [] }
|
||||
amount = 0
|
||||
|
||||
hours_available = credits
|
||||
@slots.each do |slot|
|
||||
amount += get_slot_price(base_amount,
|
||||
slot,
|
||||
is_privileged,
|
||||
elements: elements,
|
||||
has_credits: (@user.training_credits.size < hours_available),
|
||||
is_division: false)
|
||||
end
|
||||
|
||||
{ elements: elements, amount: amount }
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def credits
|
||||
return 0 if @plan.nil?
|
||||
|
||||
is_creditable = @plan.training_credits.select { |credit| credit.creditable_id == @reservable.id }.any?
|
||||
is_creditable ? @plan.training_credit_nb : 0
|
||||
end
|
||||
end
|
44
app/models/shopping_cart.rb
Normal file
44
app/models/shopping_cart.rb
Normal file
@ -0,0 +1,44 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Stores data about a shopping data
|
||||
class ShoppingCart
|
||||
attr_accessor :customer, :payment_method, :items, :coupon, :payment_schedule
|
||||
|
||||
# @param items {Array<CartItem::BaseItem>}
|
||||
# @param coupon {CartItem::Coupon}
|
||||
# @param payment_schedule {CartItem::PaymentSchedule}
|
||||
# @param customer {User}
|
||||
def initialize(customer, coupon, payment_method = '', items: [], payment_schedule: nil)
|
||||
raise TypeError unless customer.class == User
|
||||
|
||||
@customer = customer
|
||||
@payment_method = payment_method
|
||||
@items = items
|
||||
@coupon = coupon
|
||||
@payment_schedule = payment_schedule
|
||||
end
|
||||
|
||||
def total
|
||||
total_amount = 0
|
||||
all_elements = { slots: [] }
|
||||
|
||||
@items.map(&:price).each do |price|
|
||||
total_amount += price[:amount]
|
||||
all_elements.merge(price[:elements]) do |_key, old_val, new_val|
|
||||
old_val | new_val
|
||||
end
|
||||
end
|
||||
|
||||
coupon_info = @coupon.price(total_amount)
|
||||
schedule_info = @payment_schedule.schedule(coupon_info[:total_with_coupon], coupon_info[:total_without_coupon])
|
||||
|
||||
# return result
|
||||
{
|
||||
elements: all_elements,
|
||||
total: schedule_info[:total].to_i,
|
||||
before_coupon: coupon_info[:total_without_coupon].to_i,
|
||||
coupon: @coupon.coupon,
|
||||
schedule: schedule_info[:schedule]
|
||||
}
|
||||
end
|
||||
end
|
83
app/services/cart_service.rb
Normal file
83
app/services/cart_service.rb
Normal file
@ -0,0 +1,83 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Provides methods for working with cart items
|
||||
class CartService
|
||||
def initialize(operator)
|
||||
@operator = operator
|
||||
end
|
||||
|
||||
def from_hash(cart_items)
|
||||
items = []
|
||||
plan_info = plan(cart_items)
|
||||
|
||||
@customer = User.find(cart_items[:customer_id])
|
||||
|
||||
items.push(CartItem::Subscription.new(plan_info[:plan])) if cart_items[:subscription]
|
||||
items.push(reservable_from_hash(cart_items[:reservation], plan_info)) if cart_items[:reservation]
|
||||
|
||||
coupon = CartItem::Coupon.new(@customer, @operator, cart_items[:coupon_code])
|
||||
schedule = CartItem::PaymentSchedule.new(plan_info[:plan], coupon, cart_items[:payment_schedule])
|
||||
|
||||
ShoppingCart.new(
|
||||
@customer,
|
||||
coupon,
|
||||
cart_items[:payment_method],
|
||||
items: items,
|
||||
payment_schedule: schedule
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def plan(cart_items)
|
||||
plan = if @customer.subscribed_plan
|
||||
new_plan_being_bought = false
|
||||
@customer.subscribed_plan
|
||||
elsif cart_items[:subscription]
|
||||
new_plan_being_bought = true
|
||||
Plan.find(cart_items[:subscription][:plan_id])
|
||||
else
|
||||
new_plan_being_bought = false
|
||||
nil
|
||||
end
|
||||
{ plan: plan, new_subscription: new_plan_being_bought }
|
||||
end
|
||||
|
||||
def reservable_from_hash(cart_item, plan_info)
|
||||
return nil if cart_item[:reservable_id].blank?
|
||||
|
||||
reservable = cart_item[:reservable_type].constantize.find(cart_item[:reservable_id])
|
||||
case reservable
|
||||
when Machine
|
||||
CartItem::MachineReservation.new(@customer,
|
||||
@operator,
|
||||
reservable,
|
||||
cart_item[:slots_attributes],
|
||||
plan: plan_info[:plan],
|
||||
new_subscription: plan_info[:new_subscription])
|
||||
when Training
|
||||
CartItem::TrainingReservation.new(@customer,
|
||||
@operator,
|
||||
reservable,
|
||||
cart_item[:slots_attributes],
|
||||
plan: plan_info[:plan],
|
||||
new_subscription: plan_info[:new_subscription])
|
||||
when Event
|
||||
CartItem::EventReservation.new(@customer,
|
||||
@operator,
|
||||
reservable,
|
||||
cart_item[:slots_attributes],
|
||||
normal_tickets: cart_item[:nb_reserve_places],
|
||||
other_tickets: cart_item[:tickets_attributes])
|
||||
when Space
|
||||
CartItem::SpaceReservation.new(@customer,
|
||||
@operator,
|
||||
reservable,
|
||||
cart_item[:slots_attributes],
|
||||
plan: plan_info[:plan],
|
||||
new_subscription: plan_info[:new_subscription])
|
||||
else
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
@ -12,24 +12,25 @@ class CouponService
|
||||
# @param user_id {Number} user's id against the coupon will be tested for usability
|
||||
# @return {Number}
|
||||
##
|
||||
def apply(total, coupon, user_id = nil)
|
||||
def apply(total, coupon = nil, user_id = nil)
|
||||
price = total
|
||||
|
||||
coupon_object = nil
|
||||
if coupon.instance_of? Coupon
|
||||
coupon_object = coupon
|
||||
elsif coupon.instance_of? String
|
||||
coupon_object = Coupon.find_by(code: coupon)
|
||||
end
|
||||
coupon_object = if coupon.instance_of? Coupon
|
||||
coupon
|
||||
elsif coupon.instance_of? String
|
||||
Coupon.find_by(code: coupon)
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
unless coupon_object.nil?
|
||||
if coupon_object.status(user_id, total) == 'active'
|
||||
if coupon_object.type == 'percent_off'
|
||||
price -= (price * coupon_object.percent_off / 100.00).truncate
|
||||
elsif coupon_object.type == 'amount_off'
|
||||
# do not apply cash coupon unless it has a lower amount that the total price
|
||||
price -= coupon_object.amount_off if coupon_object.amount_off <= price
|
||||
end
|
||||
return price if coupon_object.nil?
|
||||
|
||||
if coupon_object.status(user_id, total) == 'active'
|
||||
if coupon_object.type == 'percent_off'
|
||||
price -= (price * coupon_object.percent_off / 100.00).truncate
|
||||
elsif coupon_object.type == 'amount_off'
|
||||
# do not apply cash coupon unless it has a lower amount that the total price
|
||||
price -= coupon_object.amount_off if coupon_object.amount_off <= price
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -184,6 +184,7 @@ Rails.application.routes.draw do
|
||||
post 'payzen/create_payment' => 'payzen#create_payment'
|
||||
post 'payzen/confirm_payment' => 'payzen#confirm_payment'
|
||||
post 'payzen/check_hash' => 'payzen#check_hash'
|
||||
post 'payzen/create_token' => 'payzen#create_token'
|
||||
|
||||
# FabAnalytics
|
||||
get 'analytics/data' => 'analytics#data'
|
||||
|
@ -32,5 +32,19 @@ class PayZen::Charge < PayZen::Client
|
||||
contrib: contrib,
|
||||
customer: customer)
|
||||
end
|
||||
|
||||
##
|
||||
# @see https://payzen.io/en-EN/rest/V4.0/api/playground/Charge/CreateToken/
|
||||
##
|
||||
def create_token(currency: Setting.get('payzen_currency'),
|
||||
order_id: nil,
|
||||
contrib: "fab-manager #{Version.current}",
|
||||
customer: nil)
|
||||
post('/Charge/CreateToken',
|
||||
currency: currency,
|
||||
orderId: order_id,
|
||||
contrib: contrib,
|
||||
customer: customer)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -52,6 +52,17 @@ class PayZen::Helper
|
||||
}
|
||||
end
|
||||
|
||||
## Generate a hash map compatible with PayZen 'V4/Customer/ShoppingCart'
|
||||
def generate_shopping_cart(cart_items, customer)
|
||||
{
|
||||
cartItemInfo: cart_items.map do |type, value|
|
||||
{
|
||||
productAmount: item.
|
||||
productType: customer.organization? ? 'SERVICE_FOR_BUSINESS' : 'SERVICE_FOR_INDIVIDUAL',
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
## Check the PayZen signature for integrity
|
||||
def check_hash(algorithm, hash_key, hash_proof, data, key = nil)
|
||||
supported_hash_algorithm = ['sha256_hmac']
|
||||
|
Loading…
x
Reference in New Issue
Block a user