@@ -2,10 +2,15 @@ defmodule Algora.Payments do
22 @ moduledoc false
33 import Ecto.Query
44
5+ alias Algora.Accounts
6+ alias Algora.Accounts.User
7+ alias Algora.Payments.Account
58 alias Algora.Payments.Customer
69 alias Algora.Payments.PaymentMethod
710 alias Algora.Payments.Transaction
811 alias Algora.Repo
12+ alias Algora.Stripe.ConnectCountries
13+ alias Algora.Util
914
1015 require Logger
1116
@@ -128,4 +133,119 @@ defmodule Algora.Payments do
128133 |> order_by ( [ t ] , desc: t . inserted_at )
129134 |> Repo . all ( )
130135 end
136+
137+ @ spec fetch_or_create_account ( user :: User . t ( ) , country :: String . t ( ) ) ::
138+ { :ok , Account . t ( ) } | { :error , Ecto.Changeset . t ( ) }
139+ def fetch_or_create_account ( user , country ) do
140+ case fetch_account ( user ) do
141+ { :ok , account } -> { :ok , account }
142+ { :error , :not_found } -> create_account ( user , country )
143+ end
144+ end
145+
146+ @ spec fetch_account ( user :: User . t ( ) ) ::
147+ { :ok , Account . t ( ) } | { :error , :not_found }
148+ def fetch_account ( user ) do
149+ Repo . fetch_by ( Account , user_id: user . id )
150+ end
151+
152+ @ spec create_account ( user :: User . t ( ) , country :: String . t ( ) ) ::
153+ { :ok , Account . t ( ) } | { :error , Ecto.Changeset . t ( ) }
154+ def create_account ( user , country ) do
155+ type = ConnectCountries . account_type ( country )
156+
157+ with { :ok , stripe_account } <- create_stripe_account ( % { country: country , type: type } ) do
158+ attrs = % {
159+ provider: "stripe" ,
160+ provider_id: stripe_account . id ,
161+ provider_meta: Util . normalize_struct ( stripe_account ) ,
162+ type: type ,
163+ user_id: user . id ,
164+ country: country
165+ }
166+
167+ % Account { }
168+ |> Account . changeset ( attrs )
169+ |> Repo . insert ( )
170+ end
171+ end
172+
173+ @ spec create_stripe_account ( attrs :: map ( ) ) ::
174+ { :ok , Stripe.Account . t ( ) } | { :error , Stripe.Error . t ( ) }
175+ defp create_stripe_account ( % { country: country , type: type } ) do
176+ case Stripe.Account . create ( % { country: country , type: to_string ( type ) } ) do
177+ { :ok , account } -> { :ok , account }
178+ { :error , _reason } -> Stripe.Account . create ( % { type: to_string ( type ) } )
179+ end
180+ end
181+
182+ @ spec create_account_link ( account :: Account . t ( ) , base_url :: String . t ( ) ) ::
183+ { :ok , Stripe.AccountLink . t ( ) } | { :error , Stripe.Error . t ( ) }
184+ def create_account_link ( account , base_url ) do
185+ Stripe.AccountLink . create ( % {
186+ account: account . provider_id ,
187+ refresh_url: "#{ base_url } /callbacks/stripe/refresh" ,
188+ return_url: "#{ base_url } /callbacks/stripe/return" ,
189+ type: "account_onboarding"
190+ } )
191+ end
192+
193+ @ spec create_login_link ( account :: Account . t ( ) ) ::
194+ { :ok , Stripe.LoginLink . t ( ) } | { :error , Stripe.Error . t ( ) }
195+ def create_login_link ( account ) do
196+ Stripe.LoginLink . create ( account . provider_id , % { } )
197+ end
198+
199+ @ spec update_account ( account :: Account . t ( ) , stripe_account :: Stripe.Account . t ( ) ) ::
200+ { :ok , Account . t ( ) } | { :error , Ecto.Changeset . t ( ) }
201+ def update_account ( account , stripe_account ) do
202+ account
203+ |> Account . changeset ( % {
204+ provider: "stripe" ,
205+ provider_id: stripe_account . id ,
206+ provider_meta: Util . normalize_struct ( stripe_account ) ,
207+ charges_enabled: stripe_account . charges_enabled ,
208+ payouts_enabled: stripe_account . payouts_enabled ,
209+ payout_interval: stripe_account . settings . payouts . schedule . interval ,
210+ payout_speed: stripe_account . settings . payouts . schedule . delay_days ,
211+ default_currency: stripe_account . default_currency ,
212+ details_submitted: stripe_account . details_submitted ,
213+ country: stripe_account . country ,
214+ service_agreement: get_service_agreement ( stripe_account )
215+ } )
216+ |> Repo . update ( )
217+ end
218+
219+ @ spec refresh_stripe_account ( user :: User . t ( ) ) ::
220+ { :ok , Account . t ( ) } | { :error , Ecto.Changeset . t ( ) } | { :error , :not_found } | { :error , Stripe.Error . t ( ) }
221+ def refresh_stripe_account ( user ) do
222+ with { :ok , account } <- fetch_account ( user ) ,
223+ { :ok , stripe_account } <- Stripe.Account . retrieve ( account . provider_id , [ ] ) ,
224+ { :ok , updated_account } <- update_account ( account , stripe_account ) do
225+ user = Accounts . get_user ( account . user_id )
226+
227+ if user && stripe_account . charges_enabled do
228+ Accounts . update_settings ( user , % { country: stripe_account . country } )
229+ end
230+
231+ { :ok , updated_account }
232+ end
233+ end
234+
235+ @ spec get_service_agreement ( account :: Stripe.Account . t ( ) ) :: String . t ( )
236+ defp get_service_agreement ( % { tos_acceptance: % { service_agreement: agreement } } = _account ) when not is_nil ( agreement ) do
237+ agreement
238+ end
239+
240+ @ spec get_service_agreement ( account :: Stripe.Account . t ( ) ) :: String . t ( )
241+ defp get_service_agreement ( % { capabilities: capabilities } ) do
242+ if is_nil ( capabilities [ :card_payments ] ) , do: "recipient" , else: "full"
243+ end
244+
245+ @ spec delete_account ( account :: Account . t ( ) ) :: { :ok , Account . t ( ) } | { :error , Ecto.Changeset . t ( ) }
246+ def delete_account ( account ) do
247+ with { :ok , _stripe_account } <- Stripe.Account . delete ( account . provider_id ) do
248+ Repo . delete ( account )
249+ end
250+ end
131251end
0 commit comments