-- pay_har_shop 新增 province_code / city_code(2026-10-08,规范 261008 5.5 + 异地收款风控) -- 2026-10-09 订正:编码统一为 GB/T 2260 完整六位(省 2 位+0000、地级 4 位+00,与汇安融 -- 对照表一致);用旧短码建的门店见本文件「短码订正」段一次性 UPDATE 过来。 -- 手工执行: psycopg2 / psql 连接 payment_platform_java 库 -- -- 【本脚本尚未执行】执行由用户做。 -- -- ── 背景 ───────────────────────────────────────────────────────────── -- 《支付宝支付接口接入规范261008》门店创建(kf.har.shop.create)参数表新增了两行必填: -- province_code | 省份编码 | varchar(16) | √ -- city_code | 市编码 | varchar(16) | √ -- 而支付宝对**异地收款**有风控 ⇒ 收款链接下单时要按顾客 IP 挑一家同地区的门店去 -- precreate。挑店读的就是下面这两列(与 HarRegionCatalog 的 GB/T 2260 编码对上), -- 所以它们既是「发上游的必填」,也是「我们自己路由的键」。 -- -- 列宽 16 取自规范。两列**都不加 NOT NULL**:见下面那条「存量补不上」。 -- -- ── ⚠ 存量门店补不上,只能重开 ──────────────────────────────────────── -- 上游**没有**门店查询/更新接口(见 V1.8 建表处注释与 HarShopEntity 的 javadoc) -- ⇒ 2026-10-08 之前建的门店,这两列永远是 NULL,无法回填。 -- 它们在挑店时会被当成「地区不匹配」而**落选** —— 这是刻意的:宁可拒收,不可把 -- 顾客导到异地门店(那正是这套东西要规避的风控)。 -- 换句话说:**存量门店从本脚本执行起就不再能用于收款链接收款**,要收款得重新建店 -- (换一个新的 third_shop_id)。 -- -- ── ⚠ 顺序:先执行本脚本,再部署代码 ────────────────────────────────── -- 反了的话不是「静默降级」而是**直接报错**:实体带上这两列后,门店列表与挑店 -- 的每一句 SELECT 都会取这两列,列不存在 ⇒ 门店列表 500、且**每一笔收款链接下单 -- 都失败**。顺序不能反。 -- -- ── 执行 ───────────────────────────────────────────────────────────── ALTER TABLE pay_har_shop ADD COLUMN IF NOT EXISTS province_code varchar(16); ALTER TABLE pay_har_shop ADD COLUMN IF NOT EXISTS city_code varchar(16); COMMENT ON COLUMN pay_har_shop.province_code IS 'GB/T 2260 六位省码(320000=江苏省)。发上游 province_code(必填),也是按顾客 IP 挑店的匹配键。2026-10-08 之前建的门店为空,且无法回填'; COMMENT ON COLUMN pay_har_shop.city_code IS 'GB/T 2260 六位市码(320100=南京市)。发上游 city_code(必填),见 province_code'; -- ── 短码订正(2026-10-09)────────────────────────────────────────────── -- 2026-10-08 到 10-09 之间用旧代码建出的门店,这两列存的是数据集短码(32 / 3201)。 -- 目录换成六位后它们会**静默落选**(挑店按字符串精确比对),所以在这里补零订正。 -- 幂等:已经六位的行(length >= 6)与 NULL 行(老店,见上面「存量补不上」)都不动, -- 重跑本脚本不会改坏任何一行。HAR 未上线,这段实际只影响测试环境已建的店。 UPDATE pay_har_shop SET province_code = rpad(province_code, 6, '0') WHERE province_code IS NOT NULL AND length(province_code) < 6; UPDATE pay_har_shop SET city_code = rpad(city_code, 6, '0') WHERE city_code IS NOT NULL AND length(city_code) < 6; -- 挑店那句查询按 merchant_code 过滤(租户谓词由拦截器另加)—— 它在收款链接的 -- **每一笔支付**上执行,给个索引免得随门店铺开变成顺扫。 CREATE INDEX IF NOT EXISTS idx_har_shop_merchant_code ON pay_har_shop (merchant_code); -- ── 只读核对(执行后跑)────────────────────────────────────────────── -- ① 列在不在、宽对不对 -- SELECT column_name, data_type, character_maximum_length, is_nullable -- FROM information_schema.columns -- WHERE table_name = 'pay_har_shop' AND column_name IN ('province_code','city_code'); -- 期望:两行,16,YES -- -- ② 索引在不在 -- SELECT indexname FROM pg_indexes -- WHERE tablename = 'pay_har_shop' AND indexname = 'idx_har_shop_merchant_code'; -- 期望:一行 -- -- ③ ★ 有多少存量门店会因缺地区而落选(记下这个数字,它就是要重开的店数) -- SELECT count(*) AS 缺地区的店 FROM pay_har_shop -- WHERE province_code IS NULL OR city_code IS NULL; -- -- ④ ★ 「短码订正」段跑完不该再有短码(期望 0 —— 非 0 就是 UPDATE 没跑到) -- SELECT count(*) AS 剩余短码 FROM pay_har_shop -- WHERE (province_code IS NOT NULL AND length(province_code) < 6) -- OR (city_code IS NOT NULL AND length(city_code) < 6);