Module: BetterAuth::Stripe::Utils

Defined in:
lib/better_auth/stripe/utils.rb

Class Method Summary collapse

Class Method Details

.active_or_trialing?(subscription) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/better_auth/stripe/utils.rb', line 70

def active_or_trialing?(subscription)
  %w[active trialing].include?(fetch(subscription, "status").to_s)
end

.checkout_line_items(config, plan, price_id, quantity, auto_managed_seats, seat_only_plan) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/better_auth/stripe/utils.rb', line 112

def checkout_line_items(config, plan, price_id, quantity, auto_managed_seats, seat_only_plan)
  items = []
  items << line_item(config, price_id, auto_managed_seats ? 1 : quantity) unless seat_only_plan
  items << {price: plan[:seat_price_id], quantity: quantity} if auto_managed_seats && plan[:seat_price_id]
  items.concat(plan_line_items(plan))
  items
end

.client(config) ⇒ Object



8
9
10
# File 'lib/better_auth/stripe/utils.rb', line 8

def client(config)
  BetterAuth::Plugins.stripe_client(config)
end

.direct_subscription_update?(old_plan, plan, auto_managed_seats) ⇒ Boolean

Returns:

  • (Boolean)


126
127
128
129
130
# File 'lib/better_auth/stripe/utils.rb', line 126

def direct_subscription_update?(old_plan, plan, auto_managed_seats)
  return true if auto_managed_seats && old_plan && old_plan[:seat_price_id] != plan[:seat_price_id]

  plan_line_items(old_plan || {}).map { |item| item[:price] } != plan_line_items(plan).map { |item| item[:price] }
end

.escape_search(value) ⇒ Object



190
191
192
# File 'lib/better_auth/stripe/utils.rb', line 190

def escape_search(value)
  value.to_s.gsub("\"", "\\\"")
end

.fetch(object, key) ⇒ Object



16
17
18
19
20
21
22
23
24
25
# File 'lib/better_auth/stripe/utils.rb', line 16

def fetch(object, key)
  return nil unless object.respond_to?(:[])

  return object[key] if object.respond_to?(:key?) && object.key?(key)

  symbol_key = key.to_sym
  return object[symbol_key] if object.respond_to?(:key?) && object.key?(symbol_key)

  object[key] || object[symbol_key]
end

.id(object) ⇒ Object



12
13
14
# File 'lib/better_auth/stripe/utils.rb', line 12

def id(object)
  fetch(object, "id")
end

.line_item(config, price_id, quantity) ⇒ Object



106
107
108
109
110
# File 'lib/better_auth/stripe/utils.rb', line 106

def line_item(config, price_id, quantity)
  item = {price: price_id}
  item[:quantity] = quantity unless metered_price?(config, price_id)
  item
end

.metered_price?(config, price_id, lookup_key = nil) ⇒ Boolean

Returns:

  • (Boolean)


132
133
134
135
136
# File 'lib/better_auth/stripe/utils.rb', line 132

def metered_price?(config, price_id, lookup_key = nil)
  price = resolve_stripe_price(config, price_id, lookup_key)
  recurring = fetch(price || {}, "recurring") || {}
  fetch(recurring, "usage_type") == "metered"
end

.pending_cancel?(subscription) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/better_auth/stripe/utils.rb', line 74

def pending_cancel?(subscription)
  !!(fetch(subscription, "cancelAtPeriodEnd") || fetch(subscription, "cancelAt"))
end

.plan_by_name(config, name) ⇒ Object



48
49
50
# File 'lib/better_auth/stripe/utils.rb', line 48

def plan_by_name(config, name)
  plans(config).find { |plan| plan[:name].to_s.downcase == name.to_s.downcase }
end

.plan_by_price_info(config, price_id, lookup_key = nil) ⇒ Object



52
53
54
55
56
# File 'lib/better_auth/stripe/utils.rb', line 52

def plan_by_price_info(config, price_id, lookup_key = nil)
  plans(config).find do |plan|
    plan[:price_id] == price_id || plan[:annual_discount_price_id] == price_id || (lookup_key && (plan[:lookup_key] == lookup_key || plan[:annual_discount_lookup_key] == lookup_key))
  end
end

.plan_line_items(plan) ⇒ Object



120
121
122
123
124
# File 'lib/better_auth/stripe/utils.rb', line 120

def plan_line_items(plan)
  Array(plan[:line_items]).map do |item|
    item.is_a?(Hash) ? BetterAuth::Plugins.normalize_hash(item) : item
  end
end

.plans(config) ⇒ Object



37
38
39
40
41
42
43
44
45
46
# File 'lib/better_auth/stripe/utils.rb', line 37

def plans(config)
  plans = subscription_options(config)[:plans] || []
  plans = plans.call if plans.respond_to?(:call)
  Array(plans).map do |plan|
    normalized = BetterAuth::Plugins.normalize_hash(plan)
    limits = fetch(plan, "limits")
    normalized[:limits] = limits if limits
    normalized
  end
end

.price_id(config, plan, annual = false) ⇒ Object



58
59
60
# File 'lib/better_auth/stripe/utils.rb', line 58

def price_id(config, plan, annual = false)
  annual ? (plan[:annual_discount_price_id] || resolve_lookup(config, plan[:annual_discount_lookup_key])) : (plan[:price_id] || resolve_lookup(config, plan[:lookup_key]))
end

.redirect?(body) ⇒ Boolean

Returns:

  • (Boolean)


180
181
182
# File 'lib/better_auth/stripe/utils.rb', line 180

def redirect?(body)
  body[:disable_redirect] != true
end

.resolve_lookup(config, lookup_key) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/better_auth/stripe/utils.rb', line 62

def resolve_lookup(config, lookup_key)
  return nil if lookup_key.to_s.empty?
  return nil unless client(config).respond_to?(:prices)

  prices = client(config).prices.list(lookup_keys: [lookup_key], active: true, limit: 1)
  fetch(Array(fetch(prices, "data")).first || {}, "id")
end

.resolve_plan_item(config, subscription) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/better_auth/stripe/utils.rb', line 86

def resolve_plan_item(config, subscription)
  items = Array(fetch(fetch(subscription, "items") || {}, "data"))
  first = items.first
  return nil unless first

  items.each do |item|
    price = fetch(item, "price") || {}
    plan = plan_by_price_info(config, fetch(price, "id"), fetch(price, "lookup_key"))
    return {item: item, plan: plan} if plan
  end
  {item: first, plan: nil} if items.length == 1
end

.resolve_quantity(subscription, plan_item, plan = nil) ⇒ Object



99
100
101
102
103
104
# File 'lib/better_auth/stripe/utils.rb', line 99

def resolve_quantity(subscription, plan_item, plan = nil)
  items = Array(fetch(fetch(subscription, "items") || {}, "data"))
  seat_price_id = plan && plan[:seat_price_id]
  seat_item = seat_price_id && items.find { |item| fetch(fetch(item, "price") || {}, "id") == seat_price_id }
  fetch(seat_item || plan_item, "quantity") || 1
end

.resolve_stripe_price(config, price_id, lookup_key = nil) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/better_auth/stripe/utils.rb', line 138

def resolve_stripe_price(config, price_id, lookup_key = nil)
  return nil unless client(config).respond_to?(:prices)

  prices = client(config).prices
  if lookup_key
    result = prices.list(lookup_keys: [lookup_key], active: true, limit: 1)
    Array(fetch(result, "data")).first
  elsif price_id && prices.respond_to?(:retrieve)
    prices.retrieve(price_id)
  end
rescue
  nil
end

.schedule_id(subscription) ⇒ Object



172
173
174
175
176
177
178
# File 'lib/better_auth/stripe/utils.rb', line 172

def schedule_id(subscription)
  schedule = fetch(subscription, "schedule")
  return nil if schedule.nil?
  return schedule if schedule.is_a?(String)

  id(schedule) || schedule.to_s
end

.stripe_pending_cancel?(subscription) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/better_auth/stripe/utils.rb', line 78

def stripe_pending_cancel?(subscription)
  !!(fetch(subscription, "cancel_at_period_end") || fetch(subscription, "cancel_at"))
end

.subscription_item(subscription) ⇒ Object



82
83
84
# File 'lib/better_auth/stripe/utils.rb', line 82

def subscription_item(subscription)
  Array(fetch(fetch(subscription, "items") || {}, "data")).first
end

.subscription_options(config) ⇒ Object



33
34
35
# File 'lib/better_auth/stripe/utils.rb', line 33

def subscription_options(config)
  BetterAuth::Plugins.normalize_hash(config[:subscription] || {})
end

.subscription_state(subscription, include_status: true, compact: true) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/better_auth/stripe/utils.rb', line 152

def subscription_state(subscription, include_status: true, compact: true)
  item = subscription_item(subscription)
  price = fetch(item || {}, "price") || {}
  recurring = fetch(price, "recurring") || {}
  state = {
    periodStart: time(fetch(item || subscription, "current_period_start")),
    periodEnd: time(fetch(item || subscription, "current_period_end")),
    cancelAtPeriodEnd: fetch(subscription, "cancel_at_period_end"),
    cancelAt: time(fetch(subscription, "cancel_at")),
    canceledAt: time(fetch(subscription, "canceled_at")),
    endedAt: time(fetch(subscription, "ended_at")),
    trialStart: time(fetch(subscription, "trial_start")),
    trialEnd: time(fetch(subscription, "trial_end")),
    billingInterval: fetch(recurring, "interval"),
    stripeScheduleId: schedule_id(subscription)
  }
  state[:status] = fetch(subscription, "status") if include_status
  compact ? state.compact : state
end

.time(value) ⇒ Object



27
28
29
30
31
# File 'lib/better_auth/stripe/utils.rb', line 27

def time(value)
  return nil unless value

  Time.at(value.to_i)
end

.url(ctx, url) ⇒ Object



184
185
186
187
188
# File 'lib/better_auth/stripe/utils.rb', line 184

def url(ctx, url)
  return url if url.to_s.match?(/\A[a-zA-Z][a-zA-Z0-9+\-.]*:/)

  "#{ctx.context.base_url}#{url.to_s.start_with?("/") ? url : "/#{url}"}"
end