微信小店数据交互与安全架构:从API设计到高并发实战

📅 2026/7/6 8:55:13
微信小店数据交互与安全架构:从API设计到高并发实战
1. 项目概述从“开店”到“守店”的认知跃迁很多朋友在搭建微信小店时往往把精力都放在了前端页面的设计和后台功能的堆砌上觉得把商品挂上去、能下单支付就算大功告成了。这其实是一个巨大的误区。真正决定一个小店能否长期稳定运营、能否赢得用户信任的恰恰是那些看不见摸不着的“里子”——数据如何安全、高效地流动以及整个系统如何抵御风险。今天我们就来深挖微信小店搭建中最核心也最容易被忽视的部分数据交互机制与安全保障体系。这不仅是技术实现更是经营思维的体现。当你点击小店里的一个“立即购买”按钮时背后发生了什么用户的地址、电话、支付信息如何在你的服务器、微信平台和第三方服务比如物流之间穿梭而不被泄露或篡改你的后台数据库如何应对突然涌入的订单洪流这些问题的答案共同构成了小店的“生命线”。理解这套机制不仅能让你在技术选型时无论是用原生开发、SaaS工具还是基于Django、Java等框架自研做出更明智的决策更能让你以“产品负责人”而非“单纯开发者”的视角去构建一个真正可靠、值得托付的电商业务。接下来我将结合常见的实现路径为你拆解这条生命线的每一个关键环节。2. 核心架构与数据流全景解析要理解数据交互首先得看清全局。一个典型的微信小店这里指功能完备的自研或深度定制型小店而非简单模板其数据流并非单向或简单的双向而是一个涉及多终端、多角色的复杂网络。2.1 核心参与角色与数据边界我们可以把整个系统抽象为四个核心角色它们之间的数据交互构成了小店的基础用户微信客户端这是交互的起点和终点。用户通过微信内的小程序或H5页面浏览商品、下单支付。从这里发出的数据最敏感的就是用户的openid微信用户在当前小程序的唯一标识、formId用于发送模板消息、以及后续的支付凭据。微信官方接口层这是腾讯提供的“中间人”和“规则制定者”。所有与微信用户身份、支付、消息、物流等相关的敏感操作都必须通过调用微信的服务器端API来完成。你的服务器不能直接操作用户的微信数据必须通过这里中转。例如获取用户手机号你需要将前端传来的code送到微信接口换取。开发者业务服务器这是你的“大脑”和“记忆中枢”。它用你熟悉的语言如Python/Django、Java/Spring Boot、Node.js等编写部署在你自己的或云端的服务器上。它负责处理核心业务逻辑管理商品库存、生成订单、计算价格、调用微信支付统一下单接口、与物流API对接、并将最终结果写入数据库。业务数据库与外部服务这是你的“仓库”。数据库如MySQL、PostgreSQL持久化存储商品、订单、用户非微信敏感信息等数据。外部服务则包括支付渠道虽然微信支付是主流但可能整合其他、物流查询API如快递鸟、短信服务等。注意这里有一个至关重要的安全原则——最小化数据持有。你的业务服务器和数据库绝对不应该存储用户的微信密码、支付密码等最高机密信息。你存储的应该是经过微信接口授权后获得的、脱敏后的业务标识如openid和你自己生成的业务数据如订单号、收货地址。2.2 一次完整下单的数据流追踪让我们以用户从浏览到完成支付的经典路径看看数据是如何在上述角色间流动的页面加载与商品展示用户端打开小程序请求商品列表页。你的服务器接收到请求通常携带了小程序前端通过wx.login获取的code用于后续换取openid以识别用户从数据库中查询商品信息状态为上架、库存大于0等将数据JSON格式返回给前端。数据特点此阶段主要是读多写少对实时性要求高。优化方向常在于数据库查询优化索引、引入Redis缓存热门商品数据。提交订单用户端用户填写收货地址、选择商品规格点击“提交订单”。前端会将商品ID、数量、收货地址信息、以及用户的openid或用于换取openid的code打包成一个请求体。你的服务器校验首先进行风控和安全校验如用户是否频繁提交商品库存是否还充足价格是否被篡改。这里会用到前端传来的openid来识别用户。创建订单校验通过后在数据库中生成一条订单记录状态为“待支付”。关键一步生成一个你自己系统内唯一的订单号通常推荐用时间戳随机数或雪花算法ID这个订单号将贯穿整个支付流程。调用微信支付使用这个订单号、总金额单位分、商品描述等信息加上你的微信支付商户密钥调用微信支付的“统一下单”API。返回支付参数微信支付接口会返回一个prepay_id预支付交易会话标识及其他生成支付签名所需的参数。你的服务器将这些参数组合、再次签名后返回给前端。数据特点进入核心事务区。数据库操作必须保证一致性如扣减库存和创建订单需在一个数据库事务中避免超卖。与微信API的交互必须保证幂等性即同一订单号重复请求微信端应返回相同结果防止重复扣款。发起支付用户端收到服务器返回的支付参数调用微信小程序的wx.requestPayment()接口唤起微信支付弹窗。微信支付系统用户输入密码或验证指纹完成支付。支付结果首先由微信支付后台异步通知到你的服务器回调地址你在统一下单时设置而不是依赖前端返回。支付结果异步通知与处理你的服务器必须提供一个公网可访问的API端点如/api/payment/notify用于接收微信支付后台发送的XML格式通知。此通知包含支付结果、订单号、微信支付订单号等。关键操作验证签名首先必须用你的商户密钥验证通知的签名确认消息确实来自微信防止伪造支付成功通知。处理业务验证通过后根据微信支付订单号或商户订单号更新你数据库中对应订单的状态为“已支付”并执行后续逻辑如增加销量、发送模板消息通知用户等。返回成功处理完成后必须返回一个特定的XML成功响应给微信否则微信会认为通知失败在一段时间内重复发送通知。数据特点异步、可靠、需幂等。你的通知处理接口必须能处理重复的通知通过检查订单状态是否已更新并且处理速度要快以免微信端超时。订单状态同步前端在支付完成后通常会轮询或通过WebSocket从你的服务器获取订单的最新状态。你的服务器根据数据库中的状态进行响应。这套流程清晰地区分了前端交互、后端逻辑、微信网关各自的职责是安全稳定数据交互的基石。3. 安全保障体系深度剖析如果说数据流是血脉那么安全体系就是免疫系统。微信小店面临的安全挑战主要来自三个方面数据泄露、业务欺诈和服务攻击。下面我们分层构建防御体系。3.1 通信链路安全全链路HTTPS与签名机制这是第一道也是最基本的防线。强制HTTPS你的业务服务器域名必须配置SSL证书确保所有前端小程序到后端的数据传输都是加密的。微信小程序平台也强制要求网络请求必须为HTTPS。这防止了数据在传输过程中被窃听或篡改。API请求签名对于重要的业务接口尤其是涉及状态变更的如提交订单、修改库存不能仅靠HTTPS。你需要设计一套签名机制。原理服务器为每个客户端或用户分配一个AppKey和AppSecret或利用用户的登录令牌。客户端在发起请求时将请求参数排除sign本身按特定规则如按参数名ASCII排序拼接成字符串再加上AppSecret通过MD5或HMAC-SHA256等算法生成一个签名sign将sign放入请求头或参数中。服务器端收到请求后用同样的规则和AppSecret重新计算签名与客户端传来的sign对比。不一致则拒绝请求。作用防止参数被篡改因为改参数会导致签名对不上也一定程度上验证了请求来源的合法性。3.2 身份认证与授权细粒度的访问控制用户身份是权限控制的基础。微信体系给我们提供了便利但也需要正确使用。基于openid的会话管理用户登录小程序后通过wx.login获取code传给你的服务器。你的服务器用code、你的小程序AppID和AppSecret调用微信接口换取session_key和openid。关键决策session_key是微信端的会话密钥绝不能传到客户端你的服务器应该用这个openid或者结合其他信息生成一个自定义的token如JWT作为该用户在你系统中的身份标识返回给前端一个自定义的登录态令牌比如一个UUID。前端后续请求都携带这个令牌你的服务器通过令牌映射回openid从而识别用户。敏感信息解密当需要获取用户手机号等敏感信息时前端通过button open-typegetPhoneNumber获取加密数据encryptedData和初始向量iv。前端将这两个参数和之前的code传给服务器。服务器用之前换取的、保存在服务端内存或缓存如Redis中的该用户的session_key对encryptedData进行AES解密才能得到明文手机号。实操心得session_key可能会失效用户长时间不操作或微信端主动更新所以解密失败时需要引导用户重新登录获取新的code和session_key。建议将session_key与openid关联存储在Redis中并设置一个合理的过期时间如2小时。接口权限控制不是所有接口都对所有用户开放。例如查询订单列表的接口必须校验当前请求用户的openid是否与订单中的购买者openid一致防止越权查看他人订单。管理后台的接口更需要严格的角色权限控制RBAC普通用户令牌访问时应返回403错误。3.3 数据安全与隐私保护存储与展示的学问数据安全不止于传输更在于存储和使用。数据库安全脱敏存储像用户手机号、身份证号这类信息在存储前应考虑进行部分脱敏如138****1234或加密存储。加密存储时注意使用强加密算法如AES并妥善管理加密密钥最好使用云服务商提供的密钥管理服务KMS。SQL注入防御使用ORM框架如Django的Model、MyBatis或参数化查询绝对避免手动拼接SQL字符串。这是Web安全的最基本要求但依然有大量漏洞源于此。最小权限原则连接数据库的账号应该只拥有其业务所需的最小权限通常是特定库的增删改查而不是root或DBA权限。日志与监控记录关键操作日志谁、在什么时候、做了什么、IP是什么尤其是管理员操作、支付回调、用户登录等。日志中同样要对敏感信息脱敏。建立异常监控例如同一IP短时间内大量请求登录接口、大量尝试错误订单号这可能是撞库或扫描攻击的征兆。3.4 业务安全与风控对抗恶意行为这是更高阶的安全直接关系到你的钱和货。防刷单与黄牛限流对核心接口如提交订单、领取优惠券实施限流。例如同一openid或同一IP在1分钟内只能提交一次订单。可以使用Redis的INCR和EXPIRE命令轻松实现。人机验证在关键操作前如秒杀活动开始前引入图形验证码或更智能的行为验证码增加自动化脚本的难度。规则引擎建立简单的风控规则例如新注册用户首次购买高价值商品、收货地址突然大量变更、同一设备频繁切换账号下单等这些订单可以自动标记为“待审核”转为人工处理。支付安全金额校验后端在创建订单时计算的金额必须与前端传来的金额进行比对防止前端被篡改后提交0.01元购买高价商品。异步通知可靠性如前所述支付成功与否必须以服务器收到的微信支付异步通知为准。前端wx.requestPayment的success回调仅表示用户发起了支付并成功输入了密码不代表资金已结算到账。绝对不要仅依据前端回调来更新订单状态。对账每日定时从微信支付平台拉取对账单与你数据库中的订单进行核对及时发现未正确处理的支付单或异常单如已支付但未发货这是金融级应用必须做的。4. 前后端数据交互模式实战详解理解了安全基础我们来看看具体如何实现高效、清晰的数据交互。这里以最常见的RESTful API设计为例并结合Django和Java Spring Boot的典型实现。4.1 API设计规范清晰是安全与效率的前提一套设计良好的API本身就能减少很多沟通和安全上的隐患。URL与HTTP方法GET /api/products获取商品列表。GET /api/products/{id}获取单个商品详情。POST /api/orders提交一个新订单。注意创建资源用POST。GET /api/orders?statuspaid查询订单列表可按状态过滤。PUT /api/orders/{id}/address修改订单的收货地址部分更新。避免使用GET方法执行修改操作如GET /api/order/delete?id1因为GET请求可能被浏览器预加载、日志记录不安全且不符合语义。统一响应格式{ code: 200, // 业务状态码200表示成功非200表示各类错误 message: 操作成功, // 对人友好的提示信息 data: { ... }, // 成功时返回的数据 timestamp: 1629091200000 // 服务器时间戳 }对于错误也应统一格式{ code: 40001, message: 商品库存不足, data: null, timestamp: 1629091200000 }这样前端可以统一处理响应根据code判断成功与否并提示message。参数传递与校验路径参数用于标识资源如/api/products/123。查询参数用于过滤、排序、分页如/api/orders?page1size10statuspaid。请求体用于创建或更新资源如提交订单时的商品列表、地址信息用JSON格式。后端必须校验所有输入参数包括类型、范围、必填项。Django可以使用SerializerSpring Boot可以使用Valid注解配合验证注解如NotNull,Size。4.2 Django REST Framework 实现示例Django因其“开箱即用”的特性在快速构建API后端时非常受欢迎。视图与序列化器# serializers.py - 定义订单提交的数据结构 from rest_framework import serializers class OrderCreateSerializer(serializers.Serializer): product_id serializers.IntegerField(requiredTrue) quantity serializers.IntegerField(min_value1, requiredTrue) address_id serializers.IntegerField(requiredTrue) # 注意这里不直接接收金额金额由后端根据商品计算 # views.py - 处理订单提交的视图 from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.db import transaction class OrderCreateView(APIView): authentication_classes [YourCustomAuth] # 你的自定义认证类基于token permission_classes [IsAuthenticated] # 确保用户已登录 transaction.atomic # 数据库事务保证原子性 def post(self, request): serializer OrderCreateSerializer(datarequest.data) if not serializer.is_valid(): return Response({code: 40000, message: 参数错误, data: serializer.errors}, statusstatus.HTTP_400_BAD_REQUEST) # 1. 获取当前用户 (从认证中) user_openid request.user.openid # 2. 校验商品库存使用select_for_update行锁防止超卖 product Product.objects.select_for_update().get(idserializer.validated_data[product_id]) if product.stock serializer.validated_data[quantity]: return Response({code: 40001, message: 库存不足}, statusstatus.HTTP_400_BAD_REQUEST) # 3. 创建订单记录 order Order.objects.create( user_openiduser_openid, productproduct, quantityserializer.validated_data[quantity], total_amountproduct.price * serializer.validated_data[quantity], statuspending_payment ) # 4. 扣减库存 product.stock - serializer.validated_data[quantity] product.save() # 5. 调用微信支付统一下单接口此处省略具体HTTP请求代码 # wechat_pay_result call_wechat_unifiedorder(...) # 假设返回 prepay_id 等参数 # 6. 返回前端支付所需参数 response_data { order_id: order.id, prepay_params: { ... } # 组装好的支付参数 } return Response({code: 200, message: 订单创建成功, data: response_data})实操心得在高并发场景下仅靠select_for_update和事务可能还不够还需要结合缓存如Redis进行库存预扣预减库存并在支付成功后再做最终扣减支付失败则回滚缓存库存。这能极大提升秒杀等场景的性能。认证与权限 你需要实现一个自定义的认证类从请求头如Authorization: Bearer your_token中提取令牌并验证其有效性将对应的用户对象或openid赋值给request.user。4.3 Spring Boot 实现示例Java生态以其严谨和强大的性能著称适合更复杂的企业级小店。Controller与DTO// OrderDTO.java - 数据传输对象 import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import lombok.Data; Data public class OrderDTO { NotNull(message 商品ID不能为空) private Long productId; NotNull(message 数量不能为空) Min(value 1, message 数量至少为1) private Integer quantity; NotNull(message 地址ID不能为空) private Long addressId; } // OrderController.java import org.springframework.web.bind.annotation.*; import org.springframework.validation.annotation.Validated; import javax.validation.Valid; RestController RequestMapping(/api/orders) Validated public class OrderController { Autowired private OrderService orderService; PostMapping public ResultOrderCreateVO createOrder(RequestBody Valid OrderDTO orderDTO, HttpServletRequest request) { // 1. 从请求属性中获取当前用户由拦截器或过滤器预先设置 String userOpenid (String) request.getAttribute(currentOpenid); // 2. 调用服务层处理核心业务逻辑 OrderCreateVO orderCreateVO orderService.createOrder(userOpenid, orderDTO); // 3. 返回统一结果 return Result.success(orderCreateVO); } } // Result.java - 统一响应封装 Data public class ResultT { private Integer code; private String message; private T data; private Long timestamp System.currentTimeMillis(); public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(success); result.setData(data); return result; } // ... 其他静态方法如 error }服务层与事务管理// OrderServiceImpl.java Service Slf4j public class OrderServiceImpl implements OrderService { Autowired private ProductMapper productMapper; Autowired private OrderMapper orderMapper; Autowired private RedisTemplateString, String redisTemplate; Override Transactional(rollbackFor Exception.class) // 声明式事务 public OrderCreateVO createOrder(String userOpenid, OrderDTO orderDTO) { // 1. 校验库存使用数据库悲观锁 Product product productMapper.selectForUpdate(orderDTO.getProductId()); if (product null || product.getStock() orderDTO.getQuantity()) { throw new BusinessException(ErrorCode.PRODUCT_STOCK_NOT_ENOUGH); } // 2. 创建订单 Order order new Order(); order.setUserOpenid(userOpenid); order.setProductId(orderDTO.getProductId()); order.setQuantity(orderDTO.getQuantity()); order.setTotalAmount(product.getPrice().multiply(new BigDecimal(orderDTO.getQuantity()))); order.setStatus(OrderStatusEnum.PENDING_PAYMENT.getCode()); orderMapper.insert(order); // 3. 扣减库存 int updateCount productMapper.decreaseStock(orderDTO.getProductId(), orderDTO.getQuantity()); if (updateCount 0) { // 乐观锁版本号控制或影响行数为0说明库存不足 throw new BusinessException(ErrorCode.PRODUCT_STOCK_NOT_ENOUGH); } // 4. 调用微信支付可异步化 WechatPayPrepayVO prepayVO wechatPayService.createPrepayOrder(order); // 5. 组装返回VO OrderCreateVO vo new OrderCreateVO(); vo.setOrderId(order.getId()); vo.setPrepayParams(prepayVO); return vo; } }踩坑记录在分布式环境下Transactional注解可能因为数据库连接池、方法内部调用等原因失效。更复杂的库存扣减场景需要引入分布式锁如基于Redis的Redisson或使用消息队列来串行化处理确保绝对的一致性。5. 高并发与性能优化实战策略当你的小店迎来爆单时流畅的数据交互背后是精心的性能设计。5.1 数据库层优化读写分离与缓存策略查询优化索引是王道为order表的user_openid和create_time字段建立复合索引可以极大加速“我的订单”查询。使用EXPLAIN命令分析慢查询。避免SELECT *只查询需要的字段减少网络传输和数据库负载。分页查询列表接口一定要支持分页LIMIT offset, size并且避免大偏移量offset。对于深度分页可以使用WHERE id last_id LIMIT size的方式。引入缓存Redis缓存热点数据将商品详情、首页活动配置等变化不频繁但访问量大的数据放入Redis。设置合理的过期时间如30分钟并在数据更新时主动清除或更新缓存Cache-Aside模式。# Django示例获取商品详情先查缓存 product_data cache.get(fproduct_detail_{product_id}) if not product_data: product Product.objects.get(idproduct_id) product_data serialize_product(product) # 序列化 cache.set(fproduct_detail_{product_id}, product_data, timeout1800) # 缓存30分钟 return product_data缓存库存信息在秒杀场景可以将商品库存预加载到Redis中下单时先在Redis中做原子性减操作DECR快速判断是否有库存然后再异步落库。这能扛住最初的流量洪峰。5.2 应用层优化异步化与连接池异步处理非核心链路支付成功后的后续操作如发送模板消息、更新积分、同步ERP等可以放入消息队列如RabbitMQ、RocketMQ、Kafka异步处理。这样支付回调接口能快速响应微信避免因处理耗时任务导致微信回调超时微信会重试。// Spring Boot RabbitMQ 示例 Service public class OrderService { Autowired private AmqpTemplate rabbitTemplate; public void handlePaySuccess(String orderId) { // 1. 更新订单状态为已支付核心操作必须同步且事务内完成 orderMapper.updateStatus(orderId, OrderStatusEnum.PAID); // 2. 发送异步消息处理后续非核心任务 rabbitTemplate.convertAndSend(order.exchange, order.paid, orderId); } } Component RabbitListener(queues order.paid.queue) public class OrderPaidListener { public void process(String orderId) { // 异步发送模板消息 wechatService.sendOrderPaidMsg(orderId); // 异步增加用户积分 userService.addPoints(orderId); // ... 其他耗时操作 } }合理使用连接池配置数据库连接池如HikariCP、Redis连接池避免频繁创建和销毁连接的开销。根据实际负载调整池的大小。5.3 前端交互优化减少请求与体验提升接口合并与懒加载首页可能需要商品列表、轮播图、公告等多个数据可以设计一个/api/home/init接口一次性返回所有数据减少HTTP请求数。对于商品详情页的“猜你喜欢”等次要内容可以在页面主体加载完成后再通过单独的异步请求加载。合理利用本地存储用户的购物车信息、收货地址列表等可以在前端小程序使用wx.setStorage进行本地缓存减少对后端的重复请求。提交订单时再从本地取出并提交。6. 监控、日志与问题排查实战指南系统上线后完善的监控和清晰的日志是快速定位问题的“眼睛”。6.1 关键监控指标你需要关注这些核心指标它们是小店健康度的晴雨表指标类别具体指标说明与告警阈值业务指标订单创建成功率 99.5% 需告警可能接口有bug或风控过严。支付成功率支付数/订单数低于行业平均如85%需排查可能是支付流程问题或用户放弃。库存超卖次数大于0即需立即告警是严重Bug。系统指标API接口平均响应时间P95响应时间 1秒 需关注 3秒 需告警优化。服务器CPU/内存使用率持续 80% 需扩容或优化。数据库连接数接近最大连接池数需告警。微信支付回调失败率 0.1% 需紧急处理会导致用户已付款但订单未成功。6.2 结构化日志记录不要再用System.out.println了。使用SLF4J LogbackJava或structlogPython记录结构化日志。// Java示例 Slf4j Service public class PaymentService { public void handleWechatNotify(String xmlData) { MapString, String notifyMap parseXml(xmlData); String orderId notifyMap.get(out_trade_no); log.info(收到微信支付通知订单号{}, 交易状态{}, orderId, notifyMap.get(return_code)); // ... 验证签名、处理业务 try { // 业务处理 log.info(订单{}支付成功处理完成, orderId); } catch (Exception e) { log.error(处理支付通知失败订单号{}, 异常信息, orderId, e); // 需要告警 } } }日志中要包含请求ID一个贯穿单次请求生命周期的唯一标识这样你可以在海量日志中轻松串联起一个用户请求在所有微服务间的流转路径。6.3 常见问题排查清单当出现问题时按照以下清单快速定位用户无法支付检查点1前端wx.requestPayment参数是否正确特别是timeStamp是字符串且为10位检查点2后端“统一下单”接口是否成功返回prepay_id查看后端日志和微信支付商户平台的“交易中心”。检查点3小程序后台的支付目录、授权域名配置是否正确检查点4用户微信余额是否充足是否触发了微信风控用户已付款但订单仍显示“待支付”这是最严重的问题之一检查点1立即查看微信支付回调通知日志。是否收到了通知通知的签名验证是否通过检查点2你的回调接口(/api/payment/notify)是否处理成功并正确返回了xmlreturn_code![CDATA[SUCCESS]]/return_code/xml如果返回错误或超时微信会重试。检查点3检查回调接口的业务逻辑。更新订单状态时是否因为数据库异常如死锁导致失败应急方案在商户平台手动查询此订单确认支付成功。然后通过后台管理工具手动将订单状态修正为“已支付”并补发相关消息。同时必须修复回调接口的Bug。商品超卖检查点1扣减库存的SQL语句是否在事务中是否使用了select ... for update或乐观锁机制检查点2在高并发下是否所有请求都通过了“库存0”的校验考虑在应用层Redis做库存预扣。检查点3日志中是否有重复的订单号检查生成订单号的逻辑是否在极高并发下出现了重复。接口响应缓慢检查点1使用监控工具如APM定位慢链路。是数据库慢还是外部API调用慢如微信接口、物流接口检查点2检查慢查询日志优化SQL或添加索引。检查点3检查服务器资源CPU、内存、磁盘IO是否达到瓶颈。构建一个健壮的微信小店数据交互与安全是贯穿始终的骨架与铠甲。它没有前端UI那么直观但每一次流畅的购买、每一笔安全的交易都依赖于这套机制在背后的稳定运行。从清晰的API设计到严谨的安全校验从高效的缓存策略到周密的监控告警每一个环节都需要你以工匠精神去打磨。记住技术实现的终点是业务价值而安全与稳定是这一切价值得以实现的前提。希望这篇深入原理与实践的剖析能帮你搭建起一个不仅“跑得通”更能“扛得住”、“信得过”的微信小店系统。