diff --git a/README.md b/README.md index 19d6f9a..7095a7e 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,7 @@ Headers: `authorization` (JWT), `x-mc-token` (required). Returns `{ count, entit #### `GET /inventory/playfab/items?filter=` -Headers: `authorization` (JWT), `x-playfab-session` (required), `x-playfab-id` (required). Returns the PlayFab Economy inventory payload with official PlayFab filter queries. +Headers: `authorization` (JWT), `x-playfab-session` (required), `x-playfab-id` (required). Returns the PlayFab Economy inventory payload with official PlayFab filter queries. Supported filter fields are `type`, `id`, and `stackId` with `eq`. #### `POST /purchase/quote` @@ -341,7 +341,11 @@ curl -sS "$BASE/inventory/entitlements?includeReceipt=true" \ -H "Authorization: Bearer $TOKEN" -H "x-mc-token: $MC" # PlayFab inventory items with filter query -curl -sS "$BASE/inventory/playfab/items?filter=InventoryItem.ItemClass%20eq%20%27Subscription%27" \ +curl -sS "$BASE/inventory/playfab/items?filter=type%20eq%20%27Subscription%27" \ + -H "Authorization: Bearer $TOKEN" -H "x-playfab-session: $ST" -H "x-playfab-id: " + +# PlayFab inventory items with shortcut parameters +curl -sS "$BASE/inventory/playfab/items?type=Subscription" \ -H "Authorization: Bearer $TOKEN" -H "x-playfab-session: $ST" -H "x-playfab-id: " # Debug: decode multiple tokens diff --git a/src/routes/inventory.routes.js b/src/routes/inventory.routes.js index a45e2fe..2d44682 100644 --- a/src/routes/inventory.routes.js +++ b/src/routes/inventory.routes.js @@ -27,6 +27,11 @@ router.get("/playfab/items", jwtMiddleware, asyncHandler(async (req, res) => { const playfabId = req.headers["x-playfab-id"]; if (!sessionTicket || !playfabId) throw badRequest("x-playfab-session and x-playfab-id are required"); const filter = String(req.query.filter || "").trim(); + const type = req.query.type ? String(req.query.type).trim() : ""; + const id = req.query.id ? String(req.query.id).trim() : ""; + const stackId = req.query.stackId ? String(req.query.stackId).trim() : ""; + if (filter && (type || id || stackId)) throw badRequest("Use filter or type/id/stackId, not both"); + if (!filter && !type && !id && !stackId) throw badRequest("Provide filter or type/id/stackId"); const countRaw = req.query.count; const count = countRaw === undefined ? null : Number(countRaw); if (count !== null && (!Number.isInteger(count) || count < 1 || count > 200)) { @@ -34,8 +39,21 @@ router.get("/playfab/items", jwtMiddleware, asyncHandler(async (req, res) => { } const continuationToken = req.query.continuationToken ? String(req.query.continuationToken) : null; const entityToken = await getEntityTokenForPlayer(sessionTicket, playfabId); - const data = await getInventoryItems(entityToken, {filter, count, continuationToken}); + const resolvedFilter = filter || buildInventoryFilter({type, id, stackId}); + const data = await getInventoryItems(entityToken, {filter: resolvedFilter, count, continuationToken}); res.json(data); })); +function buildInventoryFilter({type, id, stackId}) { + const parts = []; + if (type) parts.push(`type eq '${escapeFilterValue(type)}'`); + if (id) parts.push(`id eq '${escapeFilterValue(id)}'`); + if (stackId) parts.push(`stackId eq '${escapeFilterValue(stackId)}'`); + return parts.join(" and "); +} + +function escapeFilterValue(value) { + return value.replaceAll("'", "''"); +} + export default router; diff --git a/src/utils/swagger.js b/src/utils/swagger.js index 0ea8dd3..9909518 100644 --- a/src/utils/swagger.js +++ b/src/utils/swagger.js @@ -187,7 +187,25 @@ const options = { name: "filter", required: false, schema: {type: "string"}, - description: "PlayFab Economy filter query string." + description: "PlayFab Economy filter query string. Supported fields: type, id, stackId with eq." + }, { + in: "query", + name: "type", + required: false, + schema: {type: "string"}, + description: "Shortcut for type eq '' when filter is omitted." + }, { + in: "query", + name: "id", + required: false, + schema: {type: "string"}, + description: "Shortcut for id eq '' when filter is omitted." + }, { + in: "query", + name: "stackId", + required: false, + schema: {type: "string"}, + description: "Shortcut for stackId eq '' when filter is omitted." }, { in: "query", name: "count",