import * as sdk from 'remote-pay-cloud-api'; import { RemoteMessageParser } from '../../../json/RemoteMessageParser'; import { CloverDevice } from './CloverDevice'; import { CloverTransport } from '../transport/CloverTransport'; import { ObjectMessageSender } from '../transport/ObjectMessageSender'; import { CloverTransportObserver } from '../transport/CloverTransportObserver'; import { CloverDeviceConfiguration } from './CloverDeviceConfiguration'; import { Logger } from '../util/Logger'; /** * Default Clover Device * * This is a default implementation of the clover device. */ export declare abstract class DefaultCloverDevice extends CloverDevice implements CloverTransportObserver, ObjectMessageSender { protected logger: Logger; protected messageParser: RemoteMessageParser; private static DEFAULT_REMOTE_MESSAGE_VERSION; private _remoteMessageVersion; private static REMOTE_SDK; private static BASE64; private static BASE64_ATTACHMENT; private static id; private msgIdToTask; private imageUtil; private readonly cloverDeviceConfiguration; private readonly maxMessageSizeInChars; private static INITIAL_HEARTBEAT_DELAY; private heartbeatTimer; private heartbeatResponseTimer; private reconnectTimer; private reconnecting; private readonly heartbeatIntervalInMillis; private readonly heartbeatDisconnectTimeoutInMillis; private readonly reconnectDelayInMillis; private readonly forceConnect; constructor(configuration: CloverDeviceConfiguration); /** * @param transport * @deprecated - see onConnected. */ onDeviceConnected(transport: CloverTransport): void; /** * We are connected. What "connected" means depends on the transport mechanism. * * For network (SNPD) this means that we have connected to the Clover device. * For cloud (CPD) this means that we have connected to the cloud proxy. */ onConnected(transport: CloverTransport): void; /** * The connection attempt is complete. Set the reconnecting flag to false so that the reconnect loop can try again (if running). * @param transport */ onConnectionAttemptComplete(transport: CloverTransport): void; /** * @param transport * @deprecated - see onReady. */ onDeviceReady(transport: CloverTransport): void; /** * We are ready to send messages. This has different meanings depending on the transport mechanism. * * For network (SNPD) this means that we have connected to and successfully pinged the Clover device. * For cloud (CPD) this means that we have connected to and successfully pinged the cloud proxy. * * This is generally used to indicate that we are clear to initiate the device via a Discovery Request. * * Note: this does not mean the device is ready to take a payment through the SDK, which is solely determined * by the receipt of a Discovery Response (see DefaultCloverDevice.notifyObserversReady). */ onReady(transport: CloverTransport): void; /** * Executes a device heartbeat check (via PING) when we are connected to the device. If a PING request is not answered * within this.heartbeatResponseTimer disconnect will be called and the SDK will start reconnect attempts. */ private initiateHeartbeat; private stopHeartbeat; private clearHeartbeartResponseTimer; /** * Executes a device reconnect when we are not connected to the device and reconnect is enabled. * * The reconnect logic has been moved from the websocket transport layer to the device level to support non-direct connection * transports (e.g. cloud). For non-direct transports the transport layer does not tell the entire truth about the connection * status as it only indicates the SDKs connection to the proxy layer. In order to accurately determine the connection status * to the device we must rely on the Discovery Response (notifyObserversReady) and a device PING/PONG (see pingDevice). */ private initiateReconnect; private stopReconnect; /** * @param transport - the way to notify is defined by the transport * @param message - the optional message to send * @deprecated - see onDisconnected. */ onDeviceDisconnected(transport: CloverTransport, message?: string): void; /** * We are disconnected. What "disconnected" means depends on the transport mechanism. * * For network (SNPD) this means that we have disconnected from the Clover device. * For cloud (CPD) this means that we have disconnected from the cloud proxy. */ onDisconnected(transport: CloverTransport, message?: string, reconnect?: boolean): void; onDeviceError(deviceError: sdk.remotepay.CloverDeviceErrorEvent): void; getApplicationId(): string; protected handleRemoteMessagePING(): void; protected handleRemoteMessagePONG(): void; get remoteMessageVersion(): number; /** * Remote Message version is used for high-level feature detection e.g. is chunking supported. * We set the remote version when incoming messages are handled (handleRemoteMessageCOMMAND). * We only want to set _remoteMessageVersion if the inbound message is > than the version already set. * * @param {number} remoteMessageVersion */ set remoteMessageVersion(remoteMessageVersion: number); protected handleRemoteMessageCOMMAND(rMessage: sdk.remotemessage.RemoteMessage): void; protected handleRemoteMessageQUERY(rMessage: sdk.remotemessage.RemoteMessage): void; protected handleRemoteMessageEVENT(rMessage: sdk.remotemessage.RemoteMessage): void; protected handleRemoteMessage(rMessage: sdk.remotemessage.RemoteMessage): void; /** * Called when a raw message is received from the device * * @param {string} message - the raw message from the device */ onMessage(message: string): void; /** * Send a PONG response */ private respondToDevicePing; /** * Send a PING message */ private sendPingToDevice; /** * Notify the observers that the device is connected * * @param transport */ private notifyObserversConnected; /** * Notify the observers that the device has disconnected * * @param transport * @param message */ private notifyObserversDisconnected; /** * Notify the observers that the transport failed. * * @param errorEvent */ private notifyObserversDeviceError; /** * Notify the observers that the device is ready * * @param transport * @param drm */ private notifyObserversReady; private notifyObserverAck; private notifyObserverActivityMessage; private notifyObserversActivityResponse; private notifyObserversReadCardData; private notifyObserversRetrieveDeviceStatusResponse; private notifyObserversRetrievePaymentResponse; private notifyObserversRetrievePrintersResponse; private notifyObserversPrintJobStatusResponse; private notifyObserversCustomerProvidedDataMessage; private notifyObserversPrintCredit; private notifyObserversPrintCreditDecline; private notifyObserversPrintPayment; private notifyObserversPrintPaymentDecline; private notifyObserversPrintMerchantCopy; private notifyObserversPrintPaymentRefund; private notifyObserversResetDeviceResponse; private notifyObserversRemoteError; notifyObserversPaymentRefundResponse(refundResponseMessage: sdk.remotemessage.RefundResponseMessage): void; notifyObserversPrintMessage(refundPaymentPrintMessage: sdk.remotemessage.RefundPaymentPrintMessage): void; notifyObserversKeyPressed(keyPress: sdk.remotemessage.KeyPressMessage): void; notifyObserversCashbackSelected(cashbackSelectedMessage: sdk.remotemessage.CashbackSelectedMessage): void; notifyObserversTipAdded(tipAddedMessage: sdk.remotemessage.TipAddedMessage): void; notifyObserverTxStart(txStartResponseMessage: sdk.remotemessage.TxStartResponseMessage): void; notifyObserversTipAdjusted(tipAdjustResponseMessage: sdk.remotemessage.TipAdjustResponseMessage): void; notifyObserversPartialAuth(partialAuthMessage: sdk.remotemessage.PartialAuthMessage): void; notifyObserversPaymentVoided(voidPaymentResponseMessage: sdk.remotemessage.VoidPaymentResponseMessage): void; notifyObserversPaymentRefundVoided(voidPaymentRefundResponseMessage: sdk.remotemessage.VoidPaymentRefundResponseMessage): void; notifyObserversVerifySignature(verifySignatureMessage: sdk.remotemessage.VerifySignatureMessage): void; notifyObserversConfirmPayment(confirmPaymentMessage: sdk.remotemessage.ConfirmPaymentMessage): void; notifyObserverVaultCardResponse(vaultCardResponseMessage: sdk.remotemessage.VaultCardResponseMessage): void; notifyObserversUiState(uiStateMsg: sdk.remotemessage.UiStateMessage): void; notifyObserversCapturePreAuth(capturePreAuthResponseMessage: sdk.remotemessage.CapturePreAuthResponseMessage): void; notifyObserversIncrementPreAuth(incrementPreAuthResponseMessage: sdk.remotemessage.IncrementPreAuthResponseMessage): void; notifyObserversCloseout(closeoutResponseMessage: sdk.remotemessage.CloseoutResponseMessage): void; notifyObserversPendingPaymentsResponse(retrievePendingPaymentsResponseMessage: sdk.remotemessage.RetrievePendingPaymentsResponseMessage): void; notifyObserversTxState(txStateMsg: sdk.remotemessage.TxStateMessage): void; notifyObserversFinishCancel(finishCancelMessage: sdk.remotemessage.FinishCancelMessage): void; notifyObserversFinishOk(finishOkMessage: sdk.remotemessage.FinishOkMessage): void; notifyObserverDisplayCollectedSignature(msg: sdk.remotemessage.SignatureResponseMessage): void; notifyObserverBalanceInquiryResponse(msg: sdk.remotemessage.BalanceInquiryResponseMessage): void; notifyObserverTipResponse(msg: sdk.remotemessage.RequestTipResponseMessage): void; notifyObserversInvalidStateTransitionResponse(invalidStateTransitionMessage: sdk.remotemessage.InvalidStateTransitionMessage): void; notifyObserverDisplayReceiptOptionsResponse(showReceiptOptionsResponseMessage: sdk.remotemessage.ShowReceiptOptionsResponseMessage): void; /** * Show Payment Receipt Screen * * @param {string} orderId * @param {string} paymentId */ doShowPaymentReceiptScreen(orderId: string, paymentId: string): void; doShowReceiptScreen(orderId: string, paymentId: string, refundId: string, creditId: string, disablePrinting: boolean): void; /** * Key Press * * @param {sdk.remotemessage.KeyPress} keyPress */ doKeyPress(keyPress: sdk.remotemessage.KeyPress): void; /** * Show Thank You Screen */ doShowThankYouScreen(): void; /** * Show Welcome Screen */ doShowWelcomeScreen(): void; /** * Signature Verified * * @param {sdk.payments.Payment} payment * @param {boolean} verified */ doSignatureVerified(payment: sdk.payments.Payment, verified: boolean): void; /** * Retrieve Pending Payments */ doRetrievePendingPayments(): void; /** * Terminal Message * * @param {string} text */ doTerminalMessage(text: string): void; /** * Sends request to the clover device to send the log to the clover server * * @param message The message to display */ doSendDebugLog(message: string): void; /** * Open Cash Drawer * * @param {string} reason * @param {string} deviceId (optional) */ doOpenCashDrawer(reason: string, deviceId?: string): void; /** * Closeout * * @param {boolean} allowOpenTabs * @param {string} batchId */ doCloseout(allowOpenTabs: boolean, batchId: string): void; /** * Transaction Start * * @param {sdk.remotemessage.PayIntent} payIntent * @param {sdk.remotemessage.Order} order * @param {string} requestInfo - request type. */ doTxStart(payIntent: sdk.remotemessage.PayIntent, order: sdk.order.Order, requestInfo: string): void; /** * Tip Adjust Auth * * @param {string} orderId * @param {string} paymentId * @param {number} amount */ doTipAdjustAuth(orderId: string, paymentId: string, amount: number): void; /** * Read Cart Data * * @param {PayIntent} payIntent */ doReadCardData(payIntent: sdk.remotemessage.PayIntent): void; /** * Send a message to a running custom activity * * @param {string} actionId - the id used when the custom action was started * @param {string} payload - the message content, unrestricted format */ doSendMessageToActivity(actionId: string, payload: string): void; /** * Print Text * * @param {Array} textLines * @param printRequestId - an optional id that will be used for the printjob. This id will be used in notification calls about the status of the job. * @param printDeviceId - the printer id to use when printing. If left unset the default is used */ doPrintText(textLines: Array, printRequestId?: string, printDeviceId?: string): void; /** * Print Image (Bitmap) * * @param bitmap * @param printRequestId * @param printDeviceId */ doPrintImageObject(bitmap: any, printRequestId?: string, printDeviceId?: string): void; /** * Printing images from a url from the device is problematic. * See - https://jira.dev.clover.com/browse/SEMI-1352 * and - https://jira.dev.clover.com/browse/SEMI-1377 * * Instead of relying on the device, we can retrieve the image from the URL * and call doPrintImageObject instead of doPrintImageUrl. The doPrintImageObject * method is more robust (can handle large images via chunking, etc.). * * @param {string} url * @param {string} printRequestId * @param {string} printDeviceId */ doPrintImageUrl(url: string, printRequestId?: string, printDeviceId?: string): void; doStartActivity(action: string, payload: string, nonBlocking: boolean): void; /** * Void Payment * * @param {sdk.payments.Payment} payment * @param {sdk.order.VoidReason} voidReason * @param {boolean} disablePrinting * @param {boolean} disableReceiptSelection */ doVoidPayment(payment: sdk.payments.Payment, voidReason: sdk.order.VoidReason, disablePrinting: boolean, disableReceiptSelection: boolean): void; protected addTaskForAck(msgId: string, task: Function): void; /** * Payment Refund * * @param {string} orderId * @param {string} paymentId * @param {number} amount * @param {boolean} fullRefund * @param {boolean} disablePrinting * @param {boolean} disableReceiptSelection */ doPaymentRefund(orderId: string, paymentId: string, amount: number, fullRefund: boolean, disablePrinting?: boolean, disableReceiptSelection?: boolean): void; /** * Void Payment Refund * * @param {string} orderId * @param {string} refundId * @param {boolean} disablePrinting * @param {boolean} disableReceiptSelection */ doVoidPaymentRefund(orderId: string, refundId: string, disablePrinting: boolean, disableReceiptSelection: boolean): void; /** * Payment Refund * * @param {RefundPaymentRequest} request */ doPaymentRefundByRequest(request: sdk.remotepay.RefundPaymentRequest): void; /** * Vault Card * * @param {number} cardEntryMethods */ doVaultCard(cardEntryMethods: number): void; /** * Capture Auth * * @param {string} paymentId * @param {number} amount * @param {number} tipAmount */ doCaptureAuth(paymentId: string, amount: number, tipAmount: number): void; /** * Capture Auth * * @param {string} paymentId * @param {number} amount * @param {number} amount */ doIncrementPreAuth(paymentId: string, amount: number): void; /** * Accept Payment * * @param {Payment} payment */ doAcceptPayment(payment: sdk.payments.Payment): void; /** * Reject Payment * * @param {Payment} payment * @param {Challenge} challenge */ doRejectPayment(payment: sdk.payments.Payment, challenge: sdk.base.Challenge): void; /** * Discovery request */ doDiscoveryRequest(): void; /** * Order Update * * @param {DisplayOrder} order * @param {any} orderOperation */ doOrderUpdate(order: sdk.order.DisplayOrder, orderOperation: any): void; /** * Reset Device */ doResetDevice(): void; doRetrieveDeviceStatus(request: sdk.remotepay.RetrieveDeviceStatusRequest): void; doRetrievePayment(externalPaymentId: string): void; doRetrievePrinters(category?: sdk.printer.PrintCategory): void; doRetrievePrintJobStatus(printRequestId: string): void; /** * Loyalty */ doRegisterForCustomerProvidedData(configurations: Array): void; doSetCustomerInfo(customerInfo: sdk.remotepay.CustomerInfo): void; doCheckBalance(cardEntryMethods: number): void; doCollectSignature(acknowledge: string): void; doRequestTip(tippableAmount: number, suggestions: Array): void; /** * Dispose */ dispose(): void; sendObjectMessage(remoteMessage: sdk.remotemessage.Message, attachment?: string, attachmentEncoding?: string): string; private buildBaseRemoteMessage; /** * Special serialization handling * The top level elements should not have the "elements" wrapper on collections (arrays). * sdk.remotemessage.Message instances are the only ones this needs to happen for. This * is the result of the manner in which the serialization/deserialization happens in the * Android code. The top level objects are not (de)serialized by a * com.clover.sdk.GenericClient#extractListOther * (in the Clover common repo). The GenericClient is the tool that adds the elements * wrapper. The top level objects are (de)serialized by themselves * com.clover.remote.message.Message#fromJsonString */ private addSuppressElementsWrapper; protected buildRemoteMessageToSend(message: sdk.remotemessage.Message): sdk.remotemessage.RemoteMessage; protected buildRemoteMessages(message: sdk.remotemessage.Message, attachment?: string, attachmentEncoding?: string): string; protected static stringifyClover(key: string, value: any): any; protected sendRemoteMessage(remoteMessage: sdk.remotemessage.RemoteMessage): void; /** * If the remote message version is 2, fragmentation is supported. * * @returns {boolean} */ private isFragmentationSupported; }