Help With JSON formatting
Posted
#1
(In Topic #886)
Enthusiast

I need some help on the following
I am sending the following JSON to a web API that i use in Windows
Code
Dim jsonString As String = "\{""transactionType"":""SALE"",""amount"":""" & transAmount & """,""currency"":""GBP""}"and in Windows this works fine but in Gambas none of the extra " are sent so I receive back from the API "Invalid JSON Received"
could someone show me how I can send the JSON to the API correctly
this is the code I am using to send to the API
Code
Dim hClient As HttpClient
Dim sBuffer As String
Dim jsonString As String = "\{" "transactionType" ":" "SALE" "," "amount" ":" "" & transAmount & "" "," "currency" ":" "GBP" "}"
message(JSON.Encode(jsonString))
hClient = New HttpClient As "hClient"
With hClient
.URL = global.PS_URL & "/terminals/" & global.terminalIDNumber & "/transactions"
.Auth = 1
.User = Global.PS_USER
.Password = Global.PS_PASS
' .Headers.Add("Software-House-ID :SD45T92")
' .Headers.Add("Installer-Id: " & Global.InstallerID)
.Async = False
.Timeout = 60
.Post("application/connect.v2+json", JSON.Encode(jsonString))
End With
global.showResult("POST", hClient)
as yes as you can all see i am still struggling to work out how to send the extra 2 Headers to the API as well (i need to send them so the API would work at 100% service)
Posted
Enthusiast

string = " <COLOR color="#FF0000">"</COLOR>this should work <COLOR color="#FF0000">"</COLOR>"
Posted
Enthusiast

PJBlack said
escape the quotation mark with \
string = " <COLOR color="#FF0000">"</COLOR>this should work <COLOR color="#FF0000">"</COLOR>"
Dim jsonString As String = "{" "transactionType" ":" "SALE" ",""amount" ":" "" & transAmount & "" "," "currency" ":" "GBP" "}"
Something like that?
Posted
Enthusiast

Posted
Enthusiast

I shall try that and let you know what the status message is from the cloud server
Posted
Enthusiast

I have tired the corrections as you all said and I am still getting a Error from the API
I have even tried this bit of code
Code
Dim hClient As HttpClient
Dim sBuffer As String
' Dim jsonString As String = "\{""transactionType"":""SALE"",""amount"":""" & transAmount & """,""currency"":""GBP""}"
Dim jsonString As String = "\{¬¬transactionType¬¬:¬¬SALE¬¬,¬¬amount¬¬:¬¬" & transAmount & "¬¬¬,¬¬currency¬¬:¬¬GBP¬¬}"
jsonString = Replace(jsonString, "¬", Chr(34))
message(JSON.Encode(jsonString))
hClient = New HttpClient As "hClient"
With hClient
.URL = global.PS_URL & "/terminals/" & global.terminalIDNumber & "/transactions"
.Auth = 1
.User = Global.PS_USER
.Password = Global.PS_PASS
' .Headers.Add("Software-House-ID :SD45T92")
' .Headers.Add("Installer-Id: " & Global.InstallerID)
.Async = False
.Timeout = 60
.Post("application/connect.v2+json", JSON.Encode(jsonString))
End With
global.showResult("POST", hClient)
as you can see I replaced every " with a ¬ with in the string formation and then did a replace function at the end to get the format correct
This is what I am getting on the message box
Code
"\{\" \"transactionType\" \":\" \"SALE\" \",\" \"amount\" \":\" \"\"153\"\"\",\" \"currency\" \":\" \"GBP\" \"}"But I am still getting a Error from the card Server API I get in my list box
{"messages":{"error":["Invalid JSON received."]}}
so I am completely stumped as to what to try now I have even asked the Card Service providers as to what they are getting their end but I have not had a replay back yet.
Does anyone know what I have done wrong?
Posted
Enthusiast

Do you want the 153 to be double quoted ? and there are spaces between each element except the 153 and the comma following it has no space.
If it does require double quotes …. does it need spaces between the quotes ?
Posted
Enthusiast

Posted
Enthusiast

I am getting Unexpected "" and it is flashing next to the & \ just after the amount
so it is showing transAmount & \ "", it is the \ i am getting the error on
Sorry if I am not any help I am still figuring this out as I go along.
Posted
Enthusiast

{"transactionType":"SALE","amount":"2345.45","currency":"GBP"}
Posted
Enthusiast

Thank you for your example It worked
Thank-you
Now i just need to get status again
Posted
Enthusiast

so I have this working now (the JSON is being sent to the server with no errors) but when I get the data back from the Server it is in the following format
Code
\{"location":"https://test.connect.paymentsense.cloud/pac/terminals/12345678/transactions/661c943f","notifications":["TRANSACTION_STARTED"]}
Ivbe tried to use this
Code
If http.Status < 0 Then
Global.addtoStatusList("SORRY A Error was detected")
global.AddToDebugList(http.ErrorText)
Else
' Success - read data
If Lof(http) Then Read #http, global.sBuffer, Lof(http)
Global.addtoStatusList(global.sBuffer)
Dim vNew As Variant = JSON.Decode(global.sBuffer)
global.AddToDebugList(global.sBuffer)
Message(vNew["notifications"])
End if
but I get a error on Message(vNew["notifications"]) saying "Type Mismatch: wanted string got Variant[] instead"
do i have to process the output differently when it has more then one feed? Im trying to get the TRANSACTION_STARTED bit
Posted
Enthusiast

Message(Str(vNew["notifications"]))
Posted
Enthusiast

I need to read from the notifications Section
I have the following
Code
\{"location":"https://test.connect.paymentsense.cloud/pac/terminals/12345678/transactions/661c943f","notifications":["TRANSACTION_STARTED"]}How do I get the "TRANSACTION_STARTED" from the notifications area?
Posted
Guru

the notifications is an array so use [0] to get the first item.
Code (gambas)
- ' this is your string...
- ' turn the JSON string into a collection
- ' print the data..
Posted
Enthusiast

BruceSteers said
The format is a JSON string so use Decode to process it as a collection.
the notifications is an array so use [0] to get the first item.Code (gambas)
' this is your string... ' turn the JSON string into a collection ' print the data..
THANK-YOU THANK-YOU THANK-YOU
Posted
Guru

AndyGable said
BruceSteers said
The format is a JSON string so use Decode to process it as a collection.
the notifications is an array so use [0] to get the first item.
THANK-YOU THANK-YOU THANK-YOU
You're welcome.
It would probably be good to make a class to handle your messages and fire events relevant to the message type.
attached is a simple example I just made of a class that you can send your device text to and it will fire events based on the message type. I called it DeviceMessage.class
It just handles 'notifications' or it reports an unhandled message for anything else…
Code (gambas)
- ' Gambas class file
- '' Get the notifications sent
- '' get the location
- '' fires when a message contains notifications.
- Event Notify
- '' process text from the device
- $sLocation = jc["location"]
- jc.Remove("location")
- $aNotifications = jc["notifications"]
- Raise Notify
- jc.Remove("notifications")
- ' If here there is an unhandled message
- Print "Unhandled type"
Now in your application you would create the instance of the DeviceMessage class like so…
then send the global.sBuffer strings like
Code (gambas)
- Global.addtoStatusList(global.sBuffer)
- hMessager(global.sBuffer)
- global.AddToDebugList(global.sBuffer)
a notifications message will fire the Notify event
possibly not what you want but I was bored and thought this might help you with understanding collections, how to process various unknown variant types and setting up events.
Perhaps you could expand it do suit your needs.
Happy coding
BruceS
Posted
Enthusiast

Posted
Guru

AndyGable said
Would that class help send status messages to my point of sale software?
It's a bare bones example.
I don't know your device , you would have to add what you want to it and make it work how you need it to.
If there is a status specific message string then process it like the notifications message.
The above post has a test source app attached showing how to use it.
It will print messages about anything sent that is not notifications showing the datatype of the message so you can figure it out from there I should think <EMOJI seq="1f60a" tseq="1f60a">😊</EMOJI>
Posted
Guru

You could then add a DeviceMessage.Send() command to the class easily enough.
Posted
Enthusiast

Once a sale starts it output status in the same message
how would I pole the url? do I just have to call the same Function or can it be made to do that?
Code
Private Sub ShowSaleResults(RequestID As String, http As HttpClient)
FMain.Refresh
If http.Status < 0 Then
Global.addtoStatusList("SORRY A Error was detected")
global.AddToDebugList(http.ErrorText)
Else
' Success - read data
If Lof(http) Then Read #http, global.sBuffer, Lof(http)
Global.addtoStatusList(global.sBuffer)
Dim vNew As Variant = JSON.Decode(global.sBuffer, True)
global.AddToDebugList(global.sBuffer)
Select Case UCase(vNew["notifications"][0])
Case ""
ShowSaleResults(requestId, http)
Case "CARD_ERROR"
Global.addtoStatusList("Sorry a error has been detected with the customers card")
Case "PROCESSING_ERROR"
Global.ddtoStatusList("Sorry there has been a processing Error." & gb.CrLf & "Please check the PinPad Screen for further information")
Case "SIGNATURE_VERIFICATION"
If global.WaitingForPoS = 0 Then
Global.addtoStatusList("Requesting PoS User to confirm Card Signture")
global.WaitingForPoS = 1
'CreateSigntureSlip_FromPDQ(TerminalType, responseFromServer, IDNumber)
'SendToPoSterminal("Printdata_Signture|" & PoSSlipData)
'SendToPoSterminal("SigntureCheck")
ShowSaleResults(requestId, http)
End If
Case "TRANSACTION_FINISHED"
If Global.SigntureReq = 1 Then
LoadCardSlipData(RequestID)
'selectSlipToPrint(1, responseFromServer)
'SendToPoSterminal("Printdata_Recipit|" & PoSSlipData)
'SendToPoSterminal("TransactionCompleted|" & cardSchemeName & "|" & (amountTotal * 100))
Global.WaitingForPoS = 0
ShowSaleResults(requestId, http)
Else
If Global.WaitingForPoS = 0 Then
LoadCardSlipData(RequestID, requestId)
If UCase(Global.paymentMethod) = "KEYED" Then Global.SigntureNotNeeded = 1
Select Case Global.SigntureNotNeeded
Case 0 ' No Signutre needed
'selectSlipToPrint(0, responseFromServer) '
Select Case Global.PrintStoreSlip
Case "Yes"
'SendToPoSterminal("Printdata_Store|" & PoSSlipData)
Case "No"
'SendToPoSterminal("Storedata_Store|" & PoSSlipData & "|" & transactionNumber & "|" & IDNumber & "|" & transactionId)
End Select
Case 1 ' Signture needed
'CustomerNOTPresentCardSlip_FromPDQ(TerminalType, responseFromServer, IDNumberLocal)
'SendToPoSterminal("Printdata_Store|" & PoSSlipData)
ShowSaleResults(requestId, http)
End Select
Else
LoadCardSlipData(requestID)
'selectSlipToPrint(2, responseFromServer)
Select Case Global.PrintStoreSlip
Case "Yes"
'SendToPoSterminal("Printdata_Store|" & PoSSlipData)
Case "No"
'SendToPoSterminal("Storedata_Store|" & PoSSlipData & "|" & transactionNumber & "|" & IDNumber & "|" & transactionId)
End Select
LoadCardSlipData(Requestid)
'selectSlipToPrint(1, responseFromServer)
'SendToPoSterminal("Printdata_Recipit|" & PoSSlipData)
'SendToPoSterminal("TransactionCompleted|" & cardSchemeName & "|" & (amountTotal * 100))
ShowSaleResults(requestId, http)
End If
End If
Case "REMOVE_CARD"
'SendToPoSterminal("RemoveCard")
Global.addtoStatusList("Please ask customer to remove card") ''
ShowSaleResults(requestId, http)
Case "APPROVED"
'SendToPoSterminal("Approved")
Global.addtoStatusList("Transaction has been approved")
ShowSaleResults(requestId, http)
Case "CONNECTION_MADE"
'SendToPoSterminal("ConnectionMade")
Global.addtoStatusList("Connection Established to Payment Provider")
ShowSaleResults(requestId, http)
Case "CONNECTING"
'SendToPoSterminal("Connecting")
Global.addtoStatusList("Connecting to Payment Provider")
ShowSaleResults(requestId, http)
Case "PIN_ENTRY"
'SendToPoSterminal("EnterPIN")
Global.addtoStatusList("Waiting for customer to enter PIN")
ShowSaleResults(requestId, http)
Case "PLEASE_WAIT"
'SendToPoSterminal("PleaseWait")
Global.addtoStatusList("Please Wait...")
ShowSaleResults(requestId, http)
Case "PRESENT_CARD"
'SendToPoSterminal("InsertCard")
Global.addtoStatusList("Please insert card")
ShowSaleResults(requestId, http)
Case "INSERT_CARD"
'SendToPoSterminal("InsertCard")
Global.addtoStatusList("Card has been inserted")
ShowSaleResults(requestId, http)
Case "TRANSACTION_STARTED"
'Global.SigntureNotNeeded = 0
' Global.SigntureReq = 0
Global.addtoStatusList("Starting transacation One moment...")
ShowSaleResults(requestId, http)
End Select
End If
End
As you can see the system uses the same feed to send the full status of the transaction (from Insert Card to Complete sale)
Posted
Guru

When a message is processed the DeviceMessage.Location property is filled.
Posted
Enthusiast

with your class do I still call ShowSaleResults? to get the newest status message?
also could someone tell me why while running the transaction nothing is being added to the listbox even though I am adding messages to the list
Posted
Guru

AndyGable said
opps sorry that was a typo it should have said poll
with your class do I still call ShowSaleResults? to get the newest status message?
also could someone tell me why while running the transaction nothing is being added to the listbox even though I am adding messages to the list
How are you adding messages to the listbox?
Note.
ListBox1.List.Add(sText) will not work.
ListBox1.Add(sText) is how to do it.
A ListBox.List read returns a copy of the list only not a pointer to it.
And.
The class has one function _call() did you even read the source code i posted?
Or download the source i uploaded to see?
Or read the last message about it being bare bones and doesn't do anything much?
Good luck with your problem.
Posted
Enthusiast

BruceSteers said
AndyGable said
opps sorry that was a typo it should have said poll
with your class do I still call ShowSaleResults? to get the newest status message?
also could someone tell me why while running the transaction nothing is being added to the listbox even though I am adding messages to the list
How are you adding messages to the listbox?
Note.
ListBox1.List.Add(sText) will not work.
ListBox1.Add(sText) is how to do it.
A ListBox.List read returns a copy of the list only not a pointer to it.
And.
The class has one function _call() did you even read the source code i posted?
Or download the source i uploaded to see?
Or read the last message about it being bare bones and doesn't do anything much?
Good luck with your problem.
Hi This is the code I am using to add to my listbox
Code
Public Sub addtoStatusList(textToShow As String)
Dim gw As GridView
Dim b As Byte
fmain.lstSystemMessages.Add(Trim(textToShow)) ' add to list box
fmain.lstSystemMessages.Index = fmain.lstSystemMessages.Count - 1 ' places the blue line onto the newly added item
gw = fmain.lstSystemMessages.Children[0]
b = fmain.lstSystemMessages.List.Max
gw.Rows[b].Height = -1 ' adjust blue line if the data is over 2 or more lines
fmain.lstSystemMessages.Refresh
fmain.Refresh
End Sub
if i am not doing anything with the Status of the transaction I get Messages Showing up (Example when I click Check Status i get the Message "Terminal Ready for Transaction" but the moment a sale starts nothing seems to be added to the list (even though I have the code to do it see example)
Code
Case "TRANSACTION_STARTED"
'Global.SigntureNotNeeded = 0
'Global.SigntureReq = 0
Global.addtoStatusList("Starting transacation One moment...")
ShowSaleResults(requestId, http)
as you can see I am adding the message "Starting transaction One moment…" but it does not get added
once the transaction is cancelled on the PinPad the list box refresh and everything is showing up
could this be a update issues between the thread running on the update command?
any help would be most appreachated
1 guest and 0 members have just viewed this.



