Skip to content

durgeshPandey-dev/mock-bpp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mock-bpp-dynamic

A fully dynamic Beckn BPP (Buyer-side Protocol Provider) simulator for the EV charging network domain. Unlike template-based mocks, this service generates every on_* response at runtime from the incoming request — new order IDs, payment references, and telemetry on every call.


What this repo does

Responsibility Detail
Receives Beckn BPP requests discover, search, select, init, confirm, status, track, cancel, update, rating, support
Responds synchronously Returns ACK immediately on every valid request
Sends async callbacks Fires on_<action> to the ONIX adapter BPP caller endpoint after a configurable delay
Maintains order state In-memory state machine tracks order lifecycle across a transaction (CREATED → INITIATED → CHARGING → COMPLETED)
Simulates real telemetry on_status returns live-computed SOC %, power (kW), energy (kWh), voltage, current based on time elapsed since confirm

Where this fits in the Beckn network

BAP Application
      │
      ▼
 BAP-ONIX Adapter  (onix-bap-plugin :8001)
      │  signs request, routes to BPP side
      ▼
 BPP-ONIX Adapter  (onix-bpp-plugin :8002)
      │  validates signature, validates schema, routes to backend
      ▼
 mock-bpp-dynamic  (:9002)          ← THIS SERVICE
      │  generates on_* response
      │  POST /bpp/caller/on_<action>
      ▼
 BPP-ONIX Adapter  (onix-bpp-plugin :8002)
      │  signs response, routes back to BAP
      ▼
 BAP-ONIX Adapter  (onix-bap-plugin :8001)
      │  delivers to BAP receiver
      ▼
BAP Application

The mock-bpp sits behind the ONIX BPP adapter. It never talks directly to the BAP — all traffic flows through the adapter.


Full Beckn flow

BAP                ONIX-BAP          ONIX-BPP          mock-bpp
 │                    │                  │                  │
 │── discover ───────►│                  │                  │
 │                    │── /bpp/receiver/discover ──────────►│
 │                    │                  │  ACK ◄───────────│
 │                    │                  │                  │── (async, 500ms delay)
 │                    │◄─── /bap/receiver/on_discover ◄─────│   catalog: 5 stations × 17 connectors
 │◄── on_discover ────│                  │                  │
 │                    │                  │                  │
 │── select ─────────►│                  │                  │
 │                    │── /bpp/receiver/select ─────────────►│
 │                    │                  │  ACK ◄───────────│
 │                    │◄─── /bap/receiver/on_select ◄────────│  quoted price + buyer-finder-fee
 │◄── on_select ──────│                  │                  │
 │                    │                  │                  │
 │── init ───────────►│                  │                  │
 │                    │── /bpp/receiver/init ───────────────►│
 │                    │                  │  ACK ◄───────────│
 │                    │◄─── /bap/receiver/on_init ◄──────────│  new orderId, paymentId, txnRef, payment URL
 │◄── on_init ────────│                  │                  │
 │                    │                  │                  │
 │── confirm ────────►│                  │                  │
 │                    │── /bpp/receiver/confirm ────────────►│  starts state-machine clock
 │                    │                  │  ACK ◄───────────│
 │                    │◄─── /bap/receiver/on_confirm ◄───────│  CONFIRMED + payment COMPLETED
 │◄── on_confirm ─────│                  │                  │
 │                    │                  │                  │
 │── status ─────────►│                  │                  │
 │                    │── /bpp/receiver/status ─────────────►│
 │                    │◄─── /bap/receiver/on_status ◄────────│  live telemetry (SOC, kWh, kW …)
 │◄── on_status ──────│                  │                  │

Transaction ID is generated once by the BAP and echoed through every hop unchanged. Message ID is freshly generated by mock-bpp for every callback. Order IDs / Payment IDs are UUID-based, generated fresh at init and confirm.


Dynamic response behaviour per action

Action What mock-bpp generates
discover Catalog of 5 fixed EV stations (Bengaluru–Mysuru corridor) with 17 connector slots. Validity timestamps are fresh on every call
search Same catalog as discover
select Echoes buyer + items from request, computes: base cost + 20% surge + 15% discount + fees + 2.5% BFF
init New orderId (UUID), orderNumber, paymentId, txnRef, payment URL. beckn:paymentStatus: INITIATED
confirm Reuses orderId from request if present, generates new paymentId + txnRef. Starts the state-machine clock. beckn:paymentStatus: COMPLETED
status Reads state machine: INITIATED (0–10s) → CHARGING (10–120s) → COMPLETED (>120s). Returns live telemetry metrics
track Returns current GPS-like location of charger
cancel Marks order CANCELLED in state store
update Echoes updated order back
rating Returns feedback submission confirmation
support Returns support ticket reference

Configuration reference

Config file path is resolved in this order:

  1. CONFIG_FILE environment variable
  2. config/config.yaml (relative to binary)
  3. /app/config/config.yaml (Docker default)
server:
  port: ":9002"              # TCP port the HTTP server listens on

defaults:
  version: "1.0.0"           # Beckn protocol version echoed in context
  domain: "beckn.one:deg:ev-charging"
  country_code: "IND"
  city_code: "std:080"
  bpp_id: "my-bpp.example.com"   # Identifier of this BPP in the Beckn network
  bpp_uri: "http://mock-bpp:9002" # Publicly reachable URI of this BPP

callback:
  enabled: true              # Master switch for all async on_* callbacks
  delay_ms: 500              # Simulated processing delay before callback (ms)
  timeout_ms: 10000          # HTTP client timeout for the callback POST (ms)
  base_uri: "http://onix-bpp-plugin:8002"
  # Callback is sent to: {base_uri}/bpp/caller/on_{action}
  # Per-action enable/disable (missing key = enabled by default)
  actions:
    discover: true
    search: true
    select: true
    init: true
    confirm: true
    status: true
    track: true
    cancel: true
    update: true
    rating: true
    support: true

overrides:
  file: ""   # Optional path to a JSON file for static response overrides
             # Format: { "init": { "message": {...} }, "confirm": { "message": {...} } }
             # If an action key exists, it replaces dynamic generation for that action only

Environment variable overrides

These override the config file and are useful for container deployments where you inject secrets/endpoints as env vars:

Variable Overrides Example
CONFIG_FILE Config file path /app/config/config.yaml
BPP_ID defaults.bpp_id ev-charging.sandbox2.com
BPP_URI defaults.bpp_uri http://onix-bpp-plugin:8002/bpp/receiver
CALLBACK_BASE_URI callback.base_uri http://onix-bpp-plugin:8002

Deployment

Local (binary)

git clone https://github.com/beckn-one/mock-bpp
cd mock-bpp

# Edit config
cp config/config.yaml config/local.yaml
# Set callback.base_uri to your local ONIX BPP adapter address

CONFIG_FILE=config/local.yaml go run ./cmd/server/main.go

Health check: curl http://localhost:9002/health


Local (Docker)

docker build -t mock-bpp-dynamic:latest .

docker run -d \
  --name mock-bpp \
  -p 9002:9002 \
  -v $(pwd)/config/config.yaml:/app/config/config.yaml:ro \
  -e CALLBACK_BASE_URI=http://host.docker.internal:8002 \
  mock-bpp-dynamic:latest

Docker Compose (sandbox / UAT)

The sandbox docker-compose.yml already wires mock-bpp into the full ONIX network:

mock-bpp:
  image: mock-bpp-dynamic:latest
  pull_policy: never
  container_name: mock-bpp
  ports:
    - "9002:9002"
  volumes:
    - ./mock-bpp_config.yml:/app/config/config.yaml:ro
  environment:
    CONFIG_FILE: /app/config/config.yaml
  networks:
    - onix-network

Key config values for Docker Compose:

# mock-bpp_config.yml
defaults:
  bpp_id: "ev-charging.sandbox2.com"
  bpp_uri: "http://onix-bpp-plugin:8002/bpp/receiver"

callback:
  base_uri: "http://onix-bpp-plugin:8002"
  # Uses Docker Compose service name — works because both are on onix-network

To rebuild after a code change:

# In mock-bpp repo
docker compose build --no-cache mock-bpp

# In sandbox
cd ubc-ev-sandbox/sandbox
docker compose up -d --no-deps --force-recreate mock-bpp

Kubernetes

ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mock-bpp-config
data:
  config.yaml: |
    server:
      port: ":9002"
    defaults:
      bpp_id: "ev-charging.prod.example.com"
      bpp_uri: "http://onix-bpp-plugin.beckn.svc.cluster.local:8002/bpp/receiver"
      domain: "beckn.one:deg:ev-charging"
      version: "1.0.0"
      country_code: "IND"
      city_code: "std:080"
    callback:
      enabled: true
      delay_ms: 500
      timeout_ms: 10000
      base_uri: "http://onix-bpp-plugin.beckn.svc.cluster.local:8002"

Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mock-bpp
  namespace: beckn
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mock-bpp
  template:
    metadata:
      labels:
        app: mock-bpp
    spec:
      containers:
        - name: mock-bpp
          image: mock-bpp-dynamic:latest
          imagePullPolicy: Never   # use IfNotPresent for registry images
          ports:
            - containerPort: 9002
          env:
            - name: CONFIG_FILE
              value: /app/config/config.yaml
            # Override individual values without rebuilding:
            - name: BPP_ID
              valueFrom:
                configMapKeyRef:
                  name: mock-bpp-config
                  key: bpp_id   # or use a Secret
            - name: CALLBACK_BASE_URI
              value: "http://onix-bpp-plugin.beckn.svc.cluster.local:8002"
          volumeMounts:
            - name: config
              mountPath: /app/config
      volumes:
        - name: config
          configMap:
            name: mock-bpp-config

Service:

apiVersion: v1
kind: Service
metadata:
  name: mock-bpp
  namespace: beckn
spec:
  selector:
    app: mock-bpp
  ports:
    - port: 9002
      targetPort: 9002

Note on callback.base_uri in Kubernetes: Use the cluster-internal DNS name of the ONIX BPP adapter service: http://<service-name>.<namespace>.svc.cluster.local:<port>


UAT / Cloud (environment variables only)

For UAT or cloud deployments where you don't want to rebuild the image, override everything via env vars and mount only the config file:

docker run -d \
  --name mock-bpp \
  -p 9002:9002 \
  -v /etc/mock-bpp/config.yaml:/app/config/config.yaml:ro \
  -e BPP_ID="ev-charging.uat.example.com" \
  -e BPP_URI="https://onix-bpp.uat.example.com/bpp/receiver" \
  -e CALLBACK_BASE_URI="https://onix-bpp.uat.example.com" \
  mock-bpp-dynamic:latest

Endpoint reference

Method Path Description
GET /health Health check — returns {"status":"healthy"}
POST /discover Receive discover from CDS/BAP
POST /search Receive search
POST /select Receive select
POST /init Receive init — generates draft order
POST /confirm Receive confirm — starts charging session clock
POST /status Receive status — returns live telemetry
POST /track Receive track
POST /cancel Receive cancel — marks order CANCELLED
POST /update Receive update
POST /rating Receive rating
POST /support Receive support

Every endpoint:

  1. Returns 200 ACK synchronously (or 400 NACK on bad JSON)
  2. Fires POST {callback.base_uri}/bpp/caller/on_<action> asynchronously after delay_ms

Callback URL construction

{callback.base_uri}/bpp/caller/on_{action}

Examples:

Incoming action Callback sent to
/init http://onix-bpp-plugin:8002/bpp/caller/on_init
/confirm http://onix-bpp-plugin:8002/bpp/caller/on_confirm
/status http://onix-bpp-plugin:8002/bpp/caller/on_status

The ONIX BPP adapter (bppTxnCaller module) receives these, signs them, and forwards to the BAP.


Order state machine

The in-memory state store (internal/state) tracks each Beckn transaction_id:

select / init
      │
      ▼
  CREATED
      │
   confirm
      ▼
  INITIATED  ──── (0–10s after confirm)
      │
      ▼
  CHARGING   ──── (10–120s) live telemetry computed from elapsed time
      │
      ▼
  COMPLETED  ──── (>120s)
      │
   cancel (any time)
      ▼
  CANCELLED

State is in-memory only — it resets on container restart. This is intentional for a mock/UAT service. For persistent state across restarts, mount a volume or integrate a store.


Static response overrides

If you need a specific action to return a fixed payload (e.g., to test an error scenario or a particular edge case) without changing code:

# config.yaml
overrides:
  file: "/app/config/overrides.json"
// overrides.json
{
  "init": {
    "message": {
      "order": {
        "@context": "...",
        "@type": "beckn:Order",
        "beckn:orderStatus": "FAILED"
      }
    }
  }
}

Only actions present in the overrides file are affected. All other actions continue to use dynamic generation.


Project structure

mock-bpp/
├── cmd/server/main.go          Entry point — wires config, store, generator, handler
├── config/config.yaml          Default configuration
├── internal/
│   ├── config/config.go        Config loader (YAML + env var overrides)
│   ├── model/beckn.go          Beckn protocol types (Context, BecknRequest, AckResponse …)
│   ├── state/store.go          In-memory order state machine
│   ├── handler/handler.go      HTTP handlers — ACK/NACK + async dispatch
│   ├── callback/sender.go      Async on_* callback sender
│   └── generator/
│       ├── generator.go        Dispatcher + shared helpers (mapVal, strFromMap …)
│       ├── discover.go         Catalog: 5 EV stations × 17 connectors
│       ├── search.go           Same as discover
│       ├── select.go           Price quote from request items
│       ├── init.go             Draft order: new orderId / paymentId / txnRef
│       ├── confirm.go          Confirmed order + starts state clock
│       ├── status.go           Live telemetry from state machine
│       ├── track.go            Location response
│       ├── cancel.go           Marks order CANCELLED
│       ├── update.go           Echo updated order
│       ├── rating.go           Feedback confirmation
│       └── support.go          Support ticket reference
├── Dockerfile
└── docker-compose.yml

Dependencies

Package Purpose
github.com/google/uuid UUID generation for order/payment IDs
gopkg.in/yaml.v3 Config file parsing
Go standard library only HTTP server, JSON, logging

No database. No message queue. No external services. The binary is self-contained.

About

mock-bpp for end-to-end testing

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors