Searching by pickup and drop location of a package and receiving list of delivery service options (Node.js)
In this use case, the user searches for delivery services by specifying some details about the package, where it needs to be picked up from and dropped. As a result, the user sees a list of available delivery options to choose from and some associated costs involved.
Code snippets
Client calls the BAP server to trigger search:
router.post("/delivery/search_by_pickup_drop_location", searchByLoc);
async function searchByLoc({ body }, res) {
try {
// .. Validate the client request here
await generateSearchRequest(body)
} catch (error) {
res.status(500).send(httpResponse("NACK", error));
}
};
BAP server generates the protocol request body
// Code to generate the protocol request body i.e. function generateSearchRequest() specified above
async function generateSearchRequest(clientRequestBody) {
/*
Example Request JSON :
{
"context": {
"domain": "delivery",
"country": "IND",
"city": "std:080",
"action": "search",
"core_version": "0.9.2",
"bap_id": "https://mock_bap.com/",
"bap_uri": "https://mock_bap.com/beckn/",
"transaction_id": "1239890342",
"message_id": "123793824",
"timestamp": "2021-03-23T10:00:40.065Z"
},
"message": {
"intent" : {
"fulfillment": {
"start" : {
"location" : {
"gps" : "12.4535445,77.9283792"
}
},
"end" : {
"location" : {
"gps" : "12.4535445,77.9283792"
}
}
}
}
}
}
*/
//The below code generates the above example JSON.
const transactionId = _.get(body, "transactionId");
// Returns the Context including MessageId
const context = createContext(transactionId);
const searchRequestBody = {
context,
message: {
intent: {
fulfillment: {
// Construct from the Request
},
}
}
};
//call protocol search
const response = await callSearch(searchRequestBody);
res
.status(200)
.send({ ...response.data, messageId: context["message_id"] });
}
BAP server calls protocol search to the network
async function callSearch(searchRequestBody) {
// It lookups the registry for BG OR BPP
let uri = lookup();
// Construct Header
const headers = constructAuthHeader(); // Auth Header with digital Signature
return axios({ url: `${uri}/delivery/search`, method: "POST", data: request, headers});
}
BAP receives protocol on_search
/*
Example Response JSON:
{
"context": {
"domain": "delivery",
"country": "IND",
"city": "std:080",
"action": "on_search",
"core_version": "0.9.2",
"bap_id": "https://mock_bap.com/",
"bap_uri": "https://mock_bap.com/beckn/",
"transaction_id": "1239890342",
"message_id": "123793824",
"timestamp": "2021-03-23T10:00:40.065Z"
},
"message": {
"catalog" : {
"bpp/descriptor": {
"name": "Fast Logistics"
},
"bpp/providers" : [
{
"id": "fast-logistics",
"descriptor" : {
"name": "Fast Logistics"
},
"items" : [
{
"id": "standard",
"descriptor" : {
"name" : "Standard Delivery"
},"price" : {
"currency": "INR",
"value": "40"
},
"matched": true
},
{
"id": "express",
"descriptor" : {
"name" : "Express Delivery"
},
"price" : {
"currency": "INR",
"value": "60"
},
"recommended": true
}
]
}
]
}
}
}
*/
// Auth middleware authenticates the digital signature of the incoming request
router.post("/delivery/on_search", auth, onSearch);
async function onSearch({ body }, res) {
// Save the response to Database
await saveToDb(body);
};
Client polls BAP to get the on_search results
// Endpoint for the client to poll the search data based on the message id
async function getMessageById(req) {
try {
const messageId = _.get(req, "messageId");
// Get the data using message Id
const response = await getData(messageId);
res.status(200).send(httpResponse('ACK', "", response));
} catch(error) {
res.status(500).send(httpResponse("NACK", error));
}
};