@startuml
'https://plantuml.com/class-diagram

footer EPG Vendor
hide empty members
hide empty fields
scale max 2048 width

' === === === === === === === === === ===
' ===                 API             ===
' === === === === === === === === === ===

package Api {

abstract class AbstractClient {
#merchantId: string
#merchantKey: string
#merchantSecret: string
#live: boolean = false
#encryption: EncryptionMethod = EncryptionMethod::CBC
#send(url: string, headers: array, payload = null): object
#generateTransactionToken(merchantId: string, merchantSecret: string, merchantTransactionsIds: array): string
}

abstract class BaseHostedClient {
+transactions(request: Transactions): TransactionStatus
+transactionsByDate(request: TransactionsByDate): TransactionStatus
}

class EPGJS {
-productId: string
+authorize(request: Authorization): Authorized
+charge(request: Charge): Transaction
+refund(request: Refund): Transaction
+transactions(request: Transactions): TransactionStatus
+transactionsByDate(request: TransactionsByDate): TransactionStatus
}

class Host2Host {
+directPayment(fields: array): Transaction
+refund(request: Refund): Transaction
}

class Hosted {
+requestPaymentForm(fields: array): PlainText
}

enum OperationType {
Deposit = 'deposit'
Debit = 'debit'
Credit = 'credit'
}

AbstractClient <|-- EPGJS : extends
AbstractClient <|-- BaseHostedClient : extends
BaseHostedClient <|-- Host2Host : extends
BaseHostedClient <|-- Hosted : extends

}

' === === === === === === === === === ===

' === === === === === === === === === ===
' ===             REQUEST             ===
' === === === === === === === === === ===

package Request {

class Authorization {
-customerId: string
-country: string
-currency: string
-operations: array = OperationType::Deposit
}

class Charge {
-token: string
-customerId: string
-country: string
-currency: string
-merchantTransactionId: string
-operationType: string = OperationType::Debit
-statusURL: string
-errorURL: string
-successURL: string
-cancelURL: string
-riskValidation3ds2: RiskValidation
-cdAccountInfo3ds2: CardHolderAccountInfo
-shippingAddress: ShippingAddress
}

class Refund {
-amount: string
-transactionId: string
-merchantTransactionId: string
-paymentSolution: string
-description: string
-merchantParams: array
}

class Transactions {
-merchantTransactionsIds: array
-transactions: array
-postback: enum[0, 1] = 0
-url: string
}

class TransactionsByDate {
-from: string
-to: string
}

note right of TransactionsByDate : Formato de fecha/horan\nYYYY/MM/dd HH:mm:ss
note bottom of Charge : Campos adicionales\nse mostrarán dependiendo\nel método de pago

}

' === === === === === === === === === ===

' === === === === === === === === === ===
' ===             RESPONSE            ===
' === === === === === === === === === ===

package Response {

class PlainText {
-value: string
}

class Authorized {
-authToken
}

class Operation {
-Payfrex-response: object
-message: string
-operations: [Transaction]
-optionalTransactionParams: array
-status: string,
-workFlowResponse: object
}

class TransactionStatus {
-operations: [Transaction]
}

class Transaction {
-amount: double
-currency: string
-details: object
-merchantTransactionId: integer
-message: string
-operationType: string
-payFrexTransactionId: integer
-paymentDetails: object
-optionalTransactionParams: string
-EPGTransactionID: string
-paySolTransactionId: string
-paymentSolution: string
-status: string
-respCode: ResponseCode
}

class ResponseCode {
-code: integer
-message: string
-uuid: string
}

Operation::operations --* Transaction
TransactionStatus::operations --* Transaction
ResponseCode <-- Transaction

}

' === === === === === === === === === ===

' === === === === === === === === === ===
' ===             ENCRYPTION          ===
' === === === === === === === === === ===

package Encryption {

class ECB {
+encrypt(plainText: string, key: string): string
+decrypt(encryptedText: string, key: string): string
}

class CBC {
+encrypt(plainText: string, key: string, initialVector: string): string
+decrypt(encryptedText: string, key: string, initialVector: string): string
}

class PPKJWT {
-publicKey: string
-privateKey: string
-algorithm: string
+encode(data: object): string
+decode(encodedText: string): object
}

enum EncryptionMethod {
CBC = 'CBC'
ECB = 'ECB'
}

}

' === === === === === === === === === ===

' === === === === === === === === === ===
' ===             _3DSecure            ===
' === === === === === === === === === ===

package _3DSecure {

' === === === === === === === === === ===
' ===         _3DSecure.v2            ===
' === === === === === === === === === ===

package v2 {

class RiskValidation {
-challenge: Challenge = Challenge::NoPreference
-deliveryTimeframe: DeliveryTimeFrame = DeliveryTimeFrame::ElectronicDelivery
-preOrderDate: string
-preOrderPurchase: PreOrderPurchase = PreOrderPurchase::MerchandiseAvailable
-reorderItems: ReorderItems = ReorderItems::Reordered
-shippingMethod: ShippingMethod = ShippingMethod::Other
-transactionTypeId: TransactionType = TransactionType::Purchase
}

class CardHolderAccountInfo {
-accountAge: AccountAge = AccountAge::NoAccount
-accountChangeDate: string
-accountCreationDate: string
-passwordChangeDate: string
-paymentAccountAge: string
-provisioningAttemptsDay: integer
-purchasesLast6Months: integer
-shippingAddressUsage: string
-shippingNameInd: ShippingNameInd = ShippingNameInd::Identical
-suspiciousAccountActivityInd: SuspiciousAccountActivityInd = SuspiciousAccountActivityInd::No
-txnActivityDay: integer
-txnActivityYear: integer
}

note "Min: 0, Max: 999" as N2
CardHolderAccountInfo::provisioningAttemptsDay .. N2
N2 .. CardHolderAccountInfo::purchasesLast6Months
N2 .. CardHolderAccountInfo::txnActivityDay
N2 .. CardHolderAccountInfo::txnActivityYear

class ShippingAddress {
-address1: string
-address2: string
-city: string
-zipCode: string
-country: string
-phone: string
-deliveryEmail: string
-billAddressMatchYN: boolean
}

class BrowserInfo {
-acceptHeader: text
-userAgent: text
-screenWidth: integer
-screenHeight: integer
-screenColorDepth: integer
-screenResolution: integer
-challengeWindowSize: WindowSize
-javaEnabled: boolean
-jsEnabled: boolean
-language sting
-tzOffset: integer
-browserIP: string
}

note "Formato de fecha\nYYYY-MM-DD" as N1
RiskValidation .. N1
N1 .. CardHolderAccountInfo

' === === === === === === === === === ===
' ===        _3DSecure.V2.Enum        ===
' === === === === === === === === === ===

package Enum {

enum Challenge {
NoPreference = 01
NoChallengeRequested = 02
ChallengeRequestedMerchantPreference = 03
ChallengeRequestedRegulatoryMandate = 04
}

enum DeliveryTimeFrame {
ElectronicDelivery = 01
SameDay = 02
Overnight = 03
TwoDayOrMore = 04
}

enum PreOrderPurchase {
MerchandiseAvailable = 01
FutureAvailability = 02
}

enum ReorderItems {
FirstTime = 01
Reordered = 02
}

enum ShippingMethod {
BillingAddress = 01
AnotherVerifiedAddress = 02
DifferentThanBillingAddress = 03
ShipToStore = 04
DigitalGoods = 05
NotShipped = 06
Other = 07
}

enum TransactionType {
Purchase = 01
CheckAcceptance = 03
AccountFunding = 10
Quasi-Cash = 11
PrepaidActivationAndLoad = 28
}

enum AccountAge {
NoAccount = 01
CreatedDuringTransaction = 02
LessThan30Days = 03
From30To60Days = 04
MoreThan60Days = 05
}

enum ShippingNameInd {
Identical = 01
Different = 02
}

enum SuspiciousAccountActivityInd {
No = 01
Yes = 02
}

enum WindowSize {
W250xH400 = '250 x 400'
W390xH400 = '390 x 400'
W500xH600 = '500 x 600'
W600xH400 = '600 x 400'
FullScreen = 'Full screen'
}

}

' === === === === === === === === === ===

}

' === === === === === === === === === ===

Encryption <.. Api : uses
Request <.. Api : uses
Response <.. Api : uses
Api ..> v2 : uses

@enduml
