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_REDIRECT_URI=http://localhost:8080/api/v1/auth/uber/callback
|
||||||
UBER_OAUTH_BASE_URL=https://login.uber.com
|
UBER_OAUTH_BASE_URL=https://login.uber.com
|
||||||
UBER_API_BASE_URL=https://api.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 database path
|
||||||
SQLITE_PATH=./data/uber_wrapper.db
|
SQLITE_PATH=./data/uber_wrapper.db
|
||||||
|
|
||||||
# Shared API key for wrapper clients (optional but recommended)
|
# Shared API key for wrapper clients (optional but recommended)
|
||||||
WRAPPER_API_KEY=change-me
|
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:
|
Menu sync between POS and Uber Eats:
|
||||||
|
|
||||||
- Upload/replace menu
|
- Full menu replacement via PUT
|
||||||
- Fetch menu from Uber
|
- Fetch menu from Uber
|
||||||
- Item and modifier mapping strategy
|
- Item and modifier mapping strategy
|
||||||
- Validation and publish error handling
|
- Validation and publish error handling
|
||||||
|
|
||||||
|
Current wrapper route for full replacement:
|
||||||
|
|
||||||
|
- `PUT /api/v1/uber/menu/replace`
|
||||||
|
|||||||
@ -2,9 +2,20 @@
|
|||||||
|
|
||||||
Checklist:
|
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 OAuth connect flow
|
||||||
- Test menu upload/get
|
- Test menu upload/get
|
||||||
- Test order lifecycle actions
|
- Test order lifecycle actions
|
||||||
- Test webhook receipt and persistence
|
- Test webhook receipt and persistence
|
||||||
- Validate retry and duplicate event handling
|
- 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": {
|
"/api/v1/uber/menu": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Fetch store menu",
|
"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",
|
"name": "Generic Uber Request",
|
||||||
"request": {
|
"request": {
|
||||||
@ -135,4 +168,3 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,21 @@ async function getMenu(req, res) {
|
|||||||
return res.json({ success: true, data });
|
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) {
|
async function listOrders(req, res) {
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
merchantId: z.string().min(1),
|
merchantId: z.string().min(1),
|
||||||
@ -89,9 +104,9 @@ async function updateHours(req, res) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
genericProxy,
|
genericProxy,
|
||||||
upsertMenu,
|
upsertMenu,
|
||||||
|
replaceMenu,
|
||||||
getMenu,
|
getMenu,
|
||||||
listOrders,
|
listOrders,
|
||||||
orderAction,
|
orderAction,
|
||||||
updateHours
|
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 }) {
|
async function menuGet({ merchantId, storeId }) {
|
||||||
const uberPath = interpolatePath(uberEndpoints.menu.get, { storeId });
|
const uberPath = interpolatePath(uberEndpoints.menu.get, { storeId });
|
||||||
return callUberApi({
|
return callUberApi({
|
||||||
@ -153,9 +164,9 @@ async function updateStoreHours({ merchantId, storeId, payload }) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
genericProxy,
|
genericProxy,
|
||||||
menuUpsert,
|
menuUpsert,
|
||||||
|
menuReplace,
|
||||||
menuGet,
|
menuGet,
|
||||||
ordersList,
|
ordersList,
|
||||||
orderAction,
|
orderAction,
|
||||||
updateStoreHours
|
updateStoreHours
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,19 @@ router.post("/uber/request", asyncHandler(controller.genericProxy));
|
|||||||
*/
|
*/
|
||||||
router.post("/uber/menu/upsert", asyncHandler(controller.upsertMenu));
|
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
|
* @openapi
|
||||||
* /api/v1/uber/menu:
|
* /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));
|
router.put("/uber/stores/hours", asyncHandler(controller.updateHours));
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user