Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/mobility-core/src/Kernel/External/Payment/Interface.hs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ getCustomer ::
m CreateCustomerResp
getCustomer config customerId = case config of
JuspayConfig cfg -> Juspay.getCustomer cfg customerId
StripeConfig _ -> throwError $ InternalError "Stripe Get Customer not supported."
StripeConfig cfg -> Stripe.getCustomer cfg customerId
PaytmEDCConfig _ -> throwError $ InternalError "PaytmEDC Get Customer not supported."

createEphemeralKeys ::
Expand All @@ -273,7 +273,7 @@ createEphemeralKeys ::
) =>
PaymentServiceConfig ->
CustomerId ->
m Text
m CreateEphemeralKeysResp
createEphemeralKeys config customerId = case config of
JuspayConfig _ -> throwError $ InternalError "Juspay Create Ephemeral Keys not supported."
StripeConfig cfg -> Stripe.createEphemeralKeys cfg customerId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ createCustomer config req = do
CreateCustomerResp
{ customerId = object_reference_id,
clientAuthToken = Customer.client_auth_token <$> juspay,
clientAuthTokenExpiry = Customer.client_auth_token_expiry <$> juspay
clientAuthTokenExpiry = Customer.client_auth_token_expiry <$> juspay,
isLiveMode = Nothing
}

getCustomer ::
Expand All @@ -173,7 +174,8 @@ getCustomer config customerId = do
CreateCustomerResp
{ customerId = object_reference_id,
clientAuthToken = Customer.client_auth_token <$> juspay,
clientAuthTokenExpiry = Customer.client_auth_token_expiry <$> juspay
clientAuthTokenExpiry = Customer.client_auth_token_expiry <$> juspay,
isLiveMode = Nothing
}
mkGetCustomerReq =
Juspay.GetCustomerReq
Expand Down
107 changes: 101 additions & 6 deletions lib/mobility-core/src/Kernel/External/Payment/Interface/Stripe.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Kernel.External.Payment.Interface.Stripe
where

import Control.Applicative ((<|>))
import qualified Data.Text as T
import Data.Time
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import Kernel.External.Encryption
Expand Down Expand Up @@ -35,6 +36,8 @@ createIndividualConnectAccount ::
createIndividualConnectAccount config req = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "createIndividualConnectAccount" apiKeyServiceMode config.serviceMode
let accountReq = mkAccountReq
accountResp <- Stripe.createAccount url apiKey accountReq
let accountId = accountResp.id
Expand Down Expand Up @@ -125,6 +128,8 @@ retryAccountLink ::
retryAccountLink config accountId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "retryAccountLink" apiKeyServiceMode config.serviceMode
let accountLinkReq = mkAccountLinkReq config accountId
accountLinkResp <- Stripe.createAccountLink url apiKey accountLinkReq
let accountUrlExpiry = posixSecondsToUTCTime accountLinkResp.expires_at
Expand All @@ -143,6 +148,8 @@ getAccount ::
getAccount config accountId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "getAccount" apiKeyServiceMode config.serviceMode
accountResp <- Stripe.getAccount url apiKey accountId
let chargesEnabled = accountResp.charges_enabled
let detailsSubmitted = accountResp.details_submitted
Expand All @@ -160,11 +167,14 @@ createCustomer ::
createCustomer config req = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "createCustomer" apiKeyServiceMode config.serviceMode
let customerReq = mkCustomerReq req
customerResp <- Stripe.createCustomer url apiKey customerReq
let customerId = customerResp.id
let clientAuthToken = Nothing
let clientAuthTokenExpiry = Nothing
clientAuthToken = Nothing
clientAuthTokenExpiry = Nothing
isLiveMode = customerResp.livemode
return $ CreateCustomerResp {..}
where
mkCustomerReq :: CreateCustomerReq -> Stripe.CustomerReq
Expand All @@ -177,6 +187,26 @@ createCustomer config req = do
phone = phone
}

getCustomer ::
( Metrics.CoreMetrics m,
EncFlow m r,
HasRequestId r,
MonadReader r m
) =>
StripeCfg ->
CustomerId ->
m CreateCustomerResp
getCustomer config customerId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "getCustomer" apiKeyServiceMode config.serviceMode
customerResp <- Stripe.getCustomer url apiKey customerId
let clientAuthToken = Nothing
clientAuthTokenExpiry = Nothing
isLiveMode = customerResp.livemode
return $ CreateCustomerResp {customerId = customerResp.id, ..}

createEphemeralKeys ::
( Metrics.CoreMetrics m,
EncFlow m r,
Expand All @@ -185,13 +215,19 @@ createEphemeralKeys ::
) =>
StripeCfg ->
CustomerId ->
m Text
m CreateEphemeralKeysResp
createEphemeralKeys config customerId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "createEphemeralKeys" apiKeyServiceMode config.serviceMode
let ephemeralKeysReq = Stripe.EphemeralKeysReq {customer = customerId}
ephemeralKeysResp <- Stripe.createEphemeralKeys url apiKey ephemeralKeysReq
return ephemeralKeysResp.secret
return
CreateEphemeralKeysResp
{ ephemeralKeySecret = ephemeralKeysResp.secret,
isLiveMode = ephemeralKeysResp.livemode
}

getCardList ::
( Metrics.CoreMetrics m,
Expand All @@ -205,6 +241,8 @@ getCardList ::
getCardList config customerId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "getCardList" apiKeyServiceMode config.serviceMode
paymentMethodListResp <- Stripe.getPaymentMethodList url apiKey customerId
let cards = map mkCard paymentMethodListResp._data
return cards
Expand Down Expand Up @@ -232,6 +270,8 @@ deleteCard ::
deleteCard config paymentMethodId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "deleteCard" apiKeyServiceMode config.serviceMode
void $ Stripe.detachPaymentMethod url apiKey paymentMethodId

createPaymentIntent ::
Expand All @@ -246,6 +286,8 @@ createPaymentIntent ::
createPaymentIntent config req = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "createPaymentIntent" apiKeyServiceMode config.serviceMode
case config.chargeDestination of
-- Platform receives payment, transfers to driver (Destination Charges)
Platform -> createPlatformCharge url apiKey req
Expand Down Expand Up @@ -323,11 +365,14 @@ createSetupIntent ::
createSetupIntent config customerId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "createSetupIntent" apiKeyServiceMode config.serviceMode
let setupIntentReq = mkSetupIntentReq
setupIntentResp <- Stripe.createSetupIntent url apiKey setupIntentReq
let setupIntentId = setupIntentResp.id
let clientSecret = setupIntentResp.client_secret
let status = setupIntentResp.status
clientSecret = setupIntentResp.client_secret
status = setupIntentResp.status
isLiveMode = setupIntentResp.livemode
return $ CreateSetupIntentResp {..}
where
mkSetupIntentReq :: Stripe.SetupIntentReq
Expand All @@ -353,6 +398,8 @@ cancelPaymentIntent ::
cancelPaymentIntent config paymentIntentId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "cancelPaymentIntent" apiKeyServiceMode config.serviceMode
paymentIntentResp <- Stripe.cancelPaymentIntent url apiKey paymentIntentId
let clientSecret = paymentIntentResp.client_secret
let status = paymentIntentResp.status
Expand All @@ -371,6 +418,8 @@ updatePaymentMethodInIntent ::
updatePaymentMethodInIntent config paymentIntentId paymentMethodId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "updatePaymentMethodInIntent" apiKeyServiceMode config.serviceMode
let confirmPaymentIntentReq = Stripe.ConfirmPaymentIntentReq {payment_method = paymentMethodId}
void $ Stripe.confirmPaymentIntent url apiKey paymentIntentId confirmPaymentIntentReq

Expand All @@ -387,6 +436,8 @@ getCard ::
getCard config paymentMethodId customerId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "getCard" apiKeyServiceMode config.serviceMode
cardObjectResp <- Stripe.getCard url apiKey customerId paymentMethodId
let card = mkCard cardObjectResp
return card
Expand Down Expand Up @@ -414,6 +465,8 @@ getPaymentIntent ::
getPaymentIntent config paymentIntentId = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "getPaymentIntent" apiKeyServiceMode config.serviceMode
paymentIntentResp <- Stripe.getPaymentIntent url apiKey paymentIntentId
let clientSecret = paymentIntentResp.client_secret
let status = paymentIntentResp.status
Expand All @@ -433,6 +486,8 @@ capturePaymentIntent ::
capturePaymentIntent config paymentIntentId amount applicationFeeAmount = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "capturePaymentIntent" apiKeyServiceMode config.serviceMode
let amount_to_capture = usdToCents amount
let application_fee_amount = usdToCents applicationFeeAmount
let req = Stripe.CapturePaymentIntentReq {..}
Expand All @@ -452,6 +507,8 @@ updateAmountInPaymentIntent ::
updateAmountInPaymentIntent config paymentIntentId amount_ applicationFeeAmount = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "updateAmountInPaymentIntent" apiKeyServiceMode config.serviceMode
let amount = usdToCents amount_
let application_fee_amount = usdToCents applicationFeeAmount
let req = Stripe.IncrementAuthorizationReq {..}
Expand Down Expand Up @@ -649,6 +706,8 @@ createRefund ::
createRefund config req = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "createRefund" apiKeyServiceMode config.serviceMode
case config.chargeDestination of
-- Platform receives payment, transfers to driver (Destination Charges)
Platform -> createPlatformRefund url apiKey
Expand Down Expand Up @@ -702,6 +761,8 @@ getRefund ::
getRefund config req = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "getRefund" apiKeyServiceMode config.serviceMode
case config.chargeDestination of
Platform -> mkGetRefundResp <$> Stripe.getRefund url apiKey Nothing req.id
ConnectedAccount -> mkGetRefundResp <$> Stripe.getRefund url apiKey (Just req.driverAccountId) req.id
Expand All @@ -718,6 +779,8 @@ cancelRefund ::
cancelRefund config req = do
let url = config.url
apiKey <- decrypt config.apiKey
let apiKeyServiceMode = getServiceModeFromApiKey apiKey
logServiceModeMismatch "cancelRefund" apiKeyServiceMode config.serviceMode
case config.chargeDestination of
Platform -> mkGetRefundResp <$> Stripe.cancelRefund url apiKey Nothing req.id
ConnectedAccount -> mkGetRefundResp <$> Stripe.cancelRefund url apiKey (Just req.driverAccountId) req.id
Expand All @@ -736,3 +799,35 @@ mkGetRefundResp Stripe.RefundObject {..} =
reverseTransferId = transfer_reversal,
errorCode = failure_reason
}

-- Debug payment mode mistmatch (do not expose any credentials)
logServiceModeMismatch ::
Log m =>
Text ->
Maybe ServiceMode ->
Maybe ServiceMode ->
m ()
logServiceModeMismatch action apiKeyServiceMode cfgServiceMode = do
if (Just (fromMaybe Live cfgServiceMode) == apiKeyServiceMode)
then do
logInfo $
"Stripe service api call:"
<> action
<> "; service mode: "
<> show apiKeyServiceMode
else do
logWarning $
"Payment mode mismatch while Stripe service api call: "
<> action
<> "; api key service mode: "
<> show apiKeyServiceMode
<> "; cfg service mode: "
<> show cfgServiceMode

getServiceModeFromApiKey :: Text -> Maybe ServiceMode
getServiceModeFromApiKey apiKey
| "sk_live_" `T.isPrefixOf` apiKey = Just Live
| "sk_test_" `T.isPrefixOf` apiKey = Just Test
| "rk_live_" `T.isPrefixOf` apiKey = Just Live -- restricted key
| "rk_test_" `T.isPrefixOf` apiKey = Just Test -- restricted key
| otherwise = Nothing
11 changes: 9 additions & 2 deletions lib/mobility-core/src/Kernel/External/Payment/Interface/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -679,11 +679,17 @@ data CreateCustomerReq = CreateCustomerReq
data CreateCustomerResp = CreateCustomerResp
{ customerId :: CustomerId,
clientAuthToken :: Maybe Text,
clientAuthTokenExpiry :: Maybe UTCTime
clientAuthTokenExpiry :: Maybe UTCTime,
isLiveMode :: Maybe Bool
}
deriving stock (Show, Eq, Generic)
deriving anyclass (FromJSON, ToJSON, ToSchema)

data CreateEphemeralKeysResp = CreateEphemeralKeysResp
{ ephemeralKeySecret :: Text,
isLiveMode :: Maybe Bool
}

data OrderUpdateReq = OrderUpdateReq
{ amount :: HighPrecMoney,
orderShortId :: Text,
Expand Down Expand Up @@ -723,7 +729,8 @@ data CreatePaymentIntentResp = CreatePaymentIntentResp
data CreateSetupIntentResp = CreateSetupIntentResp
{ setupIntentId :: SetupIntentId,
clientSecret :: Text,
status :: PaymentIntentStatus
status :: PaymentIntentStatus,
isLiveMode :: Maybe Bool
}
deriving stock (Show, Eq, Generic)
deriving anyclass (FromJSON, ToJSON, ToSchema)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ data CustomerObject = CustomerObject
email :: Maybe Text,
name :: Maybe Text,
default_source :: Maybe Text,
phone :: Maybe Text
phone :: Maybe Text,
livemode :: Maybe Bool
}
deriving stock (Show, Eq, Generic, Read)
deriving anyclass (FromJSON, ToJSON, ToSchema)
Expand All @@ -83,8 +84,9 @@ newtype EphemeralKeysReq = EphemeralKeysReq

instance ToForm EphemeralKeysReq

newtype EphemeralKeysResp = EphemeralKeysResp
{ secret :: Text
data EphemeralKeysResp = EphemeralKeysResp
{ secret :: Text,
livemode :: Maybe Bool
}
deriving stock (Show, Eq, Generic, Read)
deriving anyclass (FromJSON, ToJSON, ToSchema)
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ data SetupIntentObject = SetupIntentObject
confirm :: Maybe Bool,
customer :: Maybe CustomerId,
description :: Maybe Text,
payment_method :: Maybe Text
payment_method :: Maybe Text,
livemode :: Maybe Bool
}
deriving stock (Show, Eq, Generic, Read)
deriving anyclass (FromJSON, ToJSON, ToSchema)
Loading