Files
2026-10-29 16:34:25 +08:00

17 KiB
Raw Permalink Blame History

Store.Shops 迁移说明

统一由 Controllers/ShopController.cs 暴露47个业务Action:微信39个、拼多多与微店8个。原 bxx_shop 独立控制器及重复的vdian别名已移除,原 ShopController 已重命名合并。 旧逻辑来自 KJD_WebService/BLL/BXX/BXXShopManage.cs、BLL/WXXD/WXShopManage.cs 和 BLL/WXXD/WXExpressOptimizeManage.cs。 微信店铺沿用现有实体、续费查询和被 Store.Users 引用的命名空间,补充旧表已有的 never_expires 字段。 下文先介绍拼多多/微店接口,微信完整映射和部署要求见末节。

模块内部类型、文件及方法统一不带平台前缀,后续平台通过模块区分。核心服务为 ShopService;扩展查询、详情响应和映射分别为 ShopQueryRequest、ShopDetailsInfo、ShopDetailsMapper。PddLoginShopEntity 表示导入的拼多多登录记录,PddShopEntity 保留 bxx 店铺映射。 原带平台标记的 Action 统一为 SavePddShop、UpdatePddShopLogin、DeletePddShop、GetPddShops、GetTokens、GetShopToken,客户端需同步更新路由。数据库映射、上游协议及已部署的 Shops:E57WxAccounts 配置键保持兼容。

仓储查询入口

当前仓储不使用内存缓存或 Redis。单店到期时间经 ShopQueryService → IShopRepository.GetExpireTime 读取;列表到期信息经 ShopService → IShopRepository.GetExpireTimes 一次批量查询数据库,不逐店查询。

空集合返回空结果,列表缺失到期记录按 0 处理,永久有效店铺由 Service 覆盖到期时间。列表的数据范围和跨月额度重置仍在 Service。续费沿用原有事务内 ORM 读写,不包含缓存失效管道。

本次只集中上述公共查询,没有将模块内全部 SQL 迁入 Repository。后续确需缓存时,再按查询的实时性要求实现,并覆盖事务提交后的失效路径。

调用方式

所有接口使用当前宿主认证,路由为 POST /api/v1/shop/{Action},Action采用PascalCase业务命名。 不再注册 bxx_shop、wxxd_shop 路由或旧下划线Action别名,客户端需按下表更新URL。 合并仅调整HTTP入口:读取bxx库的授权资料、店铺列表和采购备注仍使用原业务服务、权限及表映射;微店业务一并保留。 请求为 JSON DTO,字段使用 camelCase;不再发送旧版 time/code/password/obj 参数,也不再接受旧 GET 调用。 这次重写不是旧 ASMX 的无改动替换,客户端需迁移认证、URL、JSON 参数和返回值解析。 集合参数改为 JSON 数组,不再拼接逗号或 SQL 引号。

映射中的旧 action 当前 action 请求
get_pdd_client_info GetPddClients 无业务参数
get_shop_client_info GetPddShopClients ShopClientSearchRequest
e57_get_pdd_shop_token GetPddShopToken PddTokenRequest
admin_get_shop_list GetAllPddShops ShopSearchRequest
add_weidian_shop、add_vdian AddWeidianShop WeidianSaveRequest
mdy_weidian_shop、mdy_vdian UpdateWeidianShop WeidianSaveRequest
mdy_weidian_shop_cookie、mdy_vdian_cookie UpdateWeidianShopLogin WeidianCookieRequest
del_weidian_shop DeleteWeidianShop ShopIdRequest

vdian 的三个历史别名统一使用上述微店Action,不再单独暴露重复接口。 GetAllPddShops 查询bxx.shop;GetPddShops 查询wxxd.pdd_shop,两套数据不混用。 业务成功与失败由现有 ApiResult 管道包装,HTTP 200;无数据成功返回 data: null。 列表位于 data.items,总数位于 data.total。 e57 响应仅提取上游成功响应的 data,使用本系统的 code,不嵌套上游结果封套。 认证、路由等 Action 外的错误继续使用宿主现有处理机制。

新增或重复导入微店示例:

{
  "loginName": "店铺登录名",
  "shopId": "店铺ID",
  "shopAccount": "店铺名称",
  "notes": "备注"
}

更新时 shopId 定位原店铺,newShopId 修改店铺 ID; 可选字段的 null/省略表示保留原值,空串表示清空。 相同账号、登录名及店铺 ID 的重复新增转为更新。未指定店铺 ID 且登录名匹配多店时拒绝操作,防止批量误改。 Cookie 更新须提供 Cookie 或登录状态;不允许仅凭 wdToken 更新。

权限与行为

  • 管理列表要求当前账户的数据库角色为 SuperAdmin,保留原查询条件、稳定分页和每月 300 条额度重置。
  • 凭据查询仅可读取本人或明确分配给本人的店铺;管理员角色本身不扩大凭据范围。
  • 微店创建归属当前账号;本人或分配账号可更新,只有所有者能删除、修改分配账号。
  • sub_user_name 按逗号分隔的完整账号匹配,避免 owner 匹配 owner2。旧库若使用其他分隔格式,需先转换为该格式;账号之间不要带空格。
  • 管理列表不返回登录密码、Cookie、令牌。专用应用配置、店铺授权及令牌接口按其用途返回凭据,均禁止 HTTP 缓存。
  • 应用配置接口沿用已登录用户获取公共客户端配置的用途;不可把只允许服务端使用的其他应用密钥填入该配置。
  • 分配账号不能更改店铺分配关系。不存在或无权访问的资源统一报业务失败。
  • 空店铺 ID 的导入记录不创建共享额度;同一 shop_id 的登录记录共享额度。

部署

实体分别映射现有 bxx.shop、bxx.shop_api_auth、bxx.shop_add_prod_count、weidian.shop。 不自动创建或修改生产表,不迁移数据。使用现有 IFreeSql 连接,部署账号需要访问上述库。 额度和导入操作使用同一个 FreeSql 工作单元及 Serializable 隔离,失败整体回滚。 生产表应为 InnoDB;shop_add_prod_count.shop_id 应有唯一约束(旧实现的 ON DUPLICATE KEY UPDATE 已依赖该约束)。 建议确认微店 (user_name, login_name, shop_id) 与店铺 ID 查询索引,减少范围锁扫描。 按数据库原字段保留月份额度语义;跨年同月识别需要另行升级字段,未在本次改变。

通过部署配置提供 Shops:PddClients 数组;不要把真实 ClientSecret 提交到源码。 可使用环境变量:

Shops__PddClients__0__Describe
Shops__PddClients__0__ClientId
Shops__PddClients__0__ClientSecret
Shops__PddClients__0__MarketId
Shops__PddClients__0__RedirectUri
Shops__PddClients__0__IsCurrent

没有完整应用配置时接口返回明确业务错误。旧源码中的硬编码密钥未复制。 e57 使用旧实现的固定 HTTPS 地址,正常验证证书、编码 mallId,失败最多重试一次,每次超时 30 秒; 请求取消直接传递。未发送真实外部请求。 模块服务沿用 ITransientDependency;Startup 注册共享 PddTokenClient。API 通过既有程序集发现加载控制器。

验证

dotnet test Tests/Store.Shops.Tests/Store.Shops.Tests.csproj
dotnet test Tests/Store.Users.Tests/Store.Users.Tests.csproj
dotnet build Store.API/Store.API.csproj
dotnet run --project Store.API/Store.API.csproj

店铺测试使用独立临时 SQLite 库和模拟 HTTP 上游,覆盖归属/分配权限、精确账号匹配、分页、重复导入、部分更新、Cookie、删除、额度重置与回滚、上游重试,以及真实 MVC 的路由、参数绑定、统一返回和匿名拒绝。 SQLite 不验证 MySQL 范围锁、并发死锁或生产表实际结构;上线前仍需针对真实 MySQL 和 e57 联调。 可继续使用代码审查检查迁移边界和客户端适配。

微信业务Action映射

微信39项业务已合入ShopController,使用 POST /api/v1/shop/{Action};下表保留旧名字仅用于客户端迁移对照。 旧 GET/ASMX 参数、签名和密码认证不再使用;客户端使用当前宿主令牌与 JSON DTO,字段 camelCase,批量编号传数组。 无数据操作统一 ApiResult;分页结果为 data.items/data.total,支持 NotCount 的请求返回 total=-1 表示未统计。 所有响应禁用缓存。通用列表和登录名查询不输出密码、Cookie;专用 Cookie/令牌接口检查资源范围后返回必要凭据。

旧Action 当前Action 请求DTO 业务
get_shop_list GetShops ShopQueryRequest 查询本人或直属主账号分配的微信店铺
get_shop_erp_merchant GetErpMerchants ErpRequest 查询授权店铺的ERP商户余额
get_one_login_name_shop GetShopsByLoginName LoginRequest 查询登录名下的授权店铺
get_one_shop_cookie_by_app_id GetShopCookies ShopIdsRequest 批量读取授权店铺Cookie
add_shop AddShop ShopSaveRequest 主账号新增微信店铺,重复记录拒绝创建
del_shop DeleteShop LoginRequest 删除本人所属的店铺记录
mdy_shop UpdateShop ShopSaveRequest 部分更新授权微信店铺
mdy_shop_cookie_and_login_status UpdateShopLogin CookieRequest 按登录名刷新授权店铺Cookie与状态
admin_get_shop_list GetAllShops ShopQueryRequest 管理员分页查询全部店铺
sub_sa_get_select_prod_shop GetSelectionShops ShopQueryRequest 管理员按选品操作员查询店铺并刷新月度额度
update_add_prod_remaining UpdateShopQuota QuotaRequest 管理员批量设置店铺上传剩余额度
admin_mdy_shop AdminUpdateShop ShopSaveRequest 管理员修改指定账号的店铺
admin_add_shop AdminAddShop ShopSaveRequest 管理员为指定账号新增店铺
admin_del_shop AdminDeleteShop LoginRequest 管理员删除指定账号店铺
set_shop_sub_sa AssignShopOperator AssignRequest 管理员批量分配或解除选品操作员
add_waybill AddWaybill WaybillAddRequest 向当前账号导入未使用运单
del_waybill DeleteWaybills WaybillDeleteRequest 删除本人尚未预占的运单
get_waybill GetWaybills WaybillSearchRequest 分页查询本人运单
get_waybill_no_user_name GetAllWaybills WaybillSearchRequest 管理员按订单跨账号查询运单
select_and_set_waybill SelectAndUseWaybill WaybillSelectRequest 在同一事务中选择并确认使用运单
select_waybill ReserveWaybill WaybillSelectRequest 为授权订单预占运单,优先匹配绑定订单
update_used_waybill UpdateWaybillUsage WaybillUseRequest 确认使用或释放本人预占运单
add_mdy_express_optimize_rst SaveExpressOptimizeResult OptimizeResultRequest 保存授权订单物流优化结果
get_express_optimize_rst GetExpressOptimizeResults OrderSearchRequest 查询授权店铺物流优化结果
add_mdy_express_optimize_remark SaveExpressOptimizeRemark OptimizeRemarkRequest 保存或清空授权订单物流备注
get_express_optimize_remark GetExpressOptimizeRemarks OrderSearchRequest 查询授权店铺物流备注
wx_add_mdy_shop_default_address SaveShopDefaultAddress AddressRequest 维护本人的店铺默认售后地址
wx_get_shop_default_address_list GetShopDefaultAddresses AddressSearchRequest 查询本人的店铺默认地址
wx_del_shop_default_address DeleteShopDefaultAddresses ShopIdsRequest 批量删除本人的默认地址
wx_add_mdy_order_address SaveOrderAddress OrderAddressRequest 保存授权店铺订单解密地址
wx_get_order_address GetOrderAddresses OrderSearchRequest 查询授权店铺订单解密地址
wx_add_mdy_buy_url_notes SaveBuyUrlNote NoteRequest 维护当前主账号共享采购备注
wx_get_buy_url_notes GetBuyUrlNotes NoteSearchRequest 查询当前主账号共享采购备注
wx_add_mdy_29wx_pdd_shop SavePddShop PddSaveRequest 导入或更新微信业务下的拼多多店铺资料
wx_mdy_29wx_pdd_cookie_and_login_status UpdatePddShopLogin CookieRequest 刷新微信侧拼多多店铺Cookie与状态
wx_del_29wx_pdd_shop DeletePddShop LoginRequest 删除本人微信侧拼多多店铺
wx_get_29wx_pdd_shop GetPddShops ShopSearchRequest 查询授权微信侧拼多多店铺
e57_get_wx_tokens GetTokens TokenRequest 管理员读取共享微信令牌列表缓存
e57_get_wx_shop_token GetShopToken ShopIdRequest 获取授权微信店铺的e57令牌

权限与兼容性说明

  • 普通主账号查看自己的微信店铺;子账号必须同时满足父账号归属和完整账号分配匹配。账号列表用英文逗号分隔、不含空格。
  • AdminAddShop、AdminUpdateShop、AdminDeleteShop、GetAllShops、选品店铺查询、设置额度和操作员、跨账号运单查询、共享令牌列表要求数据库 SuperAdmin 角色。
  • 管理员的普通店铺、地址、单店令牌入口仍按本人的店铺范围处理;管理操作显式使用对应管理Action。
  • 管理员新增/修改/删除须传 shopUserName;普通新增仅允许主账号。微信重复新增报错;微信侧拼多多重复导入更新资料,并保留已有 Cookie。
  • 微信更新不传 shopId 时更新该登录名下授权记录;null 保留原值、空串清空。只有主账号或管理员可调整分配关系,分配对象须为直属子账号。
  • 同登录名 Cookie 更新始终限制账号范围,修复旧版跨账号同名更新问题。GetShopCookies 改传 shopIds 数组,包含无权访问的店铺时整次拒绝。
  • 默认地址仍按当前用户分别保存;订单解密地址和物流结果先限制可见店铺;采购备注由同一主账号及直属子账号共享。物流结果/备注保存必须传 shopId,不能凭订单号跨店覆盖。
  • ERP 商户只能通过授权店铺的 ERP 关联读取;公司账号展开其管理账号。结果按余额降序和记录 ID 稳定分页,total 使用真实数量,替代旧版特殊负数占位。
  • 普通店铺列表补充积分到期信息,never_expires 保留旧版有效期展示值 1893427200 且不判过期。isShowExpire 保留为兼容字段,旧实现同样未用于裁剪结果。
  • 选品模式查询两张选品表,保留每月300条共享额度重置;普通列表不触发额度重置。月份仍沿用旧字段,尚不区分跨年同月。

运单状态与事务

  • status=0 未使用、1 预占、2 已正式使用;只允许删除本人 status=0 的记录。
  • 导入要求物流公司编码、名称、运单号,且揽收时间与绑定订单至少提供一个;运单号全库去重。
  • ReserveWaybill 优先选取绑定当前订单的运单,否则仅从订单日期次日揽收、未绑定的库存随机选取;缺少订单时间时不会随意占用普通库存。
  • SelectAndUseWaybill 在同一事务内分配并使用;普通库存不要求揽收时间匹配,但不会抢占绑定其他订单的运单。
  • 分配时立即保存 shop_id,重复请求复用本人同订单已预占/使用记录;同订单不能绑定其他店铺。确认使用是幂等操作,释放只允许 status=1,不允许释放已使用运单。
  • 事务、行锁和条件更新共同保护状态变更;取消或失败释放工作单元并回滚。保留旧业务的数据库处理范围,旧版 TODO 中未实现的 e57 发货提交不被伪装为已调用。

微信部署依赖与令牌配置

除现有 wxxd.shop、wxxd.user_points_shop_expire 外,读取/写入以下旧表,不自动创建或同步结构:

  • wxxd.shop_add_prod_count、product_select、third_product_select、pdd_shop、wx_token。
  • wxxd.wx_shop_default_address、order_decrypt_address、express_optimize、express_optimize_rst、express_optimize_remark。
  • bxx.product_buy_url_notes;erp.o_shop、o_shop_group、o_user_account。

相关库需由现有 IFreeSql 连接访问。写表应使用 InnoDB;核对 shop_id、user_name/login_name/shop_id、waybill_id、user_name/order_id/status 及业务键查询索引,避免 Serializable 范围锁扩大扫描。 保留旧表已有的唯一约束;本次不执行任何生产 DDL。旧的无 shop_id 物流结果记录需要补齐真实归属后才会出现在普通用户查询中。

共享微信令牌缓存每60分钟刷新一次,e57账号由部署配置提供,例如环境变量 Shops__E57WxAccounts__1 对应 dbId=1;多个分组分别配置各自 ID。 不再硬编码旧测试账号。单店令牌复用 e57 HTTPS info?appId= 接口;共享列表使用 list?userName=,只接受 code=0 的结果。 缓存写入使用实际 dbId,同时更新 mdy_time;有效缓存可直接读取,过期或损坏缓存刷新失败时返回业务错误。 现有 PddTokenClient 扩展为共享 e57 客户端,保留拼多多入口签名和已有注册方式,不新增网络依赖。

本次验证边界

按用户要求,本次合并不新增、不运行测试;仅同步已有HTTP测试的路由、Action和服务注册,进行模块/API构建、Action命名及diff检查。 以前执行的店铺测试不能作为此次路由变更后的测试结论。 未连接真实 MySQL 或 e57;数据库结构、范围锁并发以及客户端调用仍需部署环境联调。可继续进行代码审查。