Search by folio

There is a way where you can obtain the ticket and the JSON response through the search of a sale folio.

1.- Steps to implement the search by folio.

Para realizar una búsqueda por folio, es necesario contar con la siguiente información:
To search by folio, it is necessary to have the following information:

  • {{serialNumber}} : Serial Number. 10 digit string located in the back of the terminal. (S/N). (Required).
  • {{storeId}} : ID number of commerce asigned by terminal. (Required).
  • {{access_token}} : Access token necessary to consume the service. See Get access token. (Required).
  • {{folioId}} : Order number generated when you make a sale. See information returned by terminal. (Required).
  • {{orderId}} : Order number generated when you make a sale. See information returned by terminal. This field must be added, but empty
  • {{traceability}}: JSON object to send relevant information to the commerce. (Optional).

📘

Nota.

  • The terminal must have access to internet at all times with no restrictions to the domain and subdomains *.netpay.com.mx to recieve and send requests.
  • Terminal screen must be on and the main screen of the app on foreground.

2.- Request structure.

POST http://nubeqa.netpay.com.mx:3334/integration-service/transactions/reprint

Headers

The following headers must be sent in the request

  • Content-Type: application/json
  • Authorization: Bearer {{access_token}}

Body

In the request, a JSON object must be sent according to the needed data*. At least, there must be these fields, serialNumber, orderId (empty), storeId, isSmartAccouts (true) and folioId.

Example:

{  
    "serialNumber": "{{serialNumber}}",
    "orderId": "",
    "folioId": "{{folioId}}"
    "storeId": "{{storeId}}"
}

🚧

Note

1.- It is very important to consider that in order for this functionality to be executed correctly, the orderId must be added empty , otherwise, the search will be executed by orderId and will not even consider the folioId.
2.- You should also consider that the content of folioId is sensitive to upper case and lower case letters, so you have caution when you type it.
3.- folioId must be the right one, because, if you type one that is not correct, it could print a ticket and return a random response.
4.- Finally, folioId must be unique and unrepeatable. If it were to repeat, the response will be the newest one with this folio.

3.- Request/response example.

Next, an example of a request for the search by folio and the different response messages when sending the request.

Endpoint

http://nubeqa.netpay.com.mx:3334/integration-service/transactions/reprint

curl --location --request POST 'http://nubeqa.netpay.com.mx:3334/integration-service/transactions/reprint' \
--header 'Authorization: Bearer {{access_token}}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "folioId": "{{folioId}}",
    "orderId": "",
    "serialNumber": "{{orderId}}",
    "storeId": "{{storeId}}",
    "isSmartAccounts": true
}'
var client = new RestClient("http://nubeqa.netpay.com.mx:3334/integration-service/transactions/reprint");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer {{access_token}}");
request.AddHeader("Content-Type", "application/json");
var body = @"{
" + "\n" +
@"    ""folioId"": ""{{folioId}}"",
" + "\n" +
@"    ""orderId"": """",
" + "\n" +
@"    ""serialNumber"": ""{{serialNumber}}"",
" + "\n" +
@"    ""storeId"": ""{{storeId}}"",
" + "\n" +
@"    ""isSmartAccounts"": true
" + "\n" +
@"}";
request.AddParameter("application/json", body,  ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'http://nubeqa.netpay.com.mx:3334/integration-service/transactions/reprint',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS =>'{
    "folioId": "{{folioId}}",
    "orderId": "",
    "serialNumber": "{{serialNumber}}",
    "storeId": "{{storeId}}",
    "isSmartAccounts": true
}',
  CURLOPT_HTTPHEADER => array(
    'Authorization: Bearer {{access_token}}',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;
HttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\r\n    \"folioId\": \"{{folioId}}\",\r\n    \"orderId\": \"\",\r\n    \"serialNumber\": \"{{serialNumber}}\",\r\n    \"storeId\": \"{{storeId}}\",\r\n    \"isSmartAccounts\": true\r\n}");
Request request = new Request.Builder()
  .url("http://nubeqa.netpay.com.mx:3334/integration-service/transactions/reprint")
  .method("POST", body)
  .addHeader("Authorization", "Bearer {{access_token}}")
  .addHeader("Content-Type", "application/json")
  .build();
Response response = client.newCall(request).execute();
import requests
import json

url = "http://nubeqa.netpay.com.mx:3334/integration-service/transactions/reprint"

payload = json.dumps({
  "folioId": "{{folioId}}",
  "orderId": "",
  "serialNumber": "{{serialNumber}}",
  "storeId": "{{storeId}}",
  "isSmartAccounts": True
})
headers = {
  'Authorization': 'Bearer {{access_token}}',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

*Things to keep in mind.**

  • Any programming language you wish could be used, as long as it allows to create an API REST.
  • The service must be working when you require to make sales with the terminal, because there is where the operation's response will be sent.
  • The terminal must connect with the service at all times to perform the transaction flow complitely.
  • In the event of the terminal not sending the response to the service, it must be verified instantly if the service is working correctly, so the transaction flow can de done right.

Requirements.

  • After the service was consumed, a HTTP Status Code 200 must be returned.
  • The HTTP verb returned must be POST.
  • After the service was consumed, the body must contain the following JSON parameters. (The message inside the message parameter could contain any text and the code parameter must return 00).
{
    "code": "00",
    "message": "Mensaje enviado exitosamente"
}

📘

Note.

We recommend that this functionality is added in the POS as a new module and not combined with the reprint as this has very different rules and considerations and may provoke a conflict.

Responses to the sending of the search by folio.

  • SUCCESS: This response will be obtained if the information is correct.
  • INVALID TOKEN: This response will be obtained if {{access_token}} is wrong.
  • MISSING TERMINAL: This response will be obtained if the {{serialNumber}} sent is wrong.
{
    "code": "00",
    "message": "Mensaje enviado exitosamente"
}
{
    "error": "invalid_token",
    "error_description": "Cannot convert access token to JSON"
}
{
    "code": "19",
    "message": "No se encontró la terminal"
}

5.- Returned responses to the point of sale

Succesful transaction

Example of a search by folio in a succesful transaction without PIN.

{
	"affiliation": "7389145",
	"applicationLabel": "VISA ELECTRON",
	"arqc": "F952CB0CD028B6B7",
	"aid": "A0000000032022",
	"amount": "200",
	"authCode": "TEST00",
	"bankName": "BANCOPPEL",
	"bin": "",
	"cardExpDate": "02/27",
	"cardType": "D",
	"cardTypeName": "VISA",
	"cityName": "OTHON P. BLANCO,QUINTANA ROO",
	"responseCode": "00",
	"exchangeComm": "0",
	"exchangeNat": "NONE",
	"exchangeTotal": "0",
	"exchangeUnit": "0",
	"folioNumber": "EjemploFolio",
	"hexSign": "00000200000001DA0000009E000000040800031CFF02FF035300A765326D3970CA075B7EC300F1215739F054F40051C557F3983B42B0EABB8A0DDDFF0208B4AFFF003D48D46028695497CCE9779AF00AC2D57A5E4C171ABC6A468431E0CA3C1E36BF63AE0AA273467CFF02533C6830A4767D87A231F025302D7D294A0AA6D8EE313793EE1EB5A77A8B59D73F721390FF02FF02FF02FF02FF02F786C8FEE8FF02756F4DC9D5A342FF022393EF5C60FF0225CE9069E8DCFF02153AF38EE0C1C14EF045DE42EE3C996C4EA831188E2BC840F88FB369C6BE50BD8011D350F242B02F14C91B66E17BA0D8FF0200FEBB4D196AE10073396FE9BE7A979A186C15CA11396E58EA64BAC24566BE61A0FF0286ED9FEF4B42320CABF9A44AEDA2F67F5B0DC29F96AB4B5BF0509FD1E6014FEB7D94E64AFF022488006394E2C0FF025B845195FF02606F7980FF02D5207060EBD0FF02D4E5218555FF0232B00B78B8FF02DC88931F20FF022A3747C2BD4C1583AC5E800280FF02EA4DF4215ED85B29B1E57F87D9A5755735981B7375364883B03DE1FA69833F1A38A7DCE04DC8830B0A676168E9A1B5D1283C68FD26A5084E008CC0FF023E3789C4236189FF00ACD91C0F2BF9ED98F5AF086C22EF3F696DAD601014D7F930A891FD0DDBA00DF2133E162821D9FF024CF552F14477001CCD937873F62C83625C0EA88CE550ADA239A15B06B9EDDB629370FF02BBF0D1D2D6229260FF02D64707936F458EFF02ADEA0777095CFF022D160A8FF44211E74FF668FF0288BDC5FF00351677525CFF02FD90FF02EAE0FF02A0FF02D711A1E354EB6CAF7FCC58CF9EFE201E0727410F403EE0F97C2DFDE61826EF40BA35625E39A096AD5F98DF1B7C7430271E10A6745D3D206C0EFD0BA0163738564D52C0FF025EC62EA244AF63D578F716C30F6FC7E06E28F89703834B81DE3ECFFB4FF883CB469066056B84692A2ED860630540FF0240DB122F469788FF02FF02FF02",
	"internalNumber": "",
	"isQps": 0,
	"isRePrint": true,
	"message": "Transaccion Valida",
	"moduleCharge": "1",
	"moduleLote": "1",
	"customerName": "null",
	"terminalId": "1450958877",
	"orderId": "220602134739-1450958877",
	"preAuth": "0",
	"preStatus": 0,
	"promotion": "0",
	"rePrintDate": "1.3.5.p.p_20220530",
	"rePrintMark": "VISA",
	"reprintModule": "C",
	"cardNumber": "4165",
	"storeName": "EUROPIEL CHETUMAL",
	"streetName": "AV. INSURGENTES  KM 5.025",
	"tableId": "",
	"ticketDate": "JUN. 02, 22 13:47:40",
	"tipAmount": "0",
	"tipLessAmount": "0",
	"traceability": {},
	"transDate": "2022-06-02 13:47:40.0",
	"transType": "A",
	"transactionCertificate": "F952CB0CD028B6B7"
}

Other kind of responses

{
  "responseCode": "13",
  "hasPin": false,
  "internalNumber": "",
  "message": "TRANSACCION NO PERMITIDA",
  "tableId": "",
  "traceability": {}
}
{
  "responseCode": "56",
  "hasPin": false,
  "internalNumber": "",
  "message": "TARJETA INVALIDA",
  "tableId": "",
  "traceability": {}
}
{
  "responseCode": "34",
  "hasPin": false,
  "internalNumber": "",
  "message": "TARJETA RECHAZADA",
  "tableId": "",
  "traceability": {}
}
{
  "bin": "",
  "responseCode": "34",
  "folioNumber": "prueba",
  "internalNumber": "",
  "isRePrint": false,
  "message": "TRANSACCION RECHAZADA",
  "tableId": "",
  "traceability": {}
}
{
  "bin": "",
  "responseCode": "05",
  "folioNumber": "prueba",
  "internalNumber": "",
  "isRePrint": false,
  "message": "Error de conexión",
  "tableId": "",
  "traceability": {}
}
{
  "bin": "",
  "responseCode": "02",
  "folioNumber": "prueba",
  "internalNumber": "",
  "isRePrint": false,
  "message": "Cancelado por el Usuario",
  "tableId": "",
  "traceability": {}
}

As mentioned above, different kinds of responses can be obtained according to the different cards and banks.
A responseCode different to 00 indicates that the transaction was not succesful and can we can see the reason on the message.
Como se mencionó más arriba, se pueden obtener diferentes tipos de respuesta según el banco emisor de la tarjeta. Un responseCode diferente de 00 indica que la transacción no fue exitosa y podemos ver el motivo en el message.

📘

Note.

More information for this last topic can be found in section [8.- Receiving response] (https://dash.readme.com/project/netpay/v1.0/refs/8-receiving-response)