Confirmation of a prepaid order (Node.js)
In this use case, the user confirms the delivery request by sending the proof of payment along with the other details present in the invoice and receives a confirmed order with the latest status of the fulfillment. In the case of hyperlocal delivery, the response sometimes also contains the details of the agent allocated to perform the delivery.
Code snippets
Client calls the BAP server to trigger confirm:
router.post("/delivery/confirm_prepaid_order", confirmOrder);
async function confirmOrder({ body }, res) {
try {
// .. Validate the client request before below function
await generateConfirmOrderRequest(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 generateConfirmOrderRequest() specified above
async function generateConfirmOrderRequest(clientRequestBody) {
/*
Example Request JSON :
{
"context": {
"domain": "delivery",
"country": "IND",
"city": "std:080",
"action": "confirm",
"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-06-23T07:33:02.655Z"
},
"message": {
"order": {
"provider": {
"id": "./logistics.hyperlocal-delivery/ind.blr/[email protected]"
},
"items": [
{
"id": "standard",
"quantity": {
"count": 1
}
}
],
"billing": {
"name": "John Doe",
"address": {
"door": "21A",
"name": "ABC Apartments",
"locality": "HSR Layout",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560102"
},
"email": "[email protected]",
"phone": "+919876543210",
"created_at": "2021-06-15T07:08:36.211Z",
"updated_at": "2021-06-15T07:08:36.211Z"
},
"fulfillment": {
"type": "home-delivery",
"tracking": false,
"start": {
"location": {
"gps": "12.9349377,77.6055586"
},
"time": {
"range": {
"start": "2021-06-15T07:09:30.000Z",
"end": "2021-06-15T07:10:30.000Z"
}
},
"instructions": {
"name": "pick up instructions",
"short_desc": "Don't ring doorbell"
},
"contact": {
"phone": "+919999999999",
"email": "[email protected]"
}
},
"end": {
"location": {
"gps": "12.914028, 77.638698",
"address": {
"door": "21A",
"name": "ABC Apartments",
"locality": "HSR Layout",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560102"
}
},
"time": {
"range": {
"start": "2021-06-15T07:11:36.212Z",
"end": "2021-06-15T07:12:36.212Z"
}
},
"instructions": {
"name": "drop off instructions",
"short_desc": "Leave at door step"
},
"contact": {
"phone": "+919876543210",
"email": "[email protected]"
}
}
},
"quote": {
"price": {
"currency": "INR",
"value": "40"
},
"breakup": [
{
"title": "Standard delivery",
"price": {
"currency": "INR",
"value": "40"
}
}
],
"ttl": "P4D"
},
"payment": {
"uri": "https://api.bpp.com/pay?amt=$amount&txn_id=ksh87yriuro34iyr3p4&mode=upi&vpa=bpp@upi",
"tl_method": "http/get",
"params": {
"transaction_id": "ksh87yriuro34iyr3p4",
"amount": "40",
"mode": "upi",
"vpa": "bpp@upi"
},
"type": "ON-ORDER",
"status": "PAID"
},
"created_at": "2021-06-23T07:33:02.655Z",
"updated_at": "2021-06-23T07:33:02.655Z"
}
}
}
*/
//The below code generates the above example JSON.
const transactionId = _.get(clientRequestBody, "transactionId");
// Returns the Context including MessageId
const context = createContext(transactionId);
let confirmRequestBody = {
context,
message: {
// construct from the request
}
}
//call protocol confirm order
const response = await callConfirm(confirmRequestBody);
res
.status(200)
.send({ ...response.data, messageId: context["message_id"] });
}
BAP server calls protocol confirm to the network
async function callConfirm(confirmRequestBody) {
// 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/confirm`, method: "POST", data: confirmRequestBody, headers});
}
BAP receives protocol on_confirm
/*
Example Response JSON:
{
"context": {
"domain": "delivery",
"country": "IND",
"city": "std:080",
"action": "on_confirm",
"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-06-23T07:33:02.655Z"
},
"message": {
"order": {
"id": "0f8c1e68-c041-427d-9ef4-d4d3e5b22ef9",
"state": "Active",
"items": [
{
"id": "standard",
"quantity": {
"count": 1
}
}
],
"billing": {
"name": "John Doe",
"address": {
"door": "21A",
"name": "ABC Apartments",
"locality": "HSR Layout",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560102"
},
"email": "[email protected]",
"phone": "+919876543210",
"created_at": "2021-06-15T07:08:36.211Z",
"updated_at": "2021-06-15T07:08:36.211Z"
},
"fulfillment": {
"type": "home-delivery",
"tracking": false,
"start": {
"location": {
"gps": "12.9349377,77.6055586"
},
"time": {
"range": {
"start": "2021-06-15T07:09:30.000Z",
"end": "2021-06-15T07:10:30.000Z"
}
},
"instructions": {
"name": "pick up instructions",
"short_desc": "Don't ring doorbell"
},
"contact": {
"phone": "+919999999999",
"email": "[email protected]"
}
},
"end": {
"location": {
"gps": "12.914028, 77.638698",
"address": {
"door": "21A",
"name": "ABC Apartments",
"locality": "HSR Layout",
"city": "Bengaluru",
"state": "Karnataka",
"country": "India",
"area_code": "560102"
}
},
"time": {
"range": {
"start": "2021-06-15T07:11:36.212Z",
"end": "2021-06-15T07:12:36.212Z"
}
},
"instructions": {
"name": "drop off instructions",
"short_desc": "Leave at door step"
},
"contact": {
"phone": "+919876543210",
"email": "[email protected]"
}
}
},
"quote": {
"price": {
"currency": "INR",
"value": "40"
},
"breakup": [
{
"title": "Standard delivery",
"price": {
"currency": "INR",
"value": "40"
}
}
],
"ttl": "P4D"
},
"payment": {
"uri": "https://api.bpp.com/pay?amt=$amount&txn_id=ksh87yriuro34iyr3p4&mode=upi&vpa=bpp@upi",
"tl_method": "http/get",
"params": {
"transaction_id": "ksh87yriuro34iyr3p4",
"amount": "40",
"mode": "upi",
"vpa": "bpp@upi"
},
"type": "ON-ORDER",
"status": "PAID"
},
"created_at": "2021-06-23T07:33:02.655Z",
"updated_at": "2021-06-23T07:33:02.655Z"
}
}
}
*/
// Auth middleware authenticates the digital signature of the incoming request
router.post("/delivery/on_confirm", auth, onTrack);
async function onTrack({ body }, res) {
// Save the response to Database
await saveToDb(body);
};
Client polls BAP to get the on_confirm 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));
}
};