@downcity/services 0.1.6
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/README.md +47 -0
- package/bin/accounts/db.d.ts +19 -0
- package/bin/accounts/db.d.ts.map +1 -0
- package/bin/accounts/db.js +68 -0
- package/bin/accounts/db.js.map +1 -0
- package/bin/accounts/index.d.ts +348 -0
- package/bin/accounts/index.d.ts.map +1 -0
- package/bin/accounts/index.js +681 -0
- package/bin/accounts/index.js.map +1 -0
- package/bin/accounts/oauth.d.ts +129 -0
- package/bin/accounts/oauth.d.ts.map +1 -0
- package/bin/accounts/oauth.js +220 -0
- package/bin/accounts/oauth.js.map +1 -0
- package/bin/accounts/schema.d.ts +319 -0
- package/bin/accounts/schema.d.ts.map +1 -0
- package/bin/accounts/schema.js +72 -0
- package/bin/accounts/schema.js.map +1 -0
- package/bin/balance/index.d.ts +7 -0
- package/bin/balance/index.d.ts.map +1 -0
- package/bin/balance/index.js +6 -0
- package/bin/balance/index.js.map +1 -0
- package/bin/balance/raw.d.ts +20 -0
- package/bin/balance/raw.d.ts.map +1 -0
- package/bin/balance/raw.js +75 -0
- package/bin/balance/raw.js.map +1 -0
- package/bin/balance/routes.d.ts +14 -0
- package/bin/balance/routes.d.ts.map +1 -0
- package/bin/balance/routes.js +166 -0
- package/bin/balance/routes.js.map +1 -0
- package/bin/balance/schema.d.ts +764 -0
- package/bin/balance/schema.d.ts.map +1 -0
- package/bin/balance/schema.js +185 -0
- package/bin/balance/schema.js.map +1 -0
- package/bin/balance/service.d.ts +880 -0
- package/bin/balance/service.d.ts.map +1 -0
- package/bin/balance/service.js +557 -0
- package/bin/balance/service.js.map +1 -0
- package/bin/balance/types.d.ts +326 -0
- package/bin/balance/types.d.ts.map +1 -0
- package/bin/balance/types.js +10 -0
- package/bin/balance/types.js.map +1 -0
- package/bin/balance/utils.d.ts +91 -0
- package/bin/balance/utils.d.ts.map +1 -0
- package/bin/balance/utils.js +231 -0
- package/bin/balance/utils.js.map +1 -0
- package/bin/index.d.ts +22 -0
- package/bin/index.d.ts.map +1 -0
- package/bin/index.js +16 -0
- package/bin/index.js.map +1 -0
- package/bin/payment/index.d.ts +19 -0
- package/bin/payment/index.d.ts.map +1 -0
- package/bin/payment/index.js +63 -0
- package/bin/payment/index.js.map +1 -0
- package/bin/payment/types.d.ts +107 -0
- package/bin/payment/types.d.ts.map +1 -0
- package/bin/payment/types.js +10 -0
- package/bin/payment/types.js.map +1 -0
- package/bin/payment-stripe/index.d.ts +17 -0
- package/bin/payment-stripe/index.d.ts.map +1 -0
- package/bin/payment-stripe/index.js +619 -0
- package/bin/payment-stripe/index.js.map +1 -0
- package/bin/payment-stripe/schema.d.ts +378 -0
- package/bin/payment-stripe/schema.d.ts.map +1 -0
- package/bin/payment-stripe/schema.js +47 -0
- package/bin/payment-stripe/schema.js.map +1 -0
- package/bin/payment-stripe/stripe.d.ts +38 -0
- package/bin/payment-stripe/stripe.d.ts.map +1 -0
- package/bin/payment-stripe/stripe.js +129 -0
- package/bin/payment-stripe/stripe.js.map +1 -0
- package/bin/payment-stripe/types.d.ts +331 -0
- package/bin/payment-stripe/types.d.ts.map +1 -0
- package/bin/payment-stripe/types.js +10 -0
- package/bin/payment-stripe/types.js.map +1 -0
- package/bin/usage/index.d.ts +177 -0
- package/bin/usage/index.d.ts.map +1 -0
- package/bin/usage/index.js +120 -0
- package/bin/usage/index.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/balance/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Downcity 官方 Balance 服务实现。
|
|
3
|
+
*
|
|
4
|
+
* 设计边界:
|
|
5
|
+
* - 余额是用户级全局钱包,不与 product 绑定
|
|
6
|
+
* - 服务只负责账户、流水、充值单、redeem_code 与原子加减款
|
|
7
|
+
* - 真正的计费策略应由业务方在 hook 中直接调用本服务
|
|
8
|
+
*/
|
|
9
|
+
import { InstallableService, httpError, } from "@downcity/infra";
|
|
10
|
+
import { rawAll, rawFirst, rawRun } from "./raw.js";
|
|
11
|
+
import { registerBalanceRoutes } from "./routes.js";
|
|
12
|
+
import { ACCOUNT_TABLE, LEDGER_TABLE, REDEEM_CODE_TABLE, TOPUP_TABLE, balanceAccounts, balanceLedger, balanceRedeemCodes, balanceTopups, } from "./schema.js";
|
|
13
|
+
import { generateRedeemCode, hashRedeemCode, maskRedeemCode, mergeMetaJSON, normalizeLimit, normalizeNonNegativeInteger, normalizePositiveInteger, normalizeRedeemCode, normalizeRedeemCodeStatus, normalizeText, normalizeUserId, parseAccountRow, parseLedgerRow, parseMetaJSON, parseRedeemCodeRow, parseTopupRow, randomId, readRequired, stringifyMeta, } from "./utils.js";
|
|
14
|
+
/**
|
|
15
|
+
* Balance 服务实例。
|
|
16
|
+
*
|
|
17
|
+
* 业务方应保存返回实例,并在 hook 中直接调用它的 `require()` / `sub()` / `add()`。
|
|
18
|
+
*/
|
|
19
|
+
export class BalanceService extends InstallableService {
|
|
20
|
+
id = "balance";
|
|
21
|
+
name = "Balance";
|
|
22
|
+
version = "0.1.0";
|
|
23
|
+
schema = {
|
|
24
|
+
accounts: balanceAccounts,
|
|
25
|
+
ledger: balanceLedger,
|
|
26
|
+
topups: balanceTopups,
|
|
27
|
+
redeem_codes: balanceRedeemCodes,
|
|
28
|
+
};
|
|
29
|
+
initAmount;
|
|
30
|
+
unitName;
|
|
31
|
+
constructor(options = {}) {
|
|
32
|
+
super();
|
|
33
|
+
this.initAmount = normalizeNonNegativeInteger(options.init ?? 0, "init");
|
|
34
|
+
this.unitName = String(options.unit ?? "credits").trim() || "credits";
|
|
35
|
+
this.instruction = [
|
|
36
|
+
"提供用户级全局余额、余额流水、充值单与 redeem_code 能力。",
|
|
37
|
+
`当前余额单位为 ${this.unitName},首次自动开户发放 ${this.initAmount} ${this.unitName}。`,
|
|
38
|
+
"推荐在业务 hook 中调用 require/add/sub,把具体计费策略放在业务侧,而不是写死在服务内部。",
|
|
39
|
+
"管理端可查询所有账户、流水、充值单与 redeem_code;用户侧可查询自己的余额、历史记录、充值单,并直接兑换 redeem_code。",
|
|
40
|
+
].join("\n");
|
|
41
|
+
}
|
|
42
|
+
install(ctx) {
|
|
43
|
+
registerBalanceRoutes(this, ctx);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 读取用户余额。
|
|
47
|
+
*
|
|
48
|
+
* 若账户不存在,会自动开户并按配置发放初始余额。
|
|
49
|
+
*/
|
|
50
|
+
async read(user_id) {
|
|
51
|
+
const normalizedUserId = normalizeUserId(user_id);
|
|
52
|
+
await this.ensureAccount(normalizedUserId);
|
|
53
|
+
return await this.readAccountRequired(normalizedUserId);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 检查用户余额是否足够。
|
|
57
|
+
*
|
|
58
|
+
* 余额不足时会抛出 `402 insufficient balance`。
|
|
59
|
+
*/
|
|
60
|
+
async require(user_id, amount) {
|
|
61
|
+
const normalizedUserId = normalizeUserId(user_id);
|
|
62
|
+
const normalizedAmount = normalizePositiveInteger(amount, "amount");
|
|
63
|
+
const account = await this.read(normalizedUserId);
|
|
64
|
+
if (account.balance < normalizedAmount) {
|
|
65
|
+
throw httpError(402, `insufficient balance: need ${normalizedAmount}, current ${account.balance}`);
|
|
66
|
+
}
|
|
67
|
+
return account;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 给用户加余额,并写入 `add` 流水。
|
|
71
|
+
*/
|
|
72
|
+
async add(user_id, amount, extra = {}) {
|
|
73
|
+
return await this.applyDelta(normalizeUserId(user_id), normalizePositiveInteger(amount, "amount"), "add", extra);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 给用户扣余额,并写入 `sub` 流水。
|
|
77
|
+
*/
|
|
78
|
+
async sub(user_id, amount, extra = {}) {
|
|
79
|
+
return await this.applyDelta(normalizeUserId(user_id), -normalizePositiveInteger(amount, "amount"), "sub", extra);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 查询某个用户的流水。
|
|
83
|
+
*/
|
|
84
|
+
async history(user_id, limit) {
|
|
85
|
+
return await this.listHistory({
|
|
86
|
+
user_id: normalizeUserId(user_id),
|
|
87
|
+
limit,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 读取一笔充值单。
|
|
92
|
+
*
|
|
93
|
+
* 关键说明(中文)
|
|
94
|
+
* - 这是给支付桥接层使用的公开只读能力
|
|
95
|
+
* - 充值单的状态流转仍然只能通过 finishTopup / cancelTopup 完成
|
|
96
|
+
*/
|
|
97
|
+
async readTopup(topup_id) {
|
|
98
|
+
return await this.readTopupRequired(readRequired(topup_id, "topup_id"));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 创建充值单。
|
|
102
|
+
*
|
|
103
|
+
* 这一步不会直接入账,只会生成 `pending` 充值单。
|
|
104
|
+
*/
|
|
105
|
+
async createTopup(user_id, amount, extra = {}) {
|
|
106
|
+
const normalizedUserId = normalizeUserId(user_id);
|
|
107
|
+
const normalizedAmount = normalizePositiveInteger(amount, "amount");
|
|
108
|
+
const now = new Date().toISOString();
|
|
109
|
+
const topup = {
|
|
110
|
+
topup_id: `topup_${randomId()}`,
|
|
111
|
+
user_id: normalizedUserId,
|
|
112
|
+
amount: normalizedAmount,
|
|
113
|
+
unit: this.unitName,
|
|
114
|
+
status: "pending",
|
|
115
|
+
note: normalizeText(extra.note),
|
|
116
|
+
ref: normalizeText(extra.ref),
|
|
117
|
+
metadata_json: stringifyMeta(extra.meta),
|
|
118
|
+
created_at: now,
|
|
119
|
+
updated_at: now,
|
|
120
|
+
};
|
|
121
|
+
await this.ensureAccount(normalizedUserId);
|
|
122
|
+
await rawRun(this.resolveRaw(), [
|
|
123
|
+
`INSERT INTO ${TOPUP_TABLE} (topup_id, user_id, amount, unit, status, note, ref, metadata_json, created_at, updated_at)`,
|
|
124
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
125
|
+
].join(" "), [
|
|
126
|
+
topup.topup_id,
|
|
127
|
+
topup.user_id,
|
|
128
|
+
topup.amount,
|
|
129
|
+
topup.unit,
|
|
130
|
+
topup.status,
|
|
131
|
+
topup.note,
|
|
132
|
+
topup.ref,
|
|
133
|
+
topup.metadata_json,
|
|
134
|
+
topup.created_at,
|
|
135
|
+
topup.updated_at,
|
|
136
|
+
]);
|
|
137
|
+
return topup;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 将充值单标记为完成,并真正给用户加余额。
|
|
141
|
+
*/
|
|
142
|
+
async finishTopup(topup_id, extra = {}) {
|
|
143
|
+
const current = await this.readTopupRequired(topup_id);
|
|
144
|
+
if (current.status !== "pending") {
|
|
145
|
+
throw httpError(409, `topup is already ${current.status}`);
|
|
146
|
+
}
|
|
147
|
+
const now = new Date().toISOString();
|
|
148
|
+
const changed = await rawRun(this.resolveRaw(), [
|
|
149
|
+
`UPDATE ${TOPUP_TABLE}`,
|
|
150
|
+
"SET status = ?, updated_at = ?, note = ?, ref = ?, metadata_json = ?",
|
|
151
|
+
"WHERE topup_id = ? AND status = ?",
|
|
152
|
+
].join(" "), [
|
|
153
|
+
"paid",
|
|
154
|
+
now,
|
|
155
|
+
normalizeText(extra.note) || current.note,
|
|
156
|
+
normalizeText(extra.ref) || current.ref,
|
|
157
|
+
mergeMetaJSON(current.metadata_json, extra.meta),
|
|
158
|
+
topup_id,
|
|
159
|
+
"pending",
|
|
160
|
+
]);
|
|
161
|
+
if (changed === 0) {
|
|
162
|
+
throw httpError(409, "topup is no longer pending");
|
|
163
|
+
}
|
|
164
|
+
await this.applyDelta(current.user_id, current.amount, "topup", {
|
|
165
|
+
note: normalizeText(extra.note) || current.note || "topup",
|
|
166
|
+
ref: normalizeText(extra.ref) || topup_id,
|
|
167
|
+
meta: {
|
|
168
|
+
...(parseMetaJSON(current.metadata_json)),
|
|
169
|
+
...(extra.meta ?? {}),
|
|
170
|
+
topup_id,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
return await this.readTopupRequired(topup_id);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 取消待处理充值单。
|
|
177
|
+
*/
|
|
178
|
+
async cancelTopup(topup_id, extra = {}) {
|
|
179
|
+
const current = await this.readTopupRequired(topup_id);
|
|
180
|
+
if (current.status !== "pending") {
|
|
181
|
+
throw httpError(409, `topup is already ${current.status}`);
|
|
182
|
+
}
|
|
183
|
+
const changed = await rawRun(this.resolveRaw(), [
|
|
184
|
+
`UPDATE ${TOPUP_TABLE}`,
|
|
185
|
+
"SET status = ?, updated_at = ?, note = ?, ref = ?, metadata_json = ?",
|
|
186
|
+
"WHERE topup_id = ? AND status = ?",
|
|
187
|
+
].join(" "), [
|
|
188
|
+
"canceled",
|
|
189
|
+
new Date().toISOString(),
|
|
190
|
+
normalizeText(extra.note) || current.note,
|
|
191
|
+
normalizeText(extra.ref) || current.ref,
|
|
192
|
+
mergeMetaJSON(current.metadata_json, extra.meta),
|
|
193
|
+
topup_id,
|
|
194
|
+
"pending",
|
|
195
|
+
]);
|
|
196
|
+
if (changed === 0) {
|
|
197
|
+
throw httpError(409, "topup is no longer pending");
|
|
198
|
+
}
|
|
199
|
+
return await this.readTopupRequired(topup_id);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* 创建一个新的 redeem_code。
|
|
203
|
+
*/
|
|
204
|
+
async createRedeemCode(input) {
|
|
205
|
+
const amount = normalizePositiveInteger(input.amount, "amount");
|
|
206
|
+
const now = new Date().toISOString();
|
|
207
|
+
const code = input.code ? normalizeRedeemCode(input.code) : generateRedeemCode();
|
|
208
|
+
const codeHash = await hashRedeemCode(code);
|
|
209
|
+
if (await this.readRedeemCodeByHash(codeHash)) {
|
|
210
|
+
throw httpError(409, "redeem_code already exists");
|
|
211
|
+
}
|
|
212
|
+
const redeemCode = {
|
|
213
|
+
redeem_code_id: `rc_${randomId()}`,
|
|
214
|
+
amount,
|
|
215
|
+
unit: this.unitName,
|
|
216
|
+
status: "active",
|
|
217
|
+
code_mask: maskRedeemCode(code),
|
|
218
|
+
note: normalizeText(input.note),
|
|
219
|
+
ref: normalizeText(input.ref),
|
|
220
|
+
metadata_json: stringifyMeta(input.meta),
|
|
221
|
+
redeemed_by_user_id: "",
|
|
222
|
+
redeemed_at: "",
|
|
223
|
+
created_at: now,
|
|
224
|
+
updated_at: now,
|
|
225
|
+
};
|
|
226
|
+
await rawRun(this.resolveRaw(), [
|
|
227
|
+
`INSERT INTO ${REDEEM_CODE_TABLE} (redeem_code_id, code_hash, code_mask, amount, unit, status, note, ref, metadata_json, redeemed_by_user_id, redeemed_at, created_at, updated_at)`,
|
|
228
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
229
|
+
].join(" "), [
|
|
230
|
+
redeemCode.redeem_code_id,
|
|
231
|
+
codeHash,
|
|
232
|
+
redeemCode.code_mask,
|
|
233
|
+
redeemCode.amount,
|
|
234
|
+
redeemCode.unit,
|
|
235
|
+
redeemCode.status,
|
|
236
|
+
redeemCode.note,
|
|
237
|
+
redeemCode.ref,
|
|
238
|
+
redeemCode.metadata_json,
|
|
239
|
+
redeemCode.redeemed_by_user_id,
|
|
240
|
+
redeemCode.redeemed_at,
|
|
241
|
+
redeemCode.created_at,
|
|
242
|
+
redeemCode.updated_at,
|
|
243
|
+
]);
|
|
244
|
+
return {
|
|
245
|
+
...redeemCode,
|
|
246
|
+
code,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* 用户兑换 redeem_code,并立刻给余额入账。
|
|
251
|
+
*/
|
|
252
|
+
async redeemCode(user_id, code, extra = {}) {
|
|
253
|
+
const normalizedUserId = normalizeUserId(user_id);
|
|
254
|
+
const normalizedCode = normalizeRedeemCode(code);
|
|
255
|
+
const codeHash = await hashRedeemCode(normalizedCode);
|
|
256
|
+
const current = await this.readRedeemCodeByHash(codeHash);
|
|
257
|
+
if (!current) {
|
|
258
|
+
throw httpError(404, "redeem_code not found");
|
|
259
|
+
}
|
|
260
|
+
if (current.status !== "active") {
|
|
261
|
+
throw httpError(409, `redeem_code is already ${current.status}`);
|
|
262
|
+
}
|
|
263
|
+
const now = new Date().toISOString();
|
|
264
|
+
const changed = await rawRun(this.resolveRaw(), [
|
|
265
|
+
`UPDATE ${REDEEM_CODE_TABLE}`,
|
|
266
|
+
"SET status = ?, redeemed_by_user_id = ?, redeemed_at = ?, updated_at = ?, note = ?, ref = ?, metadata_json = ?",
|
|
267
|
+
"WHERE redeem_code_id = ? AND status = ?",
|
|
268
|
+
].join(" "), [
|
|
269
|
+
"redeemed",
|
|
270
|
+
normalizedUserId,
|
|
271
|
+
now,
|
|
272
|
+
now,
|
|
273
|
+
normalizeText(extra.note) || current.note,
|
|
274
|
+
normalizeText(extra.ref) || current.ref,
|
|
275
|
+
mergeMetaJSON(current.metadata_json, extra.meta),
|
|
276
|
+
current.redeem_code_id,
|
|
277
|
+
"active",
|
|
278
|
+
]);
|
|
279
|
+
if (changed === 0) {
|
|
280
|
+
const latest = await this.readRedeemCodeRequired(current.redeem_code_id);
|
|
281
|
+
throw httpError(409, `redeem_code is already ${latest.status}`);
|
|
282
|
+
}
|
|
283
|
+
const account = await this.applyDelta(normalizedUserId, current.amount, "redeem", {
|
|
284
|
+
note: normalizeText(extra.note) || current.note || "redeem_code",
|
|
285
|
+
ref: normalizeText(extra.ref) || current.redeem_code_id,
|
|
286
|
+
meta: {
|
|
287
|
+
...(parseMetaJSON(current.metadata_json)),
|
|
288
|
+
...(extra.meta ?? {}),
|
|
289
|
+
redeem_code_id: current.redeem_code_id,
|
|
290
|
+
code_mask: current.code_mask,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
return {
|
|
294
|
+
account,
|
|
295
|
+
redeem_code: await this.readRedeemCodeRequired(current.redeem_code_id),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* 停用一个尚未兑换的 redeem_code。
|
|
300
|
+
*/
|
|
301
|
+
async disableRedeemCode(redeem_code_id, extra = {}) {
|
|
302
|
+
const current = await this.readRedeemCodeRequired(redeem_code_id);
|
|
303
|
+
if (current.status !== "active") {
|
|
304
|
+
throw httpError(409, `redeem_code is already ${current.status}`);
|
|
305
|
+
}
|
|
306
|
+
const changed = await rawRun(this.resolveRaw(), [
|
|
307
|
+
`UPDATE ${REDEEM_CODE_TABLE}`,
|
|
308
|
+
"SET status = ?, updated_at = ?, note = ?, ref = ?, metadata_json = ?",
|
|
309
|
+
"WHERE redeem_code_id = ? AND status = ?",
|
|
310
|
+
].join(" "), [
|
|
311
|
+
"disabled",
|
|
312
|
+
new Date().toISOString(),
|
|
313
|
+
normalizeText(extra.note) || current.note,
|
|
314
|
+
normalizeText(extra.ref) || current.ref,
|
|
315
|
+
mergeMetaJSON(current.metadata_json, extra.meta),
|
|
316
|
+
redeem_code_id,
|
|
317
|
+
"active",
|
|
318
|
+
]);
|
|
319
|
+
if (changed === 0) {
|
|
320
|
+
throw httpError(409, "redeem_code is no longer active");
|
|
321
|
+
}
|
|
322
|
+
return await this.readRedeemCodeRequired(redeem_code_id);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* 列出余额账户。
|
|
326
|
+
*/
|
|
327
|
+
async listUsers(limit) {
|
|
328
|
+
const rows = await rawAll(this.resolveRaw(), [
|
|
329
|
+
`SELECT user_id, balance, unit, created_at, updated_at FROM ${ACCOUNT_TABLE}`,
|
|
330
|
+
"ORDER BY updated_at DESC",
|
|
331
|
+
"LIMIT ?",
|
|
332
|
+
].join(" "), [normalizeLimit(limit)]);
|
|
333
|
+
return rows.map(parseAccountRow);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* 列出流水。
|
|
337
|
+
*/
|
|
338
|
+
async listHistory(query = {}) {
|
|
339
|
+
const params = [];
|
|
340
|
+
const where = query.user_id
|
|
341
|
+
? (() => {
|
|
342
|
+
params.push(normalizeUserId(query.user_id));
|
|
343
|
+
return "WHERE user_id = ?";
|
|
344
|
+
})()
|
|
345
|
+
: "";
|
|
346
|
+
const rows = await rawAll(this.resolveRaw(), [
|
|
347
|
+
`SELECT entry_id, user_id, kind, amount, balance_after, unit, note, ref, metadata_json, created_at FROM ${LEDGER_TABLE}`,
|
|
348
|
+
where,
|
|
349
|
+
"ORDER BY created_at DESC, rowid DESC",
|
|
350
|
+
"LIMIT ?",
|
|
351
|
+
].join(" "), [...params, normalizeLimit(query.limit)]);
|
|
352
|
+
return rows.map(parseLedgerRow);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* 列出充值单。
|
|
356
|
+
*/
|
|
357
|
+
async listTopups(query = {}) {
|
|
358
|
+
const params = [];
|
|
359
|
+
const where = query.user_id
|
|
360
|
+
? (() => {
|
|
361
|
+
params.push(normalizeUserId(query.user_id));
|
|
362
|
+
return "WHERE user_id = ?";
|
|
363
|
+
})()
|
|
364
|
+
: "";
|
|
365
|
+
const rows = await rawAll(this.resolveRaw(), [
|
|
366
|
+
`SELECT topup_id, user_id, amount, unit, status, note, ref, metadata_json, created_at, updated_at FROM ${TOPUP_TABLE}`,
|
|
367
|
+
where,
|
|
368
|
+
"ORDER BY created_at DESC",
|
|
369
|
+
"LIMIT ?",
|
|
370
|
+
].join(" "), [...params, normalizeLimit(query.limit)]);
|
|
371
|
+
return rows.map(parseTopupRow);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* 列出 redeem_code。
|
|
375
|
+
*/
|
|
376
|
+
async listRedeemCodes(query = {}) {
|
|
377
|
+
const params = [];
|
|
378
|
+
const clauses = [];
|
|
379
|
+
const status = normalizeRedeemCodeStatus(query.status);
|
|
380
|
+
if (query.user_id) {
|
|
381
|
+
clauses.push("redeemed_by_user_id = ?");
|
|
382
|
+
params.push(normalizeUserId(query.user_id));
|
|
383
|
+
}
|
|
384
|
+
if (status) {
|
|
385
|
+
clauses.push("status = ?");
|
|
386
|
+
params.push(status);
|
|
387
|
+
}
|
|
388
|
+
const where = clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "";
|
|
389
|
+
const rows = await rawAll(this.resolveRaw(), [
|
|
390
|
+
`SELECT redeem_code_id, amount, unit, status, code_mask, note, ref, metadata_json, redeemed_by_user_id, redeemed_at, created_at, updated_at FROM ${REDEEM_CODE_TABLE}`,
|
|
391
|
+
where,
|
|
392
|
+
"ORDER BY created_at DESC",
|
|
393
|
+
"LIMIT ?",
|
|
394
|
+
].join(" "), [...params, normalizeLimit(query.limit)]);
|
|
395
|
+
return rows.map(parseRedeemCodeRow);
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* 关键说明(中文)
|
|
399
|
+
* - 正数表示加款,负数表示扣款
|
|
400
|
+
* - 扣款走 SQL 条件更新,避免把余额扣成负数
|
|
401
|
+
* - 扣费策略本身不写在服务里,而是由业务 hook 调用本方法
|
|
402
|
+
*/
|
|
403
|
+
async applyDelta(user_id, delta, kind, extra) {
|
|
404
|
+
if (!Number.isInteger(delta) || delta === 0) {
|
|
405
|
+
throw new TypeError("delta must be a non-zero integer");
|
|
406
|
+
}
|
|
407
|
+
await this.ensureAccount(user_id);
|
|
408
|
+
const now = new Date().toISOString();
|
|
409
|
+
if (delta > 0) {
|
|
410
|
+
await rawRun(this.resolveRaw(), [
|
|
411
|
+
`UPDATE ${ACCOUNT_TABLE}`,
|
|
412
|
+
"SET balance = balance + ?, updated_at = ?",
|
|
413
|
+
"WHERE user_id = ?",
|
|
414
|
+
].join(" "), [delta, now, user_id]);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
const spend = Math.abs(delta);
|
|
418
|
+
const changed = await rawRun(this.resolveRaw(), [
|
|
419
|
+
`UPDATE ${ACCOUNT_TABLE}`,
|
|
420
|
+
"SET balance = balance - ?, updated_at = ?",
|
|
421
|
+
"WHERE user_id = ? AND balance >= ?",
|
|
422
|
+
].join(" "), [spend, now, user_id, spend]);
|
|
423
|
+
if (changed === 0) {
|
|
424
|
+
const current = await this.readAccountRequired(user_id);
|
|
425
|
+
throw httpError(402, `insufficient balance: need ${spend}, current ${current.balance}`);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
const account = await this.readAccountRequired(user_id);
|
|
429
|
+
await this.insertLedger({
|
|
430
|
+
entry_id: `bal_${randomId()}`,
|
|
431
|
+
user_id,
|
|
432
|
+
kind,
|
|
433
|
+
amount: delta,
|
|
434
|
+
balance_after: account.balance,
|
|
435
|
+
unit: account.unit,
|
|
436
|
+
note: normalizeText(extra.note),
|
|
437
|
+
ref: normalizeText(extra.ref),
|
|
438
|
+
metadata_json: stringifyMeta(extra.meta),
|
|
439
|
+
created_at: now,
|
|
440
|
+
});
|
|
441
|
+
return account;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* 首次见到某用户时自动开户。
|
|
445
|
+
*/
|
|
446
|
+
async ensureAccount(user_id) {
|
|
447
|
+
const now = new Date().toISOString();
|
|
448
|
+
const inserted = await rawRun(this.resolveRaw(), [
|
|
449
|
+
`INSERT OR IGNORE INTO ${ACCOUNT_TABLE} (user_id, balance, unit, created_at, updated_at)`,
|
|
450
|
+
"VALUES (?, ?, ?, ?, ?)",
|
|
451
|
+
].join(" "), [user_id, this.initAmount, this.unitName, now, now]);
|
|
452
|
+
if (inserted > 0 && this.initAmount > 0) {
|
|
453
|
+
await this.insertLedger({
|
|
454
|
+
entry_id: `bal_${randomId()}`,
|
|
455
|
+
user_id,
|
|
456
|
+
kind: "init",
|
|
457
|
+
amount: this.initAmount,
|
|
458
|
+
balance_after: this.initAmount,
|
|
459
|
+
unit: this.unitName,
|
|
460
|
+
note: "initial balance",
|
|
461
|
+
ref: "",
|
|
462
|
+
metadata_json: "{}",
|
|
463
|
+
created_at: now,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* 读取账户;不存在时报错。
|
|
469
|
+
*/
|
|
470
|
+
async readAccountRequired(user_id) {
|
|
471
|
+
const row = await rawFirst(this.resolveRaw(), [
|
|
472
|
+
`SELECT user_id, balance, unit, created_at, updated_at FROM ${ACCOUNT_TABLE}`,
|
|
473
|
+
"WHERE user_id = ?",
|
|
474
|
+
].join(" "), [user_id]);
|
|
475
|
+
if (!row) {
|
|
476
|
+
throw httpError(404, `balance account not found for user ${user_id}`);
|
|
477
|
+
}
|
|
478
|
+
return parseAccountRow(row);
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* 读取充值单;不存在时报错。
|
|
482
|
+
*/
|
|
483
|
+
async readTopupRequired(topup_id) {
|
|
484
|
+
const row = await rawFirst(this.resolveRaw(), [
|
|
485
|
+
`SELECT topup_id, user_id, amount, unit, status, note, ref, metadata_json, created_at, updated_at FROM ${TOPUP_TABLE}`,
|
|
486
|
+
"WHERE topup_id = ?",
|
|
487
|
+
].join(" "), [readRequired(topup_id, "topup_id")]);
|
|
488
|
+
if (!row) {
|
|
489
|
+
throw httpError(404, `topup not found: ${topup_id}`);
|
|
490
|
+
}
|
|
491
|
+
return parseTopupRow(row);
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* 按 ID 读取 redeem_code;不存在时报错。
|
|
495
|
+
*/
|
|
496
|
+
async readRedeemCodeRequired(redeem_code_id) {
|
|
497
|
+
const row = await rawFirst(this.resolveRaw(), [
|
|
498
|
+
`SELECT redeem_code_id, amount, unit, status, code_mask, note, ref, metadata_json, redeemed_by_user_id, redeemed_at, created_at, updated_at FROM ${REDEEM_CODE_TABLE}`,
|
|
499
|
+
"WHERE redeem_code_id = ?",
|
|
500
|
+
].join(" "), [readRequired(redeem_code_id, "redeem_code_id")]);
|
|
501
|
+
if (!row) {
|
|
502
|
+
throw httpError(404, `redeem_code not found: ${redeem_code_id}`);
|
|
503
|
+
}
|
|
504
|
+
return parseRedeemCodeRow(row);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* 按哈希读取 redeem_code;不存在时返回空。
|
|
508
|
+
*/
|
|
509
|
+
async readRedeemCodeByHash(codeHash) {
|
|
510
|
+
const row = await rawFirst(this.resolveRaw(), [
|
|
511
|
+
`SELECT redeem_code_id, code_hash, amount, unit, status, code_mask, note, ref, metadata_json, redeemed_by_user_id, redeemed_at, created_at, updated_at FROM ${REDEEM_CODE_TABLE}`,
|
|
512
|
+
"WHERE code_hash = ?",
|
|
513
|
+
].join(" "), [readRequired(codeHash, "code_hash")]);
|
|
514
|
+
return row
|
|
515
|
+
? {
|
|
516
|
+
...parseRedeemCodeRow(row),
|
|
517
|
+
code_hash: String(row.code_hash),
|
|
518
|
+
}
|
|
519
|
+
: undefined;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* 写入流水。
|
|
523
|
+
*/
|
|
524
|
+
async insertLedger(entry) {
|
|
525
|
+
await rawRun(this.resolveRaw(), [
|
|
526
|
+
`INSERT INTO ${LEDGER_TABLE} (entry_id, user_id, kind, amount, balance_after, unit, note, ref, metadata_json, created_at)`,
|
|
527
|
+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
528
|
+
].join(" "), [
|
|
529
|
+
entry.entry_id,
|
|
530
|
+
entry.user_id,
|
|
531
|
+
entry.kind,
|
|
532
|
+
entry.amount,
|
|
533
|
+
entry.balance_after,
|
|
534
|
+
entry.unit,
|
|
535
|
+
entry.note,
|
|
536
|
+
entry.ref,
|
|
537
|
+
entry.metadata_json,
|
|
538
|
+
entry.created_at,
|
|
539
|
+
]);
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* 拿到底层原始数据库对象。
|
|
543
|
+
*/
|
|
544
|
+
resolveRaw() {
|
|
545
|
+
if (!this._raw) {
|
|
546
|
+
throw new Error("balance service raw database is not ready");
|
|
547
|
+
}
|
|
548
|
+
return this._raw;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* 创建 Balance 服务实例。
|
|
553
|
+
*/
|
|
554
|
+
export function balanceService(options = {}) {
|
|
555
|
+
return new BalanceService(options);
|
|
556
|
+
}
|
|
557
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/balance/service.ts"],"names":[],"mappings":"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"}
|