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); }
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)); }