Payment terminal TIMAPI.DLL

General Help regarding HMG, Compilation, Linking, Samples

Moderator: Rathinagiri

Georg_BA
Posts: 108
Joined: Fri Apr 07, 2017 5:31 pm
DBs Used: DBF

Re: Payment terminal TIMAPI.DLL

Post by Georg_BA »

Hello Edward

Great job.
The connection already works without a problem.
I also tried changing the language. It also works without problems.
After Initialization, it starts in the default state - English, with the Change settings function, it immediately switches the language.
Just great.
I have the feeling that you are doing things with the terminal that support doesn't even know about. :roll:
And no one really had that in hand.

Many thanks for your efforts

Georg
Georg_BA
Posts: 108
Joined: Fri Apr 07, 2017 5:31 pm
DBs Used: DBF

Re: Payment terminal TIMAPI.DLL

Post by Georg_BA »

Hello Edward

I'd like to ask you one more thing when you're working on printing.
You could not create public variables (fields) where selected values would be stored during processing in the TIM-API Class.
There would only be data from the last transaction.
I tried to select values for Balance but without success.

Georg
edk
Posts: 999
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland

Re: Payment terminal TIMAPI.DLL

Post by edk »

Georg, I owe you a few words of explanation about how my class works.
Events appear during communication with the terminal, these may be notifications or responses to requests. Since I am unable to determine what I will receive in communication with the terminal at a given moment, I decided that specific events will be handled by user-defined blocks of code. What the user does with it is up to him.
For example, when it comes the response event for a request, with each received response the code of the block is executed, which we define with the ResponseEvent( { | hAttributes, cXML | anyFunction ( hAttributes, cXML ) } ) method. This event returns two arguments: the first is a hash table from which you can read what type of response (for what request) it is. The second argument is a pure XML string containing the complete response received from the terminal. Once we have this data, we can do whatever we want with it. In the demo, I used this data to display in the DATA RESPONSE, but you don't have to show it, just process it according to your needs.
Here are the other events handled by the class:

Code: Select all

StatusChangeEvent ( { | x | AnyFunction ( x ) } ) // event triggered when reading/changing terminal status
DisplayContentEvent( { | x | AnyFunction ( x ) } ) // event triggered when receiving information about changing the content shown on the terminal screen
CardInfoEvent( { | x | AnyFunction ( x ) } ) // event triggered after receiving payment card data from the terminal.
PrintMerchantEvent ( { | x| AnyFunction ( x ) } ) // event triggered when receiving a printout intended for Merchant
PrintCardholderEvent ( { | x| AnyFunction ( x ) } ) // event triggered when a printout for Cardholder is received
Replace the ResponseInfo procedure and see what it does.

Code: Select all

Procedure ResponseInfo ( hAttributes, cXMLResponse )

IF Len( cXMLResponse )  > 0

    Main.EFTResponse_.Value :=  "Response (attributes):" + CRLF
    hb_HEVAL (  hAttributes, { | key, value | Main.EFTResponse_.AddText ( LEN( Main.EFTResponse_.Value) ) := key + ": " + value + CRLF} )

    Main.EFTResponse_.AddText ( LEN( Main.EFTResponse_.Value) ) := CRLF + "Response (XML): " + CRLF + /* Add a new line between the xml tags to make it easier to clear it. */ StrTran ( cXMLResponse, "><" , ">" + CRLF + "<"  )
    
    
    DO CASE
    
        CASE hAttributes [ "FunctionGroup" ] == "Admin" .And. hAttributes [ "Function" ] == "Balance"
            //This is the response to the request "Balance"
            MsgInfo ( "Here we have the response in XML format. You can extract the data and do what you need with it." + CRLF + CRLF + cXMLResponse )
        
    ENDCASE
    
ELSE
    Main.EFTResponse_.Value := ""
ENDIF

RETURN
edk
Posts: 999
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland

Re: Payment terminal TIMAPI.DLL

Post by edk »

New version of TIMAPI Class:
  • added support for Receipt Print Items; if in the POS options for the Merchant or Cardholder printer the printing format is set to "FieldsOnly"

    Code: Select all

    hTIM_CFG [ "PrintOptionsMerchant" ] [ "PrintFormat" ] := "FieldsOnly"
    hTIM_CFG [ "PrintOptionsCardholder" ] [ "PrintFormat" ] := "FieldsOnly" 
    then the terminal returns the fields and their values instead of the ready printout. Using the new method

    Code: Select all

    PrintItemsEvent ( { | x | AnyFunction ( x ) } )
    you can define a block of code that will be executed when information about receipt printout fields is received from the terminal. As a parameter, a hash table containing the receipt type, recipient as well as fields and values is passed. In the example, the PrintItemsEFTReceipt() procedure creates a printout based on the received fields.
    • added translations of field names into other languages.

      Code: Select all

      TIM_Translate ( cID )
      method is used for this, where the parameter Id name of the field or receipt type should be given. The translation uses an extracted table from the TIMAPI library for .Net. In order to use the translation correctly, the Id field name must be properly preceded by the "rec" prefix, and for the receipt type with the "trxType" prefix. For example, if you want to obtain a translation of the receipt type "Purchase", you should specify "trxTypePurchase" as a parameter, and "recTrmId" for the "TrmId" field.
    • The language to which the phrases are to be translated is defined in

      Code: Select all

      hTIM_CFG [ "TranslateLanguage" ]
  • added the ability to configure the following settings in the terminal:
    • terminal language:

      Code: Select all

       hTIM_CFG [ "TerminalSettings" ] [ "Language" ]
    • alert tones:

      Code: Select all

      hTIM_CFG [ "TerminalSettings" ] [ "AlertTones" ]
    • keypad tones:

      Code: Select all

      hTIM_CFG [ "TerminalSettings" ] [ "KeypadTones" ]
    • display brightness:

      Code: Select all

      hTIM_CFG [ "TerminalSettings" ] [ "DisplayBrightness" ]
    • display contrast:

      Code: Select all

      hTIM_CFG [ "TerminalSettings" ] [ "DisplayContrast" ]
    • after setting the parameters, we send them to terminal using method

      Code: Select all

      ChangeSettings()
  • improved request handling and response for multi-threading
  • Code: Select all

    hTIM_CFG [ "ResponseXML" ]
    returns the last received response to the request. I demonstrated the use of this variable in the Balance and ChangeSettings functions.
  • In the example in the Balance function, I showed how you can set up your own data container using a class, the data stored in the container can be accessed in any function or procedure, it is not required to create public variables. Procedures or functions only need access to the TIMAPI object. It can be passed as a parameter.
Attachments
TIM_APIClass_02092023.7z
(64.27 KiB) Downloaded 347 times
Georg_BA
Posts: 108
Joined: Fri Apr 07, 2017 5:31 pm
DBs Used: DBF

Re: Payment terminal TIMAPI.DLL

Post by Georg_BA »

Hi Edward

This version reports an error when loading the payment card.
I am attaching the error report.

It doesn't matter if it's a contactless login, or if I insert the card into the reader. Annex ..._2

Georg
Attachments
TIM_APIClass20230902_2.zip
(3.38 KiB) Downloaded 361 times
TIM_APIClass20230902.zip
(3.31 KiB) Downloaded 311 times
edk
Posts: 999
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland

Re: Payment terminal TIMAPI.DLL

Post by edk »

Interesting :o The simulator always returns recipient as "Merchant" or "Cardholder", and your test terminal also returns "Both".
Because there is no "BrandName" field returned for Merchant / Cardholder this error occurs.
As a homework, try modifying the PrintItemsEFTReceipt function to include the three recipient variants :idea: If you fail, I will help you. Solving this issue will increase your skills with hash tables.
Hints: https://github.com/Petewg/harbour-core/ ... -functions
Georg_BA
Posts: 108
Joined: Fri Apr 07, 2017 5:31 pm
DBs Used: DBF

Re: Payment terminal TIMAPI.DLL

Post by Georg_BA »

I'm going to do my homework :D
I am writing the result of my efforts.
Georg
Georg_BA
Posts: 108
Joined: Fri Apr 07, 2017 5:31 pm
DBs Used: DBF

Re: Payment terminal TIMAPI.DLL

Post by Georg_BA »

Hi Edward

Homework not done.
I analyzed the PrintItemsEFTReceipt function, step by step.
I don't see a solution there, I added the value cRecipient == "Both"
but as I assumed, I have a third document Recipient: Both
In my opinion, all values should be loaded first, and then the document type "Merchant", "Cardholder" should be created.

I did not find the "Disclaimer" value anywhere

Code: Select all

Function PrintItemsEFTReceipt ( hPrintItems, oTIMApi )
Local aReceiptHeader := oTIMAPi:hTIM_CFG [ "ReceiptHeader" ]
Local nHeaderLine, nHeaderLines := Len ( aReceiptHeader )
Local nReceipt, nReceipts := Len ( hPrintItems )
Local nItem, nItems, hItems, cItemKey, xItemValue
Local cReceiptType, cRecipient, nRecipient, nRecipients, hRecipients
Local cPrintOut, nPrintWidth , cTranslatedText, cLeft, cRight


FOR nReceipt := 1 TO nReceipts
    
    //1st Node - Receipt Type, eg. Purchase, Credit, ...

    cReceiptType := hb_HKeyAt( hPrintItems, nReceipt )

    hRecipients := hPrintItems [ cReceiptType ] 

    nRecipients := Len ( hRecipients ) 

    
    FOR nRecipient := 1 TO nRecipients
    
        //2nd Node - Receipient: Merchant / Cardholder
        
        cRecipient := hb_HKeyAt( hRecipients, nRecipient )

        /*        
        IF cRecipient == "Merchant"
            nPrintWidth := oTIMApi:hTIM_CFG [ "PrintOptionsMerchant" ] [ "PrintWidth" ]
        ELSE
            nPrintWidth := oTIMApi:hTIM_CFG [ "PrintOptionsCardholder" ] [ "PrintWidth" ]
        ENDIF
		*/
		
		//IF cRecipient == "Cardholder"
		   nPrintWidth := oTIMApi:hTIM_CFG [ "PrintOptionsCardholder" ] [ "PrintWidth" ]
        //ELSE
           nPrintWidth := oTIMApi:hTIM_CFG [ "PrintOptionsMerchant" ] [ "PrintWidth" ]            
        //ENDIF
        
        cPrintOut := ""
        
        //Let's make a header.
        
        cPrintOut += MakePrintLine ( Replicate ("-=", nPrintWidth / 2 ), , "C", nPrintWidth )
        
        FOR nHeaderLine := 1 TO nHeaderLines 
            cPrintOut += MakePrintLine ( aReceiptHeader [ nHeaderLine ], , "C", nPrintWidth )
        NEXT nHeaderLine
        
        cPrintOut += MakePrintLine ( Replicate ("-=", nPrintWidth / 2 ), , "C", nPrintWidth )
        
        cTranslatedText := oTIMApi:TIM_Translate ( "rec" + cRecipient  /* Field names have a "rec" prefix in the translation table. */ )
        
        cPrintOut += MakePrintLine ( ".: " + cTranslatedText + " :.", , "C", nPrintWidth )
        
        cPrintOut += MakePrintLine ( , , , nPrintWidth )
        
        cTranslatedText := oTIMApi:TIM_Translate ( "trxType" + cReceiptType  /* Transaction types have a "trxType" prefix in the translation table. */ )
        
        cPrintOut += MakePrintLine ( cTranslatedText, , "L", nPrintWidth )
        cPrintOut += MakePrintLine ( , , , nPrintWidth )
        
        IF cReceiptType == "Purchase" .Or. ;
           cReceiptType == "PurchaseForcedAcceptance" .Or. ;
           cReceiptType == "PurchaseWithCashback" .Or. ;
           cReceiptType == "PurchasePhoneAuthorized" .Or. ;
           cReceiptType == "PurchasePhoneOrdered" .Or. ;
           cReceiptType == "Credit" .Or. ;
           cReceiptType == "CashAdvance"
        
            //Printout form for Purchase/Credit/etc transaction
            IF cRecipient == "Both"
               cPrintOut += MakePrintLine ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "BrandName" ], , "L", nPrintWidth )
            ELSE
	   		   //msgbox(cRecipient,nRecipient)
			ENDIF
			   
            IF cRecipient == "Cardholder"
                cPrintOut += MakePrintLine ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "CardNumberPrintableCardholder" ] , , "L", nPrintWidth )
            ELSEIF cRecipient == "Merchant"
                cPrintOut += MakePrintLine ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "CardNumberPrintableMerchant" ] , , "L", nPrintWidth )
            ENDIF
            
            cPrintOut += MakePrintLine ( , , , nPrintWidth )

           IF cRecipient == "Both"
/*
<sixml:ReceiptItem ReceiptItemType="AccPer" Recipient="Both">340</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="AcqId" Recipient="Both">00999100022</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="Aid" Recipient="Both">A0000000032020</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="Amount" Recipient="Both">427</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="AuthCode" Recipient="Both">562257</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="BrandName" Recipient="Both">V PAY</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="CardNumberEnc" Recipient="Both">0832F7DAB1A1DE0368BFA0D533708C30</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="Currency" Recipient="Both">EUR</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="Exponent" Recipient="Both">2</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="KeyPanReceiptIndex" Recipient="Both">2</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="PosEntryMode" Recipient="Both">97</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="TenderName" Recipient="Both">VPAY contactless</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="TimeStampDate" Recipient="Both">20230904</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="TimeStampTime" Recipient="Both">114758</sixml:ReceiptItem>
<sixml:ReceiptItem ReceiptItemType="TrmId" Recipient="Both">31397105</sixml:ReceiptItem>
*/
		   
            cLeft := hb_DtoC ( hb_StoD ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "TimeStampDate" ] ), "DD.MM.YYYY" )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "TimeStampTime" ]
            cRight := Left( cRight, 2 ) + ":" + SubStr( cRight, 3, 2 ) + ":" + Right ( cRight, 2 )
            
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )

 
            cLeft := oTIMApi:TIM_Translate ( "rec" + "TrmId"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "TrmId" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "Aid"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "Aid" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
        endif 
        if	cRecipient == "Merchant"  	
            cLeft := oTIMApi:TIM_Translate ( "rec" + "TrxSeqCnt"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "TrxSeqCnt" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
		endif	
        IF cRecipient == "Merchant"    
            cLeft := oTIMApi:TIM_Translate ( "rec" + "TrxRefNum"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "TrxRefNum" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
        endif 
        IF cRecipient == "Both"		
            cLeft := oTIMApi:TIM_Translate ( "rec" + "AuthCode"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "AuthCode" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "AcqId"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "AcqId" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
        endif 
        IF cRecipient == "Merchant"		
            cLeft := oTIMApi:TIM_Translate ( "rec" + "CardExpiryDate"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "CardExpiryDate" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
		endif	
            
            cPrintOut += MakePrintLine ( , , , nPrintWidth )
        IF cRecipient == "Both"    
            cLeft := oTIMApi:TIM_Translate ( "rec" + "Amount"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := AllTrim ( Str ( Val ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "Amount" ] ) / ( 10 ^ Val ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "Exponent" ] ) ) ) )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "Currency"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := hPrintItems [ cReceiptType ] [ cRecipient ] [ "Currency" ]
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
		endif	
            
            cPrintOut += MakePrintLine ( , , , nPrintWidth )
            
            //cPrintOut += MakePrintLine ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "Disclaimer" ], , "C", nPrintWidth )
            
        ELSE
        
            //Printout form for other transaction ( print all fields )
        
            hItems := hPrintItems [ cReceiptType ] [ cRecipient ]
            nItems := Len ( hItems )
            
            FOR nItem := 1 TO nItems
            
                //Items - fileds and values
                
                cItemKey   := hb_HKeyAt( hItems, nItem )
                xItemValue := hItems [ cItemKey ]
                
                IF cItemKey == "Exponent"       //skip print this field
                    LOOP
                ENDIF
                
                cLeft := cItemKey
                cTranslatedText := oTIMApi:TIM_Translate ( "rec" + cItemKey  /* Field names have a "rec" prefix in the translation table. */ )
                IF .Not. Empty ( cTranslatedText )
                    cLeft := cTranslatedText
                ENDIF
                
                IF cItemKey == "Amount"
                    cRight := AllTrim ( Str ( Val ( xItemValue ) / ( 10 ^ Val ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "Exponent" ] ) ) ) )
                ELSE
                    cRight := xItemValue
                ENDIF
                
                cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
                
            NEXT nItem

            cPrintOut += MakePrintLine ( , , , nPrintWidth )
        
        ENDIF
            
        PrintEFTReceipt ( cPrintOut, cRecipient )
        
    NEXT nRecipient

NEXT nReceipt

RETURN

Georg
edk
Posts: 999
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland

Re: Payment terminal TIMAPI.DLL

Post by edk »

Georg_BA wrote: Mon Sep 04, 2023 11:23 am Hi Edward

Homework not done.
I analyzed the PrintItemsEFTReceipt function, step by step.
I don't see a solution there, I added the value cRecipient == "Both"
but as I assumed, I have a third document Recipient: Both
In my opinion, all values should be loaded first, and then the document type "Merchant", "Cardholder" should be created.

I did not find the "Disclaimer" value anywhere

Georg
In my opinion, all values should be loaded first, and then the document type "Merchant", "Cardholder" should be created.
Good reasoning, too bad you didn't follow that lead :!:

Just check if the field is present in the node: [ ReceiptType ] [ Recipient ], if there is no "Merchant"|"Cardholder" is to see if it appears in "Both".

Code: Select all

Function PrintItemsEFTReceipt ( hPrintItems, oTIMApi )
Local aReceiptHeader := oTIMAPi:hTIM_CFG [ "ReceiptHeader" ]
Local nHeaderLine, nHeaderLines := Len ( aReceiptHeader )
Local nReceipt, nReceipts := Len ( hPrintItems )
Local nItem, nItems, hItems, cItemKey, xItemValue
Local cReceiptType, cRecipient, nRecipient, nRecipients, hRecipients
Local cPrintOut, nPrintWidth , cTranslatedText, cLeft, cRight, n 

FOR nReceipt := 1 TO nReceipts
    
    //1st Node - Receipt Type, eg. Purchase, Credit, ...

    cReceiptType := hb_HKeyAt( hPrintItems, nReceipt )
    
    hRecipients := hPrintItems [ cReceiptType ] 
    nRecipients := Len ( hRecipients ) 
    
    FOR nRecipient := 1 TO 2
    
        //2nd Node - Recipient: Merchant / Cardholder / Both
        
        IF nRecipient = 1
            cRecipient := "Merchant"
        ELSE
            cRecipient := "Cardholder"
        ENDIF
        
        IF .Not. hb_HHasKey( hRecipients, cRecipient ) //We check if the recipient is in the hash table
            LOOP
        ENDIF
        
        
        IF cRecipient == "Merchant"
            nPrintWidth := oTIMApi:hTIM_CFG [ "PrintOptionsMerchant" ] [ "PrintWidth" ]
        ELSE
            nPrintWidth := oTIMApi:hTIM_CFG [ "PrintOptionsCardholder" ] [ "PrintWidth" ]
        ENDIF
        
        cPrintOut := ""
        
        //Let's make a header.
        
        cPrintOut += MakePrintLine ( Replicate ("-=", nPrintWidth / 2 ), , "C", nPrintWidth )
        
        FOR nHeaderLine := 1 TO nHeaderLines 
            cPrintOut += MakePrintLine ( aReceiptHeader [ nHeaderLine ], , "C", nPrintWidth )
        NEXT nHeaderLine
        
        cPrintOut += MakePrintLine ( Replicate ("-=", nPrintWidth / 2 ), , "C", nPrintWidth )
        
        cTranslatedText := oTIMApi:TIM_Translate ( "rec" + cRecipient  /* Field names have a "rec" prefix in the translation table. */ )
        
        cPrintOut += MakePrintLine ( ".: " + cTranslatedText + " :.", , "C", nPrintWidth )
        
        cPrintOut += MakePrintLine ( , , , nPrintWidth )
        
        cTranslatedText := oTIMApi:TIM_Translate ( "trxType" + cReceiptType  /* Transaction types have a "trxType" prefix in the translation table. */ )
        
        cPrintOut += MakePrintLine ( cTranslatedText, , "L", nPrintWidth )
        cPrintOut += MakePrintLine ( , , , nPrintWidth )
        
        IF cReceiptType == "Purchase" .Or. ;
           cReceiptType == "PurchaseForcedAcceptance" .Or. ;
           cReceiptType == "PurchaseWithCashback" .Or. ;
           cReceiptType == "PurchasePhoneAuthorized" .Or. ;
           cReceiptType == "PurchasePhoneOrdered" .Or. ;
           cReceiptType == "Credit" .Or. ;
           cReceiptType == "CashAdvance"
        
            //Printout form for Purchase/Credit/etc transaction
            
            cPrintOut += MakePrintLine ( GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "BrandName" ), , "L", nPrintWidth )
            
            IF cRecipient == "Cardholder"
                cPrintOut += MakePrintLine ( GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "CardNumberPrintableCardholder" ), , "L", nPrintWidth )
            ELSE
                cPrintOut += MakePrintLine ( GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "CardNumberPrintableMerchant" ), , "L", nPrintWidth )
            ENDIF
            
            cPrintOut += MakePrintLine ( , , , nPrintWidth )
            
            cLeft := hb_DtoC ( hb_StoD ( GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "TimeStampDate") ), "DD.MM.YYYY" )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "TimeStampTime" )
            cRight := Left( cRight, 2 ) + ":" + SubStr( cRight, 3, 2 ) + ":" + Right ( cRight, 2 )
            
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
 
            cLeft := oTIMApi:TIM_Translate ( "rec" + "TrmId"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "TrmId" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "Aid"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "Aid" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "TrxSeqCnt"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "TrxSeqCnt" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "TrxRefNum"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "TrxRefNum" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "AuthCode"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "AuthCode" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "AcqId"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "AcqId" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "CardExpiryDate"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "CardExpiryDate" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cPrintOut += MakePrintLine ( , , , nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "Amount"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := AllTrim ( Str ( Val ( GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "Amount" ) ) / ( 10 ^ Val ( GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "Exponent" ) ) ) ) )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cLeft := oTIMApi:TIM_Translate ( "rec" + "Currency"  /* Field names have a "rec" prefix in the translation table. */ )
            cRight := GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "Currency" )
            cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
            
            cPrintOut += MakePrintLine ( , , , nPrintWidth )
            
            cPrintOut += MakePrintLine ( GetRecipientField ( hPrintItems [ cReceiptType ], cRecipient, "Disclaimer" ), , "C", nPrintWidth )
            
        ELSE
        
            //Printout form for other transaction ( print all fields )
            
            FOR n := 1 TO 2
        
               IF n = 1
                    hItems := hPrintItems [ cReceiptType ] [ cRecipient ]
               ELSE
                    hItems := hPrintItems [ cReceiptType ] [ "Both" ]
               ENDIF
               
               nItems := Len ( hItems )
                
               FOR nItem := 1 TO nItems
                
                   //Items - fileds and values
                   
                   cItemKey   := hb_HKeyAt( hItems, nItem )
                   xItemValue := hItems [ cItemKey ]
                    
                   IF cItemKey == "Exponent"       //skip print this field
                       LOOP
                   ENDIF
                    
                   cLeft := cItemKey
                   cTranslatedText := oTIMApi:TIM_Translate ( "rec" + cItemKey  /* Field names have a "rec" prefix in the translation table. */ )
                   IF .Not. Empty ( cTranslatedText )
                       cLeft := cTranslatedText
                   ENDIF
                    
                   IF cItemKey == "Amount"
                       cRight := AllTrim ( Str ( Val ( xItemValue ) / ( 10 ^ Val ( hPrintItems [ cReceiptType ] [ cRecipient ] [ "Exponent" ] ) ) ) )
                   ELSE
                       cRight := xItemValue
                   ENDIF
                    
                   cPrintOut += MakePrintLine ( cLeft, cRight, "J", nPrintWidth )
                    
               NEXT nItem
               
            NEXT n

            cPrintOut += MakePrintLine ( , , , nPrintWidth )
        
        ENDIF
            
        PrintEFTReceipt ( cPrintOut, cRecipient )
        
    NEXT nRecipient

NEXT nReceipt

RETURN
***********************************
Function GetRecipientField ( hReceiptType, cRecipient, cField )
Local cValue := ""
IF hb_HHasKey( hReceiptType [ cRecipient ], cField )
    cValue := hReceiptType [ cRecipient ] [ cField ]
ELSEIF hb_HHasKey( hReceiptType [ "Both" ], cField )
    cValue := hReceiptType [ "Both" ] [ cField ]
ENDIF
RETURN cValue
*******************************
Georg_BA
Posts: 108
Joined: Fri Apr 07, 2017 5:31 pm
DBs Used: DBF

Re: Payment terminal TIMAPI.DLL

Post by Georg_BA »

Hello,
I declare success, the certification is approved

I would like to thank Edward without whom this would not have been possible

I am attaching the final version, a selection from the program, which is certified.
There are also screenshots from working with the payment terminal.

One of the modifications is in TIMAPI_Class.prg, METHOD TIM_Translate ( cID ) CLASS TIMAPI returned an empty value, then the given data was missing on the printed document

Code: Select all

METHOD TIM_Translate ( cID ) CLASS TIMAPI
// !!! vzdy musi vratit nie prazdnu hodnotu !!!!
Local cStrTranslate, aLines, aFields, nFieldID, nFieldLanguage, nLine, vrat:='', vrat_t:=''

if left(cID,3)='rec'
      vrat:=alltrim(substr(cID,4,60))
elseif left(cID,7)='trxType'
      vrat:=alltrim(substr(cID,8,60))
else   
     vrat:=cID 
endif

if ! tim_ltans
   return vrat   
endif

//IF .Not. File ( "TIM_Translations.csv" )                     //rem Georg
IF .Not. File (cesta1+'BIN\'+"TIM_Translations.csv" )
   //RETURN ""                                     //change Georg
   return vrat    
ENDIF

//cStrTranslate := FileStr ( "TIM_Translations.csv" )                 //rem Georg
cStrTranslate := FileStr (cesta1+'BIN\'+"TIM_Translations.csv" )
The second is the modification of the created log file
I require an annotated entry with the current status of the payment terminal

I have the specified values defined in the INI file and they are tim_logi:=.t.,tim_logf:=.t.

Code: Select all

FUNCTION TIMaddlog( cTxt, lMsgStop )
Default lMsgStop := .F.

//tim_1.log_.AddText ( LEN( tim_1.log_.Value) ) := cTxt + CRLF                   //rem Georg
if tim_logi
   StrFile ( '[INFO] ('+dtos(date())+' '+time()+') '+ cTxt + CRLF , tim_logfile, .T. )
endif

IF lMsgStop .and. !tim_pstop
    //MsgStop ( cTxt, "TIM-API Stop" )                 	//rem Georg
	a2_msgstop(cTxt, "TIM-API Stop")
	if IsWindowDefined ("tim_1")
	   tim_1.cancel_.enabled:=.t.
	endif
ENDIF
DO events
RETURN nil

Code: Select all

FUNCTION TIMaddlogf( cTxt )
   StrFile ( '[FINER] ('+dtos(date())+' '+time()+') '+ cTxt + CRLF , tim_logfile, .T. )
DO events
RETURN nil
In conclusion: many thanks Erward
Source: 99.5% EDK, 0.5% Georg
Design: Georg :D

Best regards, Georg
Attachments
timapi_231009.zip
(383.31 KiB) Downloaded 360 times
TIMAPI_stop_pressstop.jpg
TIMAPI_stop_pressstop.jpg (93.24 KiB) Viewed 27784 times
TIMAPI_stop_ecr.jpg
TIMAPI_stop_ecr.jpg (96.95 KiB) Viewed 27784 times
TIMAPI_stop_cardholder.jpg
TIMAPI_stop_cardholder.jpg (160.86 KiB) Viewed 27784 times
TIMAPI_noconnect_balance.jpg
TIMAPI_noconnect_balance.jpg (91.96 KiB) Viewed 27784 times
TIMAPI_noconnect.jpg
TIMAPI_noconnect.jpg (100.65 KiB) Viewed 27784 times
Post Reply