Skip to content

Commit

Permalink
Backend/enhancement: HyperVerge RC API Integration (#638)
Browse files Browse the repository at this point in the history
* Backend/enhancement: HyperVerge RC API Integration

* Backend/enhancement: HyperVerge DL API Integration.
  • Loading branch information
ratnadeep-99 authored Feb 6, 2025
1 parent 157cb2c commit fe5c8a1
Show file tree
Hide file tree
Showing 12 changed files with 788 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ data HyperVergeError
| HVBadRequestError Text
| HVError Text
| HVBadInputError Text
| HVMissingPayloadError Text
deriving (Eq, Show, IsBecknAPIError)

instanceExceptionWithParent 'HTTPException ''HyperVergeError
Expand All @@ -35,18 +36,21 @@ instance IsBaseError HyperVergeError where
HVBadRequestError msg -> Just $ "Bad Request with message: " <> msg
HVError msg -> Just $ "HyperVerge Error with message: " <> msg
HVBadInputError msg -> Just $ "Bad Input with message: " <> msg
HVMissingPayloadError msg -> Just $ "Missing payload in a 200 Hyperverge Response !!!!! Due to : " <> msg

instance IsHTTPError HyperVergeError where
toErrorCode = \case
HVUnauthorizedError -> "HV_UNAUTHORIZED"
HVBadRequestError _ -> "HV_BAD_REQUEST"
HVError _ -> "HV_ERROR"
HVBadInputError _ -> "HV_BAD_INPUT"
HVMissingPayloadError _ -> "HV_MISSING_PAYLOAD_ERROR"

toHttpCode = \case
HVUnauthorizedError -> E401
HVBadRequestError _ -> E400
HVError _ -> E400
HVBadInputError _ -> E400
HVMissingPayloadError _ -> E400

instance IsAPIError HyperVergeError
2 changes: 2 additions & 0 deletions lib/mobility-core/src/Kernel/External/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ instance ToHttpApiData Language where

type ServiceFlow m r = (EncFlow m r, EsqDBFlow m r, CacheFlow m r)

type VerificationFlow m r = (MonadFlow m, CacheFlow m r, EsqDBFlow m r, MonadReader r m, EncFlow m r)

data SchedulerType = RedisBased | DbBased deriving (Show, Enum, Eq, Read, Generic, FromDhall)

type HasSchedulerName r = HasField "schedulerSetName" r Text
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ verifyRC req = do
pucValidityUpto = Nothing,
manufacturerModel = res.manufacturerModel,
mYManufacturing = Nothing,
colour = Nothing,
color = Nothing,
fuelType = res.fuelType,
bodyType = res.bodyType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
-}

module Kernel.External.Verification.GovtData.Types where

import Data.Time (UTCTime)
Expand Down
147 changes: 144 additions & 3 deletions lib/mobility-core/src/Kernel/External/Verification/HyperVerge/Flow.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

module Kernel.External.Verification.HyperVerge.Flow where

import qualified Data.Aeson as DA
import qualified Data.Text as DT
import EulerHS.Types (EulerClient, ManagerSelector (..), client)
import Kernel.External.Encryption
Expand All @@ -24,8 +25,9 @@ import Kernel.Prelude
import Kernel.Tools.Metrics.CoreMetrics (CoreMetrics)
import Kernel.Types.Error (ExternalAPICallError (..))
import Kernel.Utils.Common
import qualified Kernel.Utils.Text as KUT
import Servant hiding (throwError)
import Servant.Client.Core (ClientError)
import Servant.Client.Core

type HyperVergeSdkVerificationAPI =
"v1"
Expand Down Expand Up @@ -61,14 +63,153 @@ checkHyperVergeSdkVerificationResponse ::
checkHyperVergeSdkVerificationResponse url resp = fromEitherM (hyperVergeError url) resp >>= validateHyperVergeSdkVerificationResponse

hyperVergeError :: BaseUrl -> ClientError -> ExternalAPICallError
hyperVergeError = ExternalAPICallError (Just "HYPERVERGE_SDK_VERIFICATION_API_ERROR")
hyperVergeError = ExternalAPICallError (Just "HYPERVERGE_API_ERROR")

validateHyperVergeSdkVerificationResponse :: (MonadThrow m, Log m) => HyperVergeTypes.HyperVergeSdkVerificationRes -> m HyperVergeTypes.HyperVergeSdkVerificationRes
validateHyperVergeSdkVerificationResponse resp = do
logDebug $ "HyperVerge SDK Verification Response: " <> show resp
case resp.statusCode of
Just 401 -> throwError $ HVUnauthorizedError
Just 401 -> throwError HVUnauthorizedError
Just 400 -> throwError $ HVBadRequestError (fromMaybe "No Message found in resp or Failed to parse error !!!!" $ join (resp.result <&> (.error)))
Just 422 -> throwError $ HVBadInputError (fromMaybe "No Message found in resp or Failed to parse error !!!!" $ join (resp.result <&> (.error)))
Just 200 -> return resp
_ -> throwError $ HVError ("The response from HV is : " <> show resp)

type VerifyRCAsyncAPI =
"v1"
:> "async"
:> "RCVerification"
:> Header "appId" Text
:> Header "appKey" Text
:> Header "transactionId" Text
:> ReqBody '[JSON] HyperVergeTypes.VerifyRCAsyncReq
:> Post '[JSON] HyperVergeTypes.VerifyRCAsyncResp

rcAsyncVerificationClient :: Maybe Text -> Maybe Text -> Maybe Text -> HyperVergeTypes.VerifyRCAsyncReq -> EulerClient HyperVergeTypes.VerifyRCAsyncResp
rcAsyncVerificationClient = client (Proxy :: Proxy VerifyRCAsyncAPI)

verifyRCAsync ::
( HasCallStack,
EncFlow m r,
MonadFlow m,
CoreMetrics m
) =>
HyperVergeTypes.HyperVergeRCDLVerificationConfig ->
Text ->
HyperVergeTypes.VerifyRCAsyncReq ->
m HyperVergeTypes.VerifyRCAsyncResp
verifyRCAsync cfg transactionId req = do
decrypt cfg.appKey >>= \key -> callAPI' (Just $ ManagerSelector $ DT.pack hyperVergeHttpManagerKey) cfg.url (rcAsyncVerificationClient (Just cfg.appId) (Just key) (Just transactionId) req) "HV-RC_ASYNC_VERIFICATION-API" (Proxy @VerifyRCAsyncAPI) >>= checkHyperVergeRCAsyncVerificationResp cfg.url

checkHyperVergeRCAsyncVerificationResp ::
( HasCallStack,
MonadFlow m,
CoreMetrics m
) =>
BaseUrl ->
Either ClientError HyperVergeTypes.VerifyRCAsyncResp ->
m HyperVergeTypes.VerifyRCAsyncResp
checkHyperVergeRCAsyncVerificationResp url resp = fromEitherM (hyperVergeError url) resp >>= validateHyperVergeRCAsyncVerificationResponse

validateHyperVergeRCAsyncVerificationResponse :: (MonadThrow m, Log m) => HyperVergeTypes.VerifyRCAsyncResp -> m HyperVergeTypes.VerifyRCAsyncResp
validateHyperVergeRCAsyncVerificationResponse resp = do
logDebug $ "HyperVerge RC Verification Response: " <> show resp
case resp.statusCode of
401 -> throwError HVUnauthorizedError
400 -> throwError $ HVBadRequestError (fromMaybe "No Message found in resp or Failed to parse error !!!!" resp.message)
200 -> return resp
_ -> throwError $ HVError ("The response from HV is : " <> show resp)

type VerifyDLAsyncAPI =
"v1"
:> "async"
:> "checkDL"
:> Header "appId" Text
:> Header "appKey" Text
:> Header "transactionId" Text
:> ReqBody '[JSON] HyperVergeTypes.HyperVergeDLVerificationReq
:> Post '[JSON] HyperVergeTypes.HyperVergeDLVerificationResp

dlAsyncVerificationClient :: Maybe Text -> Maybe Text -> Maybe Text -> HyperVergeTypes.HyperVergeDLVerificationReq -> EulerClient HyperVergeTypes.HyperVergeDLVerificationResp
dlAsyncVerificationClient = client (Proxy :: Proxy VerifyDLAsyncAPI)

verifyDLAsync ::
( HasCallStack,
EncFlow m r,
MonadFlow m,
CoreMetrics m
) =>
HyperVergeTypes.HyperVergeRCDLVerificationConfig ->
Text ->
HyperVergeTypes.HyperVergeDLVerificationReq ->
m HyperVergeTypes.HyperVergeDLVerificationResp
verifyDLAsync cfg transactionId req = do
decrypt cfg.appKey >>= \key -> callAPI' (Just $ ManagerSelector $ DT.pack hyperVergeHttpManagerKey) cfg.url (dlAsyncVerificationClient (Just cfg.appId) (Just key) (Just transactionId) req) "HV-DL_ASYNC_VERIFICATION-API" (Proxy @VerifyDLAsyncAPI) >>= checkHyperVergeDLAsyncVerificationResp cfg.url

checkHyperVergeDLAsyncVerificationResp ::
( HasCallStack,
MonadFlow m,
CoreMetrics m
) =>
BaseUrl ->
Either ClientError HyperVergeTypes.HyperVergeDLVerificationResp ->
m HyperVergeTypes.HyperVergeDLVerificationResp
checkHyperVergeDLAsyncVerificationResp url resp = fromEitherM (hyperVergeError url) resp >>= validateHyperVergeDLAsyncVerificationResponse

validateHyperVergeDLAsyncVerificationResponse :: (MonadThrow m, Log m) => HyperVergeTypes.HyperVergeDLVerificationResp -> m HyperVergeTypes.HyperVergeDLVerificationResp
validateHyperVergeDLAsyncVerificationResponse resp = do
logDebug $ "HyperVerge DL Verification Response: " <> show resp
case resp.statusCode of
401 -> throwError HVUnauthorizedError
400 -> throwError $ HVBadRequestError (fromMaybe "No Message found in resp or Failed to parse error !!!!" resp.error)
200 -> return resp
_ -> throwError $ HVError ("The response from HV is : " <> show resp)

type GetVerificationStatusAPI =
"v1"
:> "async"
:> Header "appId" Text
:> Header "appKey" Text
:> Capture "workflowId" Text
:> MandatoryQueryParam "requestId" Text
:> Get '[JSON] DA.Value

getVerificationStatusClient :: Maybe Text -> Maybe Text -> Text -> Text -> EulerClient DA.Value
getVerificationStatusClient = client (Proxy :: Proxy GetVerificationStatusAPI)

getVerificationStatus ::
( HasCallStack,
EncFlow m r,
MonadFlow m,
CoreMetrics m
) =>
HyperVergeTypes.HyperVergeRCDLVerificationConfig ->
Text ->
Text ->
m (HyperVergeTypes.GetVerificationStatusResp, Text)
getVerificationStatus cfg workflowId reqId = do
decrypt cfg.appKey >>= \key -> callAPI' (Just $ ManagerSelector $ DT.pack hyperVergeHttpManagerKey) cfg.url (getVerificationStatusClient (Just cfg.appId) (Just key) workflowId reqId) "HV-GET_VERIFICATION_RESULT-API" (Proxy @GetVerificationStatusAPI) >>= checkHyperVergeGetVerificationStatusResp cfg.url

checkHyperVergeGetVerificationStatusResp ::
( HasCallStack,
MonadFlow m,
CoreMetrics m
) =>
BaseUrl ->
Either ClientError DA.Value ->
m (HyperVergeTypes.GetVerificationStatusResp, Text)
checkHyperVergeGetVerificationStatusResp url resp = fromEitherM (hyperVergeError url) resp >>= \rsp -> (,KUT.encodeToText rsp) <$> (validateHyperVergeGetVerificationStatusResp =<< convertValueToRespType rsp)
where
convertValueToRespType :: (MonadThrow m, Log m) => DA.Value -> m HyperVergeTypes.GetVerificationStatusResp
convertValueToRespType rsp = case DA.fromJSON rsp of
DA.Error err -> throwError $ HVError ("Could not parse HyperVerge getVerificationStatus resp. Reason: " <> DT.pack err <> "Resp: " <> show rsp)
DA.Success pyload -> return pyload

validateHyperVergeGetVerificationStatusResp :: (MonadThrow m, Log m) => HyperVergeTypes.GetVerificationStatusResp -> m HyperVergeTypes.GetVerificationStatusResp
validateHyperVergeGetVerificationStatusResp resp = do
logDebug $ "HyperVerge getVerificationStatus Response: " <> show resp
case resp.statusCode of
401 -> throwError HVUnauthorizedError
400 -> throwError $ HVBadRequestError (fromMaybe "No Message found in resp or Failed to parse error !!!!" resp.message)
200 -> if isNothing resp.result then throwError (HVMissingPayloadError $ fromMaybe ("Unknown reason !!!!! Resp : " <> show resp) resp.message) else return resp
_ -> throwError $ HVError ("The response from HV is : " <> show resp)
Loading

0 comments on commit fe5c8a1

Please sign in to comment.