public static string BuildMessage(ECRMessage msg)
        {
            // Assemble the message according to protocol
            string message =
                "00"                                                                     // Identifier
                + msg.TerminalID.ToString("D2")                                          // Terminal ID
                + "00"                                                                   // Source ID
                + msg.NextTransactionNo.ToString("D4")                                   // Sequential number
                + msg.TransactionType                                                    // Transaction type
                + (msg.POSPrints ? "1" : "0")                                            // Printer flag
                + msg.CashierID.ToString("D2")                                           // Cashier ID
                + FS
                + (msg.TransactionAmount != 0 ? "" + msg.TransactionAmount : "")         // Transaction amount 1
                + FS + FS
                + "+0"                                                                   // Amount Exponent
                + FS
                + (msg.CurrencyISO > 0 ? msg.CurrencyISO.ToString("D3") : "")            // Amount currency
                + FS + FS + FS + FS
                + msg.AuthorizationCode                                                  // Authorization code
                + FS + FS + FS
                + msg.InputLabel                                                         // Input label
                + FS
                + msg.InsurancePolicyNumber                                              // Insurance policy number
                + FS
                + msg.InstallmentsNumber                                                 // Installments number
                + FS + FS
                + msg.LanguageID                                                         // Language from Consts.Language
                + FS
                + msg.PrintData                                                          // Data that should be printed on receipt.
                + FS + FS
                + (msg.TransactionAmountCash != 0 ? "" + msg.TransactionAmountCash : "") // In case of Sale+Cash transaction this field contains Cash amount.
                + FS
                + msg.PayservicesData                                                    // TLV based data
                + FS
                + msg.TransactionActivationCode                                          // Transaction Activation Code for Mobile Payment
                + FS
                + msg.InstantPaymentRef                                                  // Reference number for Instant Payment
                + FS
                + msg.QRCodeData                                                         // QR code data for Instant Payment
                + FS
                + ((char)0x03).ToString();

            message = ((char)0x02).ToString() + message + (char)GetLRC(Encoding.ASCII.GetBytes(message));
            return(message);
        }
Example #2
0
        public SaleResult Sale(Int64 Amount)
        {
            if (!_connected)
            {
                return(new SaleResult(false, null));
            }

            // Build the message to send to the device
            ECRMessage msg = new ECRMessage();

            msg.NextTransactionNo = NextTransactionNo;
            msg.CurrencyISO       = CurrencyISO;
            msg.POSPrints         = POSPrints;
            msg.CashierID         = CashierID;
            msg.TransactionAmount = Amount;
            msg.TransactionType   = Consts.TransactionType.SALE;
            msg.LanguageID        = Language;

            // Clear the buffer
            POSPort.ReadExisting();
            // Send the message to the device
            POSPort.Write(msg.Message);

            /// To verify that the device got our message, we wait for ACK or 0x06 response
            /// If the device got our message, and it was not in correct format, we will get 0x15 as response, which is NACK
            /// We have allowed time for the device to get back to us and that, by specification, is 1 second
            /// After 1 second we send it the message once again, and hopefully it will receive it this time
            /// After 3 tries, the transaction will be marked as unsuccessful, with communication error.

            int  sendTry = 0;
            int  ms      = 0;
            bool success = false;

            #region Waiting for ACK/NACK

            while (true)
            {
                if (receivedACK)
                {
                    success      = true;
                    receivedACK  = false;
                    receivedNACK = false;
                    break;
                }
                if (receivedNACK)
                {
                    success      = false;
                    receivedACK  = false;
                    receivedNACK = false;
                    break;
                }
                if (ms > 1000)
                {
                    ms = 0;
                    sendTry++;
                    if (sendTry == 3)
                    {
                        break;
                    }
                    POSPort.Write(msg.Message);
                }
                System.Threading.Thread.Sleep(1);
                ms++;
            }

            #endregion Waiting for ACK/NACK

            if (!success)
            {
                return(new SaleResult(false, null));
            }

            /// After we receive 0x06, we wait for the message on the end of the transaction that tells us
            /// wether the transaction was successful or not, and other params such as cause, transaction date, amount, time etc...

            #region Waiting for Message

            lastPOSMsg = null;
            while (lastPOSMsg == null)
            {
            }

            #endregion Waiting for Message

            /// Message received, check it and send the response if message is correct and
            /// if transaction was successful
            if (lastPOSMsg.TransactionFlag == Consts.TransactionFlag.ACCEPTED_WITH_AUTH ||
                lastPOSMsg.TransactionFlag == Consts.TransactionFlag.ACCEPTED_WITHOUT_AUTH)
            {
                // Transaction was successful :D
                // Send ACK and return transaction successful
                POSPort.Write(((char)0x06).ToString());
            }
            else if (lastPOSMsg.TransactionFlag == Consts.TransactionFlag.REFUSED ||
                     lastPOSMsg.TransactionFlag == Consts.TransactionFlag.ERROR ||
                     lastPOSMsg.TransactionFlag == Consts.TransactionFlag.COMMUNICATION_ERROR)
            {
                // Transaction wasn't successful :(
                // Send ACK and return transaction unsuccessful
                POSPort.Write(((char)0x06).ToString());
                return(new SaleResult(false, lastPOSMsg));
            }
            else
            {
                // Message probably not valid, send NACK
                POSPort.Write(((char)0x15).ToString());
                return(new SaleResult(false, null));
            }

            // If everything goes as planned, this lines of code should be executed
            NextTransactionNo++;
            return(new SaleResult(true, lastPOSMsg));
        }