@onesub/server 0.13.1 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +26 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +26 -4
- package/dist/index.js.map +1 -1
- package/dist/providers/apple.d.ts +8 -0
- package/dist/providers/apple.d.ts.map +1 -1
- package/dist/providers/google.d.ts +8 -0
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/mock.d.ts +2 -0
- package/dist/providers/mock.d.ts.map +1 -1
- package/dist/routes/purchase.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -248,10 +248,12 @@ function mockValidateAppleProduct(receipt, expectedProductId) {
|
|
|
248
248
|
const outcome = classifyMockReceipt(receipt);
|
|
249
249
|
if (!outcomePasses(outcome, "apple")) return null;
|
|
250
250
|
const productId = expectedProductId ?? "mock_product";
|
|
251
|
+
const tokenMatch = receipt.match(/#token=([^#]+)/);
|
|
251
252
|
return {
|
|
252
253
|
transactionId: deterministicTransactionId(`mock_apple_${productId}`, receipt),
|
|
253
254
|
productId,
|
|
254
|
-
purchasedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
255
|
+
purchasedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
256
|
+
...tokenMatch ? { appAccountToken: tokenMatch[1] } : {}
|
|
255
257
|
};
|
|
256
258
|
}
|
|
257
259
|
function mockValidateGoogleSubscription(receipt, productId) {
|
|
@@ -273,9 +275,11 @@ function mockValidateGoogleSubscription(receipt, productId) {
|
|
|
273
275
|
function mockValidateGoogleProduct(receipt, productId) {
|
|
274
276
|
const outcome = classifyMockReceipt(receipt);
|
|
275
277
|
if (!outcomePasses(outcome, "google")) return null;
|
|
278
|
+
const tokenMatch = receipt.match(/#token=([^#]+)/);
|
|
276
279
|
return {
|
|
277
280
|
transactionId: deterministicTransactionId(`mock_google_${productId}`, receipt),
|
|
278
|
-
purchasedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
281
|
+
purchasedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
282
|
+
...tokenMatch ? { obfuscatedExternalAccountId: tokenMatch[1] } : {}
|
|
279
283
|
};
|
|
280
284
|
}
|
|
281
285
|
|
|
@@ -439,7 +443,8 @@ async function validateAppleConsumableReceipt(signedTransaction, config, expecte
|
|
|
439
443
|
return {
|
|
440
444
|
transactionId,
|
|
441
445
|
productId: tx.productId,
|
|
442
|
-
purchasedAt: tx.purchaseDate ? new Date(tx.purchaseDate).toISOString() : (/* @__PURE__ */ new Date()).toISOString()
|
|
446
|
+
purchasedAt: tx.purchaseDate ? new Date(tx.purchaseDate).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
447
|
+
appAccountToken: tx.appAccountToken ?? void 0
|
|
443
448
|
};
|
|
444
449
|
}
|
|
445
450
|
async function decodeAppleNotification(payload, skipJwsVerification = false) {
|
|
@@ -998,7 +1003,8 @@ async function validateGoogleProductReceipt(purchaseToken, productId, config, ty
|
|
|
998
1003
|
}
|
|
999
1004
|
return {
|
|
1000
1005
|
transactionId: purchase.orderId,
|
|
1001
|
-
purchasedAt: purchase.purchaseTimeMillis ? new Date(parseInt(purchase.purchaseTimeMillis, 10)).toISOString() : (/* @__PURE__ */ new Date()).toISOString()
|
|
1006
|
+
purchasedAt: purchase.purchaseTimeMillis ? new Date(parseInt(purchase.purchaseTimeMillis, 10)).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
1007
|
+
obfuscatedExternalAccountId: purchase.obfuscatedExternalAccountId
|
|
1002
1008
|
};
|
|
1003
1009
|
}
|
|
1004
1010
|
function decodeGoogleNotification(payload) {
|
|
@@ -1544,6 +1550,7 @@ function createPurchaseRouter(config, purchaseStore) {
|
|
|
1544
1550
|
}
|
|
1545
1551
|
let transactionId = null;
|
|
1546
1552
|
let purchasedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1553
|
+
let boundAccountId = null;
|
|
1547
1554
|
if (platform === "apple") {
|
|
1548
1555
|
if (!config.apple) {
|
|
1549
1556
|
sendError(res, 500, ONESUB_ERROR_CODE.APPLE_CONFIG_MISSING, "Apple configuration not provided", NO_PURCHASE);
|
|
@@ -1553,6 +1560,7 @@ function createPurchaseRouter(config, purchaseStore) {
|
|
|
1553
1560
|
if (result) {
|
|
1554
1561
|
transactionId = result.transactionId;
|
|
1555
1562
|
purchasedAt = result.purchasedAt;
|
|
1563
|
+
boundAccountId = result.appAccountToken ?? null;
|
|
1556
1564
|
}
|
|
1557
1565
|
} else {
|
|
1558
1566
|
if (!config.google) {
|
|
@@ -1568,12 +1576,26 @@ function createPurchaseRouter(config, purchaseStore) {
|
|
|
1568
1576
|
if (result) {
|
|
1569
1577
|
transactionId = result.transactionId;
|
|
1570
1578
|
purchasedAt = result.purchasedAt;
|
|
1579
|
+
boundAccountId = result.obfuscatedExternalAccountId ?? null;
|
|
1571
1580
|
}
|
|
1572
1581
|
}
|
|
1573
1582
|
if (!transactionId) {
|
|
1574
1583
|
sendError(res, 422, ONESUB_ERROR_CODE.RECEIPT_VALIDATION_FAILED, "Receipt validation failed", NO_PURCHASE);
|
|
1575
1584
|
return;
|
|
1576
1585
|
}
|
|
1586
|
+
if (boundAccountId && boundAccountId.toLowerCase() !== userId.toLowerCase()) {
|
|
1587
|
+
log.warn(
|
|
1588
|
+
`[onesub/purchase] account binding mismatch for transaction ${transactionId}: token does not match userId ${userId}`
|
|
1589
|
+
);
|
|
1590
|
+
sendError(
|
|
1591
|
+
res,
|
|
1592
|
+
409,
|
|
1593
|
+
ONESUB_ERROR_CODE.TRANSACTION_BELONGS_TO_OTHER_USER,
|
|
1594
|
+
"TRANSACTION_BELONGS_TO_OTHER_USER",
|
|
1595
|
+
NO_PURCHASE
|
|
1596
|
+
);
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1577
1599
|
const existing = await purchaseStore.getPurchaseByTransactionId(transactionId);
|
|
1578
1600
|
let action = "new";
|
|
1579
1601
|
if (existing) {
|