barion 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +158 -0
- data/Rakefile +34 -0
- data/app/assets/config/barion_manifest.js +1 -0
- data/app/assets/stylesheets/barion/application.css +15 -0
- data/app/assets/stylesheets/barion/main.css +4 -0
- data/app/controllers/barion/application_controller.rb +7 -0
- data/app/controllers/barion/main_controller.rb +28 -0
- data/app/helpers/barion/application_helper.rb +7 -0
- data/app/helpers/barion/main_helper.rb +7 -0
- data/app/models/barion/address.rb +60 -0
- data/app/models/barion/application_record.rb +10 -0
- data/app/models/barion/gift_card_purchase.rb +66 -0
- data/app/models/barion/item.rb +88 -0
- data/app/models/barion/payer_account.rb +119 -0
- data/app/models/barion/payment.rb +348 -0
- data/app/models/barion/payment_transaction.rb +134 -0
- data/app/models/barion/purchase.rb +107 -0
- data/app/models/concerns/barion/currencies.rb +11 -0
- data/app/models/concerns/barion/data_formats.rb +12 -0
- data/app/models/concerns/barion/json_serializer.rb +106 -0
- data/app/views/barion/main/land.html.erb +7 -0
- data/config/initializers/barion.rb +9 -0
- data/config/routes.rb +10 -0
- data/db/migrate/20201222235354_create_barion_payments.rb +59 -0
- data/db/migrate/20201223001557_create_barion_addresses.rb +21 -0
- data/db/migrate/20201223002427_create_barion_payment_transactions.rb +28 -0
- data/db/migrate/20201223003219_create_barion_purchases.rb +24 -0
- data/db/migrate/20210111051233_create_barion_payer_accounts.rb +28 -0
- data/db/migrate/20210128220347_create_barion_items.rb +21 -0
- data/db/migrate/20210201120609_create_barion_gift_card_purchases.rb +14 -0
- data/lib/barion.rb +100 -0
- data/lib/barion/engine.rb +14 -0
- data/lib/barion/version.rb +5 -0
- data/lib/tasks/auto_annotate_models.rake +59 -0
- data/lib/tasks/barion_tasks.rake +4 -0
- metadata +207 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: barion_payment_transactions
|
6
|
+
#
|
7
|
+
# id :integer not null, primary key
|
8
|
+
# comment :string
|
9
|
+
# currency :string(3)
|
10
|
+
# payee :string not null
|
11
|
+
# payer :string
|
12
|
+
# status :integer default("prepared"), not null
|
13
|
+
# total :decimal(, ) not null
|
14
|
+
# transaction_time :datetime
|
15
|
+
# transaction_type :integer
|
16
|
+
# created_at :datetime not null
|
17
|
+
# updated_at :datetime not null
|
18
|
+
# payee_transactions_id :bigint
|
19
|
+
# payment_id :bigint
|
20
|
+
# pos_transaction_id :string not null
|
21
|
+
# related_id :string
|
22
|
+
# transaction_id :string
|
23
|
+
#
|
24
|
+
# Indexes
|
25
|
+
#
|
26
|
+
# index_barion_payment_transactions_on_payee (payee)
|
27
|
+
# index_barion_payment_transactions_on_payee_transactions_id (payee_transactions_id)
|
28
|
+
# index_barion_payment_transactions_on_payment_id (payment_id)
|
29
|
+
# index_barion_payment_transactions_on_pos_transaction_id (pos_transaction_id)
|
30
|
+
# index_barion_payment_transactions_on_status (status)
|
31
|
+
# index_barion_payment_transactions_on_transaction_id (transaction_id)
|
32
|
+
#
|
33
|
+
# Foreign Keys
|
34
|
+
#
|
35
|
+
# payee_transactions_id (payee_transactions_id => barion_payment_transactions.id)
|
36
|
+
# payment_id (payment_id => barion_payments.id)
|
37
|
+
#
|
38
|
+
module Barion
|
39
|
+
# Barion Transaction implementation
|
40
|
+
class PaymentTransaction < ApplicationRecord
|
41
|
+
include ::Barion::Currencies
|
42
|
+
include ::Barion::JsonSerializer
|
43
|
+
|
44
|
+
enum status: {
|
45
|
+
prepared: 0, started: 1, succeeded: 2, timeout: 3, shop_is_deleted: 4,
|
46
|
+
shop_is_closed: 5, rejected: 6, rejected_by_shop: 12, storno: 13, reserved: 14,
|
47
|
+
deleted: 15, expired: 16, authorized: 17, reversed: 18, invalid_payment_record: 210,
|
48
|
+
payment_time_out: 211, invalid_payment_status: 212,
|
49
|
+
payment_sender_or_recipient_is_invalid: 213, unknown: 255
|
50
|
+
}, _default: :prepared
|
51
|
+
enum transaction_type: {
|
52
|
+
shop: 1, transfer_to_existing_user: 2, transfer_to_technical_account: 3,
|
53
|
+
reserve: 16, storno_reserve: 17, card_processing_fee: 21, gateway_fee: 22,
|
54
|
+
card_processing_fee_storno: 23, unspecified: 100, card_payment: 150,
|
55
|
+
refund: 151, refund_to_bank_card: 152, storno_un_successful_refund_to_bank_card: 153,
|
56
|
+
under_review: 180, release_review: 190, bank_transfer_payment: 200,
|
57
|
+
refund_to_bank_account: 201, storno_un_successful_refund_to_bank_account: 202,
|
58
|
+
bank_transfer_payment_fee: 203
|
59
|
+
}
|
60
|
+
|
61
|
+
belongs_to :payment, inverse_of: :payment_transactions
|
62
|
+
has_many :items,
|
63
|
+
inverse_of: :payment_transaction,
|
64
|
+
after_add: :calc_total,
|
65
|
+
after_remove: :calc_total
|
66
|
+
attribute :total, :decimal, default: 0.0
|
67
|
+
attribute :pos_transaction_id, :string
|
68
|
+
|
69
|
+
validates :payee, presence: true
|
70
|
+
validates :status, presence: true
|
71
|
+
validates :pos_transaction_id, presence: true
|
72
|
+
validates :items, presence: true
|
73
|
+
validates_associated :items
|
74
|
+
|
75
|
+
after_initialize :set_defaults
|
76
|
+
|
77
|
+
def currency=(val = nil)
|
78
|
+
super(val || payment&.currency)
|
79
|
+
end
|
80
|
+
|
81
|
+
def set_defaults
|
82
|
+
self.currency = payment&.currency if currency.nil?
|
83
|
+
self.payee = ::Barion.default_payee if payee.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
def total=(value)
|
87
|
+
value = calc_item_totals if value.nil?
|
88
|
+
super(value)
|
89
|
+
end
|
90
|
+
|
91
|
+
def serialize_options
|
92
|
+
{ except: %i[id status created_at updated_at transaction_type related_id],
|
93
|
+
include: %i[items],
|
94
|
+
map: {
|
95
|
+
keys: {
|
96
|
+
_all: :camelize,
|
97
|
+
pos_transaction_id: 'POSTransactionId'
|
98
|
+
},
|
99
|
+
values: {
|
100
|
+
_all: proc { |v| v.respond_to?(:camelize) ? v.camelize : v },
|
101
|
+
_except: %w[items pos_transaction_id payee comment]
|
102
|
+
}
|
103
|
+
} }
|
104
|
+
end
|
105
|
+
|
106
|
+
def deserialize_options
|
107
|
+
{
|
108
|
+
except: %i[items],
|
109
|
+
map: {
|
110
|
+
keys: {
|
111
|
+
_all: :underscore,
|
112
|
+
POSTransactionId: 'pos_transaction_id'
|
113
|
+
},
|
114
|
+
values: {
|
115
|
+
_all: proc { |v| v.respond_to?(:underscore) ? v.underscore : v },
|
116
|
+
_except: %w[Currency]
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
protected
|
123
|
+
|
124
|
+
def calc_item_totals
|
125
|
+
items.sum(&:item_total)
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def calc_total(_item)
|
131
|
+
self.total = calc_item_totals
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# == Schema Information
|
4
|
+
#
|
5
|
+
# Table name: barion_purchases
|
6
|
+
#
|
7
|
+
# id :integer not null, primary key
|
8
|
+
# availability_indicator :integer
|
9
|
+
# delivery_email_address :string
|
10
|
+
# delivery_timeframe :integer
|
11
|
+
# pre_order_date :datetime
|
12
|
+
# purchase_date :datetime
|
13
|
+
# purchase_type :integer
|
14
|
+
# re_order_indicator :integer
|
15
|
+
# recurring_expiry :datetime
|
16
|
+
# recurring_frequency :integer
|
17
|
+
# shipping_address_indicator :integer
|
18
|
+
# created_at :datetime not null
|
19
|
+
# updated_at :datetime not null
|
20
|
+
# payment_id :bigint
|
21
|
+
#
|
22
|
+
# Indexes
|
23
|
+
#
|
24
|
+
# index_barion_purchases_on_delivery_email_address (delivery_email_address)
|
25
|
+
# index_barion_purchases_on_delivery_timeframe (delivery_timeframe)
|
26
|
+
# index_barion_purchases_on_payment_id (payment_id)
|
27
|
+
#
|
28
|
+
module Barion
|
29
|
+
# Represents a purchase in Barion engine
|
30
|
+
class Purchase < ApplicationRecord
|
31
|
+
include ::Barion::JsonSerializer
|
32
|
+
|
33
|
+
enum availability_indicator: {
|
34
|
+
merchandise_available: 0,
|
35
|
+
future_availability: 10
|
36
|
+
}, _default: :merchandise_available
|
37
|
+
|
38
|
+
attr_accessor :delivery_email_address
|
39
|
+
|
40
|
+
enum delivery_timeframe: {
|
41
|
+
electronic_delivery: 0,
|
42
|
+
same_day_shipping: 10,
|
43
|
+
overnight_shipping: 20,
|
44
|
+
two_day_or_more_shipping: 30
|
45
|
+
}
|
46
|
+
enum re_order_indicator: {
|
47
|
+
first_time_ordered: 0,
|
48
|
+
reordered: 10
|
49
|
+
}
|
50
|
+
enum shipping_address_indicator: {
|
51
|
+
ship_to_cardholders_billing_address: 0,
|
52
|
+
ship_to_another_verified_address: 10,
|
53
|
+
ship_to_different_address: 20,
|
54
|
+
ship_to_store: 30,
|
55
|
+
digital_goods: 40,
|
56
|
+
travel_and_event_tickets: 50,
|
57
|
+
other: 60
|
58
|
+
}
|
59
|
+
enum purchase_type: {
|
60
|
+
goods_and_service_purchase: 0,
|
61
|
+
check_acceptance: 1,
|
62
|
+
account_funding: 2,
|
63
|
+
quasi_cash_transaction: 3,
|
64
|
+
pre_paid_vacation_and_loan: 4
|
65
|
+
}
|
66
|
+
|
67
|
+
belongs_to :payment, inverse_of: :purchase_information
|
68
|
+
has_one :gift_card_purchase
|
69
|
+
|
70
|
+
validates :recurring_frequency,
|
71
|
+
numericality: { only_integer: true },
|
72
|
+
inclusion: { in: 0..9_999 },
|
73
|
+
allow_nil: true
|
74
|
+
|
75
|
+
with_options if: :initial_recurring_payment? do |purchase|
|
76
|
+
purchase.validates :recurring_frequency, presence: true
|
77
|
+
purchase.validates :recurring_expiry, presence: true
|
78
|
+
end
|
79
|
+
|
80
|
+
def serialize_options
|
81
|
+
{ except: %i[id created_at updated_at],
|
82
|
+
include: %i[gift_card_purchase],
|
83
|
+
map: {
|
84
|
+
keys: {
|
85
|
+
_all: :camelize
|
86
|
+
},
|
87
|
+
values: {
|
88
|
+
_all: proc { |v| v.respond_to?(:camelize) ? v.camelize : v },
|
89
|
+
pre_order_date: :as_datetime,
|
90
|
+
recurring_expiry: :as_datetime,
|
91
|
+
purchase_date: :as_datetime,
|
92
|
+
availability_indicator: :as_enum_id,
|
93
|
+
delivery_timeframe: :as_enum_id,
|
94
|
+
re_order_indicator: :as_ennum_id,
|
95
|
+
shipping_address_indicator: :as_enum_id,
|
96
|
+
purchase_type: :as_enum_id
|
97
|
+
}
|
98
|
+
} }
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def initial_recurring_payment?
|
104
|
+
payment.recurring? and payment.initiate_recurrence
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Barion
|
4
|
+
# JSON serialization solution for Barion
|
5
|
+
module JsonSerializer
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def serialize_options
|
9
|
+
{}
|
10
|
+
end
|
11
|
+
|
12
|
+
def deserialize_options
|
13
|
+
{}
|
14
|
+
end
|
15
|
+
|
16
|
+
def key_names
|
17
|
+
{}
|
18
|
+
end
|
19
|
+
|
20
|
+
def serializable_hash(options = {})
|
21
|
+
options ||= serialize_options
|
22
|
+
result = super(serialize_options.merge(options))
|
23
|
+
if serialize_options.key?(:map)
|
24
|
+
map = serialize_options[:map]
|
25
|
+
convert_values(result, map[:values], &map[:values][:_all]) if map.key?(:values)
|
26
|
+
convert_keys(result, map[:keys], &map[:keys][:_all]) if map.key?(:keys)
|
27
|
+
end
|
28
|
+
result.compact!
|
29
|
+
end
|
30
|
+
|
31
|
+
def deserialize(hash, options = {})
|
32
|
+
options ||= deserialize_options
|
33
|
+
deserialize_options.merge(options)
|
34
|
+
return unless deserialize_options.key?(:map)
|
35
|
+
|
36
|
+
map = deserialize_options[:map]
|
37
|
+
convert_values(hash, map[:values], &map[:values][:_all]) if map.key?(:values)
|
38
|
+
return unless map.key?(:keys)
|
39
|
+
|
40
|
+
convert_keys(hash, map[:keys], &map[:keys][:_all])
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_response(response)
|
44
|
+
exceptions = deserialize_options.fetch(:except, {})
|
45
|
+
associations = deserialize_options.fetch(:assoc, {})
|
46
|
+
|
47
|
+
hash = deserialize(response)
|
48
|
+
hash.map do |key, value|
|
49
|
+
next if exceptions.include?(key.to_sym)
|
50
|
+
|
51
|
+
association = self.class.reflect_on_association(key)
|
52
|
+
if association
|
53
|
+
(model_key_name, key_name) = associations[key.to_sym].shift
|
54
|
+
value.each do |params|
|
55
|
+
id = params[key_name]
|
56
|
+
item = association.klass.send("find_by_#{model_key_name}", id)
|
57
|
+
item.send(:process_response, params.compact!)
|
58
|
+
end
|
59
|
+
elsif respond_to?("#{key}=")
|
60
|
+
send("#{key}=", value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def convert_keys(hash, map, &block)
|
68
|
+
hash.transform_keys! { |k| map.fetch(k.to_sym, k) unless k.nil? }
|
69
|
+
hash.transform_keys!(&block) if block_given?
|
70
|
+
end
|
71
|
+
|
72
|
+
def convert_values(hash, map, &block)
|
73
|
+
hash.each do |k, v|
|
74
|
+
ks = k.to_sym
|
75
|
+
hash[k] = send(map[ks], ks, v) if v.present? && map.key?(ks) && respond_to?(map[ks], true)
|
76
|
+
end
|
77
|
+
hash_exceptions = hash.slice(*map[:_except])
|
78
|
+
hash.transform_values!(&block) if block_given?
|
79
|
+
hash.merge!(hash_exceptions)
|
80
|
+
end
|
81
|
+
|
82
|
+
def as_time(_, sec)
|
83
|
+
day, sec = sec.divmod(1.days)
|
84
|
+
hour, sec = sec.divmod(1.hour)
|
85
|
+
min, sec = sec.divmod(1.minute)
|
86
|
+
format('%<day>d.%02<hour>d:%02<min>d:%02<sec>d', day: day, hour: hour, min: min, sec: sec)
|
87
|
+
end
|
88
|
+
|
89
|
+
def as_datetime(_, date)
|
90
|
+
date.as_json.delete_suffix('Z')
|
91
|
+
end
|
92
|
+
|
93
|
+
def as_list(_, string)
|
94
|
+
string.camelize.split(',')
|
95
|
+
end
|
96
|
+
|
97
|
+
def as_enum_id(enum, id)
|
98
|
+
hash = self.class.send(enum.to_s.pluralize)
|
99
|
+
hash.fetch(id)
|
100
|
+
end
|
101
|
+
|
102
|
+
def as_string(_, value)
|
103
|
+
value.to_s
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Creates Barion::Payment record persistency
|
4
|
+
class CreateBarionPayments < ActiveRecord::Migration[6.0]
|
5
|
+
def change
|
6
|
+
# rubocop:disable Metrics/BlockLength
|
7
|
+
create_table :barion_payments do |t|
|
8
|
+
t.string :poskey, index: true, null: false
|
9
|
+
t.integer :payment_type, index: true, default: 0, null: false
|
10
|
+
t.integer :reservation_period, limit: 8
|
11
|
+
t.integer :delayed_capture_period, limit: 6
|
12
|
+
t.string :payment_window, limit: 6
|
13
|
+
t.boolean :guest_check_out
|
14
|
+
t.boolean :initiate_recurrence
|
15
|
+
t.string :recurrence_id, limit: 100, index: true
|
16
|
+
t.integer :funding_sources, default: 0
|
17
|
+
t.string :payment_request_id, limit: 100, index: true
|
18
|
+
t.string :payer_hint, limit: 256
|
19
|
+
t.string :card_holder_name_hint, limit: 45
|
20
|
+
t.integer :recurrence_type, default: 0
|
21
|
+
t.string :trace_id, limit: 100
|
22
|
+
t.string :redirect_url, limit: 2000
|
23
|
+
t.string :callback_url, limit: 2000
|
24
|
+
|
25
|
+
t.string :order_number, limit: 100, index: true
|
26
|
+
t.string :locale, limit: 10, null: false
|
27
|
+
t.string :currency, limit: 3, null: false
|
28
|
+
t.string :payer_phone_number, limit: 30
|
29
|
+
t.string :payer_work_phone_number, limit: 30
|
30
|
+
t.string :payer_home_number, limit: 30
|
31
|
+
t.integer :challenge_preference, default: 0
|
32
|
+
t.string :checksum, null: false
|
33
|
+
|
34
|
+
t.string :payment_id, index: true
|
35
|
+
t.integer :status, index: true, null: false
|
36
|
+
t.string :qr_url, limit: 2000
|
37
|
+
t.integer :recurrence_result
|
38
|
+
t.string :gateway_url, limit: 2000
|
39
|
+
|
40
|
+
t.string :pos_id
|
41
|
+
t.string :pos_name
|
42
|
+
t.string :pos_owner_email
|
43
|
+
t.string :pos_owner_country
|
44
|
+
t.integer :funding_source
|
45
|
+
t.datetime :created_at_barion
|
46
|
+
t.datetime :started_at
|
47
|
+
t.datetime :completed_at
|
48
|
+
t.datetime :valid_until
|
49
|
+
t.datetime :reserved_until
|
50
|
+
t.datetime :delayed_capture_until
|
51
|
+
t.decimal :total
|
52
|
+
t.string :suggested_local
|
53
|
+
t.integer :fraud_risk_score
|
54
|
+
|
55
|
+
t.timestamps
|
56
|
+
end
|
57
|
+
# rubocop:enable Metrics/BlockLength
|
58
|
+
end
|
59
|
+
end
|