feat: align getting-started guidance with menu PUT replace and sandbox setup
This commit is contained in:
parent
156f7cdd58
commit
522f46fd1e
@ -7,10 +7,12 @@ UBER_CLIENT_SECRET=your_client_secret
|
||||
UBER_REDIRECT_URI=http://localhost:8080/api/v1/auth/uber/callback
|
||||
UBER_OAUTH_BASE_URL=https://login.uber.com
|
||||
UBER_API_BASE_URL=https://api.uber.com
|
||||
# Sandbox values when testing:
|
||||
# UBER_OAUTH_BASE_URL=https://sandbox-auth.uber.com
|
||||
# UBER_API_BASE_URL=https://test-api.uber.com
|
||||
|
||||
# SQLite database path
|
||||
SQLITE_PATH=./data/uber_wrapper.db
|
||||
|
||||
# Shared API key for wrapper clients (optional but recommended)
|
||||
WRAPPER_API_KEY=change-me
|
||||
|
||||
|
||||
31
docs/developer-portal/01-getting-started-audit.md
Normal file
31
docs/developer-portal/01-getting-started-audit.md
Normal file
@ -0,0 +1,31 @@
|
||||
# 01 Getting Started Audit
|
||||
|
||||
Source checked: Uber Eats "Getting Started" section shared by you.
|
||||
|
||||
## Implemented Now
|
||||
|
||||
- OAuth-based authentication foundation is present.
|
||||
- Store/menu/order/webhook modules exist.
|
||||
- Multi-merchant model is implemented.
|
||||
- Sandbox guidance updated with official sandbox domains.
|
||||
- Full menu replacement support added via `PUT /api/v1/uber/menu/replace`.
|
||||
|
||||
## Partly Implemented
|
||||
|
||||
- Store management:
|
||||
Hours update exists, but typed online/offline and settings endpoints are pending.
|
||||
- Order processing:
|
||||
Core actions exist, but full BYOC and advanced workflows are pending.
|
||||
|
||||
## Not Yet Implemented
|
||||
|
||||
- Written-approval and scope entitlement checks (operational process outside API code).
|
||||
- Formal quality gate automation for all production standards.
|
||||
- Full typed coverage for promotions/reporting APIs.
|
||||
|
||||
## Current Safe Fallback
|
||||
|
||||
For any endpoint not yet typed, use:
|
||||
|
||||
- `POST /api/v1/uber/request`
|
||||
|
||||
@ -2,8 +2,11 @@
|
||||
|
||||
Menu sync between POS and Uber Eats:
|
||||
|
||||
- Upload/replace menu
|
||||
- Full menu replacement via PUT
|
||||
- Fetch menu from Uber
|
||||
- Item and modifier mapping strategy
|
||||
- Validation and publish error handling
|
||||
|
||||
Current wrapper route for full replacement:
|
||||
|
||||
- `PUT /api/v1/uber/menu/replace`
|
||||
|
||||
@ -2,9 +2,20 @@
|
||||
|
||||
Checklist:
|
||||
|
||||
- Create a dedicated TESTING app in Uber Developer Dashboard
|
||||
- Use sandbox domains in `.env`:
|
||||
- `UBER_OAUTH_BASE_URL=https://sandbox-auth.uber.com`
|
||||
- `UBER_API_BASE_URL=https://test-api.uber.com`
|
||||
- Test OAuth connect flow
|
||||
- Test menu upload/get
|
||||
- Test order lifecycle actions
|
||||
- Test webhook receipt and persistence
|
||||
- Validate retry and duplicate event handling
|
||||
|
||||
Validation sequence:
|
||||
|
||||
1. Authentication token generation and authorized call test
|
||||
2. Store status/hours API smoke tests
|
||||
3. Full menu replacement test via PUT
|
||||
4. Order webhook receipt and lifecycle action tests
|
||||
5. Error and retry behavior checks
|
||||
|
||||
@ -202,6 +202,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/uber/menu/replace": {
|
||||
"put": {
|
||||
"summary": "Replace store menu (full upload)",
|
||||
"tags": [
|
||||
"Uber Menu"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Menu replaced"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/uber/menu": {
|
||||
"get": {
|
||||
"summary": "Fetch store menu",
|
||||
|
||||
@ -83,6 +83,39 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Replace Menu (PUT)",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"header": [
|
||||
{
|
||||
"key": "x-api-key",
|
||||
"value": "{{apiKey}}"
|
||||
},
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"merchantId\": \"{{merchantId}}\",\n \"storeId\": \"{{storeId}}\",\n \"menu\": {\n \"categories\": []\n }\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/v1/uber/menu/replace",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"v1",
|
||||
"uber",
|
||||
"menu",
|
||||
"replace"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Generic Uber Request",
|
||||
"request": {
|
||||
@ -135,4 +168,3 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -40,6 +40,21 @@ async function getMenu(req, res) {
|
||||
return res.json({ success: true, data });
|
||||
}
|
||||
|
||||
async function replaceMenu(req, res) {
|
||||
const schema = z.object({
|
||||
merchantId: z.string().min(1),
|
||||
storeId: z.string().min(1),
|
||||
menu: z.any()
|
||||
});
|
||||
const payload = schema.parse(req.body);
|
||||
const data = await proxyService.menuReplace({
|
||||
merchantId: payload.merchantId,
|
||||
storeId: payload.storeId,
|
||||
payload: payload.menu
|
||||
});
|
||||
return res.json({ success: true, data });
|
||||
}
|
||||
|
||||
async function listOrders(req, res) {
|
||||
const schema = z.object({
|
||||
merchantId: z.string().min(1),
|
||||
@ -89,9 +104,9 @@ async function updateHours(req, res) {
|
||||
module.exports = {
|
||||
genericProxy,
|
||||
upsertMenu,
|
||||
replaceMenu,
|
||||
getMenu,
|
||||
listOrders,
|
||||
orderAction,
|
||||
updateHours
|
||||
};
|
||||
|
||||
|
||||
@ -94,6 +94,17 @@ async function menuUpsert({ merchantId, storeId, payload }) {
|
||||
});
|
||||
}
|
||||
|
||||
async function menuReplace({ merchantId, storeId, payload }) {
|
||||
const uberPath = interpolatePath(uberEndpoints.menu.upsert, { storeId });
|
||||
return callUberApi({
|
||||
merchantId,
|
||||
method: "PUT",
|
||||
uberPath,
|
||||
body: payload,
|
||||
wrapperRoute: "/api/v1/uber/menu/replace"
|
||||
});
|
||||
}
|
||||
|
||||
async function menuGet({ merchantId, storeId }) {
|
||||
const uberPath = interpolatePath(uberEndpoints.menu.get, { storeId });
|
||||
return callUberApi({
|
||||
@ -153,9 +164,9 @@ async function updateStoreHours({ merchantId, storeId, payload }) {
|
||||
module.exports = {
|
||||
genericProxy,
|
||||
menuUpsert,
|
||||
menuReplace,
|
||||
menuGet,
|
||||
ordersList,
|
||||
orderAction,
|
||||
updateStoreHours
|
||||
};
|
||||
|
||||
|
||||
@ -30,6 +30,19 @@ router.post("/uber/request", asyncHandler(controller.genericProxy));
|
||||
*/
|
||||
router.post("/uber/menu/upsert", asyncHandler(controller.upsertMenu));
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/v1/uber/menu/replace:
|
||||
* put:
|
||||
* summary: Replace store menu (full upload)
|
||||
* tags:
|
||||
* - Uber Menu
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Menu replaced
|
||||
*/
|
||||
router.put("/uber/menu/replace", asyncHandler(controller.replaceMenu));
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/v1/uber/menu:
|
||||
@ -89,4 +102,3 @@ router.post("/uber/orders/:orderId/action", asyncHandler(controller.orderAction)
|
||||
router.put("/uber/stores/hours", asyncHandler(controller.updateHours));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user