Skip to content

Commit

Permalink
Pay now with payment intent
Browse files Browse the repository at this point in the history
  • Loading branch information
ciukstar committed Nov 30, 2023
1 parent 09b695f commit 9afd44c
Show file tree
Hide file tree
Showing 18 changed files with 262 additions and 246 deletions.
27 changes: 13 additions & 14 deletions config/routes.yesodroutes
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@

/create-payment-intent CreatePaymentIntentR POST
/checkout/#UserId CheckoutR GET

/scratch ScratchR GET

/billing/#UserId/billing BillingR GET
/billing/#UserId/invoices InvoicesR GET
Expand Down Expand Up @@ -35,17 +33,18 @@
/appointments/#BookId AppointmentR GET POST
/appointments AppointmentsR GET

/book/search BookSearchR GET POST
/book/end BookEndR GET
/book/#UserId/pay-completion BookPayCompletionR GET
/book/#UserId/payment-intent BookPaymentIntentR POST
/book/#UserId/pay-now BookPayNowR GET
/book/#UserId/pay-at-venue BookPayAtVenueR GET
/book/#UserId/pay BookPayR GET POST
/book/customer BookCustomerR GET POST
/book/time BookTimeR GET POST
/book/staff BookStaffR GET POST
/book BookOffersR GET POST
/book/search BookSearchR GET POST
/book/end BookEndR GET
/book/#UserId/pi/#Text BookPaymentIntentCancelR POST
/book/#UserId/pay-completion BookPayCompletionR GET
/book/#UserId/pi/#Int/#Text BookPaymentIntentR POST
/book/#UserId/pay-now BookPayNowR GET
/book/#UserId/pay-at-venue BookPayAtVenueR GET
/book/#UserId/pay BookPayR GET POST
/book/customer BookCustomerR GET POST
/book/time BookTimeR GET POST
/book/staff BookStaffR GET POST
/book BookOffersR GET POST

/aboutus AboutUsR GET

Expand Down
3 changes: 3 additions & 0 deletions messages/en.msg
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
PaymentIntentCancelled: Payment intent was cancelled
Pay: Pay
PaymentAmount: Payment amount
TotalPrice: Total price
Completion: Completion
Checkout: Checkout
Expand Down
3 changes: 3 additions & 0 deletions messages/fr.msg
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
PaymentIntentCancelled: L'intention de paiement a été annulée
Pay: Payez
PaymentAmount: Montant du paiement
TotalPrice: Prix ​​total
Completion: Finalisation
Checkout: Vérifier
Expand Down
3 changes: 3 additions & 0 deletions messages/ro.msg
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
PaymentIntentCancelled: Intenția de plată a fost anulată
Pay: Plătiți
PaymentAmount: Suma de plată
TotalPrice: Prețul total
Completion: Finalizare
Checkout: Verifică
Expand Down
3 changes: 3 additions & 0 deletions messages/ru.msg
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
PaymentIntentCancelled: Намерение платежа было отменено
Pay: Заплатить
PaymentAmount: Сумма платежа
TotalPrice: Итоговая цена
Completion: Завершение
Checkout: Оформить заказ
Expand Down
5 changes: 3 additions & 2 deletions src/Application.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import Demo.DemoDataEN (populateEN)
-- Import all relevant handler modules here.
-- Don't forget to add new modules to your cabal file!

import Handler.Checkout (getCheckoutR, postCreatePaymentIntentR)
import Handler.Scratch (getScratchR)

import Handler.Billing
( getBillingR, getInvoicesR )
Expand Down Expand Up @@ -87,7 +87,8 @@ import Handler.Book
, getBookCustomerR, postBookCustomerR
, getBookPayR, postBookPayR
, getBookPayAtVenueR
, getBookPayNowR, postBookPaymentIntentR, getBookPayCompletionR
, getBookPayNowR, postBookPaymentIntentR
, postBookPaymentIntentCancelR, getBookPayCompletionR
, getBookEndR
, getBookSearchR, postBookSearchR
)
Expand Down
8 changes: 4 additions & 4 deletions src/Foundation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ instance Yesod App where

isAuthorized :: Route App -> Bool -> Handler AuthResult

isAuthorized ScratchR _ = return Authorized

isAuthorized (StaticR _) _ = return Authorized

isAuthorized (AuthR _) _ = return Authorized
Expand All @@ -131,9 +133,6 @@ instance Yesod App where
isAuthorized RobotsR _ = return Authorized
isAuthorized PhotoPlaceholderR _ = return Authorized


isAuthorized r@(CreatePaymentIntentR) _ = setUltDest r >> isAuthenticated
isAuthorized r@(CheckoutR _) _ = setUltDest r >> isAuthenticated
isAuthorized r@(InvoicesR _) _ = setUltDest r >> isAuthenticated
isAuthorized r@(BillingR _) _ = setUltDest r >> isAuthenticated

Expand Down Expand Up @@ -231,8 +230,9 @@ instance Yesod App where
isAuthorized ContactR _ = return Authorized

isAuthorized BookEndR _ = return Authorized
isAuthorized (BookPaymentIntentCancelR _ _) _ = isAuthenticated
isAuthorized (BookPayCompletionR _) _ = isAuthenticated
isAuthorized (BookPaymentIntentR _) _ = isAuthenticated
isAuthorized (BookPaymentIntentR {}) _ = isAuthenticated
isAuthorized (BookPayNowR _) _ = isAuthenticated
isAuthorized (BookPayAtVenueR _) _ = isAuthenticated
isAuthorized (BookPayR _) _ = isAuthenticated
Expand Down
133 changes: 102 additions & 31 deletions src/Handler/Book.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Handler.Book
, getBookPayNowR
, postBookPaymentIntentR
, getBookPayCompletionR
, postBookPaymentIntentCancelR
, getBookEndR
, getBookSearchR
, postBookSearchR
Expand All @@ -33,6 +34,7 @@ import Data.Aeson.Lens (key)
import Data.Aeson (object, (.=))
import qualified Data.Aeson as A (Value)
import Data.Bifunctor (Bifunctor(second))
import qualified Data.ByteString as BS (empty)
import Data.Either (isLeft)
import Data.Maybe (maybeToList, isJust, fromMaybe)
import Data.Fixed (Centi)
Expand All @@ -51,8 +53,10 @@ import Network.Wreq
( postWith, defaults, auth, basicAuth, FormParam ((:=)), responseBody
)
import Text.Hamlet (Html)
import Text.Julius (rawJS)
import Text.Shakespeare.I18N (renderMessage, SomeMessage (SomeMessage))
import Text.Read (readMaybe)
import Text.Printf (printf)

import Yesod.Core
( Yesod(defaultLayout), YesodRequest (reqGetParams), liftHandler
Expand Down Expand Up @@ -99,7 +103,7 @@ import Foundation
, HomeR, AppointmentsR, AppointmentR, ProfileR, ServiceThumbnailR
, BookOffersR, BookStaffR, BookTimeR, BookCustomerR, BookPayR
, BookPayNowR, BookPayCompletionR, BookPayAtVenueR, BookEndR
, BookSearchR, BookPaymentIntentR
, BookSearchR, BookPaymentIntentR, BookPaymentIntentCancelR
)
, AdminR (AdmStaffPhotoR)
, AppMessage
Expand All @@ -120,7 +124,8 @@ import Foundation
, MsgUserProfile, MsgNavigationMenu, MsgNoOffersYet, MsgNoOffersFound
, MsgNoCategoriesFound, MsgCongratulations, MsgShowMyAppointments
, MsgPaymentMethod, MsgPayAtVenue, MsgPayNow, MsgDebitCreditCard, MsgCheckout
, MsgCompletionTime, MsgCompletion, MsgTotalPrice
, MsgCompletionTime, MsgCompletion, MsgTotalPrice, MsgPaymentAmount, MsgPay
, MsgPaymentIntentCancelled
)
)

Expand All @@ -141,10 +146,21 @@ import Model
)

import Menu (menu)


getBookPayAtVenueR :: UserId -> Handler Html
getBookPayAtVenueR uid = do
user <- maybeAuth
let times = []
let rids = []
let oids = []
let dates = []

postPaymentR :: Handler Html
postPaymentR = undefined
curr <- getCurrentRoute

defaultLayout $ do
setTitleI MsgPaymentMethod
-- $( widgetFile "book/payment/payment")


getBookPayCompletionR :: UserId -> Handler Html
Expand All @@ -157,52 +173,107 @@ getBookPayCompletionR uid = do
$(widgetFile "book/payment/completion")


postBookPaymentIntentR :: UserId -> Handler A.Value
postBookPaymentIntentR uid = do
let stripeApi = "https://api.stripe.com/v1/payment_intents"
postBookPaymentIntentCancelR :: UserId -> Text -> Handler ()
postBookPaymentIntentCancelR uid intent = do
stati <- reqGetParams <$> getRequest
let api = printf "https://api.stripe.com/v1/payment_intents/%s/cancel" intent
sk <- encodeUtf8 . appStripeSk . appSettings <$> getYesod
let opts = defaults & auth ?~ basicAuth sk ""
r <- liftIO $ postWith opts api BS.empty
addMessageI info MsgPaymentIntentCancelled
redirect (BookPayR uid,("pm",pack $ show PayNow) : stati)


postBookPaymentIntentR :: UserId -> Int -> Text -> Handler A.Value
postBookPaymentIntentR uid cents currency = do
let api = "https://api.stripe.com/v1/payment_intents"
sk <- encodeUtf8 . appStripeSk . appSettings <$> getYesod
let opts = defaults & auth ?~ basicAuth sk ""
r <- liftIO $ postWith opts stripeApi [ "amount" := (1300 :: Int)
, "currency" := ("usd" :: Text)
, "payment_method_types[]" := ("card" :: Text)
]
r <- liftIO $ postWith opts api [ "amount" := cents
, "currency" := currency
, "payment_method_types[]" := ("card" :: Text)
]

returnJson $ object [ "clientSecret" .= (r ^? responseBody . key "client_secret")]


getBookPayNowR :: UserId -> Handler Html
getBookPayNowR uid = do
stati <- reqGetParams <$> getRequest
user <- maybeAuth
pk <- appStripePk . appSettings <$> getYesod
let times = []
let rids = []
let oids = []
let dates = []

curr <- getCurrentRoute
rids <- filter ((== "rid") . fst) . reqGetParams <$> getRequest
oids <- filter ((== "oid") . fst) . reqGetParams <$> getRequest
dates <- filter ((== "date") . fst) . reqGetParams <$> getRequest
times <- filter ((== "time") . fst) . reqGetParams <$> getRequest

items <- runDB $ queryItems [] Nothing (toSqlKey . read . unpack . snd <$> oids)

let amount = sumOf (folded . _1 . _2 . to entityVal . _offerPrice) items
let cents = truncate $ 100 * amount

currency <- maybe "USD" unValue <$> runDB ( selectOne $ do
x <- from $ table @Business
return $ x ^. BusinessCurrency )

curr <- getCurrentRoute
formPaymentIntentCancel <- newIdent
sectionPriceTag <- newIdent
formPayment <- newIdent
elementPayment <- newIdent
buttonSubmitPayment <- newIdent
buttonCancelPayment <- newIdent
defaultLayout $ do
setTitleI MsgCheckout
addScriptRemote "https://js.stripe.com/v3/"
$(widgetFile "book/payment/checkout/checkout")


getBookPayAtVenueR :: UserId -> Handler Html
getBookPayAtVenueR uid = do
user <- maybeAuth
let times = []
let rids = []
let oids = []
let dates = []

curr <- getCurrentRoute

defaultLayout $ do
setTitleI MsgPaymentMethod
-- $( widgetFile "book/payment/payment")
postBookPayR :: UserId -> Handler Html
postBookPayR uid = do
stati <- reqGetParams <$> getRequest
user <- maybeAuth

rids <- filter ((== "rid") . fst) . reqGetParams <$> getRequest
oids <- filter ((== "oid") . fst) . reqGetParams <$> getRequest
dates <- filter ((== "date") . fst) . reqGetParams <$> getRequest
times <- filter ((== "time") . fst) . reqGetParams <$> getRequest
pms <- filter ((== "pm") . fst) . reqGetParams <$> getRequest

postBookPayR :: UserId -> Handler Html
postBookPayR uid = undefined
let payMethod = (read . unpack . snd <$>) $ LS.head pms

items <- runDB $ queryItems [] Nothing (toSqlKey . read . unpack . snd <$> oids)
role <- runDB $ selectOne $ do
x :& s <- from $ table @Role `innerJoin` table @Staff `on` (\(x :& s) -> x ^. RoleStaff ==. s ^. StaffId)
where_ $ x ^. RoleId `in_` valList (toSqlKey . read . unpack . snd <$> rids)
return (s,x)

business <- runDB $ selectOne $ from $ table @Business
currency <- (unValue <$>) <$> runDB ( selectOne $ do
x <- from $ table @Business
return $ x ^. BusinessCurrency )

((fr,fw),et) <- runFormPost $ formPayMethod
payMethod uid stati user
((read . unpack . snd <$>) $ LS.head dates)
((read . unpack . snd <$>) $ LS.head times)
business
items items role (maybeToList role)

case fr of
FormSuccess (items,role,day,time,addr,tzo,tz,Entity uid _,PayNow) -> do
redirect (BookPayNowR uid,stati)
FormSuccess (items,role,day,time,addr,tzo,tz,Entity uid _,PayAtVenue) -> do
redirect (BookPayAtVenueR uid)
_ -> do
msgs <- getMessages
setUltDestCurrent
sectionPriceTag <- newIdent
formPaymentMethod <- newIdent
defaultLayout $ do
setTitleI MsgPaymentMethod
$(widgetFile "book/payment/payment")


getBookPayR :: UserId -> Handler Html
Expand Down
51 changes: 0 additions & 51 deletions src/Handler/Checkout.hs

This file was deleted.

14 changes: 14 additions & 0 deletions src/Handler/Scratch.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}

module Handler.Scratch (getScratchR) where


import Foundation (Handler)
import Text.Hamlet (Html)
import Yesod.Core (Yesod(defaultLayout))
import Settings (widgetFile)

getScratchR :: Handler Html
getScratchR = do
defaultLayout $(widgetFile "scratch/scratch")
8 changes: 0 additions & 8 deletions templates/book/checkout/checkout.hamlet

This file was deleted.

Loading

0 comments on commit 9afd44c

Please sign in to comment.