Tracking an order (Node.js)

In this use case, the user usually clicks on "Track Order" or sometimes, the application automatically renders the tracking screen as part of the order screen. Here the seller usually sends a tracking link to the tracking page of the order.

Track

Code snippets

Client calls the BAP server to trigger track:

    router.post("/local_retail/track_order", trackOrder);

    async function trackOrder({ body }, res) {
        try {
            //  .. Validate the client request before below function
            await generateTrackRequest(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 generateTrackRequest() specified above

    async function generateTrackRequest(body) {
/*
Example Request JSON :
{
    "context": {
        "domain": "nic2004:52110",
        "country": "IND",
        "city": "std:080",
        "action": "track",
        "core_version": "0.9.1",
        "bap_id": "https://mock_bap.com/",
        "bap_uri": "https://mock_bap.com/beckn/",
        "bpp_id": "https://mock_bpp.com/",
        "bpp_uri": "https://mock_bpp.com/beckn/",
        "transaction_id": "1209849124",
        "message_id": "12341242347",
        "timestamp": "2021-03-23T10:00:40.065Z"
    },
    "message": {
        "order_id": "order_1",
        "callback_url": "https://mock_bap.com/order_track?orderId=order_1"
    }
}
*/
        //The below code generates the above example JSON.
        const transactionId = _.get(body, "transactionId");
        // Returns the Context including MessageId
        const context = createContext(transactionId);
        const trackRequestBody = {
            context,
            message:  {
                // Construct from the request
            }
        };
        //call protocol track
        const response = await callTrack(trackRequestBody);
        res
        .status(200)
        .send({ ...response.data, messageId: context["message_id"] });
    }

BAP server calls protocol track to the network

    async function callTrack(trackRequestBody) {
        // 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}/local_retail/status`, method: "POST", headers, data: trackRequestBody });
    }

BAP receives protocol on_track

/*
Example Response JSON:
{
    "context": {
        "domain": "nic2004:52110",
        "country": "IND",
        "city": "std:080",
        "action": "on_track",
        "core_version": "0.9.1",
        "bap_id": "https://mock_bap.com/",
        "bap_uri": "https://mock_bap.com/beckn/",
        "bpp_id": "https://mock_bpp.com/",
        "bpp_uri": "https://mock_bpp.com/beckn/",
        "transaction_id": "1209849124",
        "message_id": "12341242343",
        "timestamp": "2021-03-23T10:00:40.065Z"
    },
    "message": {
        "tracking": {
            "tl_method": "http/get",
            "url": "https://track.mock_bpp.com?order_id=order_1",
            "status": "active"
        }
    }
}
*/
    // Auth middleware authenticates the digital signature of the incoming request
    router.post("/local_retail/on_track", auth, onStatus);
    async function onStatus({ body }, res) {
        // Save the response to Database
        await saveToDb(body);
    };

Client polls BAP to get the on_track 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));
        }
    };