Search by location for consultation options nearby (Java)
In this use case, the user simply searches for doctors, clinics and hospitals around his location.
Code snippets
Client calls the BAP server to trigger search:
@PostMapping("/healthcare_consultation/search_by_location")
public ResponseEntity searchByLocation(
@RequestHeader HttpHeaders headers,
@RequestBody ClientSearchRequest request) {
var response = bapApplicationService.generateSearchRequest(request, headers);
return ResponseEntity.ok(response);
}
BAP server generates the protocol request body
/*
Example Request JSON:
{
"context": {
"domain": "nic2004:85121",
"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": {
"end": {
"location": {
"gps": "12.4535445,77.9283792"
}
}
}
}
}
}
*/
public Response generateSearchRequest(ClientSearchRequest request, HttpHeaders headers) {
var messageId = UUID.randomUUID().toString();
// Check and create transaction id if not passed
var txnId = StringUtils.hasText(request.getTransactionId())
? request.getTransactionId()
: UUID.randomUUID().toString();
// Construct the request similar to the example given above
var context = Context.builder().domain(request.getDomain())
.action(Context.ActionEnum.search)
.messageId(messageId)
.transactionId(txnId)
.transactionId(UUID.randomUUID().toString())
.timestamp(new Date().toString())
.build();
var intentBuilder = Intent.builder();
// Construct fulflilment object for the given location
intentBuilder = intentBuilder.fulflilment(ClientAssembler.of(request.getFulfilment()));
// Construct the protocol specific object to be passed to the BPP/BG
var searchRequest = SearchRequest.builder()
.context(context)
.message(SearchMessage.builder()
.intent(intentBuilder.build())
.build())
.build();
return invokeSearch(searchRequest, headers);
}
}
BAP server calls protocol search to the network
public Response invokeSearch(SearchRequest request, HttpHeaders headers) {
// Call to look up function which returns the the public key and BPP/BG Endpoint to be called
var url = lookUp(headers);
//Call BPP Search api
var searchResponse = apiClient.post(url[0] + Context.ActionEnum.search,
constructRequestHeaders(),
request,
Response.class);
if (responseEntity.getBody() == null || responseEntity.getBody().getError() != null ||
"NACK".equals(responseEntity.getBody().getMessage().getAck().getStatus())) {
// Return custom error to the client
return null;
}
return searchResponse.getBody();
}
BAP receives protocol on_search
/*
Example Response JSON:
{
"context": {
"domain": "nic2004:85121",
"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": "Clinic Chains BPP"
},
"bpp/providers": [
{
"id": "good-health-clinic",
"descriptor": {
"name": "Good Health Clinic"
},
"locations": [
{
"id": "good-health-koramangala",
"gps": "12.9349377,77.6055586"
}
],
"categories": [
{
"id": "dermatology",
"descriptor": {
"name": "Dermatology"
}
},
{
"id": "family-medicine",
"descriptor": {
"name": "Family medicine"
}
}
],
"items": [
{
"id": "dr_veena",
"descriptor": {
"name": "Dr.Veena in person consultation"
},
"category_id": "dermatology",
"location_id": "good-health-koramangala",
"matched": true
},
{
"id": "dr_veena_slot_1",
"parent_item_id": "dr_veena",
"descriptor": {
"name": "Dr.Veena in person morning slot 1"
},
"time": {
"range": {
"start": "2021-08-11T04:30:00.000Z",
"end": "2021-08-11T05:30:00.000Z"
}
},
"price": {
"currency": "INR",
"value": "1000"
}
},
{
"id": "dr_veena_slot_2",
"parent_item_id": "dr_veena",
"descriptor": {
"name": "Dr.Veena in person morning slot 2"
},
"time": {
"range": {
"start": "2021-08-11T05:30:00.000Z",
"end": "2021-08-11T06:30:00.000Z"
}
},
"price": {
"currency": "INR",
"value": "1000"
}
},
{
"id": "dr_tony",
"descriptor": {
"name": "Dr.Tony online consultation"
},
"category_id": "family-medicine",
"matched": true
},
{
"id": "dr_tony_slot_1",
"parent_item_id": "dr_tony",
"descriptor": {
"name": "Dr.Tony online slot 1"
},
"time": {
"range": {
"start": "2021-08-11T07:30:00.000Z",
"end": "2021-08-11T08:30:00.000Z"
}
},
"price": {
"currency": "INR",
"value": "1000"
}
},
{
"id": "dr_tony_slot_2",
"parent_item_id": "dr_tony",
"descriptor": {
"name": "Dr.Tony online slot 1"
},
"time": {
"range": {
"start": "2021-08-11T08:30:00.000Z",
"end": "2021-08-11T09:30:00.000Z"
}
},
"price": {
"currency": "INR",
"value": "1000"
}
}
]
},
{
"id": "healthy-clinic",
"descriptor": {
"name": "Healthy Clinic"
},
"locations": [
{
"id": "healthy-skin-clinic-koramangala",
"gps": "12.9349377,77.6055586"
}
],
"categories": [
{
"id": "dermatology",
"descriptor": {
"name": "Dermatology"
}
}
],
"items": [
{
"id": "dr_noor",
"descriptor": {
"name": "Dr.Noor online consultation"
},
"category_id": "dermatology",
"matched": true
},
{
"id": "dr_noor_slot_1",
"parent_item_id": "dr_noor",
"descriptor": {
"name": "Dr.Noor online slot 1"
},
"time": {
"range": {
"start": "2021-08-11T07:30:00.000Z",
"end": "2021-08-11T08:30:00.000Z"
}
},
"price": {
"currency": "INR",
"value": "1000"
}
},
{
"id": "dr_noor_slot_2",
"parent_item_id": "dr_noor",
"descriptor": {
"name": "Dr.Noor online slot 1"
},
"time": {
"range": {
"start": "2021-08-11T08:30:00.000Z",
"end": "2021-08-11T09:30:00.000Z"
}
},
"price": {
"currency": "INR",
"value": "1000"
}
}
]
}
]
}
}
}
*/
@PostMapping("/bap/on_search")
public ResponseEntity onSearch(
@RequestHeader HttpHeaders headers,
@RequestBody OnSearchRequest request) {
var response = bapCallbackApplicationService.onSearch(request, headers);
return ResponseEntity.ok(response);
}
public Response onSearch(OnSearchRequest request, HttpHeaders headers) {
// Validate the headers received
var isHeadersValid = validateHeaders(headers);
// Construct and return error if the received headers are invalid
if (!isHeadersValid) return null;
// Store the data received based on message id for the client to poll
saveToDB(request);
return Response.of("ACK", null);
}
Client polls BAP to get the on_search results
// Endpoint for the client to poll the search data based on the message id
@GetMapping("/healthcare_consultation/on_search")
public ResponseEntity searchByMessageId(
@PathVariable(ClientRoutes.PARAM_MESSAGE_ID) String messageId,
@RequestHeader HttpHeaders headers) {
var data = bapApplicationService.getSearchData(messageId);
return ResponseEntity.ok(data);
}