Handle store.menu_refresh_request webhook with store metadata tracking
This commit is contained in:
parent
64f214f3ae
commit
bc3d4e6641
@ -16,6 +16,10 @@ Source checked: Uber Eats "Webhook" section shared by you.
|
||||
- `resource_id`
|
||||
- `resource_href`
|
||||
- signature and dedupe key
|
||||
- Added explicit event handling for `store.menu_refresh_request`:
|
||||
- mapped via `store_id`
|
||||
- records latest menu refresh request metadata on `uber_connections`
|
||||
- stores webhook UUID and `X-Environment` marker
|
||||
|
||||
## Existing Before
|
||||
|
||||
@ -27,4 +31,3 @@ Source checked: Uber Eats "Webhook" section shared by you.
|
||||
- Per-event downstream job workers (accept/deny SLA orchestration).
|
||||
- Alerting if order accept/deny not sent before timeout window.
|
||||
- Full typed schema validation per webhook `event_type`.
|
||||
|
||||
|
||||
@ -25,8 +25,17 @@ Common event types handled:
|
||||
- `delivery.state_changed`
|
||||
- `store.provisioned`
|
||||
- `store.deprovisioned`
|
||||
- `store.menu_refresh_request`
|
||||
- `store.status.changed`
|
||||
|
||||
Menu refresh handling:
|
||||
|
||||
- On `store.menu_refresh_request`, wrapper records the request on the mapped Uber store connection.
|
||||
- Persisted fields include:
|
||||
- `last_menu_refresh_requested_at`
|
||||
- `last_menu_refresh_webhook_uuid`
|
||||
- `last_webhook_environment` (from `X-Environment`)
|
||||
|
||||
Retail fulfillment follow-up:
|
||||
|
||||
- On `orders.fulfillment_issues.resolved`, fetch updated order details and inspect customer acknowledgment before next action.
|
||||
|
||||
@ -1659,6 +1659,42 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Webhook Ingest - Menu Refresh (Simulation)",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "X-Uber-Signature",
|
||||
"value": "replace-with-valid-hmac"
|
||||
},
|
||||
{
|
||||
"key": "X-Environment",
|
||||
"value": "production"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"event_type\": \"store.menu_refresh_request\",\n \"partner_store_id\": \"123456\",\n \"resource_href\": \"https://api.uber.com/v1/eats/stores/{{storeId}}\",\n \"store_id\": \"{{storeId}}\",\n \"webhook_meta\": {\n \"client_id\": \"app_client_id\",\n \"webhook_config_id\": \"merchant-integration.menu-refresh-request\",\n \"webhook_msg_timestamp\": 1622813397,\n \"webhook_msg_uuid\": \"b2340f4c-6dd7-4d65-a9bc-016631a2a13a\"\n }\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/v1/webhooks/uber",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"v1",
|
||||
"webhooks",
|
||||
"uber"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Generic Uber Request",
|
||||
"request": {
|
||||
|
||||
@ -107,6 +107,31 @@ const uberConnectionRepository = {
|
||||
return this.findByMerchantId(merchantId);
|
||||
},
|
||||
|
||||
markMenuRefreshRequestedByStoreId(uberStoreId, payload) {
|
||||
const existing = this.findByUberStoreId(uberStoreId);
|
||||
if (!existing) {
|
||||
return null;
|
||||
}
|
||||
const timestamp = nowIso();
|
||||
db.prepare(
|
||||
`
|
||||
UPDATE uber_connections
|
||||
SET last_menu_refresh_requested_at = ?,
|
||||
last_menu_refresh_webhook_uuid = ?,
|
||||
last_webhook_environment = ?,
|
||||
updated_at = ?
|
||||
WHERE uber_store_id = ?
|
||||
`
|
||||
).run(
|
||||
payload?.requestedAt || timestamp,
|
||||
payload?.webhookMsgUuid || null,
|
||||
payload?.environment || null,
|
||||
timestamp,
|
||||
uberStoreId
|
||||
);
|
||||
return this.findByUberStoreId(uberStoreId);
|
||||
},
|
||||
|
||||
list() {
|
||||
return db
|
||||
.prepare(`
|
||||
|
||||
@ -120,6 +120,16 @@ function initSchema() {
|
||||
if (!tableHasColumn("api_logs", "order_id")) {
|
||||
db.exec("ALTER TABLE api_logs ADD COLUMN order_id TEXT");
|
||||
}
|
||||
|
||||
if (!tableHasColumn("uber_connections", "last_menu_refresh_requested_at")) {
|
||||
db.exec("ALTER TABLE uber_connections ADD COLUMN last_menu_refresh_requested_at TEXT");
|
||||
}
|
||||
if (!tableHasColumn("uber_connections", "last_menu_refresh_webhook_uuid")) {
|
||||
db.exec("ALTER TABLE uber_connections ADD COLUMN last_menu_refresh_webhook_uuid TEXT");
|
||||
}
|
||||
if (!tableHasColumn("uber_connections", "last_webhook_environment")) {
|
||||
db.exec("ALTER TABLE uber_connections ADD COLUMN last_webhook_environment TEXT");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@ -87,6 +87,23 @@ function applyProvisioningStateFromWebhook(eventType, payload) {
|
||||
uberConnectionRepository.setStatusByMerchantId(connection.merchant_id, nextStatus);
|
||||
}
|
||||
|
||||
function applyMenuRefreshRequestFromWebhook(eventType, payload, headers) {
|
||||
if (eventType !== "store.menu_refresh_request") {
|
||||
return;
|
||||
}
|
||||
|
||||
const storeId = extractStoreId(payload);
|
||||
if (!storeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
uberConnectionRepository.markMenuRefreshRequestedByStoreId(String(storeId), {
|
||||
requestedAt: new Date().toISOString(),
|
||||
webhookMsgUuid: payload?.webhook_meta?.webhook_msg_uuid || null,
|
||||
environment: headers?.["x-environment"] || null
|
||||
});
|
||||
}
|
||||
|
||||
async function handleUberWebhook(req, res) {
|
||||
if (!verifyBasicAuthIfConfigured(req)) {
|
||||
return res.status(401).json({
|
||||
@ -133,6 +150,7 @@ async function handleUberWebhook(req, res) {
|
||||
});
|
||||
|
||||
applyProvisioningStateFromWebhook(eventType, req.body || {});
|
||||
applyMenuRefreshRequestFromWebhook(eventType, req.body || {}, req.headers || {});
|
||||
|
||||
return res.status(200).end();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user