| 12345678910111213141516171819202122232425262728 |
- import dayjs from "dayjs";
- /**
- * 门店编号(third_shop_id)自动生成 —— 汇安融门店创建表单用。
- *
- * 形状:`SP` + `yyyyMMddHHmmss` + 16 位随机,共 32 字符,正好吃满
- * `third_shop_id` 的 varchar(32)。改成自动生成是因为运营手填这个编号的代价不对称:
- * 撞号 ⇒ 上游按「重复提交」拒绝建店;填错一个字符 ⇒ 上游没有更新接口,事后补不上。
- *
- * 两个刻意的选择:
- * - 字母表去掉 0/1/I/O(连同数字段共 32 个字符):编号要能在电话/微信里念得出来,
- * 去掉易混字符,一个歧义就少一类抄错。
- * - 32 是 2 的幂 ⇒ 取随机字节的低 5 位做下标是无偏的(256 % 32 == 0),无需拒绝采样。
- * 随机源必须是 crypto.getRandomValues:这个编号在上游是**幂等键**,撞号等于
- * 整笔建店被拒,Math.random 的碰撞概率和可预测性都不能接受。
- */
- const ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
- export function generateShopCode(now: Date = new Date()): string {
- const stamp = dayjs(now).format("YYYYMMDDHHmmss");
- const bytes = new Uint8Array(16);
- crypto.getRandomValues(bytes);
- let rand = "";
- for (const b of bytes) {
- rand += ALPHABET[b & 31];
- }
- return `SP${stamp}${rand}`;
- }
|