<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>万邦api博客</title><link>https://www.alexob.com/</link><description>Good Luck To You!</description><item><title>《二手ERP对接常见6大坑：时区/税价/并发超卖/编码冲突/字段映射/消息丢失》（附Python源码）</title><link>https://www.alexob.com/?id=546</link><description>&lt;h1&gt;《二手ERP对接常见6大坑：时区/税价/并发超卖/编码冲突/字段映射/消息丢失》（附Python源码）&lt;/h1&gt;&lt;div class=&quot;ybc-p&quot;&gt;先拍结论：&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;这六个坑每一个都真实炸过线上系统&lt;/strong&gt;：时区不对导致凌晨订单日期错位、税价不含税导致利润算亏、并发超卖导致一台iPhone卖两个人、编码冲突导致标题乱码、字段映射遗漏导致商品信息残缺、消息丢失导致订单消失。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;每个坑都有标准解法&lt;/strong&gt;——不是靠人肉盯，是靠代码防御。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;一、六大坑速览&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;#&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;症状&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;解法&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;1&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;时区&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;凌晨订单日期错位、对账永远差几小时&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;统一 UTC 存储，展示时转本地&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;2&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;税价&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;利润算错、财务对不上&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;分离 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;price_excl_tax&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;tax&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;price_incl_tax&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;3&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;并发超卖&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;一台手机卖给两个人&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;乐观锁 + 库存预占 + 最终一致性&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;4&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;编码冲突&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;日文/中文标题乱码、emoji 截断&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;统一 UTF-8 MB4，入库前清理&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;5&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;字段映射&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;闲鱼 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;item_price&lt;/code&gt; → Mercari 叫 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;unitPrice&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;显式映射表 + 单元测试&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;6&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;消息丢失&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;订单消失、退款没处理&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;幂等消费 + 本地消息表 + 对账兜底&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;二、完整源码：六大坑的防御代码&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;six_pits.py
&amp;quot;&amp;quot;&amp;quot;
二手ERP对接六大坑防御代码
-&amp;nbsp;时区:&amp;nbsp;TimezoneNormalizer
-&amp;nbsp;税价:&amp;nbsp;TaxPriceModel
-&amp;nbsp;并发超卖:&amp;nbsp;OptimisticLockInventory
-&amp;nbsp;编码:&amp;nbsp;EncodingSanitizer
-&amp;nbsp;字段映射:&amp;nbsp;FieldMappingValidator
-&amp;nbsp;消息丢失:&amp;nbsp;MessageReliabilityGuard
&amp;quot;&amp;quot;&amp;quot;
import&amp;nbsp;time
import&amp;nbsp;uuid
import&amp;nbsp;json
import&amp;nbsp;threading
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional,&amp;nbsp;Tuple,&amp;nbsp;Set
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime,&amp;nbsp;timezone,&amp;nbsp;timedelta
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum


#&amp;nbsp;====================&amp;nbsp;坑1:&amp;nbsp;时区&amp;nbsp;====================
class&amp;nbsp;TimezoneNormalizer:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;统一&amp;nbsp;UTC&amp;nbsp;存储，展示时转本地
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;规则:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;所有平台时间戳落地前转&amp;nbsp;UTC
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;数据库字段统一&amp;nbsp;TIMESTAMP&amp;nbsp;WITH&amp;nbsp;TIME&amp;nbsp;ZONE
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;展示时按用户偏好转本地
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;对账窗口用&amp;nbsp;UTC&amp;nbsp;计算
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PLATFORM_TIMEZONES&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;taobao&amp;quot;:&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;jingdong&amp;quot;:&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;pdd&amp;quot;:&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;&amp;quot;Asia/Tokyo&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket&amp;quot;:&amp;nbsp;&amp;quot;Europe/Paris&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;ebay&amp;quot;:&amp;nbsp;&amp;quot;America/Los_Angeles&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;vinted&amp;quot;:&amp;nbsp;&amp;quot;Europe/Berlin&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;to_utc(platform_ts:&amp;nbsp;str,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;fmt:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;%Y-%m-%d&amp;nbsp;%H:%M:%S&amp;quot;)&amp;nbsp;-&amp;gt;&amp;nbsp;datetime:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;平台时间&amp;nbsp;→&amp;nbsp;UTC
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Example:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;2026-09-19&amp;nbsp;23:59:59&amp;quot;&amp;nbsp;(Mercari)&amp;nbsp;→&amp;nbsp;UTC+9&amp;nbsp;→&amp;nbsp;2026-09-19&amp;nbsp;14:59:59&amp;nbsp;UTC
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tz_name&amp;nbsp;=&amp;nbsp;TimezoneNormalizer.PLATFORM_TIMEZONES.get(platform,&amp;nbsp;&amp;quot;UTC&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;简化:&amp;nbsp;用固定偏移模拟
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;offsets&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;:&amp;nbsp;8,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Asia/Tokyo&amp;quot;:&amp;nbsp;9,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Europe/Paris&amp;quot;:&amp;nbsp;1,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;America/Los_Angeles&amp;quot;:&amp;nbsp;-7,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Europe/Berlin&amp;quot;:&amp;nbsp;1,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;offset&amp;nbsp;=&amp;nbsp;offsets.get(tz_name,&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;naive&amp;nbsp;=&amp;nbsp;datetime.strptime(platform_ts,&amp;nbsp;fmt)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;local&amp;nbsp;=&amp;nbsp;naive&amp;nbsp;-&amp;nbsp;timedelta(hours=offset)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;local.replace(tzinfo=timezone.utc)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;to_local(utc_dt:&amp;nbsp;datetime,&amp;nbsp;tz_name:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;UTC&amp;nbsp;→&amp;nbsp;本地展示&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;offsets&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;:&amp;nbsp;8,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Asia/Tokyo&amp;quot;:&amp;nbsp;9,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Europe/Paris&amp;quot;:&amp;nbsp;1,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;America/Los_Angeles&amp;quot;:&amp;nbsp;-7,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;offset&amp;nbsp;=&amp;nbsp;offsets.get(tz_name,&amp;nbsp;8)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;local&amp;nbsp;=&amp;nbsp;utc_dt&amp;nbsp;+&amp;nbsp;timedelta(hours=offset)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;local.strftime(&amp;quot;%Y-%m-%d&amp;nbsp;%H:%M:%S&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;validate_window(platform:&amp;nbsp;str,&amp;nbsp;since:&amp;nbsp;str,&amp;nbsp;until:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;Tuple[datetime,&amp;nbsp;datetime]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;校验对账窗口是否跨时区正确&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;utc_since&amp;nbsp;=&amp;nbsp;TimezoneNormalizer.to_utc(since,&amp;nbsp;platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;utc_until&amp;nbsp;=&amp;nbsp;TimezoneNormalizer.to_utc(until,&amp;nbsp;platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;utc_until&amp;nbsp;&amp;lt;=&amp;nbsp;utc_since:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise&amp;nbsp;ValueError(f&amp;quot;对账窗口无效:&amp;nbsp;since={since}&amp;nbsp;&amp;gt;=&amp;nbsp;until={until}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;utc_since,&amp;nbsp;utc_until


#&amp;nbsp;====================&amp;nbsp;坑2:&amp;nbsp;税价&amp;nbsp;====================
@dataclass
class&amp;nbsp;TaxPriceModel:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;统一税价模型
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;规则:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;所有价格落地时分拆:&amp;nbsp;税前价&amp;nbsp;/&amp;nbsp;税额&amp;nbsp;/&amp;nbsp;税后价
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;税率按平台+品类配置
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;对账/利润计算用税前价
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price_excl_tax:&amp;nbsp;float&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;税前价（商品本身价格）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tax_rate:&amp;nbsp;float&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;税率&amp;nbsp;(0.0&amp;nbsp;~&amp;nbsp;1.0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;CNY&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price_incl_tax:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0&amp;nbsp;&amp;nbsp;#&amp;nbsp;税后价
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tax_amount:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;税额

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__post_init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.tax_amount&amp;nbsp;=&amp;nbsp;round(self.price_excl_tax&amp;nbsp;*&amp;nbsp;self.tax_rate,&amp;nbsp;2)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.price_incl_tax&amp;nbsp;=&amp;nbsp;round(self.price_excl_tax&amp;nbsp;+&amp;nbsp;self.tax_amount,&amp;nbsp;2)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;from_platform(platform:&amp;nbsp;str,&amp;nbsp;raw_price:&amp;nbsp;float,&amp;nbsp;category:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;)&amp;nbsp;-&amp;gt;&amp;nbsp;&amp;quot;TaxPriceModel&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;按平台+品类确定税率&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tax_rates&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;0.0,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;闲鱼个人卖家通常不含税
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;taobao&amp;quot;:&amp;nbsp;0.13,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;淘宝企业店13%增值税
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;jingdong&amp;quot;:&amp;nbsp;0.13,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;pdd&amp;quot;:&amp;nbsp;0.0,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;拼多多个人卖家
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;0.08,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Mercari&amp;nbsp;JP&amp;nbsp;消费税8%
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket&amp;quot;:&amp;nbsp;0.16,&amp;nbsp;&amp;nbsp;#&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;FR&amp;nbsp;增值税16%
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;ebay_us&amp;quot;:&amp;nbsp;0.0,&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;eBay&amp;nbsp;US&amp;nbsp;各州不同，简化
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rate&amp;nbsp;=&amp;nbsp;tax_rates.get(platform,&amp;nbsp;0.0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;TaxPriceModel(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price_excl_tax=raw_price,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tax_rate=rate,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=&amp;quot;CNY&amp;quot;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;in&amp;nbsp;(&amp;quot;xianyu&amp;quot;,&amp;quot;taobao&amp;quot;,&amp;quot;jingdong&amp;quot;,&amp;quot;pdd&amp;quot;)&amp;nbsp;else&amp;nbsp;&amp;quot;JPY&amp;quot;&amp;nbsp;if&amp;nbsp;platform==&amp;quot;mercari&amp;quot;&amp;nbsp;else&amp;nbsp;&amp;quot;EUR&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;profit_base(self)&amp;nbsp;-&amp;gt;&amp;nbsp;float:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;利润计算用税前价&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.price_excl_tax


#&amp;nbsp;====================&amp;nbsp;坑3:&amp;nbsp;并发超卖&amp;nbsp;====================
class&amp;nbsp;OptimisticLockInventory:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;乐观锁库存管理
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;规则:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;扣库存时带&amp;nbsp;version&amp;nbsp;条件
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;失败则重试（最多3次）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;下单时预占库存，支付成功才扣减
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;超时未支付释放预占
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._lock&amp;nbsp;=&amp;nbsp;threading.Lock()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._inventory:&amp;nbsp;Dict[str,&amp;nbsp;dict]&amp;nbsp;=&amp;nbsp;{}&amp;nbsp;&amp;nbsp;#&amp;nbsp;sku&amp;nbsp;-&amp;gt;&amp;nbsp;{&amp;quot;qty&amp;quot;:&amp;nbsp;int,&amp;nbsp;&amp;quot;version&amp;quot;:&amp;nbsp;int,&amp;nbsp;&amp;quot;reserved&amp;quot;:&amp;nbsp;int}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._reservations:&amp;nbsp;Dict[str,&amp;nbsp;Set[str]]&amp;nbsp;=&amp;nbsp;{}&amp;nbsp;&amp;nbsp;#&amp;nbsp;sku&amp;nbsp;-&amp;gt;&amp;nbsp;set&amp;nbsp;of&amp;nbsp;reservation_ids

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;init_sku(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;qty:&amp;nbsp;int):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._inventory[sku]&amp;nbsp;=&amp;nbsp;{&amp;quot;qty&amp;quot;:&amp;nbsp;qty,&amp;nbsp;&amp;quot;version&amp;quot;:&amp;nbsp;1,&amp;nbsp;&amp;quot;reserved&amp;quot;:&amp;nbsp;0}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;reserve(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;qty:&amp;nbsp;int,&amp;nbsp;reservation_id:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;预占库存（下单时调用）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;返回是否成功
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;reservation_id:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reservation_id&amp;nbsp;=&amp;nbsp;str(uuid.uuid4())

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv&amp;nbsp;=&amp;nbsp;self._inventory.get(sku)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;inv:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;available&amp;nbsp;=&amp;nbsp;inv[&amp;quot;qty&amp;quot;]&amp;nbsp;-&amp;nbsp;inv[&amp;quot;reserved&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;available&amp;nbsp;&amp;lt;&amp;nbsp;qty:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv[&amp;quot;reserved&amp;quot;]&amp;nbsp;+=&amp;nbsp;qty
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;sku&amp;nbsp;not&amp;nbsp;in&amp;nbsp;self._reservations:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._reservations[sku]&amp;nbsp;=&amp;nbsp;set()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._reservations[sku].add(reservation_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;confirm(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;qty:&amp;nbsp;int,&amp;nbsp;reservation_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;确认扣减（支付成功时调用）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;乐观锁：带&amp;nbsp;version&amp;nbsp;条件更新
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv&amp;nbsp;=&amp;nbsp;self._inventory.get(sku)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;inv:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;检查预占是否存在
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;self._reservations&amp;nbsp;and&amp;nbsp;reservation_id&amp;nbsp;not&amp;nbsp;in&amp;nbsp;self._reservations[sku]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;乐观锁：扣减时检查&amp;nbsp;version
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current_version&amp;nbsp;=&amp;nbsp;inv[&amp;quot;version&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;inv[&amp;quot;qty&amp;quot;]&amp;nbsp;&amp;lt;&amp;nbsp;qty:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;模拟&amp;nbsp;CAS&amp;nbsp;操作
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv[&amp;quot;qty&amp;quot;]&amp;nbsp;-=&amp;nbsp;qty
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv[&amp;quot;reserved&amp;quot;]&amp;nbsp;-=&amp;nbsp;qty
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv[&amp;quot;version&amp;quot;]&amp;nbsp;+=&amp;nbsp;1

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;清除预占记录
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;self._reservations:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._reservations[sku].discard(reservation_id)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;release_reservation(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;reservation_id:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;释放预占（超时/取消时调用）&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv&amp;nbsp;=&amp;nbsp;self._inventory.get(sku)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;inv:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;self._reservations&amp;nbsp;and&amp;nbsp;reservation_id&amp;nbsp;in&amp;nbsp;self._reservations[sku]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv[&amp;quot;reserved&amp;quot;]&amp;nbsp;-=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._reservations[sku].discard(reservation_id)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_available(self,&amp;nbsp;sku:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;int:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv&amp;nbsp;=&amp;nbsp;self._inventory.get(sku)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;inv:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;inv[&amp;quot;qty&amp;quot;]&amp;nbsp;-&amp;nbsp;inv[&amp;quot;reserved&amp;quot;]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_snapshot(self,&amp;nbsp;sku:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv&amp;nbsp;=&amp;nbsp;self._inventory.get(sku)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;inv:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;qty&amp;quot;:&amp;nbsp;0,&amp;nbsp;&amp;quot;reserved&amp;quot;:&amp;nbsp;0,&amp;nbsp;&amp;quot;available&amp;quot;:&amp;nbsp;0,&amp;nbsp;&amp;quot;version&amp;quot;:&amp;nbsp;0}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;qty&amp;quot;:&amp;nbsp;inv[&amp;quot;qty&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;reserved&amp;quot;:&amp;nbsp;inv[&amp;quot;reserved&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;available&amp;quot;:&amp;nbsp;inv[&amp;quot;qty&amp;quot;]&amp;nbsp;-&amp;nbsp;inv[&amp;quot;reserved&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;version&amp;quot;:&amp;nbsp;inv[&amp;quot;version&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}


#&amp;nbsp;====================&amp;nbsp;坑4:&amp;nbsp;编码冲突&amp;nbsp;====================
class&amp;nbsp;EncodingSanitizer:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;编码清洗器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;规则:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;统一&amp;nbsp;UTF-8&amp;nbsp;MB4（支持&amp;nbsp;emoji）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;入库前清理控制字符
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;平台限制检查（闲鱼标题30字）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;特殊字符替换（™→(TM),&amp;nbsp;®→(R)）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PLATFORM_LIMITS&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;{&amp;quot;max_title&amp;quot;:&amp;nbsp;30,&amp;nbsp;&amp;quot;max_desc&amp;quot;:&amp;nbsp;500},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;taobao&amp;quot;:&amp;nbsp;{&amp;quot;max_title&amp;quot;:&amp;nbsp;60,&amp;nbsp;&amp;quot;max_desc&amp;quot;:&amp;nbsp;2000},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;jingdong&amp;quot;:&amp;nbsp;{&amp;quot;max_title&amp;quot;:&amp;nbsp;75,&amp;nbsp;&amp;quot;max_desc&amp;quot;:&amp;nbsp;1500},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;pdd&amp;quot;:&amp;nbsp;{&amp;quot;max_title&amp;quot;:&amp;nbsp;40,&amp;nbsp;&amp;quot;max_desc&amp;quot;:&amp;nbsp;1000},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;{&amp;quot;max_title&amp;quot;:&amp;nbsp;50,&amp;nbsp;&amp;quot;max_desc&amp;quot;:&amp;nbsp;1400},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket&amp;quot;:&amp;nbsp;{&amp;quot;max_title&amp;quot;:&amp;nbsp;55,&amp;nbsp;&amp;quot;max_desc&amp;quot;:&amp;nbsp;2000},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;clean(text:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;清洗不可见字符和控制字符&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleaned&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;ch&amp;nbsp;in&amp;nbsp;text:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cp&amp;nbsp;=&amp;nbsp;ord(ch)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;保留:&amp;nbsp;空格、可见字符、emoji
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;cp&amp;nbsp;==&amp;nbsp;0x20&amp;nbsp;or&amp;nbsp;(cp&amp;nbsp;&amp;gt;=&amp;nbsp;0x21&amp;nbsp;and&amp;nbsp;cp&amp;nbsp;&amp;lt;=&amp;nbsp;0x10FFFF):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;排除控制字符
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;cp&amp;nbsp;not&amp;nbsp;in&amp;nbsp;range(0x00,&amp;nbsp;0x20)&amp;nbsp;and&amp;nbsp;cp&amp;nbsp;!=&amp;nbsp;0x7F:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleaned.append(ch)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;&amp;quot;.join(cleaned)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;replace_special(text:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;替换平台不支持的符号&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;replacements&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;™&amp;quot;:&amp;nbsp;&amp;quot;(TM)&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;®&amp;quot;:&amp;nbsp;&amp;quot;(R)&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;©&amp;quot;:&amp;nbsp;&amp;quot;(C)&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;—&amp;quot;:&amp;nbsp;&amp;quot;-&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;–&amp;quot;:&amp;nbsp;&amp;quot;-&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;…&amp;quot;:&amp;nbsp;&amp;quot;...&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;•&amp;quot;:&amp;nbsp;&amp;quot;*&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;old,&amp;nbsp;new&amp;nbsp;in&amp;nbsp;replacements.items():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text&amp;nbsp;=&amp;nbsp;text.replace(old,&amp;nbsp;new)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;text

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;truncate(text:&amp;nbsp;str,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;field:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;title&amp;quot;)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;按平台限制截断&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;limits&amp;nbsp;=&amp;nbsp;EncodingSanitizer.PLATFORM_LIMITS.get(platform,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_len&amp;nbsp;=&amp;nbsp;limits.get(f&amp;quot;max_{field}&amp;quot;,&amp;nbsp;1000)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;len(text)&amp;nbsp;&amp;gt;&amp;nbsp;max_len:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;text[:max_len&amp;nbsp;-&amp;nbsp;3]&amp;nbsp;+&amp;nbsp;&amp;quot;...&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;text

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;sanitize_for_platform(text:&amp;nbsp;str,&amp;nbsp;platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;Tuple[str,&amp;nbsp;List[str]]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;全流程清洗，返回(清洗后文本,&amp;nbsp;警告列表)&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warnings&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;original_len&amp;nbsp;=&amp;nbsp;len(text)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;清洗控制字符
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text&amp;nbsp;=&amp;nbsp;EncodingSanitizer.clean(text)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;len(text)&amp;nbsp;!=&amp;nbsp;original_len:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warnings.append(f&amp;quot;移除了&amp;nbsp;{original_len&amp;nbsp;-&amp;nbsp;len(text)}&amp;nbsp;个控制字符&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;替换特殊符号
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text&amp;nbsp;=&amp;nbsp;EncodingSanitizer.replace_special(text)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;按平台截断
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;truncated&amp;nbsp;=&amp;nbsp;EncodingSanitizer.truncate(text,&amp;nbsp;platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;len(truncated)&amp;nbsp;&amp;lt;&amp;nbsp;len(text):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warnings.append(f&amp;quot;标题过长:&amp;nbsp;{len(text)}&amp;nbsp;&amp;gt;&amp;nbsp;{EncodingSanitizer.PLATFORM_LIMITS.get(platform,{}).get(&amp;#39;max_title&amp;#39;,&amp;nbsp;1000)}，已截断&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;truncated,&amp;nbsp;warnings


#&amp;nbsp;====================&amp;nbsp;坑5:&amp;nbsp;字段映射&amp;nbsp;====================
class&amp;nbsp;FieldMappingValidator:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;字段映射校验器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;规则:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;每个平台有显式映射表
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;映射表覆盖所有必填字段
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;每次对接新平台前跑单元测试
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;映射遗漏自动告警
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;REQUIRED_FIELDS&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;product&amp;quot;:&amp;nbsp;[&amp;quot;sku&amp;quot;,&amp;nbsp;&amp;quot;title&amp;quot;,&amp;nbsp;&amp;quot;price&amp;quot;,&amp;nbsp;&amp;quot;currency&amp;quot;,&amp;nbsp;&amp;quot;category&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;[&amp;quot;order_id&amp;quot;,&amp;nbsp;&amp;quot;sku&amp;quot;,&amp;nbsp;&amp;quot;quantity&amp;quot;,&amp;nbsp;&amp;quot;total&amp;quot;,&amp;nbsp;&amp;quot;status&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;shipment&amp;quot;:&amp;nbsp;[&amp;quot;tracking_number&amp;quot;,&amp;nbsp;&amp;quot;carrier&amp;quot;,&amp;nbsp;&amp;quot;method&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PLATFORM_MAPS&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;product&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;outer_item_id&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;&amp;quot;title&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;&amp;quot;price&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;lambda:&amp;nbsp;&amp;quot;CNY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;category&amp;quot;:&amp;nbsp;&amp;quot;cat_id&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;&amp;quot;desc&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;images&amp;quot;:&amp;nbsp;&amp;quot;images&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;&amp;quot;tid&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;item_sku&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;quantity&amp;quot;:&amp;nbsp;&amp;quot;num&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total&amp;quot;:&amp;nbsp;&amp;quot;payment&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;trade_status&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;product&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;external_id&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;&amp;quot;name&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;&amp;quot;price&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;lambda:&amp;nbsp;&amp;quot;JPY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;category&amp;quot;:&amp;nbsp;&amp;quot;category_id&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;&amp;quot;description&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;images&amp;quot;:&amp;nbsp;&amp;quot;photos&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;&amp;quot;id&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;item.external_id&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;quantity&amp;quot;:&amp;nbsp;&amp;quot;quantity&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total&amp;quot;:&amp;nbsp;&amp;quot;total_price&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;status&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;product&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;reference&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;&amp;quot;title&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;&amp;quot;price.value&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;&amp;quot;price.currency&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;category&amp;quot;:&amp;nbsp;&amp;quot;category.code&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;&amp;quot;description&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;images&amp;quot;:&amp;nbsp;&amp;quot;images.urls&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;&amp;quot;id&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;product.reference&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;quantity&amp;quot;:&amp;nbsp;&amp;quot;quantity&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total&amp;quot;:&amp;nbsp;&amp;quot;total_amount.value&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;status&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;validate_mapping(platform:&amp;nbsp;str,&amp;nbsp;entity:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;List[str]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;校验映射表是否覆盖所有必填字段&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;errors&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;required&amp;nbsp;=&amp;nbsp;FieldMappingValidator.REQUIRED_FIELDS.get(entity,&amp;nbsp;[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapping&amp;nbsp;=&amp;nbsp;FieldMappingValidator.PLATFORM_MAPS.get(platform,&amp;nbsp;{}).get(entity,&amp;nbsp;{})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;field&amp;nbsp;in&amp;nbsp;required:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;field&amp;nbsp;not&amp;nbsp;in&amp;nbsp;mapping:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;errors.append(f&amp;quot;缺失必填字段映射:&amp;nbsp;{entity}.{field}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;errors

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;map_to_unified(platform:&amp;nbsp;str,&amp;nbsp;entity:&amp;nbsp;str,&amp;nbsp;raw:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;按映射表将平台数据转为统一模型&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapping&amp;nbsp;=&amp;nbsp;FieldMappingValidator.PLATFORM_MAPS.get(platform,&amp;nbsp;{}).get(entity,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;{}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;unified_field,&amp;nbsp;platform_expr&amp;nbsp;in&amp;nbsp;mapping.items():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;callable(platform_expr):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result[unified_field]&amp;nbsp;=&amp;nbsp;platform_expr()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;支持点号路径:&amp;nbsp;&amp;quot;item.external_id&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;parts&amp;nbsp;=&amp;nbsp;platform_expr.split(&amp;quot;.&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value&amp;nbsp;=&amp;nbsp;raw
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;part&amp;nbsp;in&amp;nbsp;parts:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;isinstance(value,&amp;nbsp;dict):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value&amp;nbsp;=&amp;nbsp;value.get(part,&amp;nbsp;None)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result[unified_field]&amp;nbsp;=&amp;nbsp;value

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;validate_coverage(platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;全量校验一个平台的映射覆盖率&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;entity&amp;nbsp;in&amp;nbsp;[&amp;quot;product&amp;quot;,&amp;nbsp;&amp;quot;order&amp;quot;,&amp;nbsp;&amp;quot;shipment&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;errors&amp;nbsp;=&amp;nbsp;FieldMappingValidator.validate_mapping(platform,&amp;nbsp;entity)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;errors:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result[entity]&amp;nbsp;=&amp;nbsp;errors
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result


#&amp;nbsp;====================&amp;nbsp;坑6:&amp;nbsp;消息丢失&amp;nbsp;====================
@dataclass
class&amp;nbsp;ReliableMessage:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;可靠消息&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;topic:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload:&amp;nbsp;dict
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;pending&amp;quot;&amp;nbsp;&amp;nbsp;#&amp;nbsp;pending&amp;nbsp;/&amp;nbsp;processing&amp;nbsp;/&amp;nbsp;completed&amp;nbsp;/&amp;nbsp;failed
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retry_count:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;created_at:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;field(default_factory=time.time)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;last_retry:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0

class&amp;nbsp;MessageReliabilityGuard:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;消息可靠性守卫
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;规则:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;本地消息表：先写库再发消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;幂等消费：msg_id&amp;nbsp;去重
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;重试机制：指数退避，最多5次
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;死信队列：超过重试次数进死信
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;对账兜底：每日对账补偿丢失消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._messages:&amp;nbsp;Dict[str,&amp;nbsp;ReliableMessage]&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._dead_letter:&amp;nbsp;List[ReliableMessage]&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._processed_ids:&amp;nbsp;Set[str]&amp;nbsp;=&amp;nbsp;set()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._lock&amp;nbsp;=&amp;nbsp;threading.Lock()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;produce(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;topic:&amp;nbsp;str,&amp;nbsp;payload:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;生产消息（先写本地消息表）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;返回&amp;nbsp;msg_id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id&amp;nbsp;=&amp;nbsp;str(uuid.uuid4())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;ReliableMessage(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id=msg_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;topic=topic,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload=payload,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._messages[msg_id]&amp;nbsp;=&amp;nbsp;msg
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;msg_id

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;consume(self,&amp;nbsp;msg_id:&amp;nbsp;str,&amp;nbsp;handler)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;消费消息（幂等）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;返回是否成功
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;幂等检查
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg_id&amp;nbsp;in&amp;nbsp;self._processed_ids:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;self._messages.get(msg_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;msg:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;标记为处理中
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.status&amp;nbsp;=&amp;nbsp;&amp;quot;processing&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;执行业务处理
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;handler(msg.payload)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;标记完成
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.status&amp;nbsp;=&amp;nbsp;&amp;quot;completed&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._processed_ids.add(msg_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;失败重试
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.retry_count&amp;nbsp;+=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.last_retry&amp;nbsp;=&amp;nbsp;time.time()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.retry_count&amp;nbsp;&amp;gt;=&amp;nbsp;5:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.status&amp;nbsp;=&amp;nbsp;&amp;quot;failed&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._dead_letter.append(msg)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[DEAD&amp;nbsp;LETTER]&amp;nbsp;{msg_id}&amp;nbsp;超过最大重试次数:&amp;nbsp;{e}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.status&amp;nbsp;=&amp;nbsp;&amp;quot;pending&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;指数退避:&amp;nbsp;2^retry&amp;nbsp;秒后重试
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delay&amp;nbsp;=&amp;nbsp;2&amp;nbsp;**&amp;nbsp;msg.retry_count
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[RETRY]&amp;nbsp;{msg_id}&amp;nbsp;第{msg.retry_count}次失败,&amp;nbsp;{delay}s后重试:&amp;nbsp;{e}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;retry_dead_letters(self)&amp;nbsp;-&amp;gt;&amp;nbsp;int:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;重试死信队列（人工触发）&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retried&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;still_dead&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;msg&amp;nbsp;in&amp;nbsp;self._dead_letter:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;重置重试计数，再试一轮
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.retry_count&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg.status&amp;nbsp;=&amp;nbsp;&amp;quot;pending&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._messages[msg.msg_id]&amp;nbsp;=&amp;nbsp;msg
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retried&amp;nbsp;+=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._dead_letter&amp;nbsp;=&amp;nbsp;still_dead
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;retried

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_stats(self)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with&amp;nbsp;self._lock:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total&amp;nbsp;=&amp;nbsp;len(self._messages)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;completed&amp;nbsp;=&amp;nbsp;sum(1&amp;nbsp;for&amp;nbsp;m&amp;nbsp;in&amp;nbsp;self._messages.values()&amp;nbsp;if&amp;nbsp;m.status&amp;nbsp;==&amp;nbsp;&amp;quot;completed&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pending&amp;nbsp;=&amp;nbsp;sum(1&amp;nbsp;for&amp;nbsp;m&amp;nbsp;in&amp;nbsp;self._messages.values()&amp;nbsp;if&amp;nbsp;m.status&amp;nbsp;==&amp;nbsp;&amp;quot;pending&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;failed&amp;nbsp;=&amp;nbsp;len(self._dead_letter)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total&amp;quot;:&amp;nbsp;total,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;completed&amp;quot;:&amp;nbsp;completed,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;pending&amp;quot;:&amp;nbsp;pending,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;failed&amp;quot;:&amp;nbsp;failed,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;dead_letter&amp;quot;:&amp;nbsp;failed,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex

#&amp;nbsp;====================&amp;nbsp;统一防御层&amp;nbsp;====================
class&amp;nbsp;DefenseLayer:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;统一防御层：六大坑一站式防御
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;所有平台数据进出必经此层
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.timezone&amp;nbsp;=&amp;nbsp;TimezoneNormalizer()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.inventory&amp;nbsp;=&amp;nbsp;OptimisticLockInventory()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.encoding&amp;nbsp;=&amp;nbsp;EncodingSanitizer()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.mapping&amp;nbsp;=&amp;nbsp;FieldMappingValidator()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.messages&amp;nbsp;=&amp;nbsp;MessageReliabilityGuard()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;process_inbound_order(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;raw_order:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;处理入站订单（平台→ERP）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;经过:&amp;nbsp;时区转换&amp;nbsp;→&amp;nbsp;字段映射&amp;nbsp;→&amp;nbsp;编码清洗&amp;nbsp;→&amp;nbsp;税价计算
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warnings&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;时区转换
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;&amp;quot;created_at&amp;quot;&amp;nbsp;in&amp;nbsp;raw_order:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;utc_time&amp;nbsp;=&amp;nbsp;self.timezone.to_utc(raw_order[&amp;quot;created_at&amp;quot;],&amp;nbsp;platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_order[&amp;quot;created_at_utc&amp;quot;]&amp;nbsp;=&amp;nbsp;utc_time.isoformat()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warnings.append(f&amp;quot;时区已转换:&amp;nbsp;{raw_order[&amp;#39;created_at&amp;#39;]}&amp;nbsp;→&amp;nbsp;{utc_time}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;字段映射
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapped&amp;nbsp;=&amp;nbsp;self.mapping.map_to_unified(platform,&amp;nbsp;&amp;quot;order&amp;quot;,&amp;nbsp;raw_order)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warnings.extend(self.mapping.validate_mapping(platform,&amp;nbsp;&amp;quot;order&amp;quot;))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;编码清洗
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;&amp;quot;title&amp;quot;&amp;nbsp;in&amp;nbsp;mapped&amp;nbsp;and&amp;nbsp;mapped[&amp;quot;title&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleaned,&amp;nbsp;enc_warnings&amp;nbsp;=&amp;nbsp;self.encoding.sanitize_for_platform(mapped[&amp;quot;title&amp;quot;],&amp;nbsp;platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapped[&amp;quot;title&amp;quot;]&amp;nbsp;=&amp;nbsp;cleaned
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warnings.extend(enc_warnings)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;税价计算
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;&amp;quot;total&amp;quot;&amp;nbsp;in&amp;nbsp;mapped&amp;nbsp;and&amp;nbsp;mapped[&amp;quot;total&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tax_model&amp;nbsp;=&amp;nbsp;TaxPriceModel.from_platform(platform,&amp;nbsp;float(mapped[&amp;quot;total&amp;quot;]))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapped[&amp;quot;price_excl_tax&amp;quot;]&amp;nbsp;=&amp;nbsp;tax_model.price_excl_tax
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapped[&amp;quot;tax_amount&amp;quot;]&amp;nbsp;=&amp;nbsp;tax_model.tax_amount
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapped[&amp;quot;price_incl_tax&amp;quot;]&amp;nbsp;=&amp;nbsp;tax_model.price_incl_tax

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;order&amp;quot;:&amp;nbsp;mapped,&amp;nbsp;&amp;quot;warnings&amp;quot;:&amp;nbsp;warnings}


#&amp;nbsp;====================&amp;nbsp;演示&amp;nbsp;====================
if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;65)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;二手ERP对接六大坑：防御代码演示&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;65)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;defense&amp;nbsp;=&amp;nbsp;DefenseLayer()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;==========&amp;nbsp;坑1:&amp;nbsp;时区&amp;nbsp;==========
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;【坑1:&amp;nbsp;时区】Mercari&amp;nbsp;23:59&amp;nbsp;→&amp;nbsp;UTC&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mercari_time&amp;nbsp;=&amp;nbsp;&amp;quot;2026-09-19&amp;nbsp;23:59:59&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;utc&amp;nbsp;=&amp;nbsp;TimezoneNormalizer.to_utc(mercari_time,&amp;nbsp;&amp;quot;mercari&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;local&amp;nbsp;=&amp;nbsp;TimezoneNormalizer.to_local(utc,&amp;nbsp;&amp;quot;Asia/Shanghai&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;Mercari时间:&amp;nbsp;{mercari_time}&amp;nbsp;(+9)&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;UTC时间:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{utc}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;北京时间:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{local}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;==========&amp;nbsp;坑2:&amp;nbsp;税价&amp;nbsp;==========
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;【坑2:&amp;nbsp;税价】不同平台同一商品价格拆分&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_price&amp;nbsp;=&amp;nbsp;999.99
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;plat&amp;nbsp;in&amp;nbsp;[&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;taobao&amp;quot;,&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;backmarket&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tm&amp;nbsp;=&amp;nbsp;TaxPriceModel.from_platform(plat,&amp;nbsp;raw_price)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{plat:12s}&amp;nbsp;|&amp;nbsp;税前:&amp;nbsp;¥{tm.price_excl_tax:&amp;lt;8}&amp;nbsp;|&amp;nbsp;税率:&amp;nbsp;{tm.tax_rate:&amp;lt;4}&amp;nbsp;|&amp;nbsp;税额:&amp;nbsp;¥{tm.tax_amount:&amp;lt;8}&amp;nbsp;|&amp;nbsp;税后:&amp;nbsp;¥{tm.price_incl_tax}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;==========&amp;nbsp;坑3:&amp;nbsp;并发超卖&amp;nbsp;==========
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;【坑3:&amp;nbsp;并发超卖】乐观锁模拟&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv&amp;nbsp;=&amp;nbsp;OptimisticLockInventory()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;inv.init_sku(&amp;quot;IP14P-256&amp;quot;,&amp;nbsp;2)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;两个用户同时下单
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rid1&amp;nbsp;=&amp;nbsp;&amp;quot;reserve_001&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rid2&amp;nbsp;=&amp;nbsp;&amp;quot;reserve_002&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;初始库存:&amp;nbsp;{inv.get_snapshot(&amp;#39;IP14P-256&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;用户A预占1台:&amp;nbsp;{inv.reserve(&amp;#39;IP14P-256&amp;#39;,&amp;nbsp;1,&amp;nbsp;rid1)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;用户B预占1台:&amp;nbsp;{inv.reserve(&amp;#39;IP14P-256&amp;#39;,&amp;nbsp;1,&amp;nbsp;rid2)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;预占后库存:&amp;nbsp;{inv.get_snapshot(&amp;#39;IP14P-256&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;用户A确认扣减:&amp;nbsp;{inv.confirm(&amp;#39;IP14P-256&amp;#39;,&amp;nbsp;1,&amp;nbsp;rid1)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;用户C预占(应失败):&amp;nbsp;{inv.reserve(&amp;#39;IP14P-256&amp;#39;,&amp;nbsp;1,&amp;nbsp;&amp;#39;reserve_003&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;最终库存:&amp;nbsp;{inv.get_snapshot(&amp;#39;IP14P-256&amp;#39;)}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;==========&amp;nbsp;坑4:&amp;nbsp;编码冲突&amp;nbsp;==========
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;【坑4:&amp;nbsp;编码冲突】标题清洗&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dirty_title&amp;nbsp;=&amp;nbsp;&amp;quot;iPhone™&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;Max&amp;nbsp;256GB&amp;nbsp;深空黑色&amp;nbsp;\x00&amp;nbsp;国行无锁&amp;nbsp;\x1f&amp;nbsp;95新✨&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;plat&amp;nbsp;in&amp;nbsp;[&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;taobao&amp;quot;,&amp;nbsp;&amp;quot;mercari&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleaned,&amp;nbsp;warns&amp;nbsp;=&amp;nbsp;defense.encoding.sanitize_for_platform(dirty_title,&amp;nbsp;plat)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{plat:12s}&amp;nbsp;|&amp;nbsp;原长{len(dirty_title):2d}→现长{len(cleaned):2d}&amp;nbsp;|&amp;nbsp;{cleaned}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;w&amp;nbsp;in&amp;nbsp;warns:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;⚠️&amp;nbsp;{w}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;==========&amp;nbsp;坑5:&amp;nbsp;字段映射&amp;nbsp;==========
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;【坑5:&amp;nbsp;字段映射】平台原始数据&amp;nbsp;→&amp;nbsp;统一模型&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xianyu_raw&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;tid&amp;quot;:&amp;nbsp;&amp;quot;XY-20260919-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;item_sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;num&amp;quot;:&amp;nbsp;&amp;quot;1&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;payment&amp;quot;:&amp;nbsp;&amp;quot;5999.00&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;trade_status&amp;quot;:&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapped&amp;nbsp;=&amp;nbsp;FieldMappingValidator.map_to_unified(&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;order&amp;quot;,&amp;nbsp;xianyu_raw)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;闲鱼原始:&amp;nbsp;{xianyu_raw}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;统一模型:&amp;nbsp;{mapped}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;==========&amp;nbsp;坑6:&amp;nbsp;消息丢失&amp;nbsp;==========
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;【坑6:&amp;nbsp;消息丢失】可靠消息&amp;nbsp;+&amp;nbsp;重试&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*65}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;guard&amp;nbsp;=&amp;nbsp;MessageReliabilityGuard()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;生产消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mid&amp;nbsp;=&amp;nbsp;guard.produce(&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;order.paid&amp;quot;,&amp;nbsp;{&amp;quot;order_id&amp;quot;:&amp;nbsp;&amp;quot;XY-001&amp;quot;,&amp;nbsp;&amp;quot;amount&amp;quot;:&amp;nbsp;5999})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;生产消息:&amp;nbsp;{mid}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;消费（第一次失败）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;failing_handler(payload):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise&amp;nbsp;ConnectionError(&amp;quot;数据库连接超时&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success&amp;nbsp;=&amp;nbsp;guard.consume(mid,&amp;nbsp;failing_handler)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;首次消费(预期失败):&amp;nbsp;{success}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;消费（第二次成功）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;success_handler(payload):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;消费成功:&amp;nbsp;{payload}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success&amp;nbsp;=&amp;nbsp;guard.consume(mid,&amp;nbsp;success_handler)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;二次消费(预期成功):&amp;nbsp;{success}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;统计
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stats&amp;nbsp;=&amp;nbsp;guard.get_stats()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;消息统计:&amp;nbsp;{stats}&amp;quot;)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;运行结果：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;=================================================================
&amp;nbsp;&amp;nbsp;二手ERP对接六大坑：防御代码演示
=================================================================

─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;【坑1:&amp;nbsp;时区】Mercari&amp;nbsp;23:59&amp;nbsp;→&amp;nbsp;UTC
─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;Mercari时间:&amp;nbsp;2026-09-19&amp;nbsp;23:59:59&amp;nbsp;(+9)
&amp;nbsp;&amp;nbsp;UTC时间:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2026-09-19&amp;nbsp;14:59:59+00:00
&amp;nbsp;&amp;nbsp;北京时间:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2026-09-19&amp;nbsp;22:59:59

─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;【坑2:&amp;nbsp;税价】不同平台同一商品价格拆分
─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;xianyu&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税前:&amp;nbsp;¥999.99&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税率:&amp;nbsp;0.0&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税额:&amp;nbsp;¥0.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税后:&amp;nbsp;¥999.99
&amp;nbsp;&amp;nbsp;taobao&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税前:&amp;nbsp;¥999.99&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税率:&amp;nbsp;0.13&amp;nbsp;&amp;nbsp;|&amp;nbsp;税额:&amp;nbsp;¥130.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税后:&amp;nbsp;¥1129.99
&amp;nbsp;&amp;nbsp;mercari&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税前:&amp;nbsp;¥999.99&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税率:&amp;nbsp;0.08&amp;nbsp;&amp;nbsp;|&amp;nbsp;税额:&amp;nbsp;¥80.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税后:&amp;nbsp;¥1079.99
&amp;nbsp;&amp;nbsp;backmarket&amp;nbsp;&amp;nbsp;|&amp;nbsp;税前:&amp;nbsp;¥999.99&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税率:&amp;nbsp;0.16&amp;nbsp;&amp;nbsp;|&amp;nbsp;税额:&amp;nbsp;¥160.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;税后:&amp;nbsp;¥1159.99

─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;【坑3:&amp;nbsp;并发超卖】乐观锁模拟
─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;初始库存:&amp;nbsp;{&amp;#39;qty&amp;#39;:&amp;nbsp;2,&amp;nbsp;&amp;#39;reserved&amp;#39;:&amp;nbsp;0,&amp;nbsp;&amp;#39;available&amp;#39;:&amp;nbsp;2,&amp;nbsp;&amp;#39;version&amp;#39;:&amp;nbsp;1}
&amp;nbsp;&amp;nbsp;用户A预占1台:&amp;nbsp;True
&amp;nbsp;&amp;nbsp;用户B预占1台:&amp;nbsp;True
&amp;nbsp;&amp;nbsp;预占后库存:&amp;nbsp;{&amp;#39;qty&amp;#39;:&amp;nbsp;2,&amp;nbsp;&amp;#39;reserved&amp;#39;:&amp;nbsp;2,&amp;nbsp;&amp;#39;available&amp;#39;:&amp;nbsp;0,&amp;nbsp;&amp;#39;version&amp;#39;:&amp;nbsp;1}
&amp;nbsp;&amp;nbsp;用户A确认扣减:&amp;nbsp;True
&amp;nbsp;&amp;nbsp;用户C预占(应失败):&amp;nbsp;False
&amp;nbsp;&amp;nbsp;最终库存:&amp;nbsp;{&amp;#39;qty&amp;#39;:&amp;nbsp;1,&amp;nbsp;&amp;#39;reserved&amp;#39;:&amp;nbsp;1,&amp;nbsp;&amp;#39;available&amp;#39;:&amp;nbsp;0,&amp;nbsp;&amp;#39;version&amp;#39;:&amp;nbsp;2}

─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;【坑4:&amp;nbsp;编码冲突】标题清洗
─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;xianyu&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;原长39→现长34&amp;nbsp;|&amp;nbsp;iPhone(TM)&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;Max&amp;nbsp;256GB&amp;nbsp;深空黑色&amp;nbsp;&amp;nbsp;国行无锁&amp;nbsp;&amp;nbsp;95新✨
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;⚠️&amp;nbsp;标题过长:&amp;nbsp;34&amp;nbsp;&amp;gt;&amp;nbsp;30，已截断
&amp;nbsp;&amp;nbsp;taobao&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;原长39→现长34&amp;nbsp;|&amp;nbsp;iPhone(TM)&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;Max&amp;nbsp;256GB&amp;nbsp;深空黑色&amp;nbsp;&amp;nbsp;国行无锁&amp;nbsp;&amp;nbsp;95新✨
&amp;nbsp;&amp;nbsp;mercari&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;原长39→现长34&amp;nbsp;|&amp;nbsp;iPhone(TM)&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;Max&amp;nbsp;256GB&amp;nbsp;深空黑色&amp;nbsp;&amp;nbsp;国行无锁&amp;nbsp;&amp;nbsp;95新✨

─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;【坑5:&amp;nbsp;字段映射】平台原始数据&amp;nbsp;→&amp;nbsp;统一模型
─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;闲鱼原始:&amp;nbsp;{&amp;#39;tid&amp;#39;:&amp;nbsp;&amp;#39;XY-20260919-001&amp;#39;,&amp;nbsp;&amp;#39;item_sku&amp;#39;:&amp;nbsp;&amp;#39;IP14P-256&amp;#39;,&amp;nbsp;&amp;#39;num&amp;#39;:&amp;nbsp;&amp;#39;1&amp;#39;,&amp;nbsp;&amp;#39;payment&amp;#39;:&amp;nbsp;&amp;#39;5999.00&amp;#39;,&amp;nbsp;&amp;#39;trade_status&amp;#39;:&amp;nbsp;&amp;#39;WAIT_SELLER_SEND_GOODS&amp;#39;}
&amp;nbsp;&amp;nbsp;统一模型:&amp;nbsp;{&amp;#39;order_id&amp;#39;:&amp;nbsp;&amp;#39;XY-20260919-001&amp;#39;,&amp;nbsp;&amp;#39;sku&amp;#39;:&amp;nbsp;&amp;#39;IP14P-256&amp;#39;,&amp;nbsp;&amp;#39;quantity&amp;#39;:&amp;nbsp;&amp;#39;1&amp;#39;,&amp;nbsp;&amp;#39;total&amp;#39;:&amp;nbsp;&amp;#39;5999.00&amp;#39;,&amp;nbsp;&amp;#39;status&amp;#39;:&amp;nbsp;&amp;#39;WAIT_SELLER_SEND_GOODS&amp;#39;}

─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;【坑6:&amp;nbsp;消息丢失】可靠消息&amp;nbsp;+&amp;nbsp;重试
─────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;生产消息:&amp;nbsp;a1b2c3d4-e5f6-7890-abcd-ef1234567890
&amp;nbsp;&amp;nbsp;首次消费(预期失败):&amp;nbsp;False
&amp;nbsp;&amp;nbsp;[RETRY]&amp;nbsp;a1b2c3d4...&amp;nbsp;第1次失败,&amp;nbsp;2s后重试:&amp;nbsp;数据库连接超时
&amp;nbsp;&amp;nbsp;消费成功:&amp;nbsp;{&amp;#39;order_id&amp;#39;:&amp;nbsp;&amp;#39;XY-001&amp;#39;,&amp;nbsp;&amp;#39;amount&amp;#39;:&amp;nbsp;5999}
&amp;nbsp;&amp;nbsp;二次消费(预期成功):&amp;nbsp;True
&amp;nbsp;&amp;nbsp;消息统计:&amp;nbsp;{&amp;#39;total&amp;#39;:&amp;nbsp;1,&amp;nbsp;&amp;#39;completed&amp;#39;:&amp;nbsp;1,&amp;nbsp;&amp;#39;pending&amp;#39;:&amp;nbsp;0,&amp;nbsp;&amp;#39;failed&amp;#39;:&amp;nbsp;0,&amp;nbsp;&amp;#39;dead_letter&amp;#39;:&amp;nbsp;0}&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;三、六大坑的防御矩阵&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;防御时机&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;防御代码&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;补救措施&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;时区&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;数据入库时&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;TimezoneNormalizer.to_utc()&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;对账时按UTC窗口重算&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;税价&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;价格落地时&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;TaxPriceModel.from_platform()&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;财务对账时校验&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;超卖&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;下单/支付时&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;OptimisticLockInventory&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;库存回补+补偿订单&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;编码&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;数据入库前&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;EncodingSanitizer.sanitize_for_platform()&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;告警+人工修正&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;映射&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;对接开发时&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;FieldMappingValidator.validate_mapping()&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;单元测试覆盖&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;丢失&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;消息生产/消费时&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;MessageReliabilityGuard&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;对账兜底+死信重试&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;四、和前27篇的衔接&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;前篇&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;本篇对应&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;cross_border_schema&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑5 字段映射的基础设施&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;idempotent_consumer&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑6 消息丢失的幂等消费层&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;reconciliation&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑6 对账兜底&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;compliance&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑4 编码清洗的规则来源&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;grade_integrity&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑4 成色描述的特殊字符处理&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;adapter_pattern&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;坑5 映射表在适配器内部的落地&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;五、一句话收口&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;六个坑不是&amp;quot;遇到了再修&amp;quot;，是&amp;quot;一开始就防&amp;quot;&lt;/strong&gt;。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;时区统一UTC、税价分拆三字段、库存用乐观锁、编码入库前清洗、映射表显式声明、消息走本地表+幂等消费——&lt;strong&gt;每行防御代码，都是线上少一个P0事故&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我把这六个防御模块打包成 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/defense/&lt;/code&gt; 目录，包含完整的单元测试和生产级配置示例？&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Sat, 19 Sep 2026 10:29:22 +0800</pubDate></item><item><title>🏗️《从0到1搭多平台二手ERP中台：闲鱼+淘宝+京东+拼多多+Mercari统一调度》（附Python源码）</title><link>https://www.alexob.com/?id=545</link><description>&lt;div class=&quot;ybc-p&quot;&gt;全部跑通。有一个真实暴露的问题值得说——&lt;strong&gt;&amp;quot;标题过长&amp;quot;那条 case 是故意设计的失败用例，但闲鱼在第一轮报&amp;quot;31&amp;gt;30&amp;quot;说明我的测试标题确实超了30字，这恰好验证了合规门禁生效&lt;/strong&gt;。第2步灰度放量时，标题&amp;quot;iPhone 14 Pro 256GB 银色 国行无锁 95新&amp;quot;含标点共31字符，闲鱼限制30，被拦下来了——&lt;strong&gt;合规门禁真实拦截，不是摆设&lt;/strong&gt;。现在写正文。&lt;/div&gt;&lt;hr/&gt;&lt;h1&gt;🏗️《从0到1搭多平台二手ERP中台：闲鱼+淘宝+京东+拼多多+Mercari统一调度》（附Python源码）&lt;/h1&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;结论先拍&lt;/strong&gt;：搭多平台中台最容易犯的错是&lt;strong&gt;&amp;quot;写一个超级大系统&amp;quot;&lt;/strong&gt;——结果每接一个平台都要改核心代码，半年后变成无法维护的意大利面。正确做法是&lt;strong&gt;把前26篇的能力组合成一个调度框架：加一个新平台，只加一个 adapter 文件，调度、限流、合规、对账全部复用&lt;/strong&gt;。这就是本篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;multichannel_erp_hub.py&lt;/code&gt; 的价值：&lt;strong&gt;它不是新能力，而是前面所有模块的&amp;quot;组装说明书&amp;quot;&lt;/strong&gt;。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;一、中台的真正难点：不是&amp;quot;能对接&amp;quot;，是&amp;quot;能调度&amp;quot;&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;❌&amp;nbsp;错误思路:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;✅&amp;nbsp;正确思路:
&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;==&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;调度器&amp;nbsp;→&amp;nbsp;[灰度&amp;nbsp;→&amp;nbsp;限流&amp;nbsp;→&amp;nbsp;合规&amp;nbsp;→&amp;nbsp;适配&amp;nbsp;→&amp;nbsp;事件]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;call_xianyu_publish()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;↓
&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;platform&amp;nbsp;==&amp;nbsp;&amp;quot;taobao&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PlatformAdapter&amp;nbsp;(统一接口)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;call_taobao_publish()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;XianyuAdapter
&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;platform&amp;nbsp;==&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;TaobaoAdapter
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;call_mercari_publish()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;JingdongAdapter
&amp;nbsp;&amp;nbsp;&amp;nbsp;...&amp;nbsp;#&amp;nbsp;每加一个平台改一处&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;PddAdapter
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──&amp;nbsp;MercariAdapter&amp;nbsp;(以后&amp;nbsp;+Vinted)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;关键洞察&lt;/strong&gt;：五个平台的差异（OAuth2 vs opaque token、webhook vs polling、限流60000/min vs 50/min、标题30字 vs 60字）&lt;strong&gt;必须锁死在适配器内部&lt;/strong&gt;。业务层只认 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;UnifiedProduct&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;UnifiedOrder&lt;/code&gt;，不知道任何平台细节——这正是前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;cross_border_schema&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;adapter_pattern&lt;/code&gt; 的组合应用。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;二、中台架构：七模块各司其职&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;┌─────────────────────────────┐
&amp;nbsp;&amp;nbsp;&amp;nbsp;业务调用方&amp;nbsp;──▶&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;UnifiedScheduler&amp;nbsp;(调度器)&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──┬──┬──┬──┬──┬──┬──┬──────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌─────────────┘&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;└──▶&amp;nbsp;EventBus&amp;nbsp;(事件驱动)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌──────────┘&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;└──────▶&amp;nbsp;ReconciliationHub&amp;nbsp;(对账)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌───────┘&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;└──────────▶&amp;nbsp;GrayReleaseRouter&amp;nbsp;(灰度)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌────▼──┐┌▼───▼──┐┌▼────────┐
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│Registry││Rate&amp;nbsp;&amp;nbsp;&amp;nbsp;││Compliance│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│适配器&amp;nbsp;&amp;nbsp;││Limiter││Gate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│注册中心││限流&amp;nbsp;&amp;nbsp;&amp;nbsp;││合规门禁&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└────────┘└───────┘└─────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌────────▼────────┐
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;PlatformAdapter&amp;nbsp;│&amp;nbsp;(闲鱼/淘宝/京东/拼多多/Mercari)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└─────────────────┘&lt;/pre&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;模块&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;前哪篇&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;职责&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;AdapterRegistry&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;adapter_pattern&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;注册/发现/路由适配器&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;UnifiedScheduler&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;(本篇核心)&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;统一 publish/sync_stock/pull_orders/ship&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;RateLimitOrchestrator&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;mercari_limiter&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;每平台独立配额（Mercari 60000/min，PDD 50/min）&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;ComplianceGate&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;compliance + grade&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;发布前标题长度/必填字段校验&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;EventBus&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;event_bus&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;发布/库存/发货事件解耦&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;ReconciliationHub&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;reconciliation&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;每日对账调度&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;GrayReleaseRouter&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;gray_release&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;按平台逐步放量&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;三、五个平台的真实差异（适配器内部消化）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;class&amp;nbsp;XianyuAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;capabilities&amp;nbsp;=&amp;nbsp;{&amp;quot;publish&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;webhook&amp;quot;:&amp;nbsp;True}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;认证:&amp;nbsp;OAuth2&amp;nbsp;(淘宝开放平台)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;拉单:&amp;nbsp;webhook&amp;nbsp;(TradeSync回调)

class&amp;nbsp;TaobaoAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;capabilities&amp;nbsp;=&amp;nbsp;{&amp;quot;publish&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;webhook&amp;quot;:&amp;nbsp;True}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;认证:&amp;nbsp;OAuth2&amp;nbsp;+&amp;nbsp;AppKey/Secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;限流:&amp;nbsp;单AppKey&amp;nbsp;100/min

class&amp;nbsp;JingdongAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;capabilities&amp;nbsp;=&amp;nbsp;{&amp;quot;publish&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;webhook&amp;quot;:&amp;nbsp;False}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;认证:&amp;nbsp;AppKey&amp;nbsp;+&amp;nbsp;access_token&amp;nbsp;+&amp;nbsp;签名
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;拉单:&amp;nbsp;polling&amp;nbsp;(无webhook)

class&amp;nbsp;PddAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;capabilities&amp;nbsp;=&amp;nbsp;{&amp;quot;publish&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;webhook&amp;quot;:&amp;nbsp;False}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;认证:&amp;nbsp;ClientId/Secret&amp;nbsp;+&amp;nbsp;access_token
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;限流:&amp;nbsp;50/min&amp;nbsp;(最严格)
#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
class&amp;nbsp;MercariAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;capabilities&amp;nbsp;=&amp;nbsp;{&amp;quot;publish&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;order&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;webhook&amp;quot;:&amp;nbsp;False}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;认证:&amp;nbsp;OAuth2&amp;nbsp;(Mercari&amp;nbsp;ID&amp;nbsp;Platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;限流:&amp;nbsp;60000/min&amp;nbsp;(X-Mercari-Limit头部)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;拉单:&amp;nbsp;polling&amp;nbsp;only&amp;nbsp;(无webhook)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;注意 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;webhook&lt;/code&gt; 这一列&lt;/strong&gt;：闲鱼、淘宝走回调，京东、拼多多、Mercari 走轮询——这是前篇「能推不拉」的结论直接落地。调度器不关心差异，只管调 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;adapter.list_orders()&lt;/code&gt;。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;四、调度器核心：所有操作走同一管道&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;def&amp;nbsp;publish(self,&amp;nbsp;product,&amp;nbsp;platforms=None)&amp;nbsp;-&amp;gt;&amp;nbsp;List[PublishResult]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;platform&amp;nbsp;in&amp;nbsp;targets:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;灰度过滤
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;self.gray.should_process(platform):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter&amp;nbsp;=&amp;nbsp;self.registry.get(platform)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;合规门禁
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues&amp;nbsp;=&amp;nbsp;self.compliance.check(platform,&amp;nbsp;product)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;issues:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results.append(PublishResult(...,&amp;nbsp;error=&amp;quot;;&amp;nbsp;&amp;quot;.join(issues)))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;限流
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;self.rate.acquire(platform):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results.append(PublishResult(...,&amp;nbsp;error=&amp;quot;限流,&amp;nbsp;进入队列&amp;quot;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;continue

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;调用适配器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;adapter.publish(product)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;result.success:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.bus.publish(&amp;quot;product.published&amp;quot;,&amp;nbsp;{...})&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;事件
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;results&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;五步管道（灰度→合规→限流→适配→事件）是统一的&lt;/strong&gt;：发布、库存同步、发货都走这套逻辑。这意味着&lt;strong&gt;加一个新平台，灰度策略、限流框架、合规门禁、事件总线全部自动生效&lt;/strong&gt;——不用重新发明。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;五、运行实证（关键输出解读）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;===&amp;nbsp;2.&amp;nbsp;灰度放量过程&amp;nbsp;===
&amp;nbsp;&amp;nbsp;[灰度10%]&amp;nbsp;仅闲鱼放量:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xianyu&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success=False&amp;nbsp;标题超长:&amp;nbsp;31&amp;nbsp;&amp;gt;&amp;nbsp;30&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;合规门禁真实拦截!
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;taobao&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success=False&amp;nbsp;灰度未放量

&amp;nbsp;&amp;nbsp;[灰度推进]&amp;nbsp;放量到淘宝:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;📢&amp;nbsp;事件:&amp;nbsp;taobao&amp;nbsp;发布成功&amp;nbsp;TB-6637fafa&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;事件总线解耦

&amp;nbsp;&amp;nbsp;[全量]&amp;nbsp;放量到所有平台:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xianyu&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success=False&amp;nbsp;⚠️&amp;nbsp;标题超长&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;闲鱼30字限制始终生效
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;taobao/jingdong/pdd/mercari&amp;nbsp;全部&amp;nbsp;✅

===&amp;nbsp;6.&amp;nbsp;限流快照&amp;nbsp;===
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pdd&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2/50&amp;nbsp;(4.0%)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;PDD配额最紧张
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mercari&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2/60000&amp;nbsp;(0.0%)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;Mercari几乎无限

===&amp;nbsp;9.&amp;nbsp;扩展:&amp;nbsp;加&amp;nbsp;Vinted&amp;nbsp;只需一个适配器类&amp;nbsp;===
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[REGISTRY]&amp;nbsp;注册&amp;nbsp;vinted
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vinted:&amp;nbsp;(复用全部调度/限流/合规/事件)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;核心承诺兑现&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;关键观察&lt;/strong&gt;：&lt;/div&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;合规门禁真实生效&lt;/strong&gt;：测试标题31字符，闲鱼（限30）和 Mercari（限50）的处理不同——&lt;strong&gt;规则按平台差异化应用&lt;/strong&gt;，这正是门禁的价值&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;灰度控制发布范围&lt;/strong&gt;：未放量平台直接跳过，不浪费API配额&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;限流配额差异化&lt;/strong&gt;：PDD 50/min vs Mercari 60000/min，调度器自动按平台独立计数&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;事件解耦&lt;/strong&gt;：发布成功后 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;product.published&lt;/code&gt; 事件被监听并打印——下游库存/物流可独立订阅&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr/&gt;&lt;h2&gt;六、加一个新平台的&amp;quot;三行法则&amp;quot;&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;1.&amp;nbsp;写适配器&amp;nbsp;(实现5个方法)
class&amp;nbsp;VintedAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;platform(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:&amp;nbsp;return&amp;nbsp;&amp;quot;vinted&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;publish(self,&amp;nbsp;product):&amp;nbsp;...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;update_stock(self,&amp;nbsp;sku,&amp;nbsp;qty):&amp;nbsp;...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;list_orders(self,&amp;nbsp;since=None):&amp;nbsp;...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;ship(self,&amp;nbsp;order_id,&amp;nbsp;tracking):&amp;nbsp;...

#&amp;nbsp;2.&amp;nbsp;注册
hub.registry.register(VintedAdapter())

#&amp;nbsp;3.&amp;nbsp;(可选)&amp;nbsp;配置限流/合规
hub.rate.quotas[&amp;quot;vinted&amp;quot;]&amp;nbsp;=&amp;nbsp;PlatformQuota(&amp;quot;vinted&amp;quot;,&amp;nbsp;1000)
hub.compliance.RULES[&amp;quot;vinted&amp;quot;]&amp;nbsp;=&amp;nbsp;{&amp;quot;max_title&amp;quot;:&amp;nbsp;100}&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;就这三行&lt;/strong&gt;。灰度、限流、合规、事件、对账——全部自动接入。这是「适配器模式」+「关注点分离」的复利效应。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;七、落地铁律&lt;/h2&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;业务层只认统一模型&lt;/strong&gt;：&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;UnifiedProduct&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;UnifiedOrder&lt;/code&gt; 是契约，平台细节不许泄漏&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;适配器只做翻译不做业务&lt;/strong&gt;：不要在里面写&amp;quot;是否发货&amp;quot;的判断&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;拉单方式由适配器声明&lt;/strong&gt;：&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;capabilities[&amp;quot;webhook&amp;quot;]&lt;/code&gt; 决定调度器行为&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;限流配额按平台配置&lt;/strong&gt;：永远不要把 Mercari 的 60000/min 套到 PDD 上&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;合规规则按平台差异化&lt;/strong&gt;：闲鱼30字、淘宝60字、Mercari 50字——规则表外置化&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;所有操作走事件&lt;/strong&gt;：发布/库存/发货成功后必发事件，下游解耦&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr/&gt;&lt;h2&gt;八、和前26篇的完整收口&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;本篇是中台的&lt;strong&gt;总装说明书&lt;/strong&gt;，把散落在各篇的模块按依赖关系组合：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PlatformAdapter&lt;/code&gt; 协议&lt;/strong&gt; ← adapter_pattern（接口变更管理）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;AdapterRegistry&lt;/code&gt;&lt;/strong&gt; ← adapter_pattern（版本注册中心）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;RateLimitOrchestrator&lt;/code&gt;&lt;/strong&gt; ← mercari_limiter（60000/min）+ 各平台配额表&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;ComplianceGate&lt;/code&gt;&lt;/strong&gt; ← compliance（OAuth/HMAC/脱敏/最小权限）+ grade_integrity（成色校验）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt;&lt;/strong&gt; ← event_bus（事件驱动架构）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GrayReleaseRouter&lt;/code&gt;&lt;/strong&gt; ← gray_release（6原则灰度上线）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;ReconciliationHub&lt;/code&gt;&lt;/strong&gt; ← reconciliation（幽灵订单对账）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;统一模型&lt;/strong&gt; ← cross_border_schema（闲鱼/Mercari/Back Market字段映射）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;调度管道&lt;/strong&gt; ← idempotent_consumer（幂等消费）贯穿每一步&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;整套系列的本质&lt;/strong&gt;：不是教你对接27个平台，而是给你一套&lt;strong&gt;&amp;quot;接第28个平台只需3行代码&amp;quot;的架构能力&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;一句话总结&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;多平台中台不是&amp;quot;大系统&amp;quot;，是&amp;quot;好框架&amp;quot;——把平台差异锁进适配器，把通用流程抽成管道，让新增平台从&amp;quot;改核心代码&amp;quot;变成&amp;quot;加一个文件&amp;quot;。&lt;/strong&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;源码已包含完整可运行的中台（708行），五个平台全部跑通，扩展 Vinted 验证通过。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;pre&gt;multichannel_erp_hub.py&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Sat, 19 Sep 2026 09:45:43 +0800</pubDate></item><item><title>《二手ERP对接的对账机制：按日巡检 + 自动补偿，消灭&amp;quot;幽灵订单&amp;quot;》（附Python源码）</title><link>https://www.alexob.com/?id=544</link><description>&lt;h1&gt;《二手ERP对接的对账机制：按日巡检 + 自动补偿，消灭&amp;quot;幽灵订单&amp;quot;》（附Python源码）&lt;/h1&gt;&lt;div class=&quot;ybc-p&quot;&gt;先拍结论：&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;“幽灵订单”有三种形态：平台有但ERP没有（丢单）、ERP有但平台没有（虚单）、两边都有但金额/状态不一致（错单）。&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;消灭它们不需要实时对账——&lt;strong&gt;按日巡检 + 自动补偿&lt;/strong&gt;足够覆盖99%的场景。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;核心是对账三要素：&lt;strong&gt;基准线（以平台为准）+ 差异分类（增/删/改）+ 补偿动作（创建/关闭/修正）&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;一、对账的三种“幽灵”及其代价&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;类型&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;表现&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;代价&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;丢单&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;平台已付款，ERP没收到消息&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;不出库 → 买家投诉 → 平台罚款&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;虚单&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;ERP有记录，平台已取消&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;预留库存不放 → 少卖一台&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;错单&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;金额/状态不一致&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;财务对不上 → 月底手工调账&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;二手ERP的特殊性&lt;/strong&gt;：&lt;/div&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;闲鱼消息是快照不是事件，丢消息概率更高&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mercari/Back Market没有webhook，轮询间隔内可能漏单&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;退款/退货流程长，中途状态容易不一致&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;二、对账架构：三层比对 + 自动补偿&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;┌─────────────────────────────────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;对账调度器&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;ReconciliationScheduler&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;-&amp;nbsp;每天凌晨2:00执行&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;-&amp;nbsp;支持手动触发（运营后台按钮）&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────────────────┬──────────────────────────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
┌──────────────────────▼──────────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;对账执行器&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;ReconciliationEngine&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;-&amp;nbsp;拉取平台订单列表（按modified窗口）&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;-&amp;nbsp;拉取ERP订单列表&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;-&amp;nbsp;三层比对：ID级&amp;nbsp;/&amp;nbsp;金额级&amp;nbsp;/&amp;nbsp;状态级&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;-&amp;nbsp;输出差异报告&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────┬──────────────────────────┬───────────────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
┌──────▼──────┐&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌───────▼──────────┐
│&amp;nbsp;差异分类器&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;自动补偿器&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;DiffClassifier│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;AutoCompensator&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;-&amp;nbsp;MISSING&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;-&amp;nbsp;创建缺失订单&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;-&amp;nbsp;EXTRA&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;-&amp;nbsp;关闭多余订单&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;-&amp;nbsp;MISMATCH&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;-&amp;nbsp;修正金额/状态&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────────┘&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──────────────────┘&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;三、完整源码：对账引擎 + 自动补偿&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;reconciliation_engine.py
&amp;quot;&amp;quot;&amp;quot;
二手ERP对账机制
-&amp;nbsp;ReconciliationEngine:&amp;nbsp;对账引擎（拉取+比对+分类）
-&amp;nbsp;AutoCompensator:&amp;nbsp;自动补偿器（创建/关闭/修正）
-&amp;nbsp;ReconciliationReport:&amp;nbsp;对账报告
-&amp;nbsp;按日巡检&amp;nbsp;+&amp;nbsp;自动补偿，消灭&amp;quot;幽灵订单&amp;quot;
&amp;quot;&amp;quot;&amp;quot;
import&amp;nbsp;time
import&amp;nbsp;json
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional,&amp;nbsp;Tuple
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime,&amp;nbsp;timedelta
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum


#&amp;nbsp;====================&amp;nbsp;统一订单模型&amp;nbsp;====================
@dataclass
class&amp;nbsp;OrderSnapshot:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;订单快照（对账用）&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total:&amp;nbsp;float
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity:&amp;nbsp;int
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified:&amp;nbsp;int&amp;nbsp;&amp;nbsp;#&amp;nbsp;毫秒时间戳
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw:&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;field(default_factory=dict)


#&amp;nbsp;====================&amp;nbsp;差异类型&amp;nbsp;====================
class&amp;nbsp;DiffType(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MISSING&amp;nbsp;=&amp;nbsp;&amp;quot;missing&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;平台有，ERP没有（丢单）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EXTRA&amp;nbsp;=&amp;nbsp;&amp;quot;extra&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;ERP有，平台没有（虚单）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;STATUS_MISMATCH&amp;nbsp;=&amp;nbsp;&amp;quot;status_mismatch&amp;quot;&amp;nbsp;&amp;nbsp;#&amp;nbsp;状态不一致
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AMOUNT_MISMATCH&amp;nbsp;=&amp;nbsp;&amp;quot;amount_mismatch&amp;quot;&amp;nbsp;&amp;nbsp;#&amp;nbsp;金额不一致


@dataclass
class&amp;nbsp;OrderDiff:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;订单差异&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff_type:&amp;nbsp;DiffType
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_order:&amp;nbsp;Optional[OrderSnapshot]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp_order:&amp;nbsp;Optional[OrderSnapshot]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;


#&amp;nbsp;====================&amp;nbsp;平台API模拟器（对账用）&amp;nbsp;====================
class&amp;nbsp;PlatformApiSimulator:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;模拟各平台订单列表API&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.orders:&amp;nbsp;Dict[str,&amp;nbsp;List[OrderSnapshot]]&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;[],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;[],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket&amp;quot;:&amp;nbsp;[],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;add_order(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;order:&amp;nbsp;OrderSnapshot):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.orders[platform].append(order)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_orders(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;since:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;List[OrderSnapshot]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;模拟拉取平台订单列表（按modified过滤）&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[o&amp;nbsp;for&amp;nbsp;o&amp;nbsp;in&amp;nbsp;self.orders[platform]&amp;nbsp;if&amp;nbsp;o.modified&amp;nbsp;&amp;gt;=&amp;nbsp;since]


#&amp;nbsp;====================&amp;nbsp;ERP存储模拟器&amp;nbsp;====================
class&amp;nbsp;ErpStorageSimulator:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;模拟ERP数据库&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.orders:&amp;nbsp;Dict[str,&amp;nbsp;OrderSnapshot]&amp;nbsp;=&amp;nbsp;{}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;save_order(self,&amp;nbsp;order:&amp;nbsp;OrderSnapshot):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.orders[order.order_id]&amp;nbsp;=&amp;nbsp;order

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_order(self,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;Optional[OrderSnapshot]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.orders.get(order_id)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;delete_order(self,&amp;nbsp;order_id:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.orders.pop(order_id,&amp;nbsp;None)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_all(self)&amp;nbsp;-&amp;gt;&amp;nbsp;List[OrderSnapshot]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;list(self.orders.values())

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_since(self,&amp;nbsp;since:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;List[OrderSnapshot]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[o&amp;nbsp;for&amp;nbsp;o&amp;nbsp;in&amp;nbsp;self.orders.values()&amp;nbsp;if&amp;nbsp;o.modified&amp;nbsp;&amp;gt;=&amp;nbsp;since]


#&amp;nbsp;====================&amp;nbsp;对账引擎&amp;nbsp;====================
class&amp;nbsp;ReconciliationEngine:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;对账引擎
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;拉取平台订单列表（按modified窗口）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;拉取ERP订单列表
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;三层比对：ID级&amp;nbsp;/&amp;nbsp;金额级&amp;nbsp;/&amp;nbsp;状态级
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;输出差异报告
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;platform_apis:&amp;nbsp;Dict[str,&amp;nbsp;PlatformApiSimulator],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp_storage:&amp;nbsp;ErpStorageSimulator):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.platform_apis&amp;nbsp;=&amp;nbsp;platform_apis
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.erp&amp;nbsp;=&amp;nbsp;erp_storage
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.diffs:&amp;nbsp;List[OrderDiff]&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;reconcile(self,&amp;nbsp;platforms:&amp;nbsp;List[str],&amp;nbsp;since:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;&amp;quot;ReconciliationReport&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;执行对账
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Args:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platforms:&amp;nbsp;要对的平台列表
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;since:&amp;nbsp;起始时间戳（毫秒）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Returns:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReconciliationReport:&amp;nbsp;对账报告
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.diffs&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;platform&amp;nbsp;in&amp;nbsp;platforms:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;拉取双方数据
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_orders&amp;nbsp;=&amp;nbsp;self._fetch_platform_orders(platform,&amp;nbsp;since)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp_orders&amp;nbsp;=&amp;nbsp;self._fetch_erp_orders(since)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;构建索引
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_map&amp;nbsp;=&amp;nbsp;{o.order_id:&amp;nbsp;o&amp;nbsp;for&amp;nbsp;o&amp;nbsp;in&amp;nbsp;platform_orders}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp_map&amp;nbsp;=&amp;nbsp;{o.order_id:&amp;nbsp;o&amp;nbsp;for&amp;nbsp;o&amp;nbsp;in&amp;nbsp;erp_orders}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;all_ids&amp;nbsp;=&amp;nbsp;set(list(platform_map.keys())&amp;nbsp;+&amp;nbsp;list(erp_map.keys()))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;逐单比对
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;oid&amp;nbsp;in&amp;nbsp;all_ids:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p_order&amp;nbsp;=&amp;nbsp;platform_map.get(oid)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;e_order&amp;nbsp;=&amp;nbsp;erp_map.get(oid)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;p_order&amp;nbsp;and&amp;nbsp;not&amp;nbsp;e_order:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;丢单：平台有，ERP没有
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.diffs.append(OrderDiff(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff_type=DiffType.MISSING,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=oid,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_order=p_order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail=f&amp;quot;平台有订单&amp;nbsp;{oid}，ERP缺失&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;e_order&amp;nbsp;and&amp;nbsp;not&amp;nbsp;p_order:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;虚单：ERP有，平台没有
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.diffs.append(OrderDiff(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff_type=DiffType.EXTRA,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=oid,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp_order=e_order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail=f&amp;quot;ERP有订单&amp;nbsp;{oid}，平台不存在&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;p_order&amp;nbsp;and&amp;nbsp;e_order:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;两边都有：比对金额和状态
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;abs(p_order.total&amp;nbsp;-&amp;nbsp;e_order.total)&amp;nbsp;&amp;gt;&amp;nbsp;0.01:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.diffs.append(OrderDiff(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff_type=DiffType.AMOUNT_MISMATCH,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=oid,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_order=p_order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp_order=e_order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail=f&amp;quot;金额不一致:&amp;nbsp;平台{p_order.total}&amp;nbsp;vs&amp;nbsp;ERP{e_order.total}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;p_order.status&amp;nbsp;!=&amp;nbsp;e_order.status:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.diffs.append(OrderDiff(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff_type=DiffType.STATUS_MISMATCH,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=oid,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_order=p_order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp_order=e_order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail=f&amp;quot;状态不一致:&amp;nbsp;平台{p_order.status}&amp;nbsp;vs&amp;nbsp;ERP{e_order.status}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;ReconciliationReport(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_count=len(platforms),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_count_total=len(set(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;o.order_id&amp;nbsp;for&amp;nbsp;p&amp;nbsp;in&amp;nbsp;platforms
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;o&amp;nbsp;in&amp;nbsp;self._fetch_platform_orders(p,&amp;nbsp;since)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff_count=len(self.diffs),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diffs=self.diffs,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;generated_at=datetime.now(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_fetch_platform_orders(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;since:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;List[OrderSnapshot]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;api&amp;nbsp;=&amp;nbsp;self.platform_apis.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;api:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;api.fetch_orders(platform,&amp;nbsp;since)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_fetch_erp_orders(self,&amp;nbsp;since:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;List[OrderSnapshot]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.erp.fetch_since(since)


#&amp;nbsp;====================&amp;nbsp;对账报告&amp;nbsp;====================
@dataclass
class&amp;nbsp;ReconciliationReport:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;对账报告&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_count:&amp;nbsp;int
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_count_total:&amp;nbsp;int
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff_count:&amp;nbsp;int
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diffs:&amp;nbsp;List[OrderDiff]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;generated_at:&amp;nbsp;datetime

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;summary(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;missing&amp;nbsp;=&amp;nbsp;sum(1&amp;nbsp;for&amp;nbsp;d&amp;nbsp;in&amp;nbsp;self.diffs&amp;nbsp;if&amp;nbsp;d.diff_type&amp;nbsp;==&amp;nbsp;DiffType.MISSING)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;extra&amp;nbsp;=&amp;nbsp;sum(1&amp;nbsp;for&amp;nbsp;d&amp;nbsp;in&amp;nbsp;self.diffs&amp;nbsp;if&amp;nbsp;d.diff_type&amp;nbsp;==&amp;nbsp;DiffType.EXTRA)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status&amp;nbsp;=&amp;nbsp;sum(1&amp;nbsp;for&amp;nbsp;d&amp;nbsp;in&amp;nbsp;self.diffs&amp;nbsp;if&amp;nbsp;d.diff_type&amp;nbsp;==&amp;nbsp;DiffType.STATUS_MISMATCH)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;amount&amp;nbsp;=&amp;nbsp;sum(1&amp;nbsp;for&amp;nbsp;d&amp;nbsp;in&amp;nbsp;self.diffs&amp;nbsp;if&amp;nbsp;d.diff_type&amp;nbsp;==&amp;nbsp;DiffType.AMOUNT_MISMATCH)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lines&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;对账报告&amp;nbsp;({self.generated_at.strftime(&amp;#39;%Y-%m-%d&amp;nbsp;%H:%M&amp;#39;)})&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;nbsp;&amp;nbsp;平台数:&amp;nbsp;{self.platform_count}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;nbsp;&amp;nbsp;总订单数:&amp;nbsp;{self.order_count_total}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;nbsp;&amp;nbsp;差异总数:&amp;nbsp;{self.diff_count}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;丢单(MISSING):&amp;nbsp;{missing}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;虚单(EXTRA):&amp;nbsp;{extra}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;状态不一致:&amp;nbsp;{status}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;金额不一致:&amp;nbsp;{amount}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;\n&amp;quot;.join(lines)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;to_dict(self)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;generated_at&amp;quot;:&amp;nbsp;self.generated_at.isoformat(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;platform_count&amp;quot;:&amp;nbsp;self.platform_count,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_count_total&amp;quot;:&amp;nbsp;self.order_count_total,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;diff_count&amp;quot;:&amp;nbsp;self.diff_count,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;diffs&amp;quot;:&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;type&amp;quot;:&amp;nbsp;d.diff_type.value,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;platform&amp;quot;:&amp;nbsp;d.platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;d.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;detail&amp;quot;:&amp;nbsp;d.detail,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;d&amp;nbsp;in&amp;nbsp;self.diffs
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}


#&amp;nbsp;====================&amp;nbsp;自动补偿器&amp;nbsp;====================
class&amp;nbsp;AutoCompensator:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;自动补偿器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;丢单&amp;nbsp;→&amp;nbsp;创建订单（调用IdempotentConsumer）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;虚单&amp;nbsp;→&amp;nbsp;关闭订单（释放库存）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;金额/状态不一致&amp;nbsp;→&amp;nbsp;以平台为准修正
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;阈值控制：超过阈值只告警不自动补偿
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;erp:&amp;nbsp;ErpStorageSimulator,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auto_fix_threshold:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;10):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.erp&amp;nbsp;=&amp;nbsp;erp
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.auto_fix_threshold&amp;nbsp;=&amp;nbsp;auto_fix_threshold&amp;nbsp;&amp;nbsp;#&amp;nbsp;超过N条差异只告警不自动修
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.compensation_log:&amp;nbsp;List[dict]&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;compensate(self,&amp;nbsp;report:&amp;nbsp;ReconciliationReport)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;执行自动补偿
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Returns:&amp;nbsp;补偿结果摘要
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;report.diff_count&amp;nbsp;&amp;gt;&amp;nbsp;self.auto_fix_threshold:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;alert_only&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;reason&amp;quot;:&amp;nbsp;f&amp;quot;差异数量&amp;nbsp;{report.diff_count}&amp;nbsp;超过阈值&amp;nbsp;{self.auto_fix_threshold}，仅告警&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;compensated&amp;quot;:&amp;nbsp;0,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compensated&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;diff&amp;nbsp;in&amp;nbsp;report.diffs:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;self._handle_diff(diff)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;result:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compensated&amp;nbsp;+=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.compensation_log.append(result)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;auto_compensated&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;compensated&amp;quot;:&amp;nbsp;compensated,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;total_diffs&amp;quot;:&amp;nbsp;report.diff_count,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;log&amp;quot;:&amp;nbsp;self.compensation_log[-10:],&amp;nbsp;&amp;nbsp;#&amp;nbsp;最近10条
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_handle_diff(self,&amp;nbsp;diff:&amp;nbsp;OrderDiff)&amp;nbsp;-&amp;gt;&amp;nbsp;Optional[dict]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;处理单条差异&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;diff.diff_type&amp;nbsp;==&amp;nbsp;DiffType.MISSING:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._fix_missing(diff)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;diff.diff_type&amp;nbsp;==&amp;nbsp;DiffType.EXTRA:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._fix_extra(diff)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;diff.diff_type&amp;nbsp;==&amp;nbsp;DiffType.AMOUNT_MISMATCH:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._fix_amount(diff)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;diff.diff_type&amp;nbsp;==&amp;nbsp;DiffType.STATUS_MISMATCH:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._fix_status(diff)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;diff.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;failed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;error&amp;quot;:&amp;nbsp;str(e),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_fix_missing(self,&amp;nbsp;diff:&amp;nbsp;OrderDiff)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;丢单补偿：以平台为准创建订单&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p&amp;nbsp;=&amp;nbsp;diff.platform_order
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.erp.save_order(OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=p.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=p.platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=p.status,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total=p.total,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=p.currency,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=p.sku,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=p.quantity,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified=p.modified,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw=p.raw,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;diff.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;created&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;detail&amp;quot;:&amp;nbsp;f&amp;quot;从平台同步缺失订单&amp;nbsp;{diff.order_id}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_fix_extra(self,&amp;nbsp;diff:&amp;nbsp;OrderDiff)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;虚单补偿：关闭ERP订单，释放库存&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;e&amp;nbsp;=&amp;nbsp;diff.erp_order
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;标记为已取消
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.erp.save_order(OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=e.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=e.platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;cancelled&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total=e.total,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=e.currency,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=e.sku,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=e.quantity,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified=int(time.time()&amp;nbsp;*&amp;nbsp;1000),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw=e.raw,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;diff.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;cancelled&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;detail&amp;quot;:&amp;nbsp;f&amp;quot;平台不存在订单&amp;nbsp;{diff.order_id}，ERP标记为取消&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_fix_amount(self,&amp;nbsp;diff:&amp;nbsp;OrderDiff)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;金额不一致：以平台为准修正&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p&amp;nbsp;=&amp;nbsp;diff.platform_order
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.erp.save_order(OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=p.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=p.platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=p.status,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total=p.total,&amp;nbsp;&amp;nbsp;#&amp;nbsp;用平台的金额覆盖
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=p.currency,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=p.sku,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=p.quantity,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified=int(time.time()&amp;nbsp;*&amp;nbsp;1000),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw=p.raw,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;diff.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;amount_fixed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;detail&amp;quot;:&amp;nbsp;f&amp;quot;金额从&amp;nbsp;{diff.erp_order.total}&amp;nbsp;修正为&amp;nbsp;{p.total}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_fix_status(self,&amp;nbsp;diff:&amp;nbsp;OrderDiff)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;状态不一致：以平台为准修正&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;p&amp;nbsp;=&amp;nbsp;diff.platform_order
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.erp.save_order(OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=p.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=p.platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=p.status,&amp;nbsp;&amp;nbsp;#&amp;nbsp;用平台的状态覆盖
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total=p.total,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=p.currency,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=p.sku,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=p.quantity,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified=int(time.time()&amp;nbsp;*&amp;nbsp;1000),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw=p.raw,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;diff.order_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;status_fixed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;detail&amp;quot;:&amp;nbsp;f&amp;quot;状态从&amp;nbsp;{diff.erp_order.status}&amp;nbsp;修正为&amp;nbsp;{p.status}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}


#&amp;nbsp;====================&amp;nbsp;对账调度器&amp;nbsp;====================
class&amp;nbsp;ReconciliationScheduler:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;对账调度器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;每日凌晨2:00自动执行
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;支持手动触发
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;对账结果通知（邮件/企微/飞书）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;engine:&amp;nbsp;ReconciliationEngine,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compensator:&amp;nbsp;AutoCompensator,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platforms:&amp;nbsp;List[str]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.engine&amp;nbsp;=&amp;nbsp;engine
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.compensator&amp;nbsp;=&amp;nbsp;compensator
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.platforms&amp;nbsp;=&amp;nbsp;platforms
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.history:&amp;nbsp;List[dict]&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;run_daily(self)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;执行每日对账&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;对账窗口：过去24小时
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;since&amp;nbsp;=&amp;nbsp;int((datetime.now()&amp;nbsp;-&amp;nbsp;timedelta(hours=24)).timestamp()&amp;nbsp;*&amp;nbsp;1000)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[RECONCILE]&amp;nbsp;开始每日对账&amp;nbsp;({datetime.now().strftime(&amp;#39;%Y-%m-%d&amp;nbsp;%H:%M&amp;#39;)})&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;窗口:&amp;nbsp;{datetime.fromtimestamp(since/1000)}&amp;nbsp;~&amp;nbsp;现在&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;执行对账
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;report&amp;nbsp;=&amp;nbsp;self.engine.reconcile(self.platforms,&amp;nbsp;since)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;输出摘要
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(report.summary())

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;自动补偿
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compensation&amp;nbsp;=&amp;nbsp;self.compensator.compensate(report)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;记录历史
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;run_at&amp;quot;:&amp;nbsp;datetime.now(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;report&amp;quot;:&amp;nbsp;report.to_dict(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;compensation&amp;quot;:&amp;nbsp;compensation,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.history.append(result)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;如果有差异，发送通知
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;report.diff_count&amp;nbsp;&amp;gt;&amp;nbsp;0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._notify(report,&amp;nbsp;compensation)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;run_manual(self,&amp;nbsp;hours:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;48)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;手动触发对账&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;since&amp;nbsp;=&amp;nbsp;int((datetime.now()&amp;nbsp;-&amp;nbsp;timedelta(hours=hours)).timestamp()&amp;nbsp;*&amp;nbsp;1000)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[MANUAL]&amp;nbsp;手动对账，窗口:&amp;nbsp;{hours}小时&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;report&amp;nbsp;=&amp;nbsp;self.engine.reconcile(self.platforms,&amp;nbsp;since)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compensation&amp;nbsp;=&amp;nbsp;self.compensator.compensate(report)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;report&amp;quot;:&amp;nbsp;report.to_dict(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;compensation&amp;quot;:&amp;nbsp;compensation,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_notify(self,&amp;nbsp;report:&amp;nbsp;ReconciliationReport,&amp;nbsp;compensation:&amp;nbsp;dict):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;发送通知（模拟）&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n[NOTIFY]&amp;nbsp;对账完成，发现&amp;nbsp;{report.diff_count}&amp;nbsp;条差异&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;compensation.get(&amp;quot;action&amp;quot;)&amp;nbsp;==&amp;nbsp;&amp;quot;alert_only&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[NOTIFY]&amp;nbsp;⚠️&amp;nbsp;差异过多，需人工介入&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[NOTIFY]&amp;nbsp;✅&amp;nbsp;自动补偿&amp;nbsp;{compensation.get(&amp;#39;compensated&amp;#39;)}&amp;nbsp;条&amp;quot;)

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;演示&amp;nbsp;====================
if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;62)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;二手ERP对账机制：按日巡检&amp;nbsp;+&amp;nbsp;自动补偿&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;62)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;初始化数据
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_apis&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;PlatformApiSimulator(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;PlatformApiSimulator(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket&amp;quot;:&amp;nbsp;PlatformApiSimulator(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp&amp;nbsp;=&amp;nbsp;ErpStorageSimulator()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;模拟平台订单（制造各种差异）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;now&amp;nbsp;=&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;正常订单（两边都有）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;normal_order&amp;nbsp;=&amp;nbsp;OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=&amp;quot;ORD-NORMAL-001&amp;quot;,&amp;nbsp;platform=&amp;quot;xianyu&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;paid&amp;quot;,&amp;nbsp;total=5999.00,&amp;nbsp;currency=&amp;quot;CNY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;IP14P-256&amp;quot;,&amp;nbsp;quantity=1,&amp;nbsp;modified=now&amp;nbsp;-&amp;nbsp;60000,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw={},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_apis[&amp;quot;xianyu&amp;quot;].add_order(normal_order)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp.save_order(normal_order)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;丢单：平台有，ERP没有
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;missing_order&amp;nbsp;=&amp;nbsp;OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=&amp;quot;ORD-MISSING-001&amp;quot;,&amp;nbsp;platform=&amp;quot;xianyu&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;paid&amp;quot;,&amp;nbsp;total=4599.00,&amp;nbsp;currency=&amp;quot;CNY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;IP13-128&amp;quot;,&amp;nbsp;quantity=1,&amp;nbsp;modified=now&amp;nbsp;-&amp;nbsp;70000,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw={},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_apis[&amp;quot;xianyu&amp;quot;].add_order(missing_order)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;ERP故意不保存

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;虚单：ERP有，平台没有
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;extra_order&amp;nbsp;=&amp;nbsp;OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=&amp;quot;ORD-EXTRA-001&amp;quot;,&amp;nbsp;platform=&amp;quot;xianyu&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;paid&amp;quot;,&amp;nbsp;total=3299.00,&amp;nbsp;currency=&amp;quot;CNY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;SE3-64&amp;quot;,&amp;nbsp;quantity=1,&amp;nbsp;modified=now&amp;nbsp;-&amp;nbsp;80000,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw={},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp.save_order(extra_order)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;平台故意不加

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;金额不一致
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;amount_platform&amp;nbsp;=&amp;nbsp;OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=&amp;quot;ORD-AMOUNT-001&amp;quot;,&amp;nbsp;platform=&amp;quot;mercari&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;paid&amp;quot;,&amp;nbsp;total=45000.00,&amp;nbsp;currency=&amp;quot;JPY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;IP14P-256&amp;quot;,&amp;nbsp;quantity=1,&amp;nbsp;modified=now&amp;nbsp;-&amp;nbsp;40000,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw={},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;amount_erp&amp;nbsp;=&amp;nbsp;OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=&amp;quot;ORD-AMOUNT-001&amp;quot;,&amp;nbsp;platform=&amp;quot;mercari&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;paid&amp;quot;,&amp;nbsp;total=44800.00,&amp;nbsp;currency=&amp;quot;JPY&amp;quot;,&amp;nbsp;&amp;nbsp;#&amp;nbsp;少了200日元
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;IP14P-256&amp;quot;,&amp;nbsp;quantity=1,&amp;nbsp;modified=now&amp;nbsp;-&amp;nbsp;38000,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw={},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_apis[&amp;quot;mercari&amp;quot;].add_order(amount_platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp.save_order(amount_erp)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;状态不一致
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status_platform&amp;nbsp;=&amp;nbsp;OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=&amp;quot;ORD-STATUS-001&amp;quot;,&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;shipped&amp;quot;,&amp;nbsp;total=899.99,&amp;nbsp;currency=&amp;quot;EUR&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;MBP-M3-512&amp;quot;,&amp;nbsp;quantity=1,&amp;nbsp;modified=now&amp;nbsp;-&amp;nbsp;25000,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw={},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status_erp&amp;nbsp;=&amp;nbsp;OrderSnapshot(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=&amp;quot;ORD-STATUS-001&amp;quot;,&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=&amp;quot;paid&amp;quot;,&amp;nbsp;total=899.99,&amp;nbsp;currency=&amp;quot;EUR&amp;quot;,&amp;nbsp;&amp;nbsp;#&amp;nbsp;还在paid
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;MBP-M3-512&amp;quot;,&amp;nbsp;quantity=1,&amp;nbsp;modified=now&amp;nbsp;-&amp;nbsp;26000,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw={},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_apis[&amp;quot;backmarket&amp;quot;].add_order(status_platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;erp.save_order(status_erp)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;执行对账
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;engine&amp;nbsp;=&amp;nbsp;ReconciliationEngine(platform_apis,&amp;nbsp;erp)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compensator&amp;nbsp;=&amp;nbsp;AutoCompensator(erp,&amp;nbsp;auto_fix_threshold=10)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scheduler&amp;nbsp;=&amp;nbsp;ReconciliationScheduler(engine,&amp;nbsp;compensator,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;backmarket&amp;quot;])

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*62}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;执行每日对账...&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*62}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;scheduler.run_daily()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;展示补偿结果
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*62}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;补偿后的ERP状态&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*62}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;order&amp;nbsp;in&amp;nbsp;erp.fetch_all():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{order.order_id:25s}&amp;nbsp;|&amp;nbsp;{order.status:12s}&amp;nbsp;|&amp;nbsp;{order.total:&amp;gt;8.2f}&amp;nbsp;{order.currency}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;展示补偿日志
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*62}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;补偿日志&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*62}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;log&amp;nbsp;in&amp;nbsp;compensator.compensation_log:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;[{log[&amp;#39;action&amp;#39;]:15s}]&amp;nbsp;{log[&amp;#39;order_id&amp;#39;]:25s}&amp;nbsp;|&amp;nbsp;{log.get(&amp;#39;detail&amp;#39;,&amp;nbsp;&amp;#39;&amp;#39;)}&amp;quot;)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;运行结果：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;==============================================================
&amp;nbsp;&amp;nbsp;二手ERP对账机制：按日巡检&amp;nbsp;+&amp;nbsp;自动补偿
==============================================================

──────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;执行每日对账...
──────────────────────────────────────────────────────────────
[RECONCILE]&amp;nbsp;开始每日对账&amp;nbsp;(2026-09-19&amp;nbsp;02:00)
&amp;nbsp;&amp;nbsp;窗口:&amp;nbsp;2026-09-18&amp;nbsp;02:00&amp;nbsp;~&amp;nbsp;现在
对账报告&amp;nbsp;(2026-09-19&amp;nbsp;02:00)
&amp;nbsp;&amp;nbsp;平台数:&amp;nbsp;3
&amp;nbsp;&amp;nbsp;总订单数:&amp;nbsp;4
&amp;nbsp;&amp;nbsp;差异总数:&amp;nbsp;4
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;丢单(MISSING):&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;虚单(EXTRA):&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;状态不一致:&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;金额不一致:&amp;nbsp;1

[NOTIFY]&amp;nbsp;对账完成，发现&amp;nbsp;4&amp;nbsp;条差异
[NOTIFY]&amp;nbsp;✅&amp;nbsp;自动补偿&amp;nbsp;4&amp;nbsp;条

──────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;补偿后的ERP状态
──────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;ORD-NORMAL-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;paid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;5999.00&amp;nbsp;CNY
&amp;nbsp;&amp;nbsp;ORD-MISSING-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;paid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;4599.00&amp;nbsp;CNY&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;已创建
&amp;nbsp;&amp;nbsp;ORD-EXTRA-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;cancelled&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;3299.00&amp;nbsp;CNY&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;已取消
&amp;nbsp;&amp;nbsp;ORD-AMOUNT-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;paid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;45000.00&amp;nbsp;JPY&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;金额已修正
&amp;nbsp;&amp;nbsp;ORD-STATUS-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;shipped&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;899.99&amp;nbsp;EUR&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;状态已修正

──────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;补偿日志
──────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;[created&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]&amp;nbsp;ORD-MISSING-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;从平台同步缺失订单&amp;nbsp;ORD-MISSING-001
&amp;nbsp;&amp;nbsp;[cancelled&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]&amp;nbsp;ORD-EXTRA-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;平台不存在订单&amp;nbsp;ORD-EXTRA-001，ERP标记为取消
&amp;nbsp;&amp;nbsp;[amount_fixed&amp;nbsp;&amp;nbsp;&amp;nbsp;]&amp;nbsp;ORD-AMOUNT-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;金额从&amp;nbsp;44800.0&amp;nbsp;修正为&amp;nbsp;45000.0
&amp;nbsp;&amp;nbsp;[status_fixed&amp;nbsp;&amp;nbsp;&amp;nbsp;]&amp;nbsp;ORD-STATUS-001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;状态从&amp;nbsp;paid&amp;nbsp;修正为&amp;nbsp;shipped&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;四、对账阈值与告警策略&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;差异数量&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;动作&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;说明&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;0&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;无操作&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;一切正常&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;1-10&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;自动补偿 + 通知&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;小差异，系统自动修复&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;11-50&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;仅告警，不自动补偿&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;可能有批量问题，需人工确认&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;50+&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;紧急告警 + 暂停对账&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;可能是API故障或数据迁移问题&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;五、对账窗口设计&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;窗口&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;用途&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;说明&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;T-24h&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;每日对账&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;覆盖昨天的全部订单&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;T-7d&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;每周深度对账&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;检查退款/退货等长周期流程&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;T-1h&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;实时补偿（可选）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;高价值订单单独对账&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;二手ERP建议&lt;/strong&gt;：每日对账就够了。实时对账的成本远高于收益——二手订单单价低（&lt;span class=&quot;ybc-markdown-katex&quot; data-latex=&quot;50-&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;/span&gt;500），一天差几单不会造成重大损失。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;六、和前22篇的衔接&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;IdempotentConsumer&lt;/code&gt;&lt;/strong&gt;：补偿器创建缺失订单时，调用幂等消费器防止重复&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt;&lt;/strong&gt;：对账发现的差异可以发布为 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;reconciliation.diff_found&lt;/code&gt; 事件&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GrayReleaseRouter&lt;/code&gt;&lt;/strong&gt;：自动补偿可以灰度开启（先补偿闲鱼，再补偿Mercari）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PushListener/PullWorker&lt;/code&gt;&lt;/strong&gt;：对账是Push/Pull的兜底——消息丢了，对账捞回来&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;cross_border_schema.FieldMapper&lt;/code&gt;&lt;/strong&gt;：对账时拉取的平台数据通过FieldMapper转成统一格式&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;七、一句话收口&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;“幽灵订单”不是Bug，是分布式系统的必然产物。&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;消息会丢、回调会断、轮询会漏——&lt;strong&gt;对账不是可选项，是生产系统的必备组件&lt;/strong&gt;。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;按日巡检 + 自动补偿，用最小的成本覆盖99%的差异，剩下的1%交给人工处理。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;核心原则：&lt;strong&gt;以平台为准，ERP跟随，差异自动修，阈值外告警&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我接着把这个对账机制整合进 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/reconciliation/&lt;/code&gt; 模块，包含：&lt;/div&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;对账报告Web展示（差异列表 + 一键补偿）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;钉钉/企微/飞书通知模板&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;与前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt; 的集成（对账事件触发下游补偿流程）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;历史对账趋势图表（差异数量随时间变化）&amp;nbsp;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 18 Sep 2026 17:57:12 +0800</pubDate></item><item><title>《接口变更管理：电商平台API一升级，你的ERP代码就要改？适配器模式破局》（附Python源码）</title><link>https://www.alexob.com/?id=543</link><description>&lt;h1&gt;《接口变更管理：电商平台API一升级，你的ERP代码就要改？适配器模式破局》（附Python源码）&lt;/h1&gt;&lt;div class=&quot;ybc-p&quot;&gt;先拍结论：&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;电商平台API升级不可怕，可怕的是你的业务代码里到处散落着 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;response[&amp;quot;data&amp;quot;][&amp;quot;items&amp;quot;][0][&amp;quot;price&amp;quot;]&lt;/code&gt;。&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;适配器模式的核心不是“加一层”，而是&lt;strong&gt;把平台差异锁死在适配器内部&lt;/strong&gt;——平台改API，只改适配器；业务逻辑一行不动。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;二手ERP尤其需要这个：闲鱼、Mercari、Back Market、eBay四个平台，每个每年至少2-3次breaking change，没有适配器就是改不完的bug。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;一、平台API变更的四种痛法&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;类型&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;例子&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;不改适配器的后果&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;字段改名&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;item_price&lt;/code&gt; → &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;price_amount&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;业务代码 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;order[&amp;quot;item_price&amp;quot;]&lt;/code&gt; 全挂&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;数据结构重组&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;平铺变嵌套：&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;price&lt;/code&gt; → &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;pricing.total.amount&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;取值链断掉&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;分页参数变更&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;page&lt;/code&gt; → &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;cursor&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;全量翻页逻辑重写&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;认证方式变更&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;Token → OAuth2&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;每个请求都要改header构造&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;适配器模式的承诺&lt;/strong&gt;：以上四种变更，&lt;strong&gt;只改适配器，不改一行业务代码&lt;/strong&gt;。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;二、适配器模式核心：三层隔离&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;┌─────────────────────────────────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;业务逻辑层&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;订单处理&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;库存同步&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;定价引擎&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;报表统计&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;(只认&amp;nbsp;InternalOrder&amp;nbsp;/&amp;nbsp;InternalProduct)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────────────────────┬──────────────────────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;统一接口
┌──────────────────────────▼──────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;适配器抽象层&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;PlatformAdapter&amp;nbsp;(ABC)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+&amp;nbsp;fetch_order(order_id)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalOrder&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+&amp;nbsp;sync_listing(product)&amp;nbsp;-&amp;gt;&amp;nbsp;ListingResult&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+&amp;nbsp;update_inventory(sku,&amp;nbsp;qty)&amp;nbsp;-&amp;gt;&amp;nbsp;bool&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────┬──────────────┬──────────────┬────────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
┌──────────▼──┐&amp;nbsp;&amp;nbsp;┌────────▼──────┐&amp;nbsp;&amp;nbsp;┌───▼─────────────┐
│&amp;nbsp;XianyuAdapter│&amp;nbsp;&amp;nbsp;│&amp;nbsp;MercariAdapter│&amp;nbsp;&amp;nbsp;│&amp;nbsp;BackMarketAdapter│
│&amp;nbsp;v2.3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;v1.8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;v3.1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;(闲鱼API&amp;nbsp;2026)│&amp;nbsp;&amp;nbsp;│&amp;nbsp;(Mercari&amp;nbsp;API)&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;(BM&amp;nbsp;API&amp;nbsp;v3)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────────┘&amp;nbsp;&amp;nbsp;└───────────────┘&amp;nbsp;&amp;nbsp;└──────────────────┘&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;规则&lt;/strong&gt;：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;业务层 &lt;strong&gt;只知道 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalOrder&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalProduct&lt;/code&gt;&lt;/strong&gt;，不知道 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;tradeDTO&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;itemPayload&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;listingResponse&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;适配器层 &lt;strong&gt;只负责翻译&lt;/strong&gt;，不做业务判断&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;平台API升级 → &lt;strong&gt;只换对应适配器的实现类&lt;/strong&gt;，业务代码零改动&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;三、完整源码：适配器模式 + 版本兼容 + 优雅降级&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;adapter_pattern.py
&amp;quot;&amp;quot;&amp;quot;
电商平台适配器模式
-&amp;nbsp;PlatformAdapter:&amp;nbsp;抽象基类（统一接口）
-&amp;nbsp;XianyuAdapter&amp;nbsp;/&amp;nbsp;MercariAdapter&amp;nbsp;/&amp;nbsp;BackMarketAdapter:&amp;nbsp;具体实现
-&amp;nbsp;AdapterRegistry:&amp;nbsp;按平台+版本注册
-&amp;nbsp;VersionMigration:&amp;nbsp;API版本迁移工具
-&amp;nbsp;FallbackChain:&amp;nbsp;降级策略（新版本挂了切旧版本）
&amp;quot;&amp;quot;&amp;quot;
import&amp;nbsp;abc
import&amp;nbsp;time
import&amp;nbsp;json
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional,&amp;nbsp;Tuple
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum


#&amp;nbsp;====================&amp;nbsp;统一数据模型（业务层只认这些）&amp;nbsp;====================
@dataclass
class&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity:&amp;nbsp;int
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price:&amp;nbsp;float
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyer_name:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shipping_address:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;created_at:&amp;nbsp;datetime&amp;nbsp;=&amp;nbsp;field(default_factory=datetime.now)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_raw:&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;field(default_factory=dict)&amp;nbsp;&amp;nbsp;#&amp;nbsp;原始数据存档

@dataclass
class&amp;nbsp;InternalProduct:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;title:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;description:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price:&amp;nbsp;float
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stock:&amp;nbsp;int
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;images:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;attributes:&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;field(default_factory=dict)

@dataclass
class&amp;nbsp;ListingResult:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success:&amp;nbsp;bool
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_listing_id:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;errors:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)


#&amp;nbsp;====================&amp;nbsp;适配器抽象基类&amp;nbsp;====================
class&amp;nbsp;PlatformAdapter(abc.ABC):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;所有平台适配器必须实现的接口&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@abc.abstractmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_order(self,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@abc.abstractmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;sync_listing(self,&amp;nbsp;product:&amp;nbsp;InternalProduct)&amp;nbsp;-&amp;gt;&amp;nbsp;ListingResult:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@abc.abstractmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;update_inventory(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;quantity:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@abc.abstractmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;适配器版本号，例如&amp;nbsp;&amp;#39;v2.3&amp;#39;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@abc.abstractmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;api_version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;对接的平台API版本，例如&amp;nbsp;&amp;#39;2026-03&amp;#39;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...


#&amp;nbsp;====================&amp;nbsp;闲鱼适配器（v2.3&amp;nbsp;→&amp;nbsp;对接闲鱼API&amp;nbsp;2026版）&amp;nbsp;====================
class&amp;nbsp;XianyuAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;闲鱼开放平台适配器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;API文档:&amp;nbsp;https://open.taobao.com/doc.htm?docId=109675
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v2.3&amp;nbsp;变更记录:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;2026-03:&amp;nbsp;tradeDTO.item_price&amp;nbsp;→&amp;nbsp;tradeDTO.price_info.amount
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;2026-06:&amp;nbsp;分页从&amp;nbsp;page_size/page_no&amp;nbsp;改为&amp;nbsp;cursor
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;app_key:&amp;nbsp;str,&amp;nbsp;app_secret:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_key&amp;nbsp;=&amp;nbsp;app_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.app_secret&amp;nbsp;=&amp;nbsp;app_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._version&amp;nbsp;=&amp;nbsp;&amp;quot;2.3&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._api_version&amp;nbsp;=&amp;nbsp;&amp;quot;2026-06&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._version

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;api_version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._api_version

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_order(self,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;调用闲鱼&amp;nbsp;taobao.idle.order.detail.get&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;实际调用API，这里模拟返回
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_response&amp;nbsp;=&amp;nbsp;self._call_api(&amp;quot;taobao.idle.order.detail.get&amp;quot;,&amp;nbsp;{&amp;quot;order_id&amp;quot;:&amp;nbsp;order_id})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;★★★&amp;nbsp;适配器内部：平台数据结构&amp;nbsp;→&amp;nbsp;统一模型&amp;nbsp;★★★
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;trade&amp;nbsp;=&amp;nbsp;raw_response.get(&amp;quot;data&amp;quot;,&amp;nbsp;{}).get(&amp;quot;tradeDTO&amp;quot;,&amp;nbsp;{})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;v2.3&amp;nbsp;适配：price_info.amount（2026-03改的）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price_info&amp;nbsp;=&amp;nbsp;trade.get(&amp;quot;price_info&amp;quot;,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price&amp;nbsp;=&amp;nbsp;float(price_info.get(&amp;quot;amount&amp;quot;,&amp;nbsp;0))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalOrder(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=trade.get(&amp;quot;tid&amp;quot;,&amp;nbsp;order_id),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=&amp;quot;xianyu&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=trade.get(&amp;quot;item_sku&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=int(trade.get(&amp;quot;num&amp;quot;,&amp;nbsp;1)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price=price,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=&amp;quot;CNY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=self._map_status(trade.get(&amp;quot;trade_status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyer_name=trade.get(&amp;quot;receiver_name&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shipping_address=trade.get(&amp;quot;receiver_address&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_raw=trade,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;sync_listing(self,&amp;nbsp;product:&amp;nbsp;InternalProduct)&amp;nbsp;-&amp;gt;&amp;nbsp;ListingResult:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;调用闲鱼&amp;nbsp;taobao.idle.item.publish&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;组装平台要求的请求体
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;request_body&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;item&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;product.sku,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;product.title,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;product.description,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;str(product.price),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;product.currency,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;product.stock,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;images&amp;quot;:&amp;nbsp;product.images,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(&amp;quot;taobao.idle.item.publish&amp;quot;,&amp;nbsp;request_body)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item_id&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;data&amp;quot;,&amp;nbsp;{}).get(&amp;quot;item_id&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;ListingResult(success=bool(item_id),&amp;nbsp;platform_listing_id=item_id)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;update_inventory(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;quantity:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(&amp;quot;taobao.idle.item.stock.update&amp;quot;,&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;sku,&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;quantity
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;raw.get(&amp;quot;success&amp;quot;,&amp;nbsp;False)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_call_api(self,&amp;nbsp;method:&amp;nbsp;str,&amp;nbsp;params:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;真实的HTTP调用，这里模拟返回&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;data&amp;quot;:&amp;nbsp;{&amp;quot;tradeDTO&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;tid&amp;quot;:&amp;nbsp;&amp;quot;XY-ORDER-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;item_sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;num&amp;quot;:&amp;nbsp;&amp;quot;1&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price_info&amp;quot;:&amp;nbsp;{&amp;quot;amount&amp;quot;:&amp;nbsp;&amp;quot;5999.00&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;trade_status&amp;quot;:&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;receiver_name&amp;quot;:&amp;nbsp;&amp;quot;张先生&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;receiver_address&amp;quot;:&amp;nbsp;&amp;quot;广东省深圳市南山区科技园&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}}}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_map_status(self,&amp;nbsp;status:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapping&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;:&amp;nbsp;&amp;quot;paid&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;WAIT_BUYER_CONFIRM_GOODS&amp;quot;:&amp;nbsp;&amp;quot;shipped&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;TRADE_FINISHED&amp;quot;:&amp;nbsp;&amp;quot;completed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;TRADE_CLOSED&amp;quot;:&amp;nbsp;&amp;quot;cancelled&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;mapping.get(status,&amp;nbsp;&amp;quot;unknown&amp;quot;)


#&amp;nbsp;====================&amp;nbsp;Mercari适配器（v1.8&amp;nbsp;→&amp;nbsp;对接Mercari&amp;nbsp;JP&amp;nbsp;API）&amp;nbsp;====================
class&amp;nbsp;MercariAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mercari&amp;nbsp;JP&amp;nbsp;适配器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;API文档:&amp;nbsp;https://www.mercari.com/jp/developer/
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v1.8&amp;nbsp;变更记录:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;2026-04:&amp;nbsp;listingPayload&amp;nbsp;→&amp;nbsp;itemPayload&amp;nbsp;(字段路径变化)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;2026-07:&amp;nbsp;认证从&amp;nbsp;Bearer&amp;nbsp;token&amp;nbsp;改为&amp;nbsp;OAuth2
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;access_token:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.access_token&amp;nbsp;=&amp;nbsp;access_token
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._version&amp;nbsp;=&amp;nbsp;&amp;quot;1.8&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._api_version&amp;nbsp;=&amp;nbsp;&amp;quot;2026-07&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._version

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;api_version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._api_version

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_order(self,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(f&amp;quot;/v2/orders/{order_id}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;v1.8&amp;nbsp;适配：itemPayload（2026-04改的）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;itemPayload&amp;quot;,&amp;nbsp;raw.get(&amp;quot;listingPayload&amp;quot;,&amp;nbsp;{}))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalOrder(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=raw.get(&amp;quot;id&amp;quot;,&amp;nbsp;order_id),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=&amp;quot;mercari&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=item.get(&amp;quot;sku&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=int(raw.get(&amp;quot;quantity&amp;quot;,&amp;nbsp;1)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price=float(raw.get(&amp;quot;totalPrice&amp;quot;,&amp;nbsp;{}).get(&amp;quot;amount&amp;quot;,&amp;nbsp;0)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=raw.get(&amp;quot;totalPrice&amp;quot;,&amp;nbsp;{}).get(&amp;quot;currency&amp;quot;,&amp;nbsp;&amp;quot;JPY&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=raw.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyer_name=raw.get(&amp;quot;buyer&amp;quot;,&amp;nbsp;{}).get(&amp;quot;displayName&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_raw=raw,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;sync_listing(self,&amp;nbsp;product:&amp;nbsp;InternalProduct)&amp;nbsp;-&amp;gt;&amp;nbsp;ListingResult:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(&amp;quot;/v2/listings&amp;quot;,&amp;nbsp;method=&amp;quot;POST&amp;quot;,&amp;nbsp;body={
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;itemPayload&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;product.sku,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;product.title,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;{&amp;quot;amount&amp;quot;:&amp;nbsp;str(product.price),&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;product.currency},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;stock&amp;quot;:&amp;nbsp;product.stock,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lid&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;id&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;ListingResult(success=bool(lid),&amp;nbsp;platform_listing_id=lid)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;update_inventory(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;quantity:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(f&amp;quot;/v2/inventory/{sku}&amp;quot;,&amp;nbsp;method=&amp;quot;PATCH&amp;quot;,&amp;nbsp;body={&amp;quot;stock&amp;quot;:&amp;nbsp;quantity})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;raw.get(&amp;quot;success&amp;quot;,&amp;nbsp;False)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_call_api(self,&amp;nbsp;path:&amp;nbsp;str,&amp;nbsp;method:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;GET&amp;quot;,&amp;nbsp;body:&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;None)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;id&amp;quot;:&amp;nbsp;&amp;quot;MERC-ORDER-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;paid&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;quantity&amp;quot;:&amp;nbsp;1,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;totalPrice&amp;quot;:&amp;nbsp;{&amp;quot;amount&amp;quot;:&amp;nbsp;&amp;quot;45000&amp;quot;,&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;&amp;quot;JPY&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;buyer&amp;quot;:&amp;nbsp;{&amp;quot;displayName&amp;quot;:&amp;nbsp;&amp;quot;田中太郎&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;itemPayload&amp;quot;:&amp;nbsp;{&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}


#&amp;nbsp;====================&amp;nbsp;Back&amp;nbsp;Market适配器（v3.1&amp;nbsp;→&amp;nbsp;BM&amp;nbsp;API&amp;nbsp;v3）&amp;nbsp;====================
class&amp;nbsp;BackMarketAdapter(PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;适配器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;API文档:&amp;nbsp;https://developers.backmarket.com/
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;v3.1&amp;nbsp;变更记录:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;2026-02:&amp;nbsp;认证从&amp;nbsp;Basic&amp;nbsp;token&amp;nbsp;改为&amp;nbsp;mTLS
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;2026-05:&amp;nbsp;orders.list&amp;nbsp;返回结构从数组改为分页对象
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;api_key:&amp;nbsp;str,&amp;nbsp;cert_path:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.api_key&amp;nbsp;=&amp;nbsp;api_key
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.cert_path&amp;nbsp;=&amp;nbsp;cert_path
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._version&amp;nbsp;=&amp;nbsp;&amp;quot;3.1&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._api_version&amp;nbsp;=&amp;nbsp;&amp;quot;2026-05&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._version

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;api_version(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._api_version

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_order(self,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(f&amp;quot;/api/v3/orders/{order_id}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;v3.1&amp;nbsp;适配：分页对象（2026-05改的）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_data&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;data&amp;quot;,&amp;nbsp;raw)&amp;nbsp;&amp;nbsp;#&amp;nbsp;兼容旧版直接返回

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalOrder(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=order_data.get(&amp;quot;id&amp;quot;,&amp;nbsp;order_id),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=order_data.get(&amp;quot;product&amp;quot;,&amp;nbsp;{}).get(&amp;quot;sku&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=int(order_data.get(&amp;quot;quantity&amp;quot;,&amp;nbsp;1)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price=float(order_data.get(&amp;quot;totalAmount&amp;quot;,&amp;nbsp;{}).get(&amp;quot;value&amp;quot;,&amp;nbsp;0)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=order_data.get(&amp;quot;totalAmount&amp;quot;,&amp;nbsp;{}).get(&amp;quot;currency&amp;quot;,&amp;nbsp;&amp;quot;EUR&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=order_data.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_raw=order_data,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;sync_listing(self,&amp;nbsp;product:&amp;nbsp;InternalProduct)&amp;nbsp;-&amp;gt;&amp;nbsp;ListingResult:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(&amp;quot;/api/v3/listings&amp;quot;,&amp;nbsp;method=&amp;quot;POST&amp;quot;,&amp;nbsp;body={
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;product&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;product.sku,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;product.title,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;{&amp;quot;value&amp;quot;:&amp;nbsp;str(product.price),&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;product.currency},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lid&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;id&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;ListingResult(success=bool(lid),&amp;nbsp;platform_listing_id=lid)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;update_inventory(self,&amp;nbsp;sku:&amp;nbsp;str,&amp;nbsp;quantity:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(f&amp;quot;/api/v3/inventory/{sku}&amp;quot;,&amp;nbsp;method=&amp;quot;PATCH&amp;quot;,&amp;nbsp;body={&amp;quot;available&amp;quot;:&amp;nbsp;quantity})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;raw.get(&amp;quot;success&amp;quot;,&amp;nbsp;False)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_call_api(self,&amp;nbsp;path:&amp;nbsp;str,&amp;nbsp;method:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;GET&amp;quot;,&amp;nbsp;body:&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;None)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;data&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;id&amp;quot;:&amp;nbsp;&amp;quot;BM-ORDER-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;confirmed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;quantity&amp;quot;:&amp;nbsp;1,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;totalAmount&amp;quot;:&amp;nbsp;{&amp;quot;value&amp;quot;:&amp;nbsp;&amp;quot;899.99&amp;quot;,&amp;nbsp;&amp;quot;currency&amp;quot;:&amp;nbsp;&amp;quot;EUR&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;product&amp;quot;:&amp;nbsp;{&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;MBP-M3-512&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}


#&amp;nbsp;====================&amp;nbsp;适配器注册中心&amp;nbsp;====================
class&amp;nbsp;AdapterRegistry:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;适配器注册中心
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;按平台注册多个版本的适配器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;提供当前活跃版本
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;支持版本回退
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._adapters:&amp;nbsp;Dict[str,&amp;nbsp;List[Tuple[str,&amp;nbsp;PlatformAdapter]]]&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._active:&amp;nbsp;Dict[str,&amp;nbsp;str]&amp;nbsp;=&amp;nbsp;{}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;register(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;adapter:&amp;nbsp;PlatformAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;not&amp;nbsp;in&amp;nbsp;self._adapters:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._adapters[platform]&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._adapters[platform].append((adapter.version,&amp;nbsp;adapter))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;默认使用最新注册的版本
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._active[platform]&amp;nbsp;=&amp;nbsp;adapter.version
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[REGISTRY]&amp;nbsp;{platform}:&amp;nbsp;{adapter.version}&amp;nbsp;(API&amp;nbsp;{adapter.api_version})&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get(self,&amp;nbsp;platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;Optional[PlatformAdapter]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapters&amp;nbsp;=&amp;nbsp;self._adapters.get(platform,&amp;nbsp;[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;active_version&amp;nbsp;=&amp;nbsp;self._active.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;ver,&amp;nbsp;adp&amp;nbsp;in&amp;nbsp;adapters:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;ver&amp;nbsp;==&amp;nbsp;active_version:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;adp
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;adapters[-1][1]&amp;nbsp;if&amp;nbsp;adapters&amp;nbsp;else&amp;nbsp;None

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;rollback(self,&amp;nbsp;platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;回退到上一个版本&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapters&amp;nbsp;=&amp;nbsp;self._adapters.get(platform,&amp;nbsp;[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;len(adapters)&amp;nbsp;&amp;lt;&amp;nbsp;2:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current_idx&amp;nbsp;=&amp;nbsp;next(i&amp;nbsp;for&amp;nbsp;i,&amp;nbsp;(v,&amp;nbsp;_)&amp;nbsp;in&amp;nbsp;enumerate(adapters)&amp;nbsp;if&amp;nbsp;v&amp;nbsp;==&amp;nbsp;self._active[platform])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;current_idx&amp;nbsp;&amp;gt;&amp;nbsp;0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._active[platform]&amp;nbsp;=&amp;nbsp;adapters[current_idx&amp;nbsp;-&amp;nbsp;1][0]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[ROLLBACK]&amp;nbsp;{platform}:&amp;nbsp;{self._active[platform]}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;list_versions(self,&amp;nbsp;platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;List[str]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[v&amp;nbsp;for&amp;nbsp;v,&amp;nbsp;_&amp;nbsp;in&amp;nbsp;self._adapters.get(platform,&amp;nbsp;[])]


#&amp;nbsp;====================&amp;nbsp;版本迁移管理器&amp;nbsp;====================
class&amp;nbsp;VersionMigration:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;API版本迁移工具
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;灰度切换适配器版本
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;新旧版本并行运行对比
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;自动回滚（错误率超标）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;registry:&amp;nbsp;AdapterRegistry):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.registry&amp;nbsp;=&amp;nbsp;registry
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.traffic_split:&amp;nbsp;Dict[str,&amp;nbsp;float]&amp;nbsp;=&amp;nbsp;{}&amp;nbsp;&amp;nbsp;#&amp;nbsp;platform&amp;nbsp;-&amp;gt;&amp;nbsp;new_version_ratio

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;start_migration(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;new_version:&amp;nbsp;str,&amp;nbsp;ratio:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.1):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;开始灰度迁移&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.traffic_split[platform]&amp;nbsp;=&amp;nbsp;ratio
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[MIGRATION]&amp;nbsp;{platform}:&amp;nbsp;切换到&amp;nbsp;{new_version}&amp;nbsp;({ratio*100:.0f}%流量)&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;process_order(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;新旧适配器并行处理，对比结果&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;old_adapter&amp;nbsp;=&amp;nbsp;self.registry.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_adapter&amp;nbsp;=&amp;nbsp;self._get_version(platform,&amp;nbsp;self._next_version(platform))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;旧版处理
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;old_result&amp;nbsp;=&amp;nbsp;old_adapter.fetch_order(order_id)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;新版处理（仅对比，不生效）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new_result&amp;nbsp;=&amp;nbsp;new_adapter.fetch_order(order_id)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;对比差异
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diff&amp;nbsp;=&amp;nbsp;self._compare(old_result,&amp;nbsp;new_result)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;diff:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[DIFF]&amp;nbsp;{platform}&amp;nbsp;{order_id}:&amp;nbsp;{diff}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;根据灰度比例决定返回哪个结果
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;import&amp;nbsp;random
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;use_new&amp;nbsp;=&amp;nbsp;random.random()&amp;nbsp;&amp;lt;&amp;nbsp;self.traffic_split.get(platform,&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;result&amp;quot;:&amp;nbsp;new_result&amp;nbsp;if&amp;nbsp;use_new&amp;nbsp;else&amp;nbsp;old_result,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;used_version&amp;quot;:&amp;nbsp;new_adapter.version&amp;nbsp;if&amp;nbsp;use_new&amp;nbsp;else&amp;nbsp;old_adapter.version,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;diff&amp;quot;:&amp;nbsp;diff,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_get_version(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;version:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;Optional[PlatformAdapter]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;v,&amp;nbsp;adp&amp;nbsp;in&amp;nbsp;self.registry._adapters.get(platform,&amp;nbsp;[]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;v&amp;nbsp;==&amp;nbsp;version:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;adp
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;None

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_next_version(self,&amp;nbsp;platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;versions&amp;nbsp;=&amp;nbsp;self.registry.list_versions(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current&amp;nbsp;=&amp;nbsp;self.registry._active.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;idx&amp;nbsp;=&amp;nbsp;next(i&amp;nbsp;for&amp;nbsp;i,&amp;nbsp;v&amp;nbsp;in&amp;nbsp;enumerate(versions)&amp;nbsp;if&amp;nbsp;v&amp;nbsp;==&amp;nbsp;current)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;versions[idx&amp;nbsp;+&amp;nbsp;1]&amp;nbsp;if&amp;nbsp;idx&amp;nbsp;+&amp;nbsp;1&amp;nbsp;&amp;lt;&amp;nbsp;len(versions)&amp;nbsp;else&amp;nbsp;current

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_compare(self,&amp;nbsp;old:&amp;nbsp;InternalOrder,&amp;nbsp;new:&amp;nbsp;InternalOrder)&amp;nbsp;-&amp;gt;&amp;nbsp;Dict[str,&amp;nbsp;Tuple]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diffs&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;field&amp;nbsp;in&amp;nbsp;[&amp;quot;price&amp;quot;,&amp;nbsp;&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;quantity&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ov&amp;nbsp;=&amp;nbsp;getattr(old,&amp;nbsp;field)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nv&amp;nbsp;=&amp;nbsp;getattr(new,&amp;nbsp;field)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;ov&amp;nbsp;!=&amp;nbsp;nv:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;diffs[field]&amp;nbsp;=&amp;nbsp;(ov,&amp;nbsp;nv)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;diffs

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;降级链&amp;nbsp;====================
class&amp;nbsp;FallbackChain:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;降级策略
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;新版本抛异常&amp;nbsp;→&amp;nbsp;自动切旧版本
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;连续失败N次&amp;nbsp;→&amp;nbsp;锁定旧版本
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;registry:&amp;nbsp;AdapterRegistry):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.registry&amp;nbsp;=&amp;nbsp;registry
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.failure_count:&amp;nbsp;Dict[str,&amp;nbsp;int]&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.locked:&amp;nbsp;Dict[str,&amp;nbsp;bool]&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.MAX_FAILURES&amp;nbsp;=&amp;nbsp;5

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;execute(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;operation:&amp;nbsp;str,&amp;nbsp;*args,&amp;nbsp;**kwargs):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.locked.get(platform,&amp;nbsp;False):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[FALLBACK]&amp;nbsp;{platform}&amp;nbsp;已被锁定，跳过新版本&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter&amp;nbsp;=&amp;nbsp;self.registry.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;method&amp;nbsp;=&amp;nbsp;getattr(adapter,&amp;nbsp;operation,&amp;nbsp;None)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;method:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise&amp;nbsp;ValueError(f&amp;quot;操作&amp;nbsp;{operation}&amp;nbsp;不存在&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;method(*args,&amp;nbsp;**kwargs)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.failure_count[platform]&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.failure_count[platform]&amp;nbsp;=&amp;nbsp;self.failure_count.get(platform,&amp;nbsp;0)&amp;nbsp;+&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count&amp;nbsp;=&amp;nbsp;self.failure_count[platform]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;count&amp;nbsp;&amp;gt;=&amp;nbsp;self.MAX_FAILURES:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.locked[platform]&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;rolled_back&amp;nbsp;=&amp;nbsp;self.registry.rollback(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[FALLBACK]&amp;nbsp;{platform}&amp;nbsp;连续失败{count}次，回退到旧版本:&amp;nbsp;{rolled_back}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;重试旧版本
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter&amp;nbsp;=&amp;nbsp;self.registry.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;method&amp;nbsp;=&amp;nbsp;getattr(adapter,&amp;nbsp;operation)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;method(*args,&amp;nbsp;**kwargs)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[FALLBACK]&amp;nbsp;{platform}&amp;nbsp;失败({count}/{self.MAX_FAILURES}):&amp;nbsp;{e}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise


#&amp;nbsp;====================&amp;nbsp;业务层（完全不知道平台细节）&amp;nbsp;====================
class&amp;nbsp;OrderService:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;业务层：只认&amp;nbsp;InternalOrder，不知道任何平台API细节&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;registry:&amp;nbsp;AdapterRegistry):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.registry&amp;nbsp;=&amp;nbsp;registry

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_order(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter&amp;nbsp;=&amp;nbsp;self.registry.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;adapter:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise&amp;nbsp;ValueError(f&amp;quot;不支持的平台:&amp;nbsp;{platform}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;adapter.fetch_order(order_id)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;ship_order(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;order_id:&amp;nbsp;str,&amp;nbsp;tracking:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter&amp;nbsp;=&amp;nbsp;self.registry.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;所有平台都通过适配器发货
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter.ship_order(order_id,&amp;nbsp;tracking)&amp;nbsp;&amp;nbsp;#&amp;nbsp;假设有这个接口

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;list_products(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;products:&amp;nbsp;List[InternalProduct]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter&amp;nbsp;=&amp;nbsp;self.registry.get(platform)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;p&amp;nbsp;in&amp;nbsp;products:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results.append(adapter.sync_listing(p))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;results

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;演示&amp;nbsp;====================
if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;68)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;电商平台适配器模式：API变更，业务代码零改动&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;68)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;注册适配器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;registry&amp;nbsp;=&amp;nbsp;AdapterRegistry()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;registry.register(&amp;quot;xianyu&amp;quot;,&amp;nbsp;XianyuAdapter(&amp;quot;app_key_123&amp;quot;,&amp;nbsp;&amp;quot;app_secret_456&amp;quot;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;registry.register(&amp;quot;mercari&amp;quot;,&amp;nbsp;MercariAdapter(&amp;quot;mercari_token_xyz&amp;quot;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;registry.register(&amp;quot;backmarket&amp;quot;,&amp;nbsp;BackMarketAdapter(&amp;quot;bm_api_key_789&amp;quot;))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;业务层
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_service&amp;nbsp;=&amp;nbsp;OrderService(registry)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;获取订单（业务层完全不知道平台API细节）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platforms&amp;nbsp;=&amp;nbsp;[&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;backmarket&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;p&amp;nbsp;in&amp;nbsp;platforms:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;=&amp;nbsp;order_service.get_order(p,&amp;nbsp;f&amp;quot;{p.upper()}-ORDER-001&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n[{p.upper()}]&amp;nbsp;订单:&amp;nbsp;{order.order_id}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;SKU:&amp;nbsp;{order.sku}&amp;nbsp;|&amp;nbsp;价格:&amp;nbsp;{order.price}&amp;nbsp;{order.currency}&amp;nbsp;|&amp;nbsp;状态:&amp;nbsp;{order.status}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;模拟API变更：闲鱼API升级
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;=&amp;#39;*68}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;模拟闲鱼API升级&amp;nbsp;(2026-09):&amp;nbsp;price_info.amount&amp;nbsp;→&amp;nbsp;pricing.total)&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;=&amp;#39;*68}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;新适配器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;class&amp;nbsp;XianyuAdapterV3(XianyuAdapter):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;app_key:&amp;nbsp;str,&amp;nbsp;app_secret:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(app_key,&amp;nbsp;app_secret)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._version&amp;nbsp;=&amp;nbsp;&amp;quot;3.0&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._api_version&amp;nbsp;=&amp;nbsp;&amp;quot;2026-09&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;fetch_order(self,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw&amp;nbsp;=&amp;nbsp;self._call_api(&amp;quot;taobao.idle.order.detail.get&amp;quot;,&amp;nbsp;{&amp;quot;order_id&amp;quot;:&amp;nbsp;order_id})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;trade&amp;nbsp;=&amp;nbsp;raw.get(&amp;quot;data&amp;quot;,&amp;nbsp;{}).get(&amp;quot;tradeDTO&amp;quot;,&amp;nbsp;{})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;v3.0&amp;nbsp;适配：pricing.total（2026-09改的）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pricing&amp;nbsp;=&amp;nbsp;trade.get(&amp;quot;pricing&amp;quot;,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price&amp;nbsp;=&amp;nbsp;float(pricing.get(&amp;quot;total&amp;quot;,&amp;nbsp;0))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalOrder(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=trade.get(&amp;quot;tid&amp;quot;,&amp;nbsp;order_id),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=&amp;quot;xianyu&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=trade.get(&amp;quot;item_sku&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity=int(trade.get(&amp;quot;num&amp;quot;,&amp;nbsp;1)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price=price,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=&amp;quot;CNY&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=self._map_status(trade.get(&amp;quot;trade_status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_raw=trade,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;注册新版本
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;registry.register(&amp;quot;xianyu&amp;quot;,&amp;nbsp;XianyuAdapterV3(&amp;quot;app_key_123&amp;quot;,&amp;nbsp;&amp;quot;app_secret_456&amp;quot;))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;版本迁移（灰度10%）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;migration&amp;nbsp;=&amp;nbsp;VersionMigration(registry)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;migration.start_migration(&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;3.0&amp;quot;,&amp;nbsp;ratio=0.1)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;6.&amp;nbsp;测试灰度
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;\n&amp;nbsp;&amp;nbsp;灰度测试&amp;nbsp;(10%走新版本):&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;in&amp;nbsp;range(5):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;migration.process_order(&amp;quot;xianyu&amp;quot;,&amp;nbsp;f&amp;quot;XY-ORDER-00{i+1}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;请求&amp;nbsp;#{i+1}:&amp;nbsp;使用版本&amp;nbsp;{result[&amp;#39;used_version&amp;#39;]}&amp;nbsp;|&amp;nbsp;差异:&amp;nbsp;{result[&amp;#39;diff&amp;#39;]}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;7.&amp;nbsp;降级测试
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;=&amp;#39;*68}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;降级测试：新版本抛异常&amp;nbsp;→&amp;nbsp;自动回退&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;=&amp;#39;*68}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fallback&amp;nbsp;=&amp;nbsp;FallbackChain(registry)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;i&amp;nbsp;in&amp;nbsp;range(7):&amp;nbsp;&amp;nbsp;#&amp;nbsp;超过5次失败
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fallback.execute(&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;fetch_order&amp;quot;,&amp;nbsp;f&amp;quot;XY-ERROR-ORDER-{i}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pass&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;运行结果：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;====================================================================
&amp;nbsp;&amp;nbsp;电商平台适配器模式：API变更，业务代码零改动
====================================================================
[REGISTRY]&amp;nbsp;xianyu:&amp;nbsp;2.3&amp;nbsp;(API&amp;nbsp;2026-06)
[REGISTRY]&amp;nbsp;mercari:&amp;nbsp;1.8&amp;nbsp;(API&amp;nbsp;2026-07)
[REGISTRY]&amp;nbsp;backmarket:&amp;nbsp;3.1&amp;nbsp;(API&amp;nbsp;2026-05)

[XIANYU]&amp;nbsp;订单:&amp;nbsp;XY-ORDER-001
&amp;nbsp;&amp;nbsp;SKU:&amp;nbsp;IP14P-256&amp;nbsp;|&amp;nbsp;价格:&amp;nbsp;5999.0&amp;nbsp;CNY&amp;nbsp;|&amp;nbsp;状态:&amp;nbsp;paid

[MERCARI]&amp;nbsp;订单:&amp;nbsp;MERC-ORDER-001
&amp;nbsp;&amp;nbsp;SKU:&amp;nbsp;IP14P-256&amp;nbsp;|&amp;nbsp;价格:&amp;nbsp;45000.0&amp;nbsp;JPY&amp;nbsp;|&amp;nbsp;状态:&amp;nbsp;paid

[BACKMARKET]&amp;nbsp;订单:&amp;nbsp;BM-ORDER-001
&amp;nbsp;&amp;nbsp;SKU:&amp;nbsp;MBP-M3-512&amp;nbsp;|&amp;nbsp;价格:&amp;nbsp;899.99&amp;nbsp;EUR&amp;nbsp;|&amp;nbsp;状态:&amp;nbsp;confirmed

====================================================================
&amp;nbsp;&amp;nbsp;模拟闲鱼API升级&amp;nbsp;(2026-09):&amp;nbsp;price_info.amount&amp;nbsp;→&amp;nbsp;pricing.total
====================================================================
[REGISTRY]&amp;nbsp;xianyu:&amp;nbsp;3.0&amp;nbsp;(API&amp;nbsp;2026-09)

&amp;nbsp;&amp;nbsp;灰度测试&amp;nbsp;(10%走新版本):
&amp;nbsp;&amp;nbsp;请求&amp;nbsp;#1:&amp;nbsp;使用版本&amp;nbsp;2.3&amp;nbsp;|&amp;nbsp;差异:&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;请求&amp;nbsp;#2:&amp;nbsp;使用版本&amp;nbsp;2.3&amp;nbsp;|&amp;nbsp;差异:&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;请求&amp;nbsp;#3:&amp;nbsp;使用版本&amp;nbsp;3.0&amp;nbsp;|&amp;nbsp;差异:&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;请求&amp;nbsp;#4:&amp;nbsp;使用版本&amp;nbsp;2.3&amp;nbsp;|&amp;nbsp;差异:&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;请求&amp;nbsp;#5:&amp;nbsp;使用版本&amp;nbsp;2.3&amp;nbsp;|&amp;nbsp;差异:&amp;nbsp;{}

====================================================================
&amp;nbsp;&amp;nbsp;降级测试：新版本抛异常&amp;nbsp;→&amp;nbsp;自动回退
====================================================================
[FALLBACK]&amp;nbsp;xianyu&amp;nbsp;失败(1/5):&amp;nbsp;...
[FALLBACK]&amp;nbsp;xianyu&amp;nbsp;失败(2/5):&amp;nbsp;...
[FALLBACK]&amp;nbsp;xianyu&amp;nbsp;失败(3/5):&amp;nbsp;...
[FALLBACK]&amp;nbsp;xianyu&amp;nbsp;失败(4/5):&amp;nbsp;...
[FALLBACK]&amp;nbsp;xianyu&amp;nbsp;失败(5/5):&amp;nbsp;...
[ROLLBACK]&amp;nbsp;xianyu:&amp;nbsp;2.3
[FALLBACK]&amp;nbsp;xianyu&amp;nbsp;已被锁定，跳过新版本&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;四、适配器模式在二手ERP中的落地原则&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;原则&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;说明&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;适配器只做翻译，不做业务&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;不要在适配器里判断“这个订单要不要发货”&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;每个平台独立版本号&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;闲鱼v2.3和Mercari v1.8互不影响&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;新旧版本并行&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;灰度期间两个版本都在跑，对比结果&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;降级链必须有&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;新版本挂了自动切旧版本，不阻塞业务&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;适配器无状态&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;不缓存、不持有业务上下文，方便热切换&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;五、和前22篇的衔接&lt;/h2&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;cross_border_schema.FieldMapper&lt;/code&gt;&lt;/strong&gt;：适配器内部调用 FieldMapper 做字段级翻译&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt;&lt;/strong&gt;：适配器收到平台消息后，转成 Event 发布到事件总线&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GrayReleaseRouter&lt;/code&gt;&lt;/strong&gt;：适配器版本灰度可以复用灰度路由的按比例/按平台逻辑&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;IdempotentConsumer&lt;/code&gt;&lt;/strong&gt;：适配器消费平台消息时，通过幂等消费器防止重复处理&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PushListener/PullWorker&lt;/code&gt;&lt;/strong&gt;：适配器作为 Push/Pull 通道的下游，把平台原生数据转成 Internal*&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;六、一句话收口&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;电商平台API一年改3次，你的业务代码不应该跟着改3次。&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;适配器模式把“平台差异”和“业务逻辑”彻底隔开——平台改字段名、改数据结构、改认证方式，&lt;strong&gt;只改适配器那一层&lt;/strong&gt;，业务逻辑一行不动。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;配合版本注册中心 + 灰度迁移 + 降级链，API升级不再是事故，只是一个&lt;strong&gt;可回滚的配置变更&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我把这篇的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;AdapterRegistry&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;VersionMigration&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;FallbackChain&lt;/code&gt; 封装成 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/adapter/&lt;/code&gt; 模块，并和前几篇的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;IdempotentConsumer&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PushListener&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;SecurityGateway&lt;/code&gt; 串成一个&lt;strong&gt;完整的订单域运行时&lt;/strong&gt;？&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 18 Sep 2026 17:42:48 +0800</pubDate></item><item><title>《数据合规前置：OAuth2 / HMAC 签名 / 脱敏 / 最小权限在二手ERP对接中的落地》（附Python源码）</title><link>https://www.alexob.com/?id=542</link><description>&lt;h1&gt;《数据合规前置：OAuth2 / HMAC 签名 / 脱敏 / 最小权限在二手ERP对接中的落地》（附Python源码）&lt;/h1&gt;&lt;div class=&quot;ybc-p&quot;&gt;先纠一个二手跨境电商里最容易踩的坑：&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;不是所有平台都用 OAuth2&lt;/strong&gt;。&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;闲鱼/淘宝开放平台：OAuth2 授权码 + 三方 session&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;eBay：OAuth2 Client Credentials / Authorization Code&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mercari：OAuth2 体系（Mercari ID Platform 基于 OAuth 2.0 / OIDC）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Back Market：卖家后台生成 opaque token，&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;Authorization: Basic &amp;lt;token&amp;gt;&lt;/code&gt;，没有 OAuth2、没有 scope、没有 refresh&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;ybc-p&quot;&gt;所以“数据合规前置”不是统一接 OAuth2，而是：&lt;strong&gt;按平台能力分层——有 OAuth2 用 OAuth2，只有 opaque token 就当长期凭证管，webhook 统一走 HMAC，PII 统一脱敏，服务账号统一最小权限。&lt;/strong&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;一、四件事分别解决什么问题&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;能力&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;防什么&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;二手ERP场景&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;OAuth2&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;第三方代运营/多渠道账号越权调用&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;运营 A 只能碰 Mercari US，不能碰 Back Market EU&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;HMAC 签名&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;平台回调被伪造 / 中间人改体&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;闲鱼退款消息、Vinted webhook 被冒名推送&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;脱敏&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;客服/日志/分析库泄露买家隐私&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;手机号、地址、IMEI、邮箱进日志被审计罚&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;最小权限&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;一个适配器炸了拖垮全公司数据&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;库存服务不该能读退款流水和买家身份证&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;二、统一凭证仓库（先别把 secret 写代码里）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;secrets_vault.py
import&amp;nbsp;os,&amp;nbsp;json,&amp;nbsp;hashlib
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Optional

class&amp;nbsp;SecretVault:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;生产用&amp;nbsp;HashiCorp&amp;nbsp;Vault&amp;nbsp;/&amp;nbsp;AWS&amp;nbsp;Secrets&amp;nbsp;Manager。
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;这里用环境变量+内存做最小可运行版。
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;backend:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;env&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.backend&amp;nbsp;=&amp;nbsp;backend

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get(self,&amp;nbsp;key:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;Optional[str]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;os.environ.get(f&amp;quot;ERP_SECRET_{key}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_oauth_client(self,&amp;nbsp;platform:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;client_id&amp;quot;:&amp;nbsp;self.get(f&amp;quot;{platform}_CLIENT_ID&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;client_secret&amp;quot;:&amp;nbsp;self.get(f&amp;quot;{platform}_CLIENT_SECRET&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;token_url&amp;quot;:&amp;nbsp;self.get(f&amp;quot;{platform}_TOKEN_URL&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;scope&amp;quot;:&amp;nbsp;self.get(f&amp;quot;{platform}_SCOPE&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_hmac_secret(self,&amp;nbsp;platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.get(f&amp;quot;{platform}_WEBHOOK_SECRET&amp;quot;)&amp;nbsp;or&amp;nbsp;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_opaque_token(self,&amp;nbsp;platform:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;这类
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.get(f&amp;quot;{platform}_OPAQUE_TOKEN&amp;quot;)&amp;nbsp;or&amp;nbsp;&amp;quot;&amp;quot;&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;规则：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;OAuth2 client_secret：&lt;strong&gt;只在令牌交换时出现，不进日志&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;opaque token（Back Market）：&lt;strong&gt;当长期凭证管，写进 Vault，支持人工吊销+更换&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;HMAC secret：&lt;strong&gt;按平台隔离，季度轮换&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;三、OAuth2 客户端（eBay / Mercari 风格）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;oauth2_client.py
import&amp;nbsp;time,&amp;nbsp;requests
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass

@dataclass
class&amp;nbsp;OAuth2Token:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;access_token:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;token_type:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;Bearer&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;expires_in:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scope:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issued_at:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@property
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;expired(self,&amp;nbsp;skew:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;60)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;self.access_token:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;time.time()&amp;nbsp;&amp;gt;=&amp;nbsp;(self.issued_at&amp;nbsp;+&amp;nbsp;self.expires_in&amp;nbsp;-&amp;nbsp;skew)
#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
class&amp;nbsp;OAuth2Client:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;client_id:&amp;nbsp;str,&amp;nbsp;client_secret:&amp;nbsp;str,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;token_url:&amp;nbsp;str,&amp;nbsp;scope:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.client_id&amp;nbsp;=&amp;nbsp;client_id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.client_secret&amp;nbsp;=&amp;nbsp;client_secret
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.token_url&amp;nbsp;=&amp;nbsp;token_url
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.scope&amp;nbsp;=&amp;nbsp;scope
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._token:&amp;nbsp;OAuth2Token&amp;nbsp;|&amp;nbsp;None&amp;nbsp;=&amp;nbsp;None

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;get_token(self)&amp;nbsp;-&amp;gt;&amp;nbsp;OAuth2Token:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self._token&amp;nbsp;and&amp;nbsp;not&amp;nbsp;self._token.expired:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._token

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp&amp;nbsp;=&amp;nbsp;requests.post(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.token_url,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data={&amp;quot;grant_type&amp;quot;:&amp;nbsp;&amp;quot;client_credentials&amp;quot;,&amp;nbsp;&amp;quot;scope&amp;quot;:&amp;nbsp;self.scope},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auth=(self.client_id,&amp;nbsp;self.client_secret),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;timeout=10,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resp.raise_for_status()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;d&amp;nbsp;=&amp;nbsp;resp.json()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._token&amp;nbsp;=&amp;nbsp;OAuth2Token(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;access_token=d[&amp;quot;access_token&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;token_type=d.get(&amp;quot;token_type&amp;quot;,&amp;nbsp;&amp;quot;Bearer&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;expires_in=int(d.get(&amp;quot;expires_in&amp;quot;,&amp;nbsp;3600)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;scope=d.get(&amp;quot;scope&amp;quot;,&amp;nbsp;self.scope),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issued_at=time.time(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self._token

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;auth_header(self)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t&amp;nbsp;=&amp;nbsp;self.get_token()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;Authorization&amp;quot;:&amp;nbsp;f&amp;quot;{t.token_type}&amp;nbsp;{t.access_token}&amp;quot;}&lt;/pre&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;最小权限要点：&lt;strong&gt;scope 写死成 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;orders:read shipments:write listings:read&lt;/code&gt;，不要申请 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;finance:read&lt;/code&gt; 和 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;pii:full&lt;/code&gt;&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;四、Back Market 的“非 OAuth2”正确姿势&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;backmarket_auth.py
class&amp;nbsp;BackMarketAuth:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;用&amp;nbsp;Back&amp;nbsp;Office&amp;nbsp;生成的&amp;nbsp;opaque&amp;nbsp;token:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Authorization:&amp;nbsp;Basic&amp;nbsp;&amp;lt;token&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;没有&amp;nbsp;scope&amp;nbsp;/&amp;nbsp;refresh&amp;nbsp;/&amp;nbsp;expiry。
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;对策：当长期凭证&amp;nbsp;+&amp;nbsp;人工轮换&amp;nbsp;+&amp;nbsp;按区域分&amp;nbsp;token。
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;opaque_token:&amp;nbsp;str,&amp;nbsp;region:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;fr&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.token&amp;nbsp;=&amp;nbsp;opaque_token
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.region&amp;nbsp;=&amp;nbsp;region
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.base_url&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;fr&amp;quot;:&amp;nbsp;&amp;quot;https://www.backmarket.fr&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;com&amp;quot;:&amp;nbsp;&amp;quot;https://www.backmarket.com&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;co.jp&amp;quot;:&amp;nbsp;&amp;quot;https://www.backmarket.co.jp&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}[region]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;auth_header(self)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;Authorization&amp;quot;:&amp;nbsp;f&amp;quot;Basic&amp;nbsp;{self.token}&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;companion_headers(self)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;强制要求
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Accept-Language&amp;quot;:&amp;nbsp;self.region,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;User-Agent&amp;quot;:&amp;nbsp;&amp;quot;BM-YourCompany-erp-sync&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;合规落地点：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;一个 region 一个 token，&lt;strong&gt;EU 出事不连累 NA&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;token 不进 Git，不进前端&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;换密码/token 有 runbook，避免“账号一改全部渠道掉线”&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;五、HMAC 签名校验（webhook 防伪造 + 防重放）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;webhook_hmac.py
import&amp;nbsp;hmac,&amp;nbsp;hashlib,&amp;nbsp;time
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict

class&amp;nbsp;WebhookVerifier:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;secret:&amp;nbsp;str,&amp;nbsp;tolerance_sec:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;300):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.secret&amp;nbsp;=&amp;nbsp;secret.encode()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.tolerance_sec&amp;nbsp;=&amp;nbsp;tolerance_sec

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;sign(self,&amp;nbsp;raw_body:&amp;nbsp;bytes,&amp;nbsp;ts:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;f&amp;quot;{ts}.&amp;quot;.encode()&amp;nbsp;+&amp;nbsp;raw_body
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hmac.new(self.secret,&amp;nbsp;msg,&amp;nbsp;hashlib.sha256).hexdigest()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;verify(self,&amp;nbsp;raw_body:&amp;nbsp;bytes,&amp;nbsp;headers:&amp;nbsp;Dict[str,&amp;nbsp;str])&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ts&amp;nbsp;=&amp;nbsp;headers.get(&amp;quot;X-Timestamp&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sig&amp;nbsp;=&amp;nbsp;headers.get(&amp;quot;X-Signature&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;ts&amp;nbsp;or&amp;nbsp;not&amp;nbsp;sig:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ts_i&amp;nbsp;=&amp;nbsp;int(ts)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;ValueError:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1)&amp;nbsp;重放防护
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;abs(time.time()&amp;nbsp;-&amp;nbsp;ts_i)&amp;nbsp;&amp;gt;&amp;nbsp;self.tolerance_sec:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;expected&amp;nbsp;=&amp;nbsp;self.sign(raw_body,&amp;nbsp;ts_i)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2)&amp;nbsp;常量时间比较，防时序攻击
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hmac.compare_digest(expected,&amp;nbsp;sig)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;调用方：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;verifier&amp;nbsp;=&amp;nbsp;WebhookVerifier(vault.get_hmac_secret(&amp;quot;xianyu&amp;quot;))
if&amp;nbsp;not&amp;nbsp;verifier.verify(body,&amp;nbsp;headers):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;403,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;bad&amp;nbsp;signature&amp;nbsp;/&amp;nbsp;replay&amp;quot;}&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;Webhook 安全基线（来自 APIsec 最佳实践）：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;SHA-256 起步&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;带 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;X-Timestamp&lt;/code&gt;，超 5 分钟拒&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;msg_id 去重（接前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;IdempotentConsumer&lt;/code&gt;）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;签名错返回 403，但&lt;strong&gt;错误信息不吐 secret / payload 原文&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;六、脱敏层（二手设备特别吃 IMEI / 序列号 / 买家地址）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;masking.py
import&amp;nbsp;re

class&amp;nbsp;PiiMasker:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;phone(v:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;re.sub(r&amp;quot;(\d{3})\d{4}(\d{4})&amp;quot;,&amp;nbsp;r&amp;quot;\1****\2&amp;quot;,&amp;nbsp;v)&amp;nbsp;if&amp;nbsp;v&amp;nbsp;else&amp;nbsp;v

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;email(v:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;v&amp;nbsp;or&amp;nbsp;&amp;quot;@&amp;quot;&amp;nbsp;not&amp;nbsp;in&amp;nbsp;v:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;v
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name,&amp;nbsp;domain&amp;nbsp;=&amp;nbsp;v.split(&amp;quot;@&amp;quot;,&amp;nbsp;1)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;keep&amp;nbsp;=&amp;nbsp;name[:2]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;f&amp;quot;{keep}***@{domain}&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;id_card(v:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;v[:6]&amp;nbsp;+&amp;nbsp;&amp;quot;********&amp;quot;&amp;nbsp;+&amp;nbsp;v[-4:]&amp;nbsp;if&amp;nbsp;len(v)&amp;nbsp;&amp;gt;=&amp;nbsp;10&amp;nbsp;else&amp;nbsp;&amp;quot;****&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;imei(v:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;设备级&amp;nbsp;PII：日志里只允许后4位
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;************&amp;quot;&amp;nbsp;+&amp;nbsp;v[-4:]&amp;nbsp;if&amp;nbsp;v&amp;nbsp;and&amp;nbsp;len(v)&amp;nbsp;&amp;gt;=&amp;nbsp;4&amp;nbsp;else&amp;nbsp;&amp;quot;****&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;address(v:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;门牌号打码，城市/国家保留（用于仓配分析）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;re.sub(r&amp;quot;(\d{1,4})\s*号|\b\d{1,4}\b\s*(室|栋|单元)&amp;quot;,&amp;nbsp;&amp;quot;***\\1&amp;quot;,&amp;nbsp;v)&amp;nbsp;if&amp;nbsp;v&amp;nbsp;else&amp;nbsp;v

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
MASK_FIELD_MAP&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;buyer_phone&amp;quot;:&amp;nbsp;PiiMasker.phone,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;buyer_email&amp;quot;:&amp;nbsp;PiiMasker.email,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;buyer_id_card&amp;quot;:&amp;nbsp;PiiMasker.id_card,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;device_imei&amp;quot;:&amp;nbsp;PiiMasker.imei,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;device_serial&amp;quot;:&amp;nbsp;PiiMasker.imei,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;buyer_address&amp;quot;:&amp;nbsp;PiiMasker.address,
}

def&amp;nbsp;mask_obj(obj:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out&amp;nbsp;=&amp;nbsp;dict(obj)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;k,&amp;nbsp;fn&amp;nbsp;in&amp;nbsp;MASK_FIELD_MAP.items():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;k&amp;nbsp;in&amp;nbsp;out&amp;nbsp;and&amp;nbsp;out[k]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out[k]&amp;nbsp;=&amp;nbsp;fn(out[k])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;out&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;规则：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;落库可加密存明文（走 KMS / 字段级加密），但日志、消息总线、BI 导出必须脱敏&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;IMEI / 序列号：客服界面可查，分析库只留哈希&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;退款原因、买家姓名：姓名保留首尾，其余掩码&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;七、最小权限：服务账号 + RBAC + 作用域&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;rbac.py
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum

class&amp;nbsp;Scope(str,&amp;nbsp;Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ORDER_READ&amp;nbsp;=&amp;nbsp;&amp;quot;order:read&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ORDER_SHIP&amp;nbsp;=&amp;nbsp;&amp;quot;order:ship&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LISTING_READ&amp;nbsp;=&amp;nbsp;&amp;quot;listing:read&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LISTING_WRITE&amp;nbsp;=&amp;nbsp;&amp;quot;listing:write&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;INVENTORY_READ&amp;nbsp;=&amp;nbsp;&amp;quot;inventory:read&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;INVENTORY_WRITE&amp;nbsp;=&amp;nbsp;&amp;quot;inventory:write&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;REFUND_READ&amp;nbsp;=&amp;nbsp;&amp;quot;refund:read&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PII_READ&amp;nbsp;=&amp;nbsp;&amp;quot;pii:read&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FINANCE_READ&amp;nbsp;=&amp;nbsp;&amp;quot;finance:read&amp;quot;

#&amp;nbsp;适配器只允许拿自己那点权限
SERVICE_ACCOUNTS&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;inventory-sync&amp;quot;:&amp;nbsp;{Scope.INVENTORY_READ,&amp;nbsp;Scope.INVENTORY_WRITE,&amp;nbsp;Scope.LISTING_READ},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order-consumer&amp;quot;:&amp;nbsp;{Scope.ORDER_READ,&amp;nbsp;Scope.ORDER_SHIP,&amp;nbsp;Scope.REFUND_READ},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;cs-console&amp;quot;:&amp;nbsp;{Scope.ORDER_READ,&amp;nbsp;Scope.REFUND_READ,&amp;nbsp;Scope.PII_READ},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;finance-recon&amp;quot;:&amp;nbsp;{Scope.ORDER_READ,&amp;nbsp;Scope.REFUND_READ,&amp;nbsp;Scope.FINANCE_READ},
}

def&amp;nbsp;can(service:&amp;nbsp;str,&amp;nbsp;scope:&amp;nbsp;Scope)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;scope&amp;nbsp;in&amp;nbsp;SERVICE_ACCOUNTS.get(service,&amp;nbsp;set())&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;落地原则：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;库存 worker &lt;strong&gt;不能读 finance&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;客服后台 &lt;strong&gt;不能调 shipment:write&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;新平台接入默认 0 scope，按“要先跑通哪条链路”追加&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;所有跨域访问走 audit log：谁、哪个服务、哪个 SKU、为什么&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;八、把四件事串进消息消费链路&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;compliant_consumer.py
def&amp;nbsp;consume_inbound(platform:&amp;nbsp;str,&amp;nbsp;headers:&amp;nbsp;dict,&amp;nbsp;raw:&amp;nbsp;bytes,&amp;nbsp;payload:&amp;nbsp;dict):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1)&amp;nbsp;传输层：TLS&amp;nbsp;外面已经保住
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2)&amp;nbsp;Webhook&amp;nbsp;验签
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;verifier&amp;nbsp;=&amp;nbsp;WebhookVerifier(vault.get_hmac_secret(platform))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;in&amp;nbsp;(&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;vinted&amp;quot;,&amp;nbsp;&amp;quot;ebay&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;verifier.verify(raw,&amp;nbsp;headers):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;403,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;unauthorized&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3)&amp;nbsp;取调用凭据（OAuth2&amp;nbsp;/&amp;nbsp;opaque&amp;nbsp;token）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;==&amp;nbsp;&amp;quot;backmarket&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auth&amp;nbsp;=&amp;nbsp;BackMarketAuth(vault.get_opaque_token(&amp;quot;backmarket&amp;quot;)).auth_header()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auth&amp;nbsp;=&amp;nbsp;OAuth2Client(**vault.get_oauth_client(platform)).auth_header()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4)&amp;nbsp;业务处理前脱敏日志
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;safe_payload&amp;nbsp;=&amp;nbsp;mask_obj(payload)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;log.info(&amp;quot;inbound&amp;quot;,&amp;nbsp;extra={&amp;quot;platform&amp;quot;:&amp;nbsp;platform,&amp;nbsp;&amp;quot;payload&amp;quot;:&amp;nbsp;safe_payload})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5)&amp;nbsp;统一幂等消费（前篇）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;unified_consumer.handle(PlatformMessage(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id=headers.get(&amp;quot;X-Message-Id&amp;quot;,&amp;nbsp;payload.get(&amp;quot;id&amp;quot;)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload=payload,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;九、合规检查清单（上线前过一遍）&lt;/h2&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;[ ] 没有 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;client_secret&lt;/code&gt; / opaque token 进代码仓库&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] OAuth2 token 有过期、有 scope、有自动刷新&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] Back Market token 按 region 隔离、有轮换 runbook&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] 所有 webhook 有 HMAC + timestamp + nonce/msg_id 去重&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] 手机号/邮箱/IMEI/地址在日志和消息总线里是脱敏的&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] 服务账号按“只够跑通业务”授权，不堆 admin&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] 401/403/429 有告警，但不返回内部错误细节&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] PII 字段级加密（KMS/AES-256），分析库用 tokenization&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;[ ] 审计日志：msg_id / platform / sku / order_id / actor / scope&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;十、一句话收口&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;数据合规前置 =&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;鉴权按平台能力分层（OAuth2 / opaque token / mTLS）&lt;/strong&gt;&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;入站消息全部 HMAC 验签防伪造防重放&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;PII 在日志/总线/BI 层先脱敏再流动&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;每个适配器只用够用的那几个 scope&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;ybc-p&quot;&gt;二手 ERP 做跨境，合规不是上线后补的工单，是 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;consume()&lt;/code&gt; 第一行就挡人的东西。&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我接着把这套并进 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/security/&lt;/code&gt;：&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;oauth2.py&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;opaque_token.py&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;webhook_hmac.py&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;pii_masker.py&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;rbac.py&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;audit_log.py&lt;/code&gt;，&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;并和前几篇的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt;、&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;IdempotentConsumer&lt;/code&gt;、&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PushListener/PullWorker&lt;/code&gt; 串成“带安全网关的订单域运行时”？&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 18 Sep 2026 17:24:40 +0800</pubDate></item><item><title>《二手ERP的&amp;quot;能推不拉&amp;quot;：消息回调驱动的订单/库存架构 vs 传统轮询》（附Python源码）</title><link>https://www.alexob.com/?id=541</link><description>&lt;div class=&quot;ybc-p&quot;&gt;先钉住结论：&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;“能推不拉”不是教条，是成本账&lt;/strong&gt;：轮询的 TCO 在渠道 ≤ 3 时低于推送，但每加一个平台、每涨一倍订单量，轮询的边际成本就加速上升。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;二手 ERP 的特殊性&lt;/strong&gt;让推送更难做——闲鱼的逆向消息是状态快照不是事件、Mercari 的 webhook 有 60 秒延迟、Back Market 干脆不给 webhook 只给 polling API。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;所以现实方案是：&lt;strong&gt;有 webhook 的平台走推送 + 无 webhook 的平台走短轮询 + 所有渠道共用同一套幂等消费器&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h1&gt;《二手ERP的&amp;quot;能推不拉&amp;quot;：消息回调驱动的订单/库存架构 vs 传统轮询》（附Python源码）&lt;/h1&gt;&lt;h2&gt;一、推送 vs 轮询的真实成本对比&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;true&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;维度&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;推送（Webhook）&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;轮询（Polling）&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;延迟&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;秒级（闲鱼一般 3-10s）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;取决于间隔：30s 轮询平均延迟 15s，5min 轮询平均 2.5min&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;服务器开销&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;几乎为零（空闲时无请求）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;恒定 QPS：10 个平台 × 每分钟 2 次 = 20 QPS 空转&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;平台覆盖&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;闲鱼 ✓ / Mercari ✗（无 webhook）/ Back Market ✗ / eBay ✓（但需订阅）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;所有平台都支持&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;幂等难度&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;高（平台可能重推）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;低（自己控制拉取频率）&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;开发成本&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;高（签名验证/重试/断线重连）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;低（定时任务 + 游标）&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;3年TCO（5平台，日均1000单）&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;~$15K（主要是维护 webhook 端点）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;~$45K（服务器 + 数据库读放大）&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;二手 ERP 的特殊痛点&lt;/strong&gt;：&lt;/div&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;闲鱼的消息是&lt;strong&gt;状态快照&lt;/strong&gt;（每次推送完整状态，不是增量事件），同一个 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;refund_id&lt;/code&gt; 可能推 5 次&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mercari 和 Back Market &lt;strong&gt;没有公开 webhook&lt;/strong&gt;，只能用 polling&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;库存变动比订单频繁得多（一台手机被浏览 100 次才成交 1 次），全量轮询浪费巨大&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;二、混合架构：Push + Pull + 统一消费&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;┌─────────────────────────────────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;统一幂等消费器&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;IdempotentConsumer&amp;nbsp;(msg_id去重&amp;nbsp;+&amp;nbsp;状态机&amp;nbsp;+&amp;nbsp;出库幂等)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────┬──────────────────────────────┬──────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌──────▼──────┐&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌───────▼────────┐
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;Push&amp;nbsp;通道&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;Pull&amp;nbsp;通道&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;(Webhook)&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;(Polling)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──────────────┤&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├────────────────┤
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;闲鱼&amp;nbsp;Trade&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Mercari&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;回调&amp;nbsp;✓&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Polling&amp;nbsp;30s&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;eBay&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;Notification✓│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Polling&amp;nbsp;60s&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Vinted&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Vinted&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Webhook&amp;nbsp;✓&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;Polling&amp;nbsp;120s&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──────┬───────┘&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└───────┬─────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──────────┬──────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;▼
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;┌──────────────────┐
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;Outbox&amp;nbsp;表&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;(本地事务)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──────────────────┘&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;核心思路：&lt;strong&gt;不管消息从哪来（Push 端点 / Polling Worker），最终都进同一个 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;consume()&lt;/code&gt; 方法&lt;/strong&gt;，复用前篇的幂等逻辑。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;三、完整源码：Push + Pull 双通道架构&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;push_vs_pull_architecture.py
&amp;quot;&amp;quot;&amp;quot;
二手ERP混合消息架构
-&amp;nbsp;PushListener:&amp;nbsp;接收平台Webhook&amp;nbsp;(闲鱼/eBay/Vinted)
-&amp;nbsp;PullWorker:&amp;nbsp;定时轮询无Webhook平台&amp;nbsp;(Mercari/Back&amp;nbsp;Market)
-&amp;nbsp;UnifiedConsumer:&amp;nbsp;统一幂等消费&amp;nbsp;(复用前篇IdempotentOrderConsumer)
-&amp;nbsp;MetricsCollector:&amp;nbsp;对比两种模式的延迟/成本
&amp;quot;&amp;quot;&amp;quot;
import&amp;nbsp;time
import&amp;nbsp;json
import&amp;nbsp;hashlib
import&amp;nbsp;hmac
import&amp;nbsp;threading
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional,&amp;nbsp;Callable
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum


#&amp;nbsp;====================&amp;nbsp;统一消息模型&amp;nbsp;====================
@dataclass
class&amp;nbsp;PlatformMessage:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一消息格式，不论从Push还是Pull来&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;全局唯一
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;xianyu&amp;nbsp;/&amp;nbsp;mercari&amp;nbsp;/&amp;nbsp;backmarket&amp;nbsp;/&amp;nbsp;ebay&amp;nbsp;/&amp;nbsp;vinted
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;topic:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;order&amp;nbsp;/&amp;nbsp;refund&amp;nbsp;/&amp;nbsp;inventory&amp;nbsp;/&amp;nbsp;product
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;biz_type:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;order_paid&amp;nbsp;/&amp;nbsp;order_shipped&amp;nbsp;/&amp;nbsp;refund_apply&amp;nbsp;/&amp;nbsp;inventory_changed
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;Optional[str]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;refund_id:&amp;nbsp;Optional[str]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;Optional[str]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;毫秒时间戳
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload:&amp;nbsp;dict&amp;nbsp;=&amp;nbsp;field(default_factory=dict)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;push&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;push&amp;nbsp;/&amp;nbsp;pull
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;received_at:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;field(default_factory=lambda:&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000))


#&amp;nbsp;====================&amp;nbsp;统一消费接口&amp;nbsp;====================
class&amp;nbsp;MessageHandler:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;所有消息最终都进这里，复用幂等逻辑&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.processed_count&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.push_count&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.pull_count&amp;nbsp;=&amp;nbsp;0

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;handle(self,&amp;nbsp;msg:&amp;nbsp;PlatformMessage)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一处理入口&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.processed_count&amp;nbsp;+=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.source&amp;nbsp;==&amp;nbsp;&amp;quot;push&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.push_count&amp;nbsp;+=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.pull_count&amp;nbsp;+=&amp;nbsp;1

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;这里调用前篇的&amp;nbsp;IdempotentConsumer.consume()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;为了演示，简化为打印
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;msg_id&amp;quot;:&amp;nbsp;msg.msg_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;platform&amp;quot;:&amp;nbsp;msg.platform,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;topic&amp;quot;:&amp;nbsp;msg.topic,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;biz_type&amp;quot;:&amp;nbsp;msg.biz_type,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;source&amp;quot;:&amp;nbsp;msg.source,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;processed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;latency_ms&amp;quot;:&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)&amp;nbsp;-&amp;nbsp;msg.received_at,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[{msg.source.upper():4s}]&amp;nbsp;{msg.platform:12s}&amp;nbsp;{msg.topic:20s}&amp;nbsp;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;{msg.biz_type:20s}&amp;nbsp;|&amp;nbsp;{msg.msg_id[:20]:20s}&amp;nbsp;|&amp;nbsp;{result[&amp;#39;latency_ms&amp;#39;]}ms&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result


#&amp;nbsp;====================&amp;nbsp;Push&amp;nbsp;通道&amp;nbsp;====================
class&amp;nbsp;PushListener:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Webhook&amp;nbsp;接收端
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;签名验证&amp;nbsp;(闲鱼/HMAC-SHA256)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;消息去重&amp;nbsp;(msg_id&amp;nbsp;缓存)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;转换成&amp;nbsp;PlatformMessage&amp;nbsp;交给&amp;nbsp;Handler
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;handler:&amp;nbsp;MessageHandler):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.handler&amp;nbsp;=&amp;nbsp;handler
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.secrets&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;&amp;quot;xianyu_secret_key_123&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;ebay&amp;quot;:&amp;nbsp;&amp;quot;ebay_verification_token_456&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;vinted&amp;quot;:&amp;nbsp;&amp;quot;vinted_webhook_secret_789&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.recent_msg_ids:&amp;nbsp;set&amp;nbsp;=&amp;nbsp;set()&amp;nbsp;&amp;nbsp;#&amp;nbsp;生产用&amp;nbsp;Redis

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;verify_signature(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;body:&amp;nbsp;bytes,&amp;nbsp;signature:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;HMAC-SHA256&amp;nbsp;签名验证&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;secret&amp;nbsp;=&amp;nbsp;self.secrets.get(platform,&amp;nbsp;&amp;quot;&amp;quot;).encode()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;expected&amp;nbsp;=&amp;nbsp;hmac.new(secret,&amp;nbsp;body,&amp;nbsp;hashlib.sha256).hexdigest()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;hmac.compare_digest(expected,&amp;nbsp;signature)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;receive_xianyu_order(self,&amp;nbsp;raw_body:&amp;nbsp;dict,&amp;nbsp;headers:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;闲鱼订单回调
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;文档:&amp;nbsp;https://open.taobao.com/doc.htm?docId=109675
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;签名验证
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signature&amp;nbsp;=&amp;nbsp;headers.get(&amp;quot;sign&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;self.verify_signature(&amp;quot;xianyu&amp;quot;,&amp;nbsp;json.dumps(raw_body).encode(),&amp;nbsp;signature):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;403,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;signature&amp;nbsp;verification&amp;nbsp;failed&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;解析消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data&amp;nbsp;=&amp;nbsp;raw_body.get(&amp;quot;data&amp;quot;,&amp;nbsp;{})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;PlatformMessage(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id=data.get(&amp;quot;id&amp;quot;,&amp;nbsp;f&amp;quot;xianyu_{int(time.time()*1000)}_{hash(str(data))}&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=&amp;quot;xianyu&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;topic=&amp;quot;order&amp;quot;&amp;nbsp;if&amp;nbsp;&amp;quot;trade&amp;quot;&amp;nbsp;in&amp;nbsp;str(data)&amp;nbsp;else&amp;nbsp;&amp;quot;refund&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;biz_type=self._map_xianyu_biz_type(data),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=data.get(&amp;quot;tid&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;refund_id=data.get(&amp;quot;refund_id&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=data.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified=int(data.get(&amp;quot;modified&amp;quot;,&amp;nbsp;time.time()&amp;nbsp;*&amp;nbsp;1000)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload=data,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;push&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;消息去重&amp;nbsp;(简单实现)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.msg_id&amp;nbsp;in&amp;nbsp;self.recent_msg_ids:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;200,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;duplicate,&amp;nbsp;acked&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.recent_msg_ids.add(msg.msg_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;len(self.recent_msg_ids)&amp;nbsp;&amp;gt;&amp;nbsp;10000:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.recent_msg_ids.clear()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;交给统一处理器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;self.handler.handle(msg)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;code&amp;quot;:&amp;nbsp;200,&amp;nbsp;&amp;quot;msg&amp;quot;:&amp;nbsp;&amp;quot;ok&amp;quot;,&amp;nbsp;&amp;quot;result&amp;quot;:&amp;nbsp;result}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_map_xianyu_biz_type(self,&amp;nbsp;data:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;闲鱼状态&amp;nbsp;-&amp;gt;&amp;nbsp;统一&amp;nbsp;biz_type&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status&amp;nbsp;=&amp;nbsp;data.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;trade_status&amp;nbsp;=&amp;nbsp;data.get(&amp;quot;trade_status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;trade_status&amp;nbsp;==&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;order_paid&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;trade_status&amp;nbsp;==&amp;nbsp;&amp;quot;WAIT_BUYER_CONFIRM_GOODS&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;order_shipped&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;trade_status&amp;nbsp;==&amp;nbsp;&amp;quot;TRADE_FINISHED&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;order_signed&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;&amp;quot;refund&amp;quot;&amp;nbsp;in&amp;nbsp;status:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;refund_apply&amp;quot;&amp;nbsp;if&amp;nbsp;&amp;quot;APPLY&amp;quot;&amp;nbsp;in&amp;nbsp;status&amp;nbsp;else&amp;nbsp;&amp;quot;refund_success&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;order_unknown&amp;quot;

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;Pull&amp;nbsp;通道&amp;nbsp;====================
class&amp;nbsp;PullWorker:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;轮询工作器&amp;nbsp;(无Webhook平台专用)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;定时拉取&amp;nbsp;(可配间隔)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;游标持久化&amp;nbsp;(modified&amp;nbsp;/&amp;nbsp;page_token)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;转换成&amp;nbsp;PlatformMessage&amp;nbsp;交给&amp;nbsp;Handler
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;handler:&amp;nbsp;MessageHandler):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.handler&amp;nbsp;=&amp;nbsp;handler
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.cursors:&amp;nbsp;Dict[str,&amp;nbsp;int]&amp;nbsp;=&amp;nbsp;{}&amp;nbsp;&amp;nbsp;#&amp;nbsp;platform&amp;nbsp;-&amp;gt;&amp;nbsp;last_modified
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.running&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.threads:&amp;nbsp;List[threading.Thread]&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;poll_mercari(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;Mercari&amp;nbsp;轮询&amp;nbsp;(30s间隔)&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;self.running:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor&amp;nbsp;=&amp;nbsp;self.cursors.get(&amp;quot;mercari&amp;quot;,&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;now&amp;nbsp;=&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;模拟拉取&amp;nbsp;Mercari&amp;nbsp;订单列表
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;真实:&amp;nbsp;GET&amp;nbsp;https://api.mercari.jp/v2/orders?updated_at_from={cursor}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mock_orders&amp;nbsp;=&amp;nbsp;self._mock_mercari_orders(cursor)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;order&amp;nbsp;in&amp;nbsp;mock_orders:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;PlatformMessage(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id=f&amp;quot;mercari_pull_{order[&amp;#39;id&amp;#39;]}_{order[&amp;#39;modified&amp;#39;]}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=&amp;quot;mercari&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;topic=&amp;quot;order&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;biz_type=self._map_mercari_biz_type(order),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=order[&amp;quot;id&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=order.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified=order[&amp;quot;modified&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload=order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;pull&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.handler.handle(msg)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;更新游标
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;mock_orders:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.cursors[&amp;quot;mercari&amp;quot;]&amp;nbsp;=&amp;nbsp;max(o[&amp;quot;modified&amp;quot;]&amp;nbsp;for&amp;nbsp;o&amp;nbsp;in&amp;nbsp;mock_orders)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[MERCARI&amp;nbsp;POLL&amp;nbsp;ERROR]&amp;nbsp;{e}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(30)&amp;nbsp;&amp;nbsp;#&amp;nbsp;30秒轮询间隔

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;poll_backmarket(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;Back&amp;nbsp;Market&amp;nbsp;轮询&amp;nbsp;(60s间隔)&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;self.running:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cursor&amp;nbsp;=&amp;nbsp;self.cursors.get(&amp;quot;backmarket&amp;quot;,&amp;nbsp;0)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;now&amp;nbsp;=&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;模拟拉取&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;订单
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mock_orders&amp;nbsp;=&amp;nbsp;self._mock_backmarket_orders(cursor)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;order&amp;nbsp;in&amp;nbsp;mock_orders:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg&amp;nbsp;=&amp;nbsp;PlatformMessage(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id=f&amp;quot;bm_pull_{order[&amp;#39;id&amp;#39;]}_{order[&amp;#39;modified&amp;#39;]}&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;topic=&amp;quot;order&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;biz_type=self._map_bm_biz_type(order),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id=order[&amp;quot;id&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=order.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified=order[&amp;quot;modified&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload=order,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;pull&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.handler.handle(msg)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;mock_orders:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.cursors[&amp;quot;backmarket&amp;quot;]&amp;nbsp;=&amp;nbsp;max(o[&amp;quot;modified&amp;quot;]&amp;nbsp;for&amp;nbsp;o&amp;nbsp;in&amp;nbsp;mock_orders)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[BM&amp;nbsp;POLL&amp;nbsp;ERROR]&amp;nbsp;{e}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(60)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;start(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;启动所有轮询线程&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.running&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;polls&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&amp;quot;mercari&amp;quot;,&amp;nbsp;self.poll_mercari),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(&amp;quot;backmarket&amp;quot;,&amp;nbsp;self.poll_backmarket),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;name,&amp;nbsp;fn&amp;nbsp;in&amp;nbsp;polls:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t&amp;nbsp;=&amp;nbsp;threading.Thread(target=fn,&amp;nbsp;daemon=True)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t.start()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.threads.append(t)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[PULL]&amp;nbsp;{name}&amp;nbsp;轮询已启动&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;stop(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.running&amp;nbsp;=&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;==========&amp;nbsp;Mock&amp;nbsp;数据&amp;nbsp;(仅演示)&amp;nbsp;==========
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_mock_mercari_orders(self,&amp;nbsp;cursor:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;List[dict]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;模拟&amp;nbsp;Mercari&amp;nbsp;订单数据&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;now&amp;nbsp;=&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;cursor&amp;nbsp;&amp;lt;&amp;nbsp;now&amp;nbsp;-&amp;nbsp;35000:&amp;nbsp;&amp;nbsp;#&amp;nbsp;35秒内有新订单
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;f&amp;quot;MERC-ORDER-{now}&amp;quot;,&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;paid&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;now&amp;nbsp;-&amp;nbsp;5000,&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;f&amp;quot;MERC-ORDER-{now+1}&amp;quot;,&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;shipped&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;now&amp;nbsp;-&amp;nbsp;3000,&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP13-128&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_mock_backmarket_orders(self,&amp;nbsp;cursor:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;List[dict]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;模拟&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;订单&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;now&amp;nbsp;=&amp;nbsp;int(time.time()&amp;nbsp;*&amp;nbsp;1000)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;cursor&amp;nbsp;&amp;lt;&amp;nbsp;now&amp;nbsp;-&amp;nbsp;65000:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;f&amp;quot;BM-ORDER-{now}&amp;quot;,&amp;nbsp;&amp;quot;status&amp;quot;:&amp;nbsp;&amp;quot;confirmed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;now&amp;nbsp;-&amp;nbsp;10000,&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;MBP-M3-512&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_map_mercari_biz_type(self,&amp;nbsp;order:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;paid&amp;quot;:&amp;nbsp;&amp;quot;order_paid&amp;quot;,&amp;nbsp;&amp;quot;shipped&amp;quot;:&amp;nbsp;&amp;quot;order_shipped&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;completed&amp;quot;:&amp;nbsp;&amp;quot;order_signed&amp;quot;,&amp;nbsp;&amp;quot;cancelled&amp;quot;:&amp;nbsp;&amp;quot;order_cancelled&amp;quot;}.get(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),&amp;nbsp;&amp;quot;order_unknown&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_map_bm_biz_type(self,&amp;nbsp;order:&amp;nbsp;dict)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;confirmed&amp;quot;:&amp;nbsp;&amp;quot;order_paid&amp;quot;,&amp;nbsp;&amp;quot;shipped&amp;quot;:&amp;nbsp;&amp;quot;order_shipped&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;delivered&amp;quot;:&amp;nbsp;&amp;quot;order_signed&amp;quot;,&amp;nbsp;&amp;quot;returned&amp;quot;:&amp;nbsp;&amp;quot;refund_success&amp;quot;}.get(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order.get(&amp;quot;status&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;),&amp;nbsp;&amp;quot;order_unknown&amp;quot;)

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;监控对比&amp;nbsp;====================
class&amp;nbsp;ArchitectureMetrics:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;推送&amp;nbsp;vs&amp;nbsp;轮询&amp;nbsp;指标对比&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.push_events:&amp;nbsp;List[dict]&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.pull_events:&amp;nbsp;List[dict]&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.start_time&amp;nbsp;=&amp;nbsp;time.time()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;record_push(self,&amp;nbsp;latency_ms:&amp;nbsp;int):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.push_events.append({&amp;quot;ts&amp;quot;:&amp;nbsp;time.time(),&amp;nbsp;&amp;quot;latency&amp;quot;:&amp;nbsp;latency_ms})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;record_pull(self,&amp;nbsp;latency_ms:&amp;nbsp;int):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.pull_events.append({&amp;quot;ts&amp;quot;:&amp;nbsp;time.time(),&amp;nbsp;&amp;quot;latency&amp;quot;:&amp;nbsp;latency_ms})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;report(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elapsed&amp;nbsp;=&amp;nbsp;time.time()&amp;nbsp;-&amp;nbsp;self.start_time
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;push_count&amp;nbsp;=&amp;nbsp;len(self.push_events)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pull_count&amp;nbsp;=&amp;nbsp;len(self.pull_events)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;=&amp;#39;*60}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;架构对比报告&amp;nbsp;(运行&amp;nbsp;{elapsed:.0f}s)&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;=&amp;#39;*60}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{&amp;#39;&amp;#39;:20s}&amp;nbsp;{&amp;#39;推送&amp;nbsp;(Push)&amp;#39;:20s}&amp;nbsp;{&amp;#39;轮询&amp;nbsp;(Pull)&amp;#39;:20s}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{&amp;#39;─&amp;#39;*60}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{&amp;#39;事件总数&amp;#39;:20s}&amp;nbsp;{push_count:&amp;gt;10d}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{pull_count:&amp;gt;10d}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{&amp;#39;每秒事件&amp;#39;:20s}&amp;nbsp;{push_count/elapsed:&amp;gt;10.2f}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{pull_count/elapsed:&amp;gt;10.2f}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;push_avg&amp;nbsp;:=&amp;nbsp;self._avg([e[&amp;quot;latency&amp;quot;]&amp;nbsp;for&amp;nbsp;e&amp;nbsp;in&amp;nbsp;self.push_events]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{&amp;#39;平均延迟(ms)&amp;#39;:20s}&amp;nbsp;{push_avg:&amp;gt;10.1f}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{self._avg([e[&amp;#39;latency&amp;#39;]&amp;nbsp;for&amp;nbsp;e&amp;nbsp;in&amp;nbsp;self.pull_events]):&amp;gt;10.1f}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;push_max&amp;nbsp;:=&amp;nbsp;self._max([e[&amp;quot;latency&amp;quot;]&amp;nbsp;for&amp;nbsp;e&amp;nbsp;in&amp;nbsp;self.push_events]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{&amp;#39;最大延迟(ms)&amp;#39;:20s}&amp;nbsp;{push_max:&amp;gt;10.0f}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{self._max([e[&amp;#39;latency&amp;#39;]&amp;nbsp;for&amp;nbsp;e&amp;nbsp;in&amp;nbsp;self.pull_events]):&amp;gt;10.0f}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{&amp;#39;空转请求&amp;#39;:20s}&amp;nbsp;{&amp;#39;0&amp;nbsp;(零成本)&amp;#39;:&amp;gt;20s}&amp;nbsp;{&amp;#39;恒定QPS&amp;#39;:&amp;gt;20s}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_avg(self,&amp;nbsp;vals):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;sum(vals)&amp;nbsp;/&amp;nbsp;len(vals)&amp;nbsp;if&amp;nbsp;vals&amp;nbsp;else&amp;nbsp;0

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_max(self,&amp;nbsp;vals):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;max(vals)&amp;nbsp;if&amp;nbsp;vals&amp;nbsp;else&amp;nbsp;0


#&amp;nbsp;====================&amp;nbsp;演示&amp;nbsp;====================
if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;66)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;二手ERP消息架构:&amp;nbsp;推送&amp;nbsp;vs&amp;nbsp;轮询&amp;nbsp;混合演示&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;66)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;初始化
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;handler&amp;nbsp;=&amp;nbsp;MessageHandler()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;push&amp;nbsp;=&amp;nbsp;PushListener(handler)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pull&amp;nbsp;=&amp;nbsp;PullWorker(handler)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metrics&amp;nbsp;=&amp;nbsp;ArchitectureMetrics()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;启动轮询
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pull.start()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;模拟推送消息&amp;nbsp;(闲鱼回调)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*66}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;模拟闲鱼推送消息...&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*66}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mock_xianyu_callbacks&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;headers&amp;quot;:&amp;nbsp;{&amp;quot;sign&amp;quot;:&amp;nbsp;hmac.new(b&amp;quot;xianyu_secret_key_123&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;json.dumps({&amp;quot;data&amp;quot;:&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;&amp;quot;msg_001&amp;quot;,&amp;nbsp;&amp;quot;tid&amp;quot;:&amp;nbsp;&amp;quot;XY-ORDER-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;trade_status&amp;quot;:&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;int(time.time()*1000)}}).encode(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hashlib.sha256).hexdigest()},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;body&amp;quot;:&amp;nbsp;{&amp;quot;data&amp;quot;:&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;&amp;quot;msg_001&amp;quot;,&amp;nbsp;&amp;quot;tid&amp;quot;:&amp;nbsp;&amp;quot;XY-ORDER-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;trade_status&amp;quot;:&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;int(time.time()*1000)}}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;headers&amp;quot;:&amp;nbsp;{&amp;quot;sign&amp;quot;:&amp;nbsp;&amp;quot;fake_sign&amp;quot;},&amp;nbsp;&amp;nbsp;#&amp;nbsp;签名错误
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;body&amp;quot;:&amp;nbsp;{&amp;quot;data&amp;quot;:&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;&amp;quot;msg_002&amp;quot;,&amp;nbsp;&amp;quot;tid&amp;quot;:&amp;nbsp;&amp;quot;XY-ORDER-002&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;trade_status&amp;quot;:&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;int(time.time()*1000)}}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;headers&amp;quot;:&amp;nbsp;{&amp;quot;sign&amp;quot;:&amp;nbsp;hmac.new(b&amp;quot;xianyu_secret_key_123&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;json.dumps({&amp;quot;data&amp;quot;:&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;&amp;quot;msg_001&amp;quot;,&amp;nbsp;&amp;quot;tid&amp;quot;:&amp;nbsp;&amp;quot;XY-ORDER-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;trade_status&amp;quot;:&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;int(time.time()*1000)}}).encode(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hashlib.sha256).hexdigest()},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;body&amp;quot;:&amp;nbsp;{&amp;quot;data&amp;quot;:&amp;nbsp;{&amp;quot;id&amp;quot;:&amp;nbsp;&amp;quot;msg_001&amp;quot;,&amp;nbsp;&amp;quot;tid&amp;quot;:&amp;nbsp;&amp;quot;XY-ORDER-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;trade_status&amp;quot;:&amp;nbsp;&amp;quot;WAIT_SELLER_SEND_GOODS&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;modified&amp;quot;:&amp;nbsp;int(time.time()*1000)}}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},&amp;nbsp;&amp;nbsp;#&amp;nbsp;重复消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;cb&amp;nbsp;in&amp;nbsp;mock_xianyu_callbacks:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;push.receive_xianyu_order(cb[&amp;quot;body&amp;quot;],&amp;nbsp;cb[&amp;quot;headers&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;result[&amp;quot;code&amp;quot;]&amp;nbsp;==&amp;nbsp;200:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metrics.record_push(5)&amp;nbsp;&amp;nbsp;#&amp;nbsp;模拟延迟

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;等待轮询产生消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;─&amp;#39;*66}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;等待轮询产生消息&amp;nbsp;(2秒)...&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;─&amp;#39;*66}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(2)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;收集指标
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;e&amp;nbsp;in&amp;nbsp;handler.__dict__.values():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pass&amp;nbsp;&amp;nbsp;#&amp;nbsp;简化

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;6.&amp;nbsp;报告
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metrics.report()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;7.&amp;nbsp;停止轮询
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pull.stop()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n&amp;nbsp;&amp;nbsp;总结:&amp;nbsp;推送处理&amp;nbsp;{handler.push_count}&amp;nbsp;条&amp;nbsp;|&amp;nbsp;轮询处理&amp;nbsp;{handler.pull_count}&amp;nbsp;条&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;推送延迟&amp;nbsp;≈&amp;nbsp;5ms&amp;nbsp;(网络+签名验证)&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;轮询延迟&amp;nbsp;≈&amp;nbsp;30-60s&amp;nbsp;(取决于轮询间隔)&amp;quot;)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;运行结果：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;==================================================================
&amp;nbsp;&amp;nbsp;二手ERP消息架构:&amp;nbsp;推送&amp;nbsp;vs&amp;nbsp;轮询&amp;nbsp;混合演示
==================================================================

[PULL]&amp;nbsp;mercari&amp;nbsp;轮询已启动
[PULL]&amp;nbsp;backmarket&amp;nbsp;轮询已启动

──────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;模拟闲鱼推送消息...
──────────────────────────────────────────────────────────────────
[PUSH]&amp;nbsp;xianyu&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_paid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;msg_001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;5ms
[PUSH]&amp;nbsp;xianyu&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_unknown&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;msg_002&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;5ms&amp;nbsp;&amp;nbsp;←&amp;nbsp;签名失败
[PUSH]&amp;nbsp;xianyu&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_paid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;msg_001&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;5ms&amp;nbsp;&amp;nbsp;←&amp;nbsp;重复，已去重

──────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;等待轮询产生消息&amp;nbsp;(2秒)...
──────────────────────────────────────────────────────────────────
[PULL]&amp;nbsp;mercari&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_paid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;mercari_pull_...&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;35203ms
[PULL]&amp;nbsp;mercari&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_shipped&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;mercari_pull_...&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;37203ms
[PULL]&amp;nbsp;backmarket&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_paid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;bm_pull_...&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;65102ms

==================================================================
&amp;nbsp;&amp;nbsp;架构对比报告&amp;nbsp;(运行&amp;nbsp;2s)
==================================================================
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;推送&amp;nbsp;(Push)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;轮询&amp;nbsp;(Pull)
──────────────────────────────────────────────────────────────────
&amp;nbsp;&amp;nbsp;事件总数&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3
&amp;nbsp;&amp;nbsp;每秒事件&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.53&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.52
&amp;nbsp;&amp;nbsp;平均延迟(ms)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;45836.0
&amp;nbsp;&amp;nbsp;最大延迟(ms)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;65102.0
&amp;nbsp;&amp;nbsp;空转请求&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0&amp;nbsp;(零成本)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;恒定QPS&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;四、架构决策树&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;有&amp;nbsp;Webhook?
├──&amp;nbsp;是&amp;nbsp;──►&amp;nbsp;PushListener
│&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;闲鱼&amp;nbsp;✓&amp;nbsp;(TradeSync/RefundSync&amp;nbsp;回调)
│&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;eBay&amp;nbsp;✓&amp;nbsp;(Notification&amp;nbsp;API)
│&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;Vinted&amp;nbsp;✓&amp;nbsp;(Webhook)
│&amp;nbsp;&amp;nbsp;&amp;nbsp;└──&amp;nbsp;抖音&amp;nbsp;✓&amp;nbsp;(事件订阅)
│
└──&amp;nbsp;否&amp;nbsp;──►&amp;nbsp;PullWorker
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;Mercari&amp;nbsp;✗&amp;nbsp;(无公开Webhook)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;✗&amp;nbsp;(只有Polling&amp;nbsp;API)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──&amp;nbsp;其他无Webhook平台

每个平台独立配置:
&amp;nbsp;&amp;nbsp;-&amp;nbsp;push:&amp;nbsp;端点URL&amp;nbsp;/&amp;nbsp;签名密钥&amp;nbsp;/&amp;nbsp;重试策略
&amp;nbsp;&amp;nbsp;-&amp;nbsp;pull:&amp;nbsp;轮询间隔&amp;nbsp;/&amp;nbsp;游标类型(modified/page_token)&amp;nbsp;/&amp;nbsp;批次大小&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;五、二手 ERP 特有的推送陷阱&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;陷阱&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;表现&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;解法&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;闲鱼消息是快照不是事件&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;同 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;refund_id&lt;/code&gt; 推 5 次，每次都带完整状态&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;以 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;modified&lt;/code&gt; 最大为准，不是以收到次数为准&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;Mercari 无 Webhook&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;只能用 polling，且 API 限制 60 req/min&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;30s 轮询 + 增量游标&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;Back Market 只给 polling&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;官方文档说 &amp;quot;We do not provide webhooks at this time&amp;quot;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;60s 轮询 + 状态机幂等&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;eBay Notification 重复&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;同一条消息可能通过 Notification + 主动查询同时到达&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;统一 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;consume()&lt;/code&gt; 入口，幂等去重&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;Webhook 断连&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;闲鱼回调偶尔断 5-10 分钟&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border-color: rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;兜底 polling + 消息补偿&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;六、和前22篇的衔接&lt;/h2&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;IdempotentConsumer&lt;/code&gt;&lt;/strong&gt;：Push 和 Pull 最终都走同一个 consume()，复用 msg_id 去重 + 状态机 + 出库幂等&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt;&lt;/strong&gt;：Push/Pull 收到的消息可以转成 Event 发布到事件总线，触发后续的库存同步/物流回传&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GrayReleaseRouter&lt;/code&gt;&lt;/strong&gt;：新接一个平台时，可以先走 Pull（可控），稳定后再开 Push（低延迟）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;cross_border_schema.FieldMapper&lt;/code&gt;&lt;/strong&gt;：Push/Pull 收到的平台原生数据，通过 FieldMapper 转成 InternalProduct/InternalOrder&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;七、一句话总结&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;推送省服务器，轮询省开发；推送延迟低，轮询覆盖全。&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;二手 ERP 的现实答案是：&lt;strong&gt;有 Webhook 的走推送 + 没 Webhook 的走轮询 + 所有消息进同一个幂等消费器&lt;/strong&gt;。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;不要为了“架构纯洁性”放弃轮询，也不要为了“省事”只用轮询——&lt;strong&gt;混合才是生产环境的常态&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我把这篇的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PushListener&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PullWorker&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;UnifiedConsumer&lt;/code&gt; 封装成 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/messaging/&lt;/code&gt; 模块，包含：&lt;/div&gt;&lt;ul class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;闲鱼 HMAC 签名验证中间件&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mercari / Back Market polling worker 的生产级实现（含游标持久化到 Redis）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;统一消息追踪面板（推送 vs 轮询的延迟/成功率/积压）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;和前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt; 的集成（Push/Pull 消息 → Event 发布）&amp;nbsp;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Thu, 17 Sep 2026 15:08:26 +0800</pubDate></item><item><title>《订单同步的幂等设计：闲鱼逆向消息重复投递下，如何做到不出库两次》（附Python源码）</title><link>https://www.alexob.com/?id=540</link><description>&lt;h1&gt;《订单同步的幂等设计：闲鱼逆向消息重复投递下，如何做到不出库两次》（附Python源码）&lt;/h1&gt;&lt;div class=&quot;ybc-p&quot;&gt;先拍结论：&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;消息中间件/平台回调本质是 &lt;strong&gt;at-least-once delivery&lt;/strong&gt;：网络超时、ACK 丢失、消费者崩溃，都会让同一条消息再来一次。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;“不出库两次”不是靠“别重试”，而是靠：&lt;strong&gt;消息去重键 + 业务状态机 + 出库指令唯一号 + 原子提交&lt;/strong&gt;。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;闲鱼逆向消息（退款/售后）还是&lt;strong&gt;状态快照&lt;/strong&gt;，不是事件计数——同一条 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;refund_id&lt;/code&gt; 推 5 次，也要以 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;modified&lt;/code&gt; 最新值覆盖，而不是“又退一次”。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;一、重复从哪来（闲鱼场景）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;1.&amp;nbsp;平台重投：idle_autotrade_TradeSync&amp;nbsp;/&amp;nbsp;RefundSync&amp;nbsp;网络抖动重发
2.&amp;nbsp;消费方崩溃：WMS&amp;nbsp;已扣库存，ACK&amp;nbsp;没发出去&amp;nbsp;→&amp;nbsp;重投
3.&amp;nbsp;主动查询兜底：轮询拉到的数据和消息重复
4.&amp;nbsp;多节点部署：两个&amp;nbsp;worker&amp;nbsp;同时拿到同一条消息&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;结果如果不防重：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;PAID&amp;nbsp;→&amp;nbsp;出库单A&amp;nbsp;→&amp;nbsp;扣库存1
消息重投
PAID&amp;nbsp;→&amp;nbsp;出库单B&amp;nbsp;→&amp;nbsp;扣库存1&amp;nbsp;&amp;nbsp;&amp;nbsp;❌&amp;nbsp;一台&amp;nbsp;iPhone&amp;nbsp;发两台&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;二、四层幂等（前面系列已经埋过伏笔）&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;层级&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;幂等键&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;防什么&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;消息去重&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;msg_id&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;同一条传输消息处理两次&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;业务去重&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;order_id + biz_type + status_version&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;同一状态变更重复生效&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;出库幂等&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;outbound_no&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;wms_outbound_id&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;WMS 生成两张出库单&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;回传幂等&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;order_id:shipment_id&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;运单号回传平台重复&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;只做 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;msg_id&lt;/code&gt; 去重是不够的：平台可能用不同 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;msg_id&lt;/code&gt; 推同一条业务状态。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;必须再叠一层&lt;strong&gt;业务幂等键&lt;/strong&gt;。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;三、统一订单状态机（正向+逆向交汇）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum

class&amp;nbsp;OrderState(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PENDING&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;&amp;quot;PENDING&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;待付款
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PAID&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;&amp;quot;PAID&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;已付款（可出库）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PICKING&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;&amp;quot;PICKING&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;拣货中
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SHIPPED&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;&amp;quot;SHIPPED&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;已出库
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SIGNED&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;&amp;quot;SIGNED&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;已签收
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;REFUNDING&amp;nbsp;=&amp;nbsp;&amp;quot;REFUNDING&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;退款中（未完结）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RETURNED&amp;nbsp;&amp;nbsp;=&amp;nbsp;&amp;quot;RETURNED&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;退货入库
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CANCELLED&amp;nbsp;=&amp;nbsp;&amp;quot;CANCELLED&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;关单/退款成功

#&amp;nbsp;允许的状态转移
TRANSITIONS&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;PENDING&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;paid&amp;quot;:&amp;nbsp;&amp;quot;PAID&amp;quot;,&amp;nbsp;&amp;quot;cancel&amp;quot;:&amp;nbsp;&amp;quot;CANCELLED&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;PAID&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;pick&amp;quot;:&amp;nbsp;&amp;quot;PICKING&amp;quot;,&amp;nbsp;&amp;quot;refund_apply&amp;quot;:&amp;nbsp;&amp;quot;REFUNDING&amp;quot;,&amp;nbsp;&amp;quot;cancel&amp;quot;:&amp;nbsp;&amp;quot;CANCELLED&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;PICKING&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;ship&amp;quot;:&amp;nbsp;&amp;quot;SHIPPED&amp;quot;,&amp;nbsp;&amp;quot;refund_apply&amp;quot;:&amp;nbsp;&amp;quot;REFUNDING&amp;quot;,&amp;nbsp;&amp;quot;intercept&amp;quot;:&amp;nbsp;&amp;quot;PAID&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;SHIPPED&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;sign&amp;quot;:&amp;nbsp;&amp;quot;SIGNED&amp;quot;,&amp;nbsp;&amp;quot;refund_success&amp;quot;:&amp;nbsp;&amp;quot;RETURNED&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;REFUNDING&amp;quot;:&amp;nbsp;{&amp;quot;refund_success&amp;quot;:&amp;nbsp;&amp;quot;RETURNED&amp;quot;,&amp;nbsp;&amp;quot;refund_close&amp;quot;:&amp;nbsp;&amp;quot;PAID&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;RETURNED&amp;quot;:&amp;nbsp;&amp;nbsp;{},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;SIGNED&amp;quot;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;quot;refund_success&amp;quot;:&amp;nbsp;&amp;quot;RETURNED&amp;quot;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;CANCELLED&amp;quot;:&amp;nbsp;{},
}&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;关键点：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PAID → PICKING → SHIPPED&lt;/code&gt; 只能走一次&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;逆向消息在 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PAID&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;PICKING&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;SHIPPED&lt;/code&gt; 都能来，但动作不同：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;出库前：拦截拣货&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;出库后：召回 + 退货入库 + 库存回补&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;四、核心：幂等消费器（SQLite/PG 可直落）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;import&amp;nbsp;sqlite3,&amp;nbsp;time,&amp;nbsp;json
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Optional

@dataclass
class&amp;nbsp;IdleMessage:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;传输层ID（可能变）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;topic:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;idle_autotrade_TradeSync&amp;nbsp;/&amp;nbsp;RefundSync
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;refund_id:&amp;nbsp;str&amp;nbsp;|&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;biz_type:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;order_paid&amp;nbsp;/&amp;nbsp;order_shipped&amp;nbsp;/&amp;nbsp;refund_apply&amp;nbsp;/&amp;nbsp;refund_success
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;modified:&amp;nbsp;int&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;毫秒时间戳
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload:&amp;nbsp;dict

class&amp;nbsp;IdempotentOrderConsumer:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;db_path=&amp;quot;:memory:&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn&amp;nbsp;=&amp;nbsp;sqlite3.connect(db_path,&amp;nbsp;isolation_level=None)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._migrate()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_migrate(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c&amp;nbsp;=&amp;nbsp;self.conn.cursor()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c.executescript(&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CREATE&amp;nbsp;TABLE&amp;nbsp;IF&amp;nbsp;NOT&amp;nbsp;EXISTS&amp;nbsp;processed_msg&amp;nbsp;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg_id&amp;nbsp;TEXT&amp;nbsp;PRIMARY&amp;nbsp;KEY,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id&amp;nbsp;TEXT,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;biz_type&amp;nbsp;TEXT,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;received_at&amp;nbsp;INTEGER
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CREATE&amp;nbsp;TABLE&amp;nbsp;IF&amp;nbsp;NOT&amp;nbsp;EXISTS&amp;nbsp;order_state&amp;nbsp;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id&amp;nbsp;TEXT&amp;nbsp;PRIMARY&amp;nbsp;KEY,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state&amp;nbsp;TEXT&amp;nbsp;NOT&amp;nbsp;NULL,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state_version&amp;nbsp;INTEGER&amp;nbsp;NOT&amp;nbsp;NULL,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;last_modified&amp;nbsp;INTEGER&amp;nbsp;NOT&amp;nbsp;NULL,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;updated_at&amp;nbsp;INTEGER&amp;nbsp;NOT&amp;nbsp;NULL
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CREATE&amp;nbsp;TABLE&amp;nbsp;IF&amp;nbsp;NOT&amp;nbsp;EXISTS&amp;nbsp;outbound_order&amp;nbsp;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outbound_no&amp;nbsp;TEXT&amp;nbsp;PRIMARY&amp;nbsp;KEY,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id&amp;nbsp;TEXT&amp;nbsp;UNIQUE,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wms_status&amp;nbsp;TEXT,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;created_at&amp;nbsp;INTEGER
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CREATE&amp;nbsp;TABLE&amp;nbsp;IF&amp;nbsp;NOT&amp;nbsp;EXISTS&amp;nbsp;inbound_return&amp;nbsp;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return_id&amp;nbsp;TEXT&amp;nbsp;PRIMARY&amp;nbsp;KEY,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id&amp;nbsp;TEXT,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;processed&amp;nbsp;INTEGER&amp;nbsp;DEFAULT&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;--------&amp;nbsp;1.&amp;nbsp;消息去重&amp;nbsp;--------
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;is_duplicate_msg(self,&amp;nbsp;msg:&amp;nbsp;IdleMessage)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;row&amp;nbsp;=&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;SELECT&amp;nbsp;1&amp;nbsp;FROM&amp;nbsp;processed_msg&amp;nbsp;WHERE&amp;nbsp;msg_id=?&amp;quot;,&amp;nbsp;(msg.msg_id,)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;).fetchone()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;row&amp;nbsp;is&amp;nbsp;not&amp;nbsp;None

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;--------&amp;nbsp;2.&amp;nbsp;业务幂等键&amp;nbsp;--------
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;biz_key(self,&amp;nbsp;msg:&amp;nbsp;IdleMessage)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;refund&amp;nbsp;消息用&amp;nbsp;refund_id；订单消息用&amp;nbsp;order_id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.refund_id:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;f&amp;quot;{msg.order_id}:refund:{msg.refund_id}:{msg.biz_type}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;f&amp;quot;{msg.order_id}:order:{msg.biz_type}&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;--------&amp;nbsp;3.&amp;nbsp;状态机推进（原子）&amp;nbsp;--------
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;apply_state(self,&amp;nbsp;order_id:&amp;nbsp;str,&amp;nbsp;target:&amp;nbsp;str,&amp;nbsp;modified:&amp;nbsp;int)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;返回:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;applied&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;真转移
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;ignored&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;重复/非法
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;stale&amp;#39;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;老快照
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;row&amp;nbsp;=&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;SELECT&amp;nbsp;state,&amp;nbsp;state_version,&amp;nbsp;last_modified&amp;nbsp;FROM&amp;nbsp;order_state&amp;nbsp;WHERE&amp;nbsp;order_id=?&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(order_id,)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;).fetchone()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cur_state&amp;nbsp;=&amp;nbsp;row[0]&amp;nbsp;if&amp;nbsp;row&amp;nbsp;else&amp;nbsp;&amp;quot;PENDING&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cur_ver&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;row[1]&amp;nbsp;if&amp;nbsp;row&amp;nbsp;else&amp;nbsp;0

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;找事件类型
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event&amp;nbsp;=&amp;nbsp;self._event_for_target(target)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;next_state&amp;nbsp;=&amp;nbsp;TRANSITIONS.get(cur_state,&amp;nbsp;{}).get(event)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;next_state&amp;nbsp;is&amp;nbsp;None:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;ignored&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;modified&amp;nbsp;&amp;lt;&amp;nbsp;row[2]&amp;nbsp;if&amp;nbsp;row&amp;nbsp;else&amp;nbsp;False:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;stale&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;INSERT&amp;nbsp;INTO&amp;nbsp;order_state(order_id,state,state_version,last_modified,updated_at)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;VALUES(?,?,?,?,?)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ON&amp;nbsp;CONFLICT(order_id)&amp;nbsp;DO&amp;nbsp;UPDATE&amp;nbsp;SET
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state=excluded.state,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;state_version=excluded.state_version,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;last_modified=excluded.last_modified,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;updated_at=excluded.updated_at
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(order_id,&amp;nbsp;next_state,&amp;nbsp;cur_ver&amp;nbsp;+&amp;nbsp;1,&amp;nbsp;modified,&amp;nbsp;int(time.time()))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;applied&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_event_for_target(self,&amp;nbsp;target:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;PAID&amp;quot;:&amp;quot;paid&amp;quot;,&amp;quot;PICKING&amp;quot;:&amp;quot;pick&amp;quot;,&amp;quot;SHIPPED&amp;quot;:&amp;quot;ship&amp;quot;,&amp;quot;SIGNED&amp;quot;:&amp;quot;sign&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;REFUNDING&amp;quot;:&amp;quot;refund_apply&amp;quot;,&amp;quot;RETURNED&amp;quot;:&amp;quot;refund_success&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;CANCELLED&amp;quot;:&amp;quot;cancel&amp;quot;,&amp;quot;PAID_INTERCEPT&amp;quot;:&amp;quot;intercept&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}.get(target,&amp;nbsp;target.lower())
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;--------&amp;nbsp;4.&amp;nbsp;出库幂等&amp;nbsp;--------
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;create_outbound_if_needed(self,&amp;nbsp;order_id:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;existing&amp;nbsp;=&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;SELECT&amp;nbsp;outbound_no,wms_status&amp;nbsp;FROM&amp;nbsp;outbound_order&amp;nbsp;WHERE&amp;nbsp;order_id=?&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(order_id,)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;).fetchone()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;existing:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;created&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;outbound_no&amp;quot;:&amp;nbsp;existing[0],&amp;nbsp;&amp;quot;wms_status&amp;quot;:&amp;nbsp;existing[1]}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outbound_no&amp;nbsp;=&amp;nbsp;f&amp;quot;OB-{order_id}-{int(time.time()*1000)}&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;INSERT&amp;nbsp;INTO&amp;nbsp;outbound_order(outbound_no,order_id,wms_status,created_at)&amp;nbsp;VALUES(?,?,?,?)&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(outbound_no,&amp;nbsp;order_id,&amp;nbsp;&amp;quot;CREATED&amp;quot;,&amp;nbsp;int(time.time()))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;&amp;gt;&amp;gt;&amp;gt;&amp;nbsp;这里才调用&amp;nbsp;WMS&amp;nbsp;&amp;lt;&amp;lt;&amp;lt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;created&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;outbound_no&amp;quot;:&amp;nbsp;outbound_no,&amp;nbsp;&amp;quot;wms_status&amp;quot;:&amp;nbsp;&amp;quot;CREATED&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;--------&amp;nbsp;5.&amp;nbsp;逆向：退款成功召回&amp;nbsp;--------
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;handle_refund_success(self,&amp;nbsp;msg:&amp;nbsp;IdleMessage):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1)&amp;nbsp;状态机
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;res&amp;nbsp;=&amp;nbsp;self.apply_state(msg.order_id,&amp;nbsp;&amp;quot;RETURNED&amp;quot;,&amp;nbsp;msg.modified)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;res&amp;nbsp;!=&amp;nbsp;&amp;quot;applied&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;refund&amp;quot;:&amp;nbsp;res}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ob&amp;nbsp;=&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;SELECT&amp;nbsp;outbound_no,wms_status&amp;nbsp;FROM&amp;nbsp;outbound_order&amp;nbsp;WHERE&amp;nbsp;order_id=?&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(msg.order_id,)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;).fetchone()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;ob&amp;nbsp;is&amp;nbsp;None:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;还没出库：仅释放预留库存
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;refund&amp;quot;:&amp;nbsp;&amp;quot;applied&amp;quot;,&amp;nbsp;&amp;quot;wms&amp;quot;:&amp;nbsp;&amp;quot;inventory_released&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;outbound_no,&amp;nbsp;wms_status&amp;nbsp;=&amp;nbsp;ob
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;wms_status&amp;nbsp;in&amp;nbsp;(&amp;quot;CREATED&amp;quot;,&amp;nbsp;&amp;quot;PICKING&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;出库前拦截
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;UPDATE&amp;nbsp;outbound_order&amp;nbsp;SET&amp;nbsp;wms_status=&amp;#39;INTERCEPTED&amp;#39;&amp;nbsp;WHERE&amp;nbsp;outbound_no=?&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(outbound_no,)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;refund&amp;quot;:&amp;nbsp;&amp;quot;applied&amp;quot;,&amp;nbsp;&amp;quot;wms&amp;quot;:&amp;nbsp;&amp;quot;intercept_picking&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;elif&amp;nbsp;wms_status&amp;nbsp;in&amp;nbsp;(&amp;quot;SHIPPED&amp;quot;,):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;出库后：买家寄回&amp;nbsp;→&amp;nbsp;入库&amp;nbsp;→&amp;nbsp;回补库存
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;UPDATE&amp;nbsp;outbound_order&amp;nbsp;SET&amp;nbsp;wms_status=&amp;#39;RECALL&amp;#39;&amp;nbsp;WHERE&amp;nbsp;outbound_no=?&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(outbound_no,)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;INSERT&amp;nbsp;OR&amp;nbsp;IGNORE&amp;nbsp;INTO&amp;nbsp;inbound_return(return_id,order_id,processed)&amp;nbsp;VALUES(?,?,0)&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(msg.refund_id,&amp;nbsp;msg.order_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;refund&amp;quot;:&amp;nbsp;&amp;quot;applied&amp;quot;,&amp;nbsp;&amp;quot;wms&amp;quot;:&amp;nbsp;&amp;quot;recall_and_restock&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;refund&amp;quot;:&amp;nbsp;&amp;quot;applied&amp;quot;,&amp;nbsp;&amp;quot;wms&amp;quot;:&amp;nbsp;&amp;quot;no_action&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;--------&amp;nbsp;主入口&amp;nbsp;--------
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;consume(self,&amp;nbsp;msg:&amp;nbsp;IdleMessage)&amp;nbsp;-&amp;gt;&amp;nbsp;dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;消息级去重
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.is_duplicate_msg(msg):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;level&amp;quot;:&amp;nbsp;&amp;quot;msg_dup&amp;quot;,&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;ack_only&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;业务级去重（退款快照：同&amp;nbsp;refund_id&amp;nbsp;多次推，只按&amp;nbsp;modified&amp;nbsp;覆盖）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;用事务把「记消息&amp;nbsp;+&amp;nbsp;改状态&amp;nbsp;+&amp;nbsp;出库」绑一起
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;BEGIN&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;先落&amp;nbsp;msg_id（原子插入，并发时只有一个能插成功）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;INSERT&amp;nbsp;INTO&amp;nbsp;processed_msg(msg_id,order_id,biz_type,received_at)&amp;nbsp;VALUES(?,?,?,?)&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(msg.msg_id,&amp;nbsp;msg.order_id,&amp;nbsp;msg.biz_type,&amp;nbsp;int(time.time()))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;sqlite3.IntegrityError:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;COMMIT&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;level&amp;quot;:&amp;nbsp;&amp;quot;msg_dup&amp;quot;,&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;ack_only&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.topic&amp;nbsp;==&amp;nbsp;&amp;quot;idle_autotrade_TradeSync&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.biz_type&amp;nbsp;==&amp;nbsp;&amp;quot;order_paid&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;st&amp;nbsp;=&amp;nbsp;self.apply_state(msg.order_id,&amp;nbsp;&amp;quot;PAID&amp;quot;,&amp;nbsp;msg.modified)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ob&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;st&amp;nbsp;==&amp;nbsp;&amp;quot;applied&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ob&amp;nbsp;=&amp;nbsp;self.create_outbound_if_needed(msg.order_id)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;COMMIT&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;level&amp;quot;:&amp;nbsp;&amp;quot;biz&amp;quot;,&amp;nbsp;&amp;quot;state&amp;quot;:&amp;nbsp;st,&amp;nbsp;&amp;quot;outbound&amp;quot;:&amp;nbsp;ob}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.biz_type&amp;nbsp;==&amp;nbsp;&amp;quot;order_shipped&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;st&amp;nbsp;=&amp;nbsp;self.apply_state(msg.order_id,&amp;nbsp;&amp;quot;SHIPPED&amp;quot;,&amp;nbsp;msg.modified)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;st&amp;nbsp;==&amp;nbsp;&amp;quot;applied&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;UPDATE&amp;nbsp;outbound_order&amp;nbsp;SET&amp;nbsp;wms_status=&amp;#39;SHIPPED&amp;#39;&amp;nbsp;WHERE&amp;nbsp;order_id=?&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(msg.order_id,)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;COMMIT&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;level&amp;quot;:&amp;nbsp;&amp;quot;biz&amp;quot;,&amp;nbsp;&amp;quot;state&amp;quot;:&amp;nbsp;st}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;msg.topic&amp;nbsp;==&amp;nbsp;&amp;quot;idle_autotrade_RefundSync&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r&amp;nbsp;=&amp;nbsp;self.handle_refund_success(msg)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;COMMIT&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;level&amp;quot;:&amp;nbsp;&amp;quot;biz&amp;quot;,&amp;nbsp;**r}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;COMMIT&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;level&amp;quot;:&amp;nbsp;&amp;quot;noop&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;ROLLBACK&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;五、为什么这样“绝对不会出库两次”&lt;/h2&gt;&lt;div class=&quot;ybc-p&quot;&gt;重复消息进来时：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;第1次：
&amp;nbsp;&amp;nbsp;msg_id&amp;nbsp;不存在
&amp;nbsp;&amp;nbsp;→&amp;nbsp;插&amp;nbsp;processed_msg&amp;nbsp;成功
&amp;nbsp;&amp;nbsp;→&amp;nbsp;PAID&amp;nbsp;状态机推进
&amp;nbsp;&amp;nbsp;→&amp;nbsp;生成&amp;nbsp;OB-xxx（outbound_order.order_id&amp;nbsp;UNIQUE）
&amp;nbsp;&amp;nbsp;→&amp;nbsp;COMMIT

第2次（同&amp;nbsp;msg_id）：
&amp;nbsp;&amp;nbsp;is_duplicate_msg&amp;nbsp;=&amp;nbsp;True&amp;nbsp;→&amp;nbsp;直接&amp;nbsp;ack，不进业务

第2次（不同&amp;nbsp;msg_id，同&amp;nbsp;order_id+paid）：
&amp;nbsp;&amp;nbsp;msg_id&amp;nbsp;插成功
&amp;nbsp;&amp;nbsp;→&amp;nbsp;apply_state(PAID)&amp;nbsp;：当前已是&amp;nbsp;PAID&amp;nbsp;→&amp;nbsp;ignored
&amp;nbsp;&amp;nbsp;→&amp;nbsp;create_outbound_if_needed&amp;nbsp;：order_id&amp;nbsp;已存在&amp;nbsp;→&amp;nbsp;返回旧&amp;nbsp;outbound_no
&amp;nbsp;&amp;nbsp;→&amp;nbsp;WMS&amp;nbsp;不会被再调一次&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;三个保险：&lt;/div&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;processed_msg.msg_id&lt;/code&gt; 主键 → 传输层去重&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;order_state&lt;/code&gt; 状态机 → 同状态不回退、不重放&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;outbound_order.order_id UNIQUE&lt;/code&gt; → 一个订单只有一张出库单&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr/&gt;&lt;h2&gt;六、闲鱼逆向消息的“快照覆盖”细节&lt;/h2&gt;&lt;div class=&quot;ybc-p&quot;&gt;退款消息不是：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;refund_apply&amp;nbsp;++
refund_success&amp;nbsp;++&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;而是：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;{&amp;nbsp;refund_id,&amp;nbsp;refund_status,&amp;nbsp;modified,&amp;nbsp;refund_fee,&amp;nbsp;reason&amp;nbsp;}&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;正确做法：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;def&amp;nbsp;upsert_refund_snapshot(self,&amp;nbsp;msg:&amp;nbsp;IdleMessage):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.conn.execute(&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;INSERT&amp;nbsp;INTO&amp;nbsp;refund_snapshot(refund_id,order_id,status,fee,reason,modified,updated_at)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;VALUES(:refund_id,:order_id,:status,:fee,:reason,:modified,strftime(&amp;#39;%s&amp;#39;,&amp;#39;now&amp;#39;))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ON&amp;nbsp;CONFLICT(refund_id)&amp;nbsp;DO&amp;nbsp;UPDATE&amp;nbsp;SET
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status=CASE&amp;nbsp;WHEN&amp;nbsp;excluded.modified&amp;nbsp;&amp;gt;=&amp;nbsp;status_table.last_modified&amp;nbsp;THEN&amp;nbsp;excluded.status&amp;nbsp;ELSE&amp;nbsp;status&amp;nbsp;END
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;简化版：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;row&amp;nbsp;=&amp;nbsp;self.conn.execute(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;SELECT&amp;nbsp;modified&amp;nbsp;FROM&amp;nbsp;refund_snapshot&amp;nbsp;WHERE&amp;nbsp;refund_id=?&amp;quot;,&amp;nbsp;(msg.refund_id,)
).fetchone()

if&amp;nbsp;row&amp;nbsp;is&amp;nbsp;None&amp;nbsp;or&amp;nbsp;msg.modified&amp;nbsp;&amp;gt;=&amp;nbsp;row[0]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;覆盖
else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;老消息，丢弃&lt;/pre&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;规则：&lt;strong&gt;以平台 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;modified&lt;/code&gt; 最大的那一条为准&lt;/strong&gt;，不是“收到几条算几次”。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;七、生产环境替换点&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;内存/SQLite&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;生产替代&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;processed_msg&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;PG 表 + &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;(msg_id)&lt;/code&gt; 主键 / Redis &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;SET msg_id 1 EX 86400&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;order_state&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;订单主表字段 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;state / state_version / last_modified&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;BEGIN/COMMIT&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;单 DB 事务；跨系统用 Outbox + CDC&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;多节点并发&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;INSERT msg_id&lt;/code&gt; 用 DB 唯一约束或 Redis &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;SETNX&lt;/code&gt; 抢锁&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;主动查询兜底&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;定时拉 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;modified&lt;/code&gt; 窗口，走同一 &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;consume()&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;分布式场景推荐 &lt;strong&gt;Outbox 模式&lt;/strong&gt;：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;1.&amp;nbsp;本地事务：写业务表&amp;nbsp;+&amp;nbsp;写&amp;nbsp;outbox&amp;nbsp;表（含&amp;nbsp;msg_id/biz_key）
2.&amp;nbsp;后台线程把&amp;nbsp;outbox&amp;nbsp;发到&amp;nbsp;MQ
3.&amp;nbsp;消费端再按&amp;nbsp;biz_key&amp;nbsp;幂等&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;这样“写库”和“发消息”要么都成、要么都败，不会出现在“已出库但消息没记”的灰态。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;八、验收用例（直接跑）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;c&amp;nbsp;=&amp;nbsp;IdempotentOrderConsumer()

m1&amp;nbsp;=&amp;nbsp;IdleMessage(&amp;quot;m1&amp;quot;,&amp;quot;idle_autotrade_TradeSync&amp;quot;,&amp;quot;O123&amp;quot;,None,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_paid&amp;quot;,&amp;quot;PAID&amp;quot;,1700000000000,{})
m2&amp;nbsp;=&amp;nbsp;IdleMessage(&amp;quot;m2&amp;quot;,&amp;quot;idle_autotrade_TradeSync&amp;quot;,&amp;quot;O123&amp;quot;,None,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_paid&amp;quot;,&amp;quot;PAID&amp;quot;,1700000000001,{})&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;不同msg_id同业务
m3&amp;nbsp;=&amp;nbsp;IdleMessage(&amp;quot;m1&amp;quot;,&amp;quot;idle_autotrade_TradeSync&amp;quot;,&amp;quot;O123&amp;quot;,None,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;order_paid&amp;quot;,&amp;quot;PAID&amp;quot;,1700000000002,{})&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;同msg_id

print(c.consume(m1))
#&amp;nbsp;{&amp;#39;level&amp;#39;:&amp;#39;biz&amp;#39;,&amp;#39;state&amp;#39;:&amp;#39;applied&amp;#39;,&amp;#39;outbound&amp;#39;:{&amp;#39;created&amp;#39;:True,...}}

print(c.consume(m2))
#&amp;nbsp;{&amp;#39;level&amp;#39;:&amp;#39;biz&amp;#39;,&amp;#39;state&amp;#39;:&amp;#39;ignored&amp;#39;,&amp;#39;outbound&amp;#39;:{&amp;#39;created&amp;#39;:False,...}}&amp;nbsp;&amp;nbsp;←&amp;nbsp;不出新出库单

print(c.consume(m3))
#&amp;nbsp;{&amp;#39;level&amp;#39;:&amp;#39;msg_dup&amp;#39;,&amp;#39;action&amp;#39;:&amp;#39;ack_only&amp;#39;}

#&amp;nbsp;逆向：退款成功
rf&amp;nbsp;=&amp;nbsp;IdleMessage(&amp;quot;r1&amp;quot;,&amp;quot;idle_autotrade_RefundSync&amp;quot;,&amp;quot;O123&amp;quot;,&amp;quot;RF1&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;refund_success&amp;quot;,&amp;quot;SUCCESS&amp;quot;,1700000100000,{})
print(c.consume(rf))
#&amp;nbsp;{&amp;#39;level&amp;#39;:&amp;#39;biz&amp;#39;,&amp;#39;refund&amp;#39;:&amp;#39;applied&amp;#39;,&amp;#39;wms&amp;#39;:&amp;#39;recall_and_restock&amp;#39;}&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;九、一句话收口&lt;/h2&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;闲鱼订单同步的幂等 =&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;msg_id 去重（传输层）&lt;/strong&gt;&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;order_id/refund_id + modified（业务层）&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;状态机只允许向前转移（语义层）&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;outbound_no 唯一（WMS 层）&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;本地事务 / Outbox（原子层）&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;少一层，就会在“网络抖动”那天出库两次、发两台、财务对不上。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我接着把这篇并进 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/core/&lt;/code&gt;：做成 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;IdempotentConsumer&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;OrderStateMachine&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;OutboxPublisher&lt;/code&gt;，并和前篇的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;EventBus&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GrayReleaseRouter&lt;/code&gt; / &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GradeIntegrityLoop&lt;/code&gt; 串成“订单域统一运行时”？&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Wed, 16 Sep 2026 09:18:02 +0800</pubDate></item><item><title>🏗️《二手ERP对接电商平台的总体方案：统一数据模型 + 事件驱动 + 灰度上线6原则》（附Python源码）</title><link>https://www.alexob.com/?id=539</link><description>&lt;div class=&quot;ybc-p&quot;&gt;收官篇终于来了。前面21篇散落在各平台的技术方案，今天用一个统一的架构把它们串起来——这不是又一个新方案，而是前面所有方案的&lt;strong&gt;组织方式&lt;/strong&gt;。&lt;/div&gt;&lt;hr/&gt;&lt;h1&gt;🏗️《二手ERP对接电商平台的总体方案：统一数据模型 + 事件驱动 + 灰度上线6原则》（附Python源码）&lt;/h1&gt;&lt;h2&gt;一、核心架构：三层两总线&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;┌─────────────────────────────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;业务应用层&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;商品管理&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;订单中心&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;库存中心&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;财务结算&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────────────────┬──────────────────────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;事件总线&amp;nbsp;(Event&amp;nbsp;Bus)
┌──────────────────────▼──────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;适配器层&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;┌────────┐&amp;nbsp;&amp;nbsp;┌────────┐&amp;nbsp;&amp;nbsp;┌────────┐&amp;nbsp;&amp;nbsp;┌────────┐&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;│闲鱼&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│Mercari&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│Back&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│eBay&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;...&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;│Adapter&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│Adapter&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│Market&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│Adapter&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│Adapter&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;└────────┘&amp;nbsp;&amp;nbsp;└────────┘&amp;nbsp;&amp;nbsp;└────────┘&amp;nbsp;&amp;nbsp;└────────┘&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────────────────┬──────────────────────────────────┘
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;数据总线&amp;nbsp;(Data&amp;nbsp;Bus)
┌──────────────────────▼──────────────────────────────────┐
│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;统一数据层&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;InternalProduct&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;InternalOrder&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;InternalInventory&amp;nbsp;│
│&amp;nbsp;&amp;nbsp;InternalShipment&amp;nbsp;│&amp;nbsp;&amp;nbsp;InternalPayment&amp;nbsp;│&amp;nbsp;&amp;nbsp;InternalReturn&amp;nbsp;&amp;nbsp;&amp;nbsp;│
└──────────────────────────────────────────────────────────┘&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;三层&lt;/strong&gt;：统一数据层 → 适配器层 → 业务应用层&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;两总线&lt;/strong&gt;：数据总线（字段映射/翻译） + 事件总线（异步解耦/灰度）&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;二、统一数据模型（数据总线核心）&lt;/h2&gt;&lt;div class=&quot;ybc-p&quot;&gt;前面22篇分散在各平台的数据模型，现在统一收口到6个核心实体：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;unified_data_model.py
&amp;quot;&amp;quot;&amp;quot;
二手ERP统一数据模型
-&amp;nbsp;6个核心实体:&amp;nbsp;Product&amp;nbsp;/&amp;nbsp;Order&amp;nbsp;/&amp;nbsp;Inventory&amp;nbsp;/&amp;nbsp;Shipment&amp;nbsp;/&amp;nbsp;Payment&amp;nbsp;/&amp;nbsp;Return
-&amp;nbsp;每个实体:&amp;nbsp;Internal*&amp;nbsp;统一字段&amp;nbsp;+&amp;nbsp;PlatformMeta&amp;nbsp;平台特定元数据
-&amp;nbsp;字段映射:&amp;nbsp;通过&amp;nbsp;FieldMapper&amp;nbsp;运行时翻译&amp;nbsp;(复用前篇&amp;nbsp;cross_border_schema)
&amp;quot;&amp;quot;&amp;quot;
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional,&amp;nbsp;Any
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime


#&amp;nbsp;====================&amp;nbsp;核心枚举&amp;nbsp;====================
class&amp;nbsp;InternalGrade(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LIKE_NEW&amp;nbsp;=&amp;nbsp;&amp;quot;like_new&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GOOD&amp;nbsp;=&amp;nbsp;&amp;quot;good&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FAIR&amp;nbsp;=&amp;nbsp;&amp;quot;fair&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PARTS&amp;nbsp;=&amp;nbsp;&amp;quot;parts&amp;quot;

class&amp;nbsp;OrderStatus(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PENDING&amp;nbsp;=&amp;nbsp;&amp;quot;pending&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CONFIRMED&amp;nbsp;=&amp;nbsp;&amp;quot;confirmed&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SHIPPED&amp;nbsp;=&amp;nbsp;&amp;quot;shipped&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DELIVERED&amp;nbsp;=&amp;nbsp;&amp;quot;delivered&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RETURNED&amp;nbsp;=&amp;nbsp;&amp;quot;returned&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CANCELLED&amp;nbsp;=&amp;nbsp;&amp;quot;cancelled&amp;quot;

class&amp;nbsp;InventoryAction(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RESERVE&amp;nbsp;=&amp;nbsp;&amp;quot;reserve&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RELEASE&amp;nbsp;=&amp;nbsp;&amp;quot;release&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DEDUCT&amp;nbsp;=&amp;nbsp;&amp;quot;deduct&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RESTOCK&amp;nbsp;=&amp;nbsp;&amp;quot;restock&amp;quot;


#&amp;nbsp;====================&amp;nbsp;6个核心实体&amp;nbsp;====================

@dataclass
class&amp;nbsp;InternalProduct:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一商品模型&amp;nbsp;(复用前篇&amp;nbsp;cross_border_schema.InternalProduct)&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;title:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;description:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price:&amp;nbsp;float
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;USD&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grade:&amp;nbsp;InternalGrade&amp;nbsp;=&amp;nbsp;InternalGrade.GOOD
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grade_detail:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_health:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;100
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_original_box:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;accessories:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;powers_on:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;camera_works:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wifi_works:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;repaired_parts:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;unlocked:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screen_scratch:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body_scratch:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dents:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;photo_urls:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;category:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;brand:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;model:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;weight_kg:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dimensions_cm:&amp;nbsp;List[float]&amp;nbsp;=&amp;nbsp;field(default_factory=list)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_meta:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;合规
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gpsr_responsible_entity:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;safety_declaration_url:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hs_code:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;origin_country:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;


@dataclass
class&amp;nbsp;InternalOrder:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一订单模型&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;xianyu&amp;nbsp;/&amp;nbsp;mercari&amp;nbsp;/&amp;nbsp;backmarket&amp;nbsp;/&amp;nbsp;ebay
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;quantity:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;USD&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status:&amp;nbsp;OrderStatus&amp;nbsp;=&amp;nbsp;OrderStatus.PENDING
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyer_name:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyer_address:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buyer_phone:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shipping_method:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shipping_cost:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tax:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;created_at:&amp;nbsp;datetime&amp;nbsp;=&amp;nbsp;field(default_factory=datetime.now)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paid_at:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shipped_at:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delivered_at:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_meta:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)


@dataclass
class&amp;nbsp;InternalInventory:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一库存模型&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;warehouse:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;default&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reserved:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;available:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;damaged:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;last_action:&amp;nbsp;InventoryAction&amp;nbsp;=&amp;nbsp;InventoryAction.RESTOCK
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;last_qty:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;updated_at:&amp;nbsp;datetime&amp;nbsp;=&amp;nbsp;field(default_factory=datetime.now)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_meta:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)


@dataclass
class&amp;nbsp;InternalShipment:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一发货模型&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shipment_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tracking_number:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;carrier:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;method:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;weight_kg:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;length_cm:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;width_cm:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;height_cm:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;declared_value:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;declared_currency:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;USD&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;origin_country:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;destination_country:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;shipped_at:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;estimated_delivery:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_meta:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)


@dataclass
class&amp;nbsp;InternalPayment:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一支付模型&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payment_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;amount:&amp;nbsp;float
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;USD&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fee:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;net_amount:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;method:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;credit_card&amp;nbsp;/&amp;nbsp;paypal&amp;nbsp;/&amp;nbsp;bank_transfer
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;completed&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;pending&amp;nbsp;/&amp;nbsp;completed&amp;nbsp;/&amp;nbsp;refunded
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;paid_at:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_meta:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)


@dataclass
class&amp;nbsp;InternalReturn:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;统一退货模型&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reason:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;reason_code:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;not_as_described&amp;nbsp;/&amp;nbsp;defective&amp;nbsp;/&amp;nbsp;wrong_item
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;condition_at_return:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;refund_amount:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;refund_currency:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;USD&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return_shipping_cost:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;returned_at:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;refunded_at:&amp;nbsp;Optional[datetime]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;restocked:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grade_downgraded:&amp;nbsp;Optional[InternalGrade]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform_meta:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;三、事件驱动架构（事件总线核心）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;event_bus.py
&amp;quot;&amp;quot;&amp;quot;
事件驱动架构
-&amp;nbsp;Event:&amp;nbsp;统一事件格式&amp;nbsp;(type&amp;nbsp;+&amp;nbsp;payload&amp;nbsp;+&amp;nbsp;metadata)
-&amp;nbsp;EventBus:&amp;nbsp;发布/订阅&amp;nbsp;+&amp;nbsp;异步处理&amp;nbsp;+&amp;nbsp;重试/死信
-&amp;nbsp;GrayReleaseRouter:&amp;nbsp;灰度路由&amp;nbsp;(按平台/SKU/比例)
-&amp;nbsp;事件类型:&amp;nbsp;product.*&amp;nbsp;/&amp;nbsp;order.*&amp;nbsp;/&amp;nbsp;inventory.*&amp;nbsp;/&amp;nbsp;return.*
&amp;quot;&amp;quot;&amp;quot;
import&amp;nbsp;json
import&amp;nbsp;time
import&amp;nbsp;random
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Callable,&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional,&amp;nbsp;Any
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;datetime&amp;nbsp;import&amp;nbsp;datetime


#&amp;nbsp;====================&amp;nbsp;事件定义&amp;nbsp;====================
@dataclass
class&amp;nbsp;Event:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;product.created&amp;nbsp;/&amp;nbsp;order.confirmed&amp;nbsp;/&amp;nbsp;inventory.changed
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;service&amp;nbsp;name
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;timestamp:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;field(default_factory=time.time)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata:&amp;nbsp;Dict[str,&amp;nbsp;Any]&amp;nbsp;=&amp;nbsp;field(default_factory=dict)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;to_json(self)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;json.dumps({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;event_id&amp;quot;:&amp;nbsp;self.event_id,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;type&amp;quot;:&amp;nbsp;self.type,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;source&amp;quot;:&amp;nbsp;self.source,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;timestamp&amp;quot;:&amp;nbsp;self.timestamp,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;payload&amp;quot;:&amp;nbsp;self.payload,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;metadata&amp;quot;:&amp;nbsp;self.metadata,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;from_json(data:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;&amp;quot;Event&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;d&amp;nbsp;=&amp;nbsp;json.loads(data)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;Event(**d)


#&amp;nbsp;====================&amp;nbsp;事件处理器&amp;nbsp;====================
EventHandler&amp;nbsp;=&amp;nbsp;Callable[[Event],&amp;nbsp;None]

class&amp;nbsp;Subscription:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;event_type:&amp;nbsp;str,&amp;nbsp;handler:&amp;nbsp;EventHandler,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;max_retries:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;3,&amp;nbsp;timeout_ms:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;5000):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.event_type&amp;nbsp;=&amp;nbsp;event_type
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.handler&amp;nbsp;=&amp;nbsp;handler
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.max_retries&amp;nbsp;=&amp;nbsp;max_retries
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.timeout_ms&amp;nbsp;=&amp;nbsp;timeout_ms


#&amp;nbsp;====================&amp;nbsp;事件总线&amp;nbsp;====================
class&amp;nbsp;EventBus:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;内存事件总线&amp;nbsp;(生产环境替换为&amp;nbsp;RabbitMQ/Kafka/RocketMQ)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;按&amp;nbsp;event_type&amp;nbsp;分发
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;重试&amp;nbsp;+&amp;nbsp;死信队列
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;灰度过滤
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.subscriptions:&amp;nbsp;Dict[str,&amp;nbsp;List[Subscription]]&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.dead_letter_queue:&amp;nbsp;List[Event]&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.gray_router:&amp;nbsp;Optional[&amp;quot;GrayReleaseRouter&amp;quot;]&amp;nbsp;=&amp;nbsp;None

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;subscribe(self,&amp;nbsp;subscription:&amp;nbsp;Subscription):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;subscription.event_type&amp;nbsp;not&amp;nbsp;in&amp;nbsp;self.subscriptions:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.subscriptions[subscription.event_type]&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.subscriptions[subscription.event_type].append(subscription)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;publish(self,&amp;nbsp;event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;handlers&amp;nbsp;=&amp;nbsp;self.subscriptions.get(event.type,&amp;nbsp;[])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;handlers:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;灰度过滤
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.gray_router&amp;nbsp;and&amp;nbsp;not&amp;nbsp;self.gray_router.should_process(event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;sub&amp;nbsp;in&amp;nbsp;handlers:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self._dispatch_with_retry(sub,&amp;nbsp;event)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_dispatch_with_retry(self,&amp;nbsp;sub:&amp;nbsp;Subscription,&amp;nbsp;event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;attempt&amp;nbsp;in&amp;nbsp;range(sub.max_retries):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sub.handler(event)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;attempt&amp;nbsp;&amp;lt;&amp;nbsp;sub.max_retries&amp;nbsp;-&amp;nbsp;1:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(2&amp;nbsp;**&amp;nbsp;attempt)&amp;nbsp;&amp;nbsp;#&amp;nbsp;指数退避
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.dead_letter_queue.append(event)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[DEAD&amp;nbsp;LETTER]&amp;nbsp;{event.type}&amp;nbsp;|&amp;nbsp;{event.event_id}&amp;nbsp;|&amp;nbsp;{e}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;set_gray_router(self,&amp;nbsp;router:&amp;nbsp;&amp;quot;GrayReleaseRouter&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.gray_router&amp;nbsp;=&amp;nbsp;router

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;灰度路由&amp;nbsp;====================
class&amp;nbsp;GrayReleaseRouter:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;灰度上线6原则实现
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.&amp;nbsp;按平台灰度:&amp;nbsp;先闲鱼&amp;nbsp;-&amp;gt;&amp;nbsp;再Mercari&amp;nbsp;-&amp;gt;&amp;nbsp;最后Back&amp;nbsp;Market
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.&amp;nbsp;按SKU灰度:&amp;nbsp;先低价值&amp;nbsp;-&amp;gt;&amp;nbsp;再高价值
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3.&amp;nbsp;按比例灰度:&amp;nbsp;10%&amp;nbsp;-&amp;gt;&amp;nbsp;30%&amp;nbsp;-&amp;gt;&amp;nbsp;100%
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4.&amp;nbsp;按用户灰度:&amp;nbsp;白名单卖家先上
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5.&amp;nbsp;按时间段灰度:&amp;nbsp;工作日白天&amp;nbsp;-&amp;gt;&amp;nbsp;周末
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6.&amp;nbsp;自动回滚:&amp;nbsp;错误率&amp;nbsp;&amp;gt;&amp;nbsp;5%&amp;nbsp;自动切回
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;平台灰度顺序
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.platform_order&amp;nbsp;=&amp;nbsp;[&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;backmarket&amp;quot;,&amp;nbsp;&amp;quot;ebay&amp;quot;,&amp;nbsp;&amp;quot;vinted&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.current_platform_index:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;比例灰度
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.traffic_percent:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;0.0&amp;nbsp;~&amp;nbsp;1.0

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;白名单
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.whitelist_skus:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.whitelist_sellers:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;自动回滚
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.error_rate:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.error_threshold:&amp;nbsp;float&amp;nbsp;=&amp;nbsp;0.05
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.auto_rollback:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;时间段
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.enabled_time_ranges:&amp;nbsp;List[tuple]&amp;nbsp;=&amp;nbsp;[]&amp;nbsp;&amp;nbsp;#&amp;nbsp;[(9,&amp;nbsp;18)]&amp;nbsp;工作日9-18点

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;should_process(self,&amp;nbsp;event:&amp;nbsp;Event)&amp;nbsp;-&amp;gt;&amp;nbsp;bool:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;灰度6原则综合判断&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;原则1:&amp;nbsp;平台灰度
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform&amp;nbsp;=&amp;nbsp;event.metadata.get(&amp;quot;platform&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;and&amp;nbsp;platform&amp;nbsp;not&amp;nbsp;in&amp;nbsp;self.platform_order[:self.current_platform_index&amp;nbsp;+&amp;nbsp;1]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;原则2:&amp;nbsp;SKU白名单
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku&amp;nbsp;=&amp;nbsp;event.payload.get(&amp;quot;sku&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;sku&amp;nbsp;and&amp;nbsp;sku&amp;nbsp;in&amp;nbsp;self.whitelist_skus:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;原则3:&amp;nbsp;比例灰度
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;random.random()&amp;nbsp;&amp;gt;&amp;nbsp;self.traffic_percent:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;原则4:&amp;nbsp;卖家白名单
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;seller&amp;nbsp;=&amp;nbsp;event.metadata.get(&amp;quot;seller&amp;quot;,&amp;nbsp;&amp;quot;&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;seller&amp;nbsp;and&amp;nbsp;seller&amp;nbsp;in&amp;nbsp;self.whitelist_sellers:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;原则5:&amp;nbsp;时间段
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.enabled_time_ranges:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;current_hour&amp;nbsp;=&amp;nbsp;datetime.now().hour
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;allowed&amp;nbsp;=&amp;nbsp;any(start&amp;nbsp;&amp;lt;=&amp;nbsp;current_hour&amp;nbsp;&amp;lt;&amp;nbsp;end
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;start,&amp;nbsp;end&amp;nbsp;in&amp;nbsp;self.enabled_time_ranges)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;allowed:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;原则6:&amp;nbsp;自动回滚
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.auto_rollback:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;False

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;True

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;advance_platform(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;推进到下一个平台&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.current_platform_index&amp;nbsp;&amp;lt;&amp;nbsp;len(self.platform_order)&amp;nbsp;-&amp;nbsp;1:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.current_platform_index&amp;nbsp;+=&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[GRAY]&amp;nbsp;推进到平台:&amp;nbsp;{self.platform_order[self.current_platform_index]}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;set_traffic(self,&amp;nbsp;percent:&amp;nbsp;float):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.traffic_percent&amp;nbsp;=&amp;nbsp;max(0.0,&amp;nbsp;min(1.0,&amp;nbsp;percent))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;report_error(self,&amp;nbsp;error_count:&amp;nbsp;int,&amp;nbsp;total_count:&amp;nbsp;int):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;total_count&amp;nbsp;&amp;gt;&amp;nbsp;0:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.error_rate&amp;nbsp;=&amp;nbsp;error_count&amp;nbsp;/&amp;nbsp;total_count
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;self.error_rate&amp;nbsp;&amp;gt;=&amp;nbsp;self.error_threshold:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.auto_rollback&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[ROLLBACK]&amp;nbsp;错误率&amp;nbsp;{self.error_rate:.1%}&amp;nbsp;&amp;gt;=&amp;nbsp;{self.error_threshold:.0%},&amp;nbsp;自动回滚&amp;quot;)


#&amp;nbsp;====================&amp;nbsp;业务事件处理器示例&amp;nbsp;====================
class&amp;nbsp;ProductEventHandlers:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;商品相关事件处理器&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;on_product_created(event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;product&amp;nbsp;=&amp;nbsp;event.payload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[EVENT]&amp;nbsp;商品创建:&amp;nbsp;{product.get(&amp;#39;sku&amp;#39;)}&amp;nbsp;|&amp;nbsp;{product.get(&amp;#39;title&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;触发:&amp;nbsp;库存初始化&amp;nbsp;+&amp;nbsp;平台同步

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;on_product_updated(event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;product&amp;nbsp;=&amp;nbsp;event.payload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[EVENT]&amp;nbsp;商品更新:&amp;nbsp;{product.get(&amp;#39;sku&amp;#39;)}&amp;nbsp;|&amp;nbsp;变更字段:&amp;nbsp;{event.metadata.get(&amp;#39;changed_fields&amp;#39;,&amp;nbsp;[])}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;触发:&amp;nbsp;平台同步&amp;nbsp;+&amp;nbsp;价格监控

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;on_product_price_changed(event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[EVENT]&amp;nbsp;价格变更:&amp;nbsp;{event.payload.get(&amp;#39;sku&amp;#39;)}&amp;nbsp;|&amp;nbsp;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;旧:&amp;nbsp;{event.metadata.get(&amp;#39;old_price&amp;#39;)}&amp;nbsp;-&amp;gt;&amp;nbsp;新:&amp;nbsp;{event.payload.get(&amp;#39;price&amp;#39;)}&amp;quot;)


class&amp;nbsp;OrderEventHandlers:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;订单相关事件处理器&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;on_order_confirmed(event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;order&amp;nbsp;=&amp;nbsp;event.payload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[EVENT]&amp;nbsp;订单确认:&amp;nbsp;{order.get(&amp;#39;order_id&amp;#39;)}&amp;nbsp;|&amp;nbsp;{order.get(&amp;#39;platform&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;触发:&amp;nbsp;库存预留&amp;nbsp;+&amp;nbsp;发货准备

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;on_order_shipped(event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[EVENT]&amp;nbsp;订单发货:&amp;nbsp;{event.payload.get(&amp;#39;order_id&amp;#39;)}&amp;nbsp;|&amp;nbsp;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;运单号:&amp;nbsp;{event.payload.get(&amp;#39;tracking_number&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;触发:&amp;nbsp;平台回传运单号&amp;nbsp;+&amp;nbsp;买家通知

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@staticmethod
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;on_order_returned(event:&amp;nbsp;Event):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;event.payload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;[EVENT]&amp;nbsp;退货:&amp;nbsp;{ret.get(&amp;#39;return_id&amp;#39;)}&amp;nbsp;|&amp;nbsp;原因:&amp;nbsp;{ret.get(&amp;#39;reason_code&amp;#39;)}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;触发:&amp;nbsp;库存回库&amp;nbsp;+&amp;nbsp;等级重检&amp;nbsp;+&amp;nbsp;退款

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;演示&amp;nbsp;====================
if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;60)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;二手ERP事件驱动架构演示&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;=&amp;quot;&amp;nbsp;*&amp;nbsp;60)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;初始化事件总线&amp;nbsp;+&amp;nbsp;灰度路由器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus&amp;nbsp;=&amp;nbsp;EventBus()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gray&amp;nbsp;=&amp;nbsp;GrayReleaseRouter()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gray.set_traffic(0.3)&amp;nbsp;&amp;nbsp;#&amp;nbsp;30%流量
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gray.platform_order&amp;nbsp;=&amp;nbsp;[&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;backmarket&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gray.current_platform_index&amp;nbsp;=&amp;nbsp;0&amp;nbsp;&amp;nbsp;#&amp;nbsp;只放闲鱼
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.set_gray_router(gray)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;注册事件处理器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.subscribe(Subscription(&amp;quot;product.created&amp;quot;,&amp;nbsp;ProductEventHandlers.on_product_created))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.subscribe(Subscription(&amp;quot;product.updated&amp;quot;,&amp;nbsp;ProductEventHandlers.on_product_updated))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.subscribe(Subscription(&amp;quot;product.price_changed&amp;quot;,&amp;nbsp;ProductEventHandlers.on_product_price_changed))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.subscribe(Subscription(&amp;quot;order.confirmed&amp;quot;,&amp;nbsp;OrderEventHandlers.on_order_confirmed))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.subscribe(Subscription(&amp;quot;order.shipped&amp;quot;,&amp;nbsp;OrderEventHandlers.on_order_shipped))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.subscribe(Subscription(&amp;quot;order.returned&amp;quot;,&amp;nbsp;OrderEventHandlers.on_order_returned))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;模拟事件流
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;events&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Event(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id=&amp;quot;evt-001&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&amp;quot;product.created&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;product-service&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload={&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256-SILVER&amp;quot;,&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;&amp;quot;iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;256GB&amp;quot;,&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;799.00},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata={&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;seller&amp;quot;:&amp;nbsp;&amp;quot;seller_a&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Event(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id=&amp;quot;evt-002&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&amp;quot;product.created&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;product-service&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload={&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP13-128-BLACK&amp;quot;,&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;&amp;quot;iPhone&amp;nbsp;13&amp;nbsp;128GB&amp;quot;,&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;499.00},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata={&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;seller&amp;quot;:&amp;nbsp;&amp;quot;seller_b&amp;quot;}&amp;nbsp;&amp;nbsp;#&amp;nbsp;Mercari&amp;nbsp;还没灰度到
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Event(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id=&amp;quot;evt-003&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&amp;quot;product.price_changed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;pricing-service&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload={&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256-SILVER&amp;quot;,&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;749.00},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata={&amp;quot;old_price&amp;quot;:&amp;nbsp;799.00,&amp;nbsp;&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;xianyu&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Event(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id=&amp;quot;evt-004&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&amp;quot;order.confirmed&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;order-service&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload={&amp;quot;order_id&amp;quot;:&amp;nbsp;&amp;quot;ORD-001&amp;quot;,&amp;nbsp;&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256-SILVER&amp;quot;,&amp;nbsp;&amp;quot;quantity&amp;quot;:&amp;nbsp;1},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata={&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;xianyu&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Event(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id=&amp;quot;evt-005&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&amp;quot;order.returned&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;return-service&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload={
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;return_id&amp;quot;:&amp;nbsp;&amp;quot;RET-001&amp;quot;,&amp;nbsp;&amp;quot;order_id&amp;quot;:&amp;nbsp;&amp;quot;ORD-001&amp;quot;,&amp;nbsp;&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;xianyu&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP14P-256-SILVER&amp;quot;,&amp;nbsp;&amp;quot;reason_code&amp;quot;:&amp;nbsp;&amp;quot;not_as_described&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;grade_downgraded&amp;quot;:&amp;nbsp;&amp;quot;good&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata={&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;xianyu&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;evt&amp;nbsp;in&amp;nbsp;events:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n---&amp;nbsp;发布事件:&amp;nbsp;{evt.type}&amp;nbsp;[{evt.event_id}]&amp;nbsp;---&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.publish(evt)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;灰度推进
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;=&amp;#39;*60}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;灰度推进:&amp;nbsp;开启Mercari&amp;nbsp;(30%流量)&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gray.advance_platform()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.publish(Event(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id=&amp;quot;evt-006&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&amp;quot;product.created&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;product-service&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload={&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP13-128-BLACK&amp;quot;,&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;&amp;quot;iPhone&amp;nbsp;13&amp;nbsp;128GB&amp;quot;,&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;449.00},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata={&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;seller&amp;quot;:&amp;nbsp;&amp;quot;seller_b&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;模拟错误率触发回滚
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;=&amp;#39;*60}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;模拟错误率过高&amp;nbsp;-&amp;gt;&amp;nbsp;自动回滚&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gray.report_error(error_count=50,&amp;nbsp;total_count=900)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;错误率:&amp;nbsp;{gray.error_rate:.1%}&amp;nbsp;|&amp;nbsp;自动回滚:&amp;nbsp;{gray.auto_rollback}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bus.publish(Event(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;event_id=&amp;quot;evt-007&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;type=&amp;quot;product.created&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source=&amp;quot;product-service&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload={&amp;quot;sku&amp;quot;:&amp;nbsp;&amp;quot;IP12-64-WHITE&amp;quot;,&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;&amp;quot;iPhone&amp;nbsp;12&amp;nbsp;64GB&amp;quot;,&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;299.00},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata={&amp;quot;platform&amp;quot;:&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;seller&amp;quot;:&amp;nbsp;&amp;quot;seller_c&amp;quot;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;))&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;运行结果：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;============================================================
二手ERP事件驱动架构演示
============================================================

---&amp;nbsp;发布事件:&amp;nbsp;product.created&amp;nbsp;[evt-001]&amp;nbsp;---
[EVENT]&amp;nbsp;商品创建:&amp;nbsp;IP14P-256-SILVER&amp;nbsp;|&amp;nbsp;iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;256GB

---&amp;nbsp;发布事件:&amp;nbsp;product.created&amp;nbsp;[evt-002]&amp;nbsp;---
(Mercari&amp;nbsp;被灰度拦截,&amp;nbsp;无输出)

---&amp;nbsp;发布事件:&amp;nbsp;product.price_changed&amp;nbsp;[evt-003]&amp;nbsp;---
[EVENT]&amp;nbsp;价格变更:&amp;nbsp;IP14P-256-SILVER&amp;nbsp;|&amp;nbsp;旧:&amp;nbsp;799.0&amp;nbsp;-&amp;gt;&amp;nbsp;新:&amp;nbsp;749.0

---&amp;nbsp;发布事件:&amp;nbsp;order.confirmed&amp;nbsp;[evt-004]&amp;nbsp;---
[EVENT]&amp;nbsp;订单确认:&amp;nbsp;ORD-001&amp;nbsp;|&amp;nbsp;xianyu

---&amp;nbsp;发布事件:&amp;nbsp;order.returned&amp;nbsp;[evt-005]&amp;nbsp;---
[EVENT]&amp;nbsp;退货:&amp;nbsp;RET-001&amp;nbsp;|&amp;nbsp;原因:&amp;nbsp;not_as_described

============================================================
灰度推进:&amp;nbsp;开启Mercari&amp;nbsp;(30%流量)
============================================================
[GRAY]&amp;nbsp;推进到平台:&amp;nbsp;mercari
---&amp;nbsp;发布事件:&amp;nbsp;product.created&amp;nbsp;[evt-006]&amp;nbsp;---
(30%概率命中,&amp;nbsp;可能不输出;&amp;nbsp;多跑几次就会命中)

============================================================
模拟错误率过高&amp;nbsp;-&amp;gt;&amp;nbsp;自动回滚
============================================================
[ROLLBACK]&amp;nbsp;错误率&amp;nbsp;5.6%&amp;nbsp;&amp;gt;=&amp;nbsp;5%,&amp;nbsp;自动回滚
---&amp;nbsp;发布事件:&amp;nbsp;product.created&amp;nbsp;[evt-007]&amp;nbsp;---
(自动回滚激活,&amp;nbsp;所有事件被拦截)&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;四、灰度上线6原则详解&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;原则&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;实现&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;为什么重要&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;1. 按平台灰度&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;platform_order&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;current_platform_index&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;闲鱼出问题只影响国内，不会炸掉Back Market EU站&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;2. 按SKU灰度&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;whitelist_skus&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;先用&lt;span class=&quot;ybc-markdown-katex&quot; data-latex=&quot;50以下的配件测，再用&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;span class=&quot;katex&quot; style=&quot;font-size: 19.36px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot; style=&quot;font-size: 19.36px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;span class=&quot;base&quot; style=&quot;font-size: 19.36px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height: 0.6833em; font-size: 19.36px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot; style=&quot;font-size: 19.36px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;mord cjk_fallback&quot; style=&quot;font-size: 19.36px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;以下的配件测，再用&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;200的手机测，最后上$1000的MacBook&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;3. 按比例灰度&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;traffic_percent&lt;/code&gt; 0.1→0.3→1.0&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;10%订单先走新逻辑，观察24小时没问题再放大&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;4. 按用户灰度&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;whitelist_sellers&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;先让合作3年的老卖家试用，新卖家走旧逻辑&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;5. 按时间段灰度&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;enabled_time_ranges&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;工作日白天上线，出问题有人修；周五下午不上线&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;strong style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;6. 自动回滚&lt;/strong&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;error_rate&lt;/code&gt; &amp;gt; 5% → &lt;code class=&quot;hyc-common-markdown__code__inline&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 2px 4px;&quot;&gt;auto_rollback=True&lt;/code&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;不等人报警，系统自己切回去&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;五、和前22篇的完整衔接&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;统一数据层&amp;nbsp;(本篇)
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;InternalProduct&amp;nbsp;←&amp;nbsp;前篇&amp;nbsp;cross_border_schema.FieldMapper
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;InternalOrder&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;前篇&amp;nbsp;ebay_secondhand_defense.OrderGuard
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;InternalInventory&amp;nbsp;←&amp;nbsp;前篇&amp;nbsp;vinted_adapter.VintedStockSync
&amp;nbsp;&amp;nbsp;└──&amp;nbsp;InternalReturn&amp;nbsp;&amp;nbsp;←&amp;nbsp;前篇&amp;nbsp;grade_integrity_loop.ReturnSignalLoop

适配器层&amp;nbsp;(前22篇)
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;xianyu_adapter&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;国内二手基础
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;mercari_rate_limiter&amp;nbsp;&amp;nbsp;←&amp;nbsp;限流/TokenPool
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;ebay_secondhand_defense&amp;nbsp;←&amp;nbsp;ConditionGuard/AccountHealth
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;vinted_adapter&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;←&amp;nbsp;GPSR/StockSync
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;backmarket_compliance_gate&amp;nbsp;←&amp;nbsp;入驻门禁/Deposit
&amp;nbsp;&amp;nbsp;└──&amp;nbsp;grade_integrity_loop&amp;nbsp;&amp;nbsp;←&amp;nbsp;A/B校验闭环

事件总线&amp;nbsp;(本篇)
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;product.created&amp;nbsp;&amp;nbsp;→&amp;nbsp;触发:&amp;nbsp;库存初始化&amp;nbsp;+&amp;nbsp;平台同步
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;order.confirmed&amp;nbsp;&amp;nbsp;→&amp;nbsp;触发:&amp;nbsp;库存预留&amp;nbsp;+&amp;nbsp;发货准备
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;order.returned&amp;nbsp;&amp;nbsp;&amp;nbsp;→&amp;nbsp;触发:&amp;nbsp;库存回库&amp;nbsp;+&amp;nbsp;等级重检&amp;nbsp;+&amp;nbsp;退款
&amp;nbsp;&amp;nbsp;└──&amp;nbsp;inventory.changed&amp;nbsp;→&amp;nbsp;触发:&amp;nbsp;平台库存同步

灰度上线&amp;nbsp;(本篇)
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;按平台:&amp;nbsp;闲鱼&amp;nbsp;→&amp;nbsp;Mercari&amp;nbsp;→&amp;nbsp;Back&amp;nbsp;Market&amp;nbsp;→&amp;nbsp;eBay&amp;nbsp;→&amp;nbsp;Vinted
&amp;nbsp;&amp;nbsp;├──&amp;nbsp;按比例:&amp;nbsp;10%&amp;nbsp;→&amp;nbsp;30%&amp;nbsp;→&amp;nbsp;100%
&amp;nbsp;&amp;nbsp;└──&amp;nbsp;自动回滚:&amp;nbsp;错误率&amp;nbsp;&amp;gt;&amp;nbsp;5%&amp;nbsp;切回&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;六、部署建议&lt;/h2&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;第一阶段&lt;/strong&gt;：统一数据模型先落地，把国内ERP的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;product&lt;/code&gt; 表通过 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;to_internal()&lt;/code&gt; 转成 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalProduct&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;第二阶段&lt;/strong&gt;：事件总线替换现有的同步调用，先从 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;order.confirmed&lt;/code&gt; 和 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;inventory.changed&lt;/code&gt; 开始&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;第三阶段&lt;/strong&gt;：灰度上线框架搭好，每次新接一个平台走完6原则&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;第四阶段&lt;/strong&gt;：适配器层逐步替换为事件驱动版本&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr/&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我把这套方案做成一个&lt;strong&gt;可运行的脚手架项目&lt;/strong&gt;：包含 FastAPI 服务、SQLite/PostgreSQL 持久化、RabbitMQ 事件总线集成、以及一个 Web 管理后台（查看灰度状态/手动回滚/事件追踪）？这样可以直接 clone 下来跑，不用从零搭。&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Wed, 16 Sep 2026 08:58:13 +0800</pubDate></item><item><title>🔄《从国内二手ERP到跨境：一套数据模型适配闲鱼 + Mercari + Back Market 的字段映射表》（附Python源码）</title><link>https://www.alexob.com/?id=538</link><description>&lt;div class=&quot;ybc-p&quot;&gt;先锚定事实：闲鱼、Mercari、Back Market 三个平台在商品等级/成色/功能/电池/维修记录/实拍图这些字段上&lt;strong&gt;没有一个是完全对齐的&lt;/strong&gt;——闲鱼用中文口语（99新/充新/有瑕疵）、Mercari 用 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;condition_int&lt;/code&gt;（1-5整数）、Back Market 用官方成色词（Premium/Excellent/Good/Fair）。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;但它们的&lt;strong&gt;业务语义可以抽象成统一的数据模型&lt;/strong&gt;——核心差异在映射层，不在存储层。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;这就是国内二手ERP出海要做的事：&lt;strong&gt;不改数据库，只加一张映射表 + 一个翻译器&lt;/strong&gt;。&lt;/div&gt;&lt;hr/&gt;&lt;h1&gt;🔄《从国内二手ERP到跨境：一套数据模型适配闲鱼 + Mercari + Back Market 的字段映射表》（附Python源码）&lt;/h1&gt;&lt;h2&gt;一、核心矛盾&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;国内ERP存:&amp;nbsp;&amp;nbsp;grade=&amp;quot;99新&amp;quot;,&amp;nbsp;category=&amp;quot;手机&amp;quot;,&amp;nbsp;brand=&amp;quot;Apple&amp;quot;,&amp;nbsp;battery_health=&amp;quot;100%&amp;quot;
Mercari要:&amp;nbsp;&amp;nbsp;condition_int=1,&amp;nbsp;category_id=20963,&amp;nbsp;brand_id=155,&amp;nbsp;condition_comment=&amp;quot;美品&amp;quot;
Back&amp;nbsp;Market:&amp;nbsp;state=&amp;quot;Premium&amp;quot;,&amp;nbsp;carrier_locked=false,&amp;nbsp;refurbished=true
闲鱼:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;level=&amp;quot;99新&amp;quot;,&amp;nbsp;cid=123,&amp;nbsp;battery_capacity=&amp;quot;100%&amp;quot;,&amp;nbsp;source=&amp;quot;个人&amp;quot;

每条listing要发3个平台&amp;nbsp;→&amp;nbsp;3套不同的payload
不改DB&amp;nbsp;→&amp;nbsp;加一层&amp;nbsp;FieldMapper&amp;nbsp;+&amp;nbsp;PlatformSchema&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;不改数据库&lt;/strong&gt;的意思是：国内二手ERP的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;product&lt;/code&gt; 表不动，只加一个 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;platform_field_map&lt;/code&gt; 配置表 + 一个 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;FieldTranslator&lt;/code&gt; 服务，运行时做 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;internal_field → platform_field&lt;/code&gt; 的转换。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;二、统一数据模型（Internal Product Schema）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;cross_border_schema.py
&amp;quot;&amp;quot;&amp;quot;
跨境二手统一商品模型&amp;nbsp;(InternalProduct)
-&amp;nbsp;只存业务语义,&amp;nbsp;不存平台格式
-&amp;nbsp;字段映射表:&amp;nbsp;internal_field&amp;nbsp;-&amp;gt;&amp;nbsp;platform_field
-&amp;nbsp;翻译器:&amp;nbsp;InternalProduct&amp;nbsp;-&amp;gt;&amp;nbsp;MercariPayload&amp;nbsp;/&amp;nbsp;BackMarketPayload&amp;nbsp;/&amp;nbsp;XianyuPayload
&amp;quot;&amp;quot;&amp;quot;
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional,&amp;nbsp;Any
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum


class&amp;nbsp;InternalGrade(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LIKE_NEW&amp;nbsp;=&amp;nbsp;&amp;quot;like_new&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;99新/充新/未使用
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GOOD&amp;nbsp;=&amp;nbsp;&amp;quot;good&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;95新/正常使用痕迹
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FAIR&amp;nbsp;=&amp;nbsp;&amp;quot;fair&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;9新/明显使用痕迹
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PARTS&amp;nbsp;=&amp;nbsp;&amp;quot;parts&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;故障/配件机


@dataclass
class&amp;nbsp;InternalProduct:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;----&amp;nbsp;核心字段&amp;nbsp;(不改DB,&amp;nbsp;只加这一层)&amp;nbsp;----
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;title:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;description:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price:&amp;nbsp;float
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;USD&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;等级/成色
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grade:&amp;nbsp;InternalGrade&amp;nbsp;=&amp;nbsp;InternalGrade.GOOD
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grade_detail:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;人工备注:&amp;nbsp;&amp;quot;屏幕有发丝划痕&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_health:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;100&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;0-100
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_original_box:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;accessories:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)&amp;nbsp;&amp;nbsp;#&amp;nbsp;[&amp;quot;charger&amp;quot;,&amp;quot;cable&amp;quot;]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;功能/维修
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;powers_on:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;camera_works:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wifi_works:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;repaired_parts:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)&amp;nbsp;&amp;nbsp;#&amp;nbsp;[&amp;quot;screen&amp;quot;,&amp;quot;battery&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;unlocked:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;网络锁

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;外观
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screen_scratch:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body_scratch:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dents:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;photo_urls:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;类目
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;category:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;&amp;quot;手机/iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;brand:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;model:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;合规
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gpsr_responsible_entity:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;EU&amp;nbsp;GPSR
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;safety_declaration_url:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;


#&amp;nbsp;====================&amp;nbsp;字段映射表&amp;nbsp;====================

#&amp;nbsp;平台&amp;nbsp;-&amp;gt;&amp;nbsp;内部字段&amp;nbsp;-&amp;gt;&amp;nbsp;(平台字段名,&amp;nbsp;转换函数)
#&amp;nbsp;转换函数:&amp;nbsp;(InternalProduct)&amp;nbsp;-&amp;gt;&amp;nbsp;value

FIELD_MAP:&amp;nbsp;Dict[str,&amp;nbsp;Dict[str,&amp;nbsp;tuple]]&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;xianyu&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;(&amp;quot;title&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.title[:30]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;(&amp;quot;desc&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.description),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;(&amp;quot;price&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;f&amp;quot;{p.price:.2f}&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;grade&amp;quot;:&amp;nbsp;(&amp;quot;level&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.LIKE_NEW:&amp;nbsp;&amp;quot;99新&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.GOOD:&amp;nbsp;&amp;quot;95新&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.FAIR:&amp;nbsp;&amp;quot;有瑕疵&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.PARTS:&amp;nbsp;&amp;quot;故障机&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}[p.grade]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;category&amp;quot;:&amp;nbsp;(&amp;quot;cid&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;XIANYU_CATEGORY_MAP.get(p.category,&amp;nbsp;&amp;quot;&amp;quot;)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;battery&amp;quot;:&amp;nbsp;(&amp;quot;battery_capacity&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;f&amp;quot;{p.battery_health}%&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;photos&amp;quot;:&amp;nbsp;(&amp;quot;images&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.photo_urls[:9]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;source&amp;quot;:&amp;nbsp;(&amp;quot;source&amp;quot;,&amp;nbsp;lambda&amp;nbsp;_:&amp;nbsp;&amp;quot;商家&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;mercari&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;(&amp;quot;name&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.title[:50]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;(&amp;quot;description&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.description[:1000]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;(&amp;quot;price&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;int(p.price)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;grade&amp;quot;:&amp;nbsp;(&amp;quot;condition_id&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.LIKE_NEW:&amp;nbsp;1,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.GOOD:&amp;nbsp;3,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.FAIR:&amp;nbsp;4,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.PARTS:&amp;nbsp;5,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}[p.grade]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;condition_comment&amp;quot;:&amp;nbsp;(&amp;quot;condition_comment&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.grade_detail),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;category&amp;quot;:&amp;nbsp;(&amp;quot;category_id&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;MERCARI_CATEGORY_MAP.get(p.category,&amp;nbsp;999)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;brand&amp;quot;:&amp;nbsp;(&amp;quot;brand_id&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;MERCARI_BRAND_MAP.get(p.brand,&amp;nbsp;888)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;photos&amp;quot;:&amp;nbsp;(&amp;quot;photos&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.photo_urls[:20]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;shipping&amp;quot;:&amp;nbsp;(&amp;quot;shipping_payer_id&amp;quot;,&amp;nbsp;lambda&amp;nbsp;_:&amp;nbsp;2),&amp;nbsp;&amp;nbsp;#&amp;nbsp;seller&amp;nbsp;pays
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket&amp;quot;:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;(&amp;quot;title&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.title[:80]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;(&amp;quot;description&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.description),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;(&amp;quot;price&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;int(p.price&amp;nbsp;*&amp;nbsp;100)),&amp;nbsp;&amp;nbsp;#&amp;nbsp;cents
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;grade&amp;quot;:&amp;nbsp;(&amp;quot;state&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.LIKE_NEW:&amp;nbsp;&amp;quot;Premium&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.GOOD:&amp;nbsp;&amp;quot;Good&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.FAIR:&amp;nbsp;&amp;quot;Fair&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.PARTS:&amp;nbsp;None,&amp;nbsp;&amp;nbsp;#&amp;nbsp;不允许
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}[p.grade]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;battery&amp;quot;:&amp;nbsp;(&amp;quot;battery_health&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.battery_health),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;carrier_lock&amp;quot;:&amp;nbsp;(&amp;quot;carrier_locked&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;not&amp;nbsp;p.unlocked),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;refurbished&amp;quot;:&amp;nbsp;(&amp;quot;refurbished&amp;quot;,&amp;nbsp;lambda&amp;nbsp;_:&amp;nbsp;True),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;repaired_parts&amp;quot;:&amp;nbsp;(&amp;quot;repairs&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;&amp;quot;,&amp;quot;.join(p.repaired_parts)&amp;nbsp;if&amp;nbsp;p.repaired_parts&amp;nbsp;else&amp;nbsp;&amp;quot;&amp;quot;),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;box&amp;quot;:&amp;nbsp;(&amp;quot;with_box&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.has_original_box),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;accessories&amp;quot;:&amp;nbsp;(&amp;quot;accessories&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.accessories),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;gpsr_entity&amp;quot;:&amp;nbsp;(&amp;quot;responsible_entity&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.gpsr_responsible_entity),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;photos&amp;quot;:&amp;nbsp;(&amp;quot;images&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.photo_urls[:10]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},
}


#&amp;nbsp;====================&amp;nbsp;类目映射表&amp;nbsp;(示例)&amp;nbsp;====================
XIANYU_CATEGORY_MAP&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;手机/iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;quot;:&amp;nbsp;12345,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;手机/iPhone&amp;nbsp;14&amp;quot;:&amp;nbsp;12346,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;平板/iPad&amp;nbsp;Pro&amp;quot;:&amp;nbsp;23456,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;笔记本/MacBook&amp;nbsp;Air&amp;quot;:&amp;nbsp;34567,
}

MERCARI_CATEGORY_MAP&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;手机/iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;quot;:&amp;nbsp;20963,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;手机/iPhone&amp;nbsp;14&amp;quot;:&amp;nbsp;21001,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;平板/iPad&amp;nbsp;Pro&amp;quot;:&amp;nbsp;21234,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;笔记本/MacBook&amp;nbsp;Air&amp;quot;:&amp;nbsp;22001,
}

MERCARI_BRAND_MAP&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Apple&amp;quot;:&amp;nbsp;155,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Samsung&amp;quot;:&amp;nbsp;156,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;Google&amp;quot;:&amp;nbsp;157,
}


#&amp;nbsp;====================&amp;nbsp;翻译器&amp;nbsp;====================
class&amp;nbsp;FieldTranslator:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;运行时翻译:&amp;nbsp;InternalProduct&amp;nbsp;-&amp;gt;&amp;nbsp;PlatformPayload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;遍历&amp;nbsp;FIELD_MAP[platform]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;执行转换函数
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;跳过&amp;nbsp;None&amp;nbsp;值&amp;nbsp;(Back&amp;nbsp;Market:&amp;nbsp;Parts等级不可售)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;platform:&amp;nbsp;str):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.map&amp;nbsp;=&amp;nbsp;FIELD_MAP.get(platform,&amp;nbsp;{})

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;translate(self,&amp;nbsp;product:&amp;nbsp;InternalProduct)&amp;nbsp;-&amp;gt;&amp;nbsp;Dict[str,&amp;nbsp;Any]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;errors&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;internal_field,&amp;nbsp;(platform_field,&amp;nbsp;transform_fn)&amp;nbsp;in&amp;nbsp;self.map.items():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;value&amp;nbsp;=&amp;nbsp;transform_fn(product)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;value&amp;nbsp;is&amp;nbsp;not&amp;nbsp;None:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;payload[platform_field]&amp;nbsp;=&amp;nbsp;value
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;Exception&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;errors.append(f&amp;quot;{internal_field}-&amp;gt;{platform_field}:&amp;nbsp;{e}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;payload&amp;quot;:&amp;nbsp;payload,&amp;nbsp;&amp;quot;errors&amp;quot;:&amp;nbsp;errors,&amp;nbsp;&amp;quot;platform&amp;quot;:&amp;nbsp;platform}


#&amp;nbsp;====================&amp;nbsp;批量适配器&amp;nbsp;====================
class&amp;nbsp;CrossBorderAdapter:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;一条&amp;nbsp;InternalProduct&amp;nbsp;-&amp;gt;&amp;nbsp;三个平台的&amp;nbsp;payload&amp;quot;&amp;quot;&amp;quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.platforms&amp;nbsp;=&amp;nbsp;[&amp;quot;xianyu&amp;quot;,&amp;nbsp;&amp;quot;mercari&amp;quot;,&amp;nbsp;&amp;quot;backmarket&amp;quot;]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;adapt_all(self,&amp;nbsp;product:&amp;nbsp;InternalProduct)&amp;nbsp;-&amp;gt;&amp;nbsp;Dict[str,&amp;nbsp;Dict]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results&amp;nbsp;=&amp;nbsp;{}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;plat&amp;nbsp;in&amp;nbsp;self.platforms:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;translator&amp;nbsp;=&amp;nbsp;FieldTranslator(plat)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results[plat]&amp;nbsp;=&amp;nbsp;translator.translate(product)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;results

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;演示&amp;nbsp;====================
if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;adapter&amp;nbsp;=&amp;nbsp;CrossBorderAdapter()

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;一台&amp;nbsp;iPhone&amp;nbsp;14&amp;nbsp;Pro,&amp;nbsp;95新,&amp;nbsp;电池88%,&amp;nbsp;换过电池,&amp;nbsp;无划痕
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phone&amp;nbsp;=&amp;nbsp;InternalProduct(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku=&amp;quot;IP14P-256-SILVER&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;title=&amp;quot;iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;256GB&amp;nbsp;Silver&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;description=&amp;quot;美版无锁,&amp;nbsp;换过电池,&amp;nbsp;功能全好,&amp;nbsp;屏幕无划痕,&amp;nbsp;边框微磨损&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;price=699.00,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;currency=&amp;quot;USD&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grade=InternalGrade.GOOD,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;grade_detail=&amp;quot;边框有轻微使用痕迹&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_health=88,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_original_box=False,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;accessories=[&amp;quot;cable&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;powers_on=True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;camera_works=True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wifi_works=True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;repaired_parts=[&amp;quot;battery&amp;quot;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;unlocked=True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screen_scratch=False,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body_scratch=True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;photo_urls=[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;https://img.example.com/ip14p_1.jpg&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;https://img.example.com/ip14p_2.jpg&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;https://img.example.com/ip14p_3.jpg&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;],
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;category=&amp;quot;手机/iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;brand=&amp;quot;Apple&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;model=&amp;quot;iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gpsr_responsible_entity=&amp;quot;GreenRefurb&amp;nbsp;SAS,&amp;nbsp;Paris,&amp;nbsp;France&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results&amp;nbsp;=&amp;nbsp;adapter.adapt_all(phone)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;plat,&amp;nbsp;result&amp;nbsp;in&amp;nbsp;results.items():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;\n{&amp;#39;=&amp;#39;*50}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{plat.upper()}&amp;nbsp;翻译结果&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;{&amp;#39;=&amp;#39;*50}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;result[&amp;quot;errors&amp;quot;]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;⚠️&amp;nbsp;错误:&amp;nbsp;{result[&amp;#39;errors&amp;#39;]}&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;k,&amp;nbsp;v&amp;nbsp;in&amp;nbsp;result[&amp;quot;payload&amp;quot;].items():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&amp;quot;&amp;nbsp;&amp;nbsp;{k:25s}:&amp;nbsp;{v}&amp;quot;)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;跑出来的关键三组 payload：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;==================================================
&amp;nbsp;&amp;nbsp;XIANYU&amp;nbsp;翻译结果
==================================================
&amp;nbsp;&amp;nbsp;title&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;256GB&amp;nbsp;Silver
&amp;nbsp;&amp;nbsp;desc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;美版无锁,&amp;nbsp;换过电池,&amp;nbsp;功能全好,&amp;nbsp;屏幕无划痕,&amp;nbsp;边框微磨损
&amp;nbsp;&amp;nbsp;price&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;699.00
&amp;nbsp;&amp;nbsp;level&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;95新
&amp;nbsp;&amp;nbsp;cid&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;12345
&amp;nbsp;&amp;nbsp;battery_capacity&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;88%
&amp;nbsp;&amp;nbsp;images&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;[&amp;#39;https://img.example.com/ip14p_1.jpg&amp;#39;,&amp;nbsp;...]
&amp;nbsp;&amp;nbsp;source&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;商家

==================================================
&amp;nbsp;&amp;nbsp;MERCARI&amp;nbsp;翻译结果
==================================================
&amp;nbsp;&amp;nbsp;name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;256GB&amp;nbsp;Silver
&amp;nbsp;&amp;nbsp;description&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;美版无锁,&amp;nbsp;换过电池,&amp;nbsp;功能全好,&amp;nbsp;屏幕无划痕,&amp;nbsp;边框微磨损
&amp;nbsp;&amp;nbsp;price&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;699
&amp;nbsp;&amp;nbsp;condition_id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;3
&amp;nbsp;&amp;nbsp;condition_comment&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;边框有轻微使用痕迹
&amp;nbsp;&amp;nbsp;category_id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;20963
&amp;nbsp;&amp;nbsp;brand_id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;155
&amp;nbsp;&amp;nbsp;photos&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;[&amp;#39;https://img.example.com/ip14p_1.jpg&amp;#39;,&amp;nbsp;...]
&amp;nbsp;&amp;nbsp;shipping_payer_id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;2

==================================================
&amp;nbsp;&amp;nbsp;BACKMARKET&amp;nbsp;翻译结果
==================================================
&amp;nbsp;&amp;nbsp;title&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;iPhone&amp;nbsp;14&amp;nbsp;Pro&amp;nbsp;256GB&amp;nbsp;Silver
&amp;nbsp;&amp;nbsp;description&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;美版无锁,&amp;nbsp;换过电池,&amp;nbsp;功能全好,&amp;nbsp;屏幕无划痕,&amp;nbsp;边框微磨损
&amp;nbsp;&amp;nbsp;price&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;69900
&amp;nbsp;&amp;nbsp;state&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;Good
&amp;nbsp;&amp;nbsp;battery_health&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;88
&amp;nbsp;&amp;nbsp;carrier_locked&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;False
&amp;nbsp;&amp;nbsp;refurbished&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;True
&amp;nbsp;&amp;nbsp;repairs&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;battery
&amp;nbsp;&amp;nbsp;with_box&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;False
&amp;nbsp;&amp;nbsp;accessories&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;[&amp;#39;cable&amp;#39;]
&amp;nbsp;&amp;nbsp;responsible_entity&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;GreenRefurb&amp;nbsp;SAS,&amp;nbsp;Paris,&amp;nbsp;France
&amp;nbsp;&amp;nbsp;images&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;[&amp;#39;https://img.example.com/ip14p_1.jpg&amp;#39;,&amp;nbsp;...]&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;三、这套模型解决的核心问题&lt;/h2&gt;&lt;div class=&quot;hyc-common-markdown__table-wrapper&quot; data-has-scroll=&quot;false&quot; style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;div style=&quot;font-size: 16px; border-collapse: separate; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;问题&lt;/div&gt;&lt;/th&gt;&lt;th style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;解法&lt;/div&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;国内ERP存&amp;quot;99新&amp;quot;，Mercari要condition_id=1&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;映射表 + 转换函数&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;Back Market要battery_health整数，闲鱼要字符串带%&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;转换函数各自处理&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;Back Market拒绝Parts等级&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;转换函数返回None → 跳过字段 / 整体拦截&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;GPSR责任实体只有EU平台需要&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;映射表只在backmarket出现&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;标题长度限制不同（闲鱼30字 / Mercari50 / BM80）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;截断函数写在映射表里&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;价格单位不同（闲鱼元 / Mercari日元 / BM欧分）&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 10.7143px 12.8571px 10.7143px 0px; border: 1px solid rgb(224, 224, 224);&quot;&gt;&lt;div class=&quot;ybc-p&quot; style=&quot;font-size: 16px; border-collapse: collapse; border-spacing: 0px; padding: 0px;&quot;&gt;转换函数各自处理&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;不改DB&lt;/strong&gt;：&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalProduct&lt;/code&gt; 不是新表，是&lt;strong&gt;运行时视图&lt;/strong&gt;——国内ERP的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;product&lt;/code&gt; 表字段通过一个简单的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;to_internal()&lt;/code&gt; 适配器转成这个统一模型，然后再分发到各个平台。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;四、架构位置&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;国内ERP&amp;nbsp;DB&amp;nbsp;(product表)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;▼
to_internal()&amp;nbsp;&amp;nbsp;←&amp;nbsp;只写一次,&amp;nbsp;适配国内ERP字段名
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;▼
InternalProduct&amp;nbsp;(统一模型)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;FieldTranslator(&amp;quot;xianyu&amp;quot;)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;→&amp;nbsp;闲鱼Payload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;FieldTranslator(&amp;quot;mercari&amp;quot;)&amp;nbsp;&amp;nbsp;&amp;nbsp;→&amp;nbsp;Mercari&amp;nbsp;API&amp;nbsp;Payload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├──&amp;nbsp;FieldTranslator(&amp;quot;backmarket&amp;quot;)→&amp;nbsp;BM&amp;nbsp;API&amp;nbsp;Payload
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└──&amp;nbsp;FieldTranslator(&amp;quot;vinted&amp;quot;)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;→&amp;nbsp;(可扩展)&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;和前篇的关系：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Grade Integrity Loop&lt;/strong&gt; 里的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalGrade&lt;/code&gt; 直接复用这里的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalGrade&lt;/code&gt;；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Back Market Compliance Gate&lt;/strong&gt; 的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;quality_charter_signed&lt;/code&gt; 和 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;gpsr_responsible_entity&lt;/code&gt; 作为 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalProduct&lt;/code&gt; 的合规字段传递；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mercari Rate Limiter&lt;/strong&gt; 的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;condition_int&lt;/code&gt; 映射也来自这里的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;FIELD_MAP[&amp;quot;mercari&amp;quot;][&amp;quot;grade&amp;quot;]&lt;/code&gt;；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;eBay ConditionGuard&lt;/strong&gt; 的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;ConditionID&lt;/code&gt; 映射同理，加一行 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;FIELD_MAP[&amp;quot;ebay&amp;quot;]&lt;/code&gt; 即可。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr/&gt;&lt;h2&gt;五、扩展指南&lt;/h2&gt;&lt;h3&gt;加一个新平台（比如 Vinted）&lt;/h3&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;FIELD_MAP[&amp;quot;vinted&amp;quot;]&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;title&amp;quot;:&amp;nbsp;(&amp;quot;title&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.title[:100]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;description&amp;quot;:&amp;nbsp;(&amp;quot;description&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.description),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;price&amp;quot;:&amp;nbsp;(&amp;quot;price&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;int(p.price)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;grade&amp;quot;:&amp;nbsp;(&amp;quot;status&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.LIKE_NEW:&amp;nbsp;&amp;quot;new_with_tags&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.GOOD:&amp;nbsp;&amp;quot;very_good&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.FAIR:&amp;nbsp;&amp;quot;good&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.PARTS:&amp;nbsp;&amp;quot;satisfactory&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}[p.grade]),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;size&amp;quot;:&amp;nbsp;(&amp;quot;size&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;VINTED_SIZE_MAP.get(p.model,&amp;nbsp;&amp;quot;&amp;quot;)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;brand&amp;quot;:&amp;nbsp;(&amp;quot;brand_id&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;VINTED_BRAND_MAP.get(p.brand,&amp;nbsp;0)),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;photos&amp;quot;:&amp;nbsp;(&amp;quot;photos&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.photo_urls[:20]),
}&lt;/pre&gt;&lt;h3&gt;加一个新字段（比如 &amp;quot;IMEI&amp;quot;）&lt;/h3&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;InternalProduct&amp;nbsp;加一行
imei:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;

#&amp;nbsp;FIELD_MAP&amp;nbsp;加一行
FIELD_MAP[&amp;quot;backmarket&amp;quot;][&amp;quot;imei&amp;quot;]&amp;nbsp;=&amp;nbsp;(&amp;quot;imei&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.imei)
FIELD_MAP[&amp;quot;mercari&amp;quot;][&amp;quot;imei&amp;quot;]&amp;nbsp;=&amp;nbsp;(&amp;quot;imei&amp;quot;,&amp;nbsp;lambda&amp;nbsp;p:&amp;nbsp;p.imei)
#&amp;nbsp;闲鱼不需要&amp;nbsp;IMEI,&amp;nbsp;不加&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;六、三条铁律&lt;/h2&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;映射表是配置，不是代码&lt;/strong&gt;：&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;FIELD_MAP&lt;/code&gt; 可以存 JSON/YAML，运营人员可维护，不用改代码就能加平台/改映射。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;转换函数必须幂等&lt;/strong&gt;：同一个 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalProduct&lt;/code&gt; 转两次得到相同的 payload，方便重试和审计。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;None 值语义明确&lt;/strong&gt;：返回 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;None&lt;/code&gt; = &amp;quot;这个字段在这个平台不可用/不允许&amp;quot;，翻译器自动跳过；不要返回空字符串或 0，否则平台可能报错。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr/&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我把这套 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;cross_border_schema.py&lt;/code&gt; 扩展成完整的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/schema/&lt;/code&gt; 包：包含 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;InternalProduct&lt;/code&gt;、&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;FieldMap Registry&lt;/code&gt;（可热加载 YAML 配置）、&lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;Validator&lt;/code&gt;（发布前校验必填字段是否都有值）、以及和 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GradeIntegrityLoop&lt;/code&gt; 联动的 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GradeConsistencyCheck&lt;/code&gt;（确保翻译后的等级和原始 QC 记录一致）？&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Tue, 15 Sep 2026 10:51:57 +0800</pubDate></item><item><title>🔁《跨境二手商品等级描述不符触发自动下架：ERP 上传数据的 A/B 级校验闭环》（附 Python 源码）</title><link>https://www.alexob.com/?id=537</link><description>&lt;div class=&quot;ybc-p&quot;&gt;核心事实先钉住：Back Market 官方成色是 &lt;strong&gt;Premium / Excellent / Good / Fair&lt;/strong&gt;，且“所有等级都必须 100% 功能正常、电池至少 80%（Premium 90%）”；成色只描述外观，功能不一致就是违反 Quality Charter。 行业里 A/B/C 只是内部口径，&lt;strong&gt;“A 标成 B 卖”叫 undergrade（亏钱），“B 标成 A 卖”叫 overgrading（退货+搜索降权+匿名测试单翻车）&lt;/strong&gt;。 所以 ERP 要做的不是“传个性别字段”，而是&lt;strong&gt;入库质检 → 内部等级 → 平台等级 → 文案/图片/电池/维修记录一致性 → 发布前 A/B 校验 → 售后退货回流再校准&lt;/strong&gt;的闭环。&lt;/div&gt;&lt;hr/&gt;&lt;h1&gt;🔁《跨境二手商品等级描述不符触发自动下架：ERP 上传数据的 A/B 级校验闭环》（附 Python 源码）&lt;/h1&gt;&lt;h2&gt;一、惨案公式（为什么 A/B 级会搞死店铺）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;内部QC说:&amp;nbsp;&amp;nbsp;&amp;quot;屏幕有发丝划痕,&amp;nbsp;算&amp;nbsp;B&amp;quot;
运营图省事:&amp;nbsp;&amp;quot;标&amp;nbsp;A&amp;nbsp;好卖,&amp;nbsp;价格+8%&amp;quot;
买家收到:&amp;nbsp;&amp;nbsp;&amp;quot;A&amp;nbsp;应该有几乎无划痕&amp;quot;
平台机制:&amp;nbsp;&amp;nbsp;描述外观&amp;nbsp;≠&amp;nbsp;实物&amp;nbsp;→&amp;nbsp;退货/客诉&amp;nbsp;→&amp;nbsp;退货率↑&amp;nbsp;→&amp;nbsp;算法降权/下架/匿名测试单&amp;nbsp;→&amp;nbsp;账户风险&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;Back Market 自己放匿名测试单（anonymous test orders），卖家自己都分不清是不是真买家；&lt;strong&gt;A 级设备如果屏幕有划痕，本身就是违约&lt;/strong&gt;。&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;行业术语：&lt;/div&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Overgrading&lt;/strong&gt; = 等级往高标（最烧钱：退货+逆向物流+搜索降权）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Grading drift&lt;/strong&gt; = 技师久了越来越松（不是故意骗，但结果一样）&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Undergrading&lt;/strong&gt; = 往低标（亏毛利，不违规）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;ERP 的活：&lt;strong&gt;让“标出去的等级”永远 ≤ “实物检出来的等级”&lt;/strong&gt;。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;二、统一等级模型（内部 A/B/C ↔ 平台 Premium/Excellent/Good/Fair）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;内部&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;外观标准&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;电池&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;平台(Back&amp;nbsp;Market)&amp;nbsp;&amp;nbsp;&amp;nbsp;抖音/闲鱼
A&amp;nbsp;/&amp;nbsp;LikeNew&amp;nbsp;&amp;nbsp;无划痕/无磕碰/近乎新&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;≥90%&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Premium/Excellent&amp;nbsp;&amp;nbsp;99新/准新
B&amp;nbsp;/&amp;nbsp;Good&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;微划痕/轻微磨损/不影响功能&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;≥80%&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Good&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;95新/正常使用
C&amp;nbsp;/&amp;nbsp;Fair&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;可见划痕/磕碰/掉漆/轻凹&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;≥80%&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Fair&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9新/明显使用
D&amp;nbsp;/&amp;nbsp;Parts&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;功能缺陷/屏裂/无法正常使用&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;不允许多数翻新平台&amp;nbsp;&amp;nbsp;For&amp;nbsp;parts&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;关键点：&lt;strong&gt;功能不通过 = 不能当 A/B/C 卖&lt;/strong&gt;；电池不达标 = 不能标 Premium；屏幕有划痕 = 不能标 Excellent/Premium。&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;这就是“A/B 级校验”的本质——&lt;strong&gt;多字段联合判定，不是单个下拉框&lt;/strong&gt;。&lt;/div&gt;&lt;hr/&gt;&lt;h2&gt;三、完整源码：Grade Integrity Loop&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;#&amp;nbsp;grade_integrity_loop.py
&amp;quot;&amp;quot;&amp;quot;
跨境二手&amp;nbsp;A/B级描述不符防御闭环
-&amp;nbsp;QcRecord:&amp;nbsp;入库质检(划痕/磕碰/电池/功能/维修)
-&amp;nbsp;InternalGrade:&amp;nbsp;由QC推导内部等级&amp;nbsp;(A/B/C/D)
-&amp;nbsp;PlatformGradeMapper:&amp;nbsp;内部等级&amp;nbsp;-&amp;gt;&amp;nbsp;BackMarket/Mercari/Vinted/eBay&amp;nbsp;平台等级
-&amp;nbsp;ListingAssertion:&amp;nbsp;发布前校验&amp;nbsp;(标称等级&amp;nbsp;&amp;lt;=&amp;nbsp;实物等级,&amp;nbsp;文案/图片/电池一致)
-&amp;nbsp;ReturnSignalLoop:&amp;nbsp;退货原因码回流&amp;nbsp;-&amp;gt;&amp;nbsp;发现&amp;nbsp;overgrading&amp;nbsp;/&amp;nbsp;grading&amp;nbsp;drift
-&amp;nbsp;AutoTakedownGuard:&amp;nbsp;高危SKU禁止发布&amp;nbsp;/&amp;nbsp;已发布触发降级或下架申请
&amp;quot;&amp;quot;&amp;quot;
from&amp;nbsp;typing&amp;nbsp;import&amp;nbsp;Dict,&amp;nbsp;List,&amp;nbsp;Optional
from&amp;nbsp;dataclasses&amp;nbsp;import&amp;nbsp;dataclass,&amp;nbsp;field
from&amp;nbsp;enum&amp;nbsp;import&amp;nbsp;Enum


#&amp;nbsp;----------------&amp;nbsp;等级枚举&amp;nbsp;----------------
class&amp;nbsp;InternalGrade(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;A&amp;nbsp;=&amp;nbsp;&amp;quot;A&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;like&amp;nbsp;new
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;B&amp;nbsp;=&amp;nbsp;&amp;quot;B&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;good&amp;nbsp;/&amp;nbsp;light&amp;nbsp;wear
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;C&amp;nbsp;=&amp;nbsp;&amp;quot;C&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;fair&amp;nbsp;/&amp;nbsp;visible&amp;nbsp;wear
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;D&amp;nbsp;=&amp;nbsp;&amp;quot;D&amp;quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;parts&amp;nbsp;/&amp;nbsp;not&amp;nbsp;functional


class&amp;nbsp;BMGrade(Enum):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PREMIUM&amp;nbsp;=&amp;nbsp;&amp;quot;Premium&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EXCELLENT&amp;nbsp;=&amp;nbsp;&amp;quot;Excellent&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GOOD&amp;nbsp;=&amp;nbsp;&amp;quot;Good&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FAIR&amp;nbsp;=&amp;nbsp;&amp;quot;Fair&amp;quot;


#&amp;nbsp;----------------&amp;nbsp;入库质检&amp;nbsp;----------------
@dataclass
class&amp;nbsp;QcRecord:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;screen_scratch:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;屏幕划痕
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;body_micro_scratch:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;机身发丝划痕
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;visible_scratches:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;肉眼可见划痕
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dents:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;False&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;凹痕
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_health:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;100&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;%
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;powers_on:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;camera_ok:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wifi_ok:&amp;nbsp;bool&amp;nbsp;=&amp;nbsp;True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;repaired_parts:&amp;nbsp;List[str]&amp;nbsp;=&amp;nbsp;field(default_factory=list)&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;[&amp;quot;screen&amp;quot;,&amp;quot;battery&amp;quot;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc_operator:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;photos:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;实拍角度数


def&amp;nbsp;infer_internal_grade(qc:&amp;nbsp;QcRecord)&amp;nbsp;-&amp;gt;&amp;nbsp;InternalGrade:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;功能不正常&amp;nbsp;-&amp;gt;&amp;nbsp;D;&amp;nbsp;电池/外观联合判定&amp;nbsp;A/B/C&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;not&amp;nbsp;(qc.powers_on&amp;nbsp;and&amp;nbsp;qc.camera_ok&amp;nbsp;and&amp;nbsp;qc.wifi_ok):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.D
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.screen_scratch:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.C
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.visible_scratches&amp;nbsp;or&amp;nbsp;qc.dents:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.C
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.battery_health&amp;nbsp;&amp;gt;=&amp;nbsp;90&amp;nbsp;and&amp;nbsp;not&amp;nbsp;qc.body_micro_scratch:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.A
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.battery_health&amp;nbsp;&amp;gt;=&amp;nbsp;80:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.B
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.C


#&amp;nbsp;----------------&amp;nbsp;平台映射&amp;nbsp;----------------
class&amp;nbsp;PlatformGradeMapper:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BM_MAP&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.A:&amp;nbsp;BMGrade.PREMIUM,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.B:&amp;nbsp;BMGrade.GOOD,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.C:&amp;nbsp;BMGrade.FAIR,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.D:&amp;nbsp;None,&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;不允许作为翻新可售
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;to_backmarket(self,&amp;nbsp;g:&amp;nbsp;InternalGrade)&amp;nbsp;-&amp;gt;&amp;nbsp;Optional[BMGrade]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;self.BM_MAP.get(g)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;to_label(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;g:&amp;nbsp;InternalGrade)&amp;nbsp;-&amp;gt;&amp;nbsp;str:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;==&amp;nbsp;&amp;quot;backmarket&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bm&amp;nbsp;=&amp;nbsp;self.to_backmarket(g)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;bm.value&amp;nbsp;if&amp;nbsp;bm&amp;nbsp;else&amp;nbsp;&amp;quot;NOT_LISTABLE&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;platform&amp;nbsp;==&amp;nbsp;&amp;quot;generic&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{InternalGrade.A:&amp;nbsp;&amp;quot;99新/准新&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.B:&amp;nbsp;&amp;quot;95新/正常使用&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.C:&amp;nbsp;&amp;quot;9新/明显使用&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.D:&amp;nbsp;&amp;quot;故障/配件机&amp;quot;}[g]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;g.value


#&amp;nbsp;----------------&amp;nbsp;发布前&amp;nbsp;A/B&amp;nbsp;校验&amp;nbsp;----------------
@dataclass
class&amp;nbsp;ListingDraft:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;platform:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed_grade:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;运营填的:&amp;nbsp;Premium&amp;nbsp;/&amp;nbsp;A&amp;nbsp;/&amp;nbsp;99新&amp;nbsp;...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;title:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;desc:&amp;nbsp;str&amp;nbsp;=&amp;nbsp;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_in_desc:&amp;nbsp;Optional[int]&amp;nbsp;=&amp;nbsp;None
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;photo_count:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc:&amp;nbsp;QcRecord&amp;nbsp;=&amp;nbsp;None


class&amp;nbsp;GradeViolation(Exception):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;issues:&amp;nbsp;List[str]):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.issues&amp;nbsp;=&amp;nbsp;issues
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(&amp;quot;;&amp;nbsp;&amp;quot;.join(issues))


class&amp;nbsp;ListingAssertion:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;mapper:&amp;nbsp;PlatformGradeMapper):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.mapper&amp;nbsp;=&amp;nbsp;mapper

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;assert_listing(self,&amp;nbsp;draft:&amp;nbsp;ListingDraft):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc&amp;nbsp;=&amp;nbsp;draft.qc
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc&amp;nbsp;is&amp;nbsp;None:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise&amp;nbsp;GradeViolation([&amp;quot;无QC记录,&amp;nbsp;禁止发布&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;real&amp;nbsp;=&amp;nbsp;infer_internal_grade(qc)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;real_bm&amp;nbsp;=&amp;nbsp;self.mapper.to_backmarket(real)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues&amp;nbsp;=&amp;nbsp;[]

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;1.&amp;nbsp;功能不达标却想卖可售等级
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;real&amp;nbsp;==&amp;nbsp;InternalGrade.D:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues.append(&amp;quot;功能不达标(InternalGrade=D),&amp;nbsp;不允许作为翻新可售&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;2.&amp;nbsp;标称等级高于实物等级&amp;nbsp;=&amp;nbsp;overgrading
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed_internal&amp;nbsp;=&amp;nbsp;self._claimed_to_internal(draft.platform,&amp;nbsp;draft.claimed_grade)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;claimed_internal&amp;nbsp;is&amp;nbsp;not&amp;nbsp;None&amp;nbsp;and&amp;nbsp;self._rank(claimed_internal)&amp;nbsp;&amp;gt;&amp;nbsp;self._rank(real):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues.append(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;overgrading:&amp;nbsp;标称&amp;nbsp;{draft.claimed_grade}({claimed_internal.value})&amp;nbsp;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;&amp;gt;&amp;nbsp;实物&amp;nbsp;{real.value}&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;3.&amp;nbsp;Back&amp;nbsp;Market:&amp;nbsp;Premium&amp;nbsp;必须电池&amp;gt;=90&amp;nbsp;且无可辨划痕
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;draft.platform&amp;nbsp;==&amp;nbsp;&amp;quot;backmarket&amp;quot;&amp;nbsp;and&amp;nbsp;draft.claimed_grade&amp;nbsp;==&amp;nbsp;&amp;quot;Premium&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.battery_health&amp;nbsp;&amp;lt;&amp;nbsp;90:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues.append(f&amp;quot;Premium&amp;nbsp;电池需&amp;gt;=90%,&amp;nbsp;实际&amp;nbsp;{qc.battery_health}%&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.body_micro_scratch&amp;nbsp;or&amp;nbsp;qc.screen_scratch:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues.append(&amp;quot;Premium&amp;nbsp;不允许任何可见/发丝划痕&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;4.&amp;nbsp;文案与电池不一致
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;draft.battery_in_desc&amp;nbsp;is&amp;nbsp;not&amp;nbsp;None&amp;nbsp;and&amp;nbsp;draft.battery_in_desc&amp;nbsp;!=&amp;nbsp;qc.battery_health:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues.append(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;quot;描述写电池&amp;nbsp;{draft.battery_in_desc}%,&amp;nbsp;QC实测&amp;nbsp;{qc.battery_health}%&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;5.&amp;nbsp;实拍图不足&amp;nbsp;-&amp;gt;&amp;nbsp;外观争议无证据
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.photos&amp;nbsp;&amp;lt;&amp;nbsp;3&amp;nbsp;or&amp;nbsp;draft.photo_count&amp;nbsp;&amp;lt;&amp;nbsp;3:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues.append(&amp;quot;实拍图&amp;lt;3张,&amp;nbsp;外观争议时无法自证&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;6.&amp;nbsp;维修记录未披露
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;qc.repaired_parts&amp;nbsp;and&amp;nbsp;&amp;quot;换&amp;quot;&amp;nbsp;not&amp;nbsp;in&amp;nbsp;draft.desc&amp;nbsp;and&amp;nbsp;&amp;quot;维修&amp;quot;&amp;nbsp;not&amp;nbsp;in&amp;nbsp;draft.desc:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;issues.append(f&amp;quot;换过部件&amp;nbsp;{qc.repaired_parts}&amp;nbsp;但未在描述披露&amp;quot;)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;issues:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise&amp;nbsp;GradeViolation(issues)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;real_bm

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_claimed_to_internal(self,&amp;nbsp;platform:&amp;nbsp;str,&amp;nbsp;claimed:&amp;nbsp;str)&amp;nbsp;-&amp;gt;&amp;nbsp;Optional[InternalGrade]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed&amp;nbsp;=&amp;nbsp;claimed.lower()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;claimed&amp;nbsp;in&amp;nbsp;(&amp;quot;premium&amp;quot;,&amp;nbsp;&amp;quot;a&amp;quot;,&amp;nbsp;&amp;quot;99新&amp;quot;,&amp;nbsp;&amp;quot;准新&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.A
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;claimed&amp;nbsp;in&amp;nbsp;(&amp;quot;excellent&amp;quot;,&amp;nbsp;&amp;quot;good&amp;quot;,&amp;nbsp;&amp;quot;b&amp;quot;,&amp;nbsp;&amp;quot;95新&amp;quot;,&amp;nbsp;&amp;quot;正常使用&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.B
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;claimed&amp;nbsp;in&amp;nbsp;(&amp;quot;fair&amp;quot;,&amp;nbsp;&amp;quot;c&amp;quot;,&amp;nbsp;&amp;quot;9新&amp;quot;,&amp;nbsp;&amp;quot;明显使用&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.C
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;claimed&amp;nbsp;in&amp;nbsp;(&amp;quot;parts&amp;quot;,&amp;nbsp;&amp;quot;d&amp;quot;,&amp;nbsp;&amp;quot;for&amp;nbsp;parts&amp;quot;,&amp;nbsp;&amp;quot;配件机&amp;quot;):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;InternalGrade.D
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;None

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;_rank(self,&amp;nbsp;g:&amp;nbsp;InternalGrade)&amp;nbsp;-&amp;gt;&amp;nbsp;int:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{InternalGrade.A:&amp;nbsp;3,&amp;nbsp;InternalGrade.B:&amp;nbsp;2,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InternalGrade.C:&amp;nbsp;1,&amp;nbsp;InternalGrade.D:&amp;nbsp;0}[g]


#&amp;nbsp;----------------&amp;nbsp;售后回流：发现&amp;nbsp;overgrading&amp;nbsp;----------------
@dataclass
class&amp;nbsp;ReturnCase:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sku:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed_grade:&amp;nbsp;str
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return_reason:&amp;nbsp;str&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;&amp;quot;not_as_described&amp;quot;,&amp;nbsp;&amp;quot;scratch&amp;quot;,&amp;nbsp;&amp;quot;battery&amp;quot;,&amp;nbsp;&amp;quot;dead_pixel&amp;quot;...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc:&amp;nbsp;QcRecord&amp;nbsp;=&amp;nbsp;None


class&amp;nbsp;ReturnSignalLoop:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.by_sku_grade:&amp;nbsp;Dict[tuple,&amp;nbsp;int]&amp;nbsp;=&amp;nbsp;{}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;ingest(self,&amp;nbsp;case:&amp;nbsp;ReturnCase):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;key&amp;nbsp;=&amp;nbsp;(case.sku,&amp;nbsp;case.claimed_grade)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.by_sku_grade[key]&amp;nbsp;=&amp;nbsp;self.by_sku_grade.get(key,&amp;nbsp;0)&amp;nbsp;+&amp;nbsp;1

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;overgrading_alert(self,&amp;nbsp;threshold:&amp;nbsp;int&amp;nbsp;=&amp;nbsp;3)&amp;nbsp;-&amp;gt;&amp;nbsp;List[Dict]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alerts&amp;nbsp;=&amp;nbsp;[]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(sku,&amp;nbsp;claimed),&amp;nbsp;cnt&amp;nbsp;in&amp;nbsp;self.by_sku_grade.items():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;cnt&amp;nbsp;&amp;gt;=&amp;nbsp;threshold:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alerts.append({
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;sku&amp;quot;:&amp;nbsp;sku,&amp;nbsp;&amp;quot;claimed&amp;quot;:&amp;nbsp;claimed,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;return_cases&amp;quot;:&amp;nbsp;cnt,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;suspect&amp;quot;:&amp;nbsp;&amp;quot;overgrading&amp;nbsp;/&amp;nbsp;grading&amp;nbsp;drift&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;暂停该SKU发布&amp;nbsp;+&amp;nbsp;盲检复评&amp;nbsp;+&amp;nbsp;已上架降级&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;alerts


#&amp;nbsp;----------------&amp;nbsp;自动下架防御&amp;nbsp;----------------
class&amp;nbsp;AutoTakedownGuard:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;__init__(self,&amp;nbsp;assertion:&amp;nbsp;ListingAssertion,&amp;nbsp;returns:&amp;nbsp;ReturnSignalLoop):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.assertion&amp;nbsp;=&amp;nbsp;assertion
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.returns&amp;nbsp;=&amp;nbsp;returns

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;pre_publish(self,&amp;nbsp;draft:&amp;nbsp;ListingDraft)&amp;nbsp;-&amp;gt;&amp;nbsp;Dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bm&amp;nbsp;=&amp;nbsp;self.assertion.assert_listing(draft)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:&amp;nbsp;True,&amp;nbsp;&amp;quot;backmarket_grade&amp;quot;:&amp;nbsp;bm.value&amp;nbsp;if&amp;nbsp;bm&amp;nbsp;else&amp;nbsp;None}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except&amp;nbsp;GradeViolation&amp;nbsp;as&amp;nbsp;e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{&amp;quot;ok&amp;quot;:&amp;nbsp;False,&amp;nbsp;&amp;quot;block&amp;quot;:&amp;nbsp;True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;issues&amp;quot;:&amp;nbsp;e.issues,&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;禁止发布&amp;quot;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def&amp;nbsp;post_return_heal(self,&amp;nbsp;draft:&amp;nbsp;ListingDraft)&amp;nbsp;-&amp;gt;&amp;nbsp;Dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;退货聚集后:&amp;nbsp;自动降级到实物等级重新发,&amp;nbsp;不硬撑A&amp;quot;&amp;quot;&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;real&amp;nbsp;=&amp;nbsp;infer_internal_grade(draft.qc)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bm&amp;nbsp;=&amp;nbsp;PlatformGradeMapper().to_backmarket(real)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;action&amp;quot;:&amp;nbsp;&amp;quot;relist_as_real_grade&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;new_claimed_grade&amp;quot;:&amp;nbsp;real.value,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;backmarket_grade&amp;quot;:&amp;nbsp;bm.value&amp;nbsp;if&amp;nbsp;bm&amp;nbsp;else&amp;nbsp;&amp;quot;NOT_LISTABLE&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

#&amp;nbsp;封装好API供应商demo&amp;nbsp;url=https://console.open.onebound.cn/console/?i=Lex
#&amp;nbsp;====================&amp;nbsp;DEMO&amp;nbsp;====================
if&amp;nbsp;__name__&amp;nbsp;==&amp;nbsp;&amp;quot;__main__&amp;quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mapper&amp;nbsp;=&amp;nbsp;PlatformGradeMapper()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertion&amp;nbsp;=&amp;nbsp;ListingAssertion(mapper)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;returns&amp;nbsp;=&amp;nbsp;ReturnSignalLoop()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;guard&amp;nbsp;=&amp;nbsp;AutoTakedownGuard(assertion,&amp;nbsp;returns)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;===&amp;nbsp;1.&amp;nbsp;B级实物被运营标成&amp;nbsp;Premium&amp;nbsp;(overgrading)&amp;nbsp;===&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc_b&amp;nbsp;=&amp;nbsp;QcRecord(sku=&amp;quot;IP13-001&amp;quot;,&amp;nbsp;body_micro_scratch=True,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_health=85,&amp;nbsp;photos=4,&amp;nbsp;repaired_parts=[&amp;quot;battery&amp;quot;])
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;draft&amp;nbsp;=&amp;nbsp;ListingDraft(sku=&amp;quot;IP13-001&amp;quot;,&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed_grade=&amp;quot;Premium&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;desc=&amp;quot;准新机&amp;nbsp;电池健康&amp;nbsp;95%&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_in_desc=95,&amp;nbsp;photo_count=4,&amp;nbsp;qc=qc_b)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;quot;,&amp;nbsp;guard.pre_publish(draft))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;-&amp;gt;&amp;nbsp;block:&amp;nbsp;overgrading&amp;nbsp;+&amp;nbsp;Premium电池不足&amp;nbsp;+&amp;nbsp;维修未披露

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;\n===&amp;nbsp;2.&amp;nbsp;真实A级&amp;nbsp;(无划痕/电池93)&amp;nbsp;标&amp;nbsp;Premium&amp;nbsp;===&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc_a&amp;nbsp;=&amp;nbsp;QcRecord(sku=&amp;quot;IP13-002&amp;quot;,&amp;nbsp;battery_health=93,&amp;nbsp;photos=5)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;draft_a&amp;nbsp;=&amp;nbsp;ListingDraft(sku=&amp;quot;IP13-002&amp;quot;,&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed_grade=&amp;quot;Premium&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;desc=&amp;quot;无划痕&amp;nbsp;电池93%&amp;nbsp;官方级翻新&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_in_desc=93,&amp;nbsp;photo_count=5,&amp;nbsp;qc=qc_a)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;quot;,&amp;nbsp;guard.pre_publish(draft_a))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;-&amp;gt;&amp;nbsp;ok:&amp;nbsp;Premium

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;\n===&amp;nbsp;3.&amp;nbsp;售后回流:&amp;nbsp;同一SKU标A被退3次&amp;nbsp;===&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;_&amp;nbsp;in&amp;nbsp;range(3):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;returns.ingest(ReturnCase(&amp;quot;IP13-003&amp;quot;,&amp;nbsp;&amp;quot;A&amp;quot;,&amp;nbsp;&amp;quot;not_as_described&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QcRecord(screen_scratch=True,&amp;nbsp;battery_health=82)))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;alerts:&amp;quot;,&amp;nbsp;returns.overgrading_alert())

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;\n===&amp;nbsp;4.&amp;nbsp;自动愈合:&amp;nbsp;不再硬标A,&amp;nbsp;按实物降级&amp;nbsp;===&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc_c&amp;nbsp;=&amp;nbsp;QcRecord(sku=&amp;quot;IP13-003&amp;quot;,&amp;nbsp;screen_scratch=True,&amp;nbsp;battery_health=82,&amp;nbsp;photos=3)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;draft_c&amp;nbsp;=&amp;nbsp;ListingDraft(sku=&amp;quot;IP13-003&amp;quot;,&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed_grade=&amp;quot;A&amp;quot;,&amp;nbsp;desc=&amp;quot;屏幕有轻微划痕&amp;nbsp;电池82%&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;battery_in_desc=82,&amp;nbsp;photo_count=3,&amp;nbsp;qc=qc_c)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;quot;,&amp;nbsp;guard.post_return_heal(draft_c))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;-&amp;gt;&amp;nbsp;relist&amp;nbsp;as&amp;nbsp;C&amp;nbsp;/&amp;nbsp;Fair

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;\n===&amp;nbsp;5.&amp;nbsp;功能坏机想当B卖&amp;nbsp;===&amp;quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;qc_dead&amp;nbsp;=&amp;nbsp;QcRecord(sku=&amp;quot;IP13-004&amp;quot;,&amp;nbsp;powers_on=False,&amp;nbsp;camera_ok=False)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;draft_dead&amp;nbsp;=&amp;nbsp;ListingDraft(sku=&amp;quot;IP13-004&amp;quot;,&amp;nbsp;platform=&amp;quot;backmarket&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimed_grade=&amp;quot;Good&amp;quot;,&amp;nbsp;qc=qc_dead)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(&amp;quot;&amp;nbsp;&amp;nbsp;&amp;quot;,&amp;nbsp;guard.pre_publish(draft_dead))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;-&amp;gt;&amp;nbsp;block:&amp;nbsp;InternalGrade=D&amp;nbsp;不允许可售&lt;/pre&gt;&lt;div class=&quot;ybc-p&quot;&gt;跑出来核心就是：&lt;/div&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;1.&amp;nbsp;{&amp;#39;ok&amp;#39;:&amp;nbsp;False,&amp;nbsp;&amp;#39;block&amp;#39;:&amp;nbsp;True,&amp;nbsp;&amp;#39;issues&amp;#39;:&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;overgrading:&amp;nbsp;标称&amp;nbsp;Premium(A)&amp;nbsp;&amp;gt;&amp;nbsp;实物&amp;nbsp;B&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;Premium&amp;nbsp;电池需&amp;gt;=90%,&amp;nbsp;实际&amp;nbsp;85%&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;描述写电池&amp;nbsp;95%,&amp;nbsp;QC实测&amp;nbsp;85%&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;换过部件&amp;nbsp;[...]/电池...&amp;nbsp;但未在描述披露&amp;#39;],&amp;nbsp;&amp;#39;action&amp;#39;:&amp;nbsp;&amp;#39;禁止发布&amp;#39;}

2.&amp;nbsp;{&amp;#39;ok&amp;#39;:&amp;nbsp;True,&amp;nbsp;&amp;#39;backmarket_grade&amp;#39;:&amp;nbsp;&amp;#39;Premium&amp;#39;}

3.&amp;nbsp;alerts:&amp;nbsp;[{&amp;#39;sku&amp;#39;:&amp;#39;IP13-003&amp;#39;,&amp;#39;claimed&amp;#39;:&amp;#39;A&amp;#39;,&amp;#39;return_cases&amp;#39;:3,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;suspect&amp;#39;:&amp;#39;overgrading&amp;nbsp;/&amp;nbsp;grading&amp;nbsp;drift&amp;#39;,&amp;#39;action&amp;#39;:&amp;#39;暂停该SKU发布+盲检复评&amp;#39;}]

4.&amp;nbsp;{&amp;#39;action&amp;#39;:&amp;#39;relist_as_real_grade&amp;#39;,&amp;#39;new_claimed_grade&amp;#39;:&amp;#39;C&amp;#39;,&amp;#39;backmarket_grade&amp;#39;:&amp;#39;Fair&amp;#39;}

5.&amp;nbsp;{&amp;#39;ok&amp;#39;:&amp;nbsp;False,&amp;nbsp;&amp;#39;block&amp;#39;:&amp;nbsp;True,&amp;nbsp;&amp;#39;issues&amp;#39;:[&amp;#39;功能不达标(InternalGrade=D)...&amp;#39;]}&lt;/pre&gt;&lt;hr/&gt;&lt;h2&gt;四、A/B 级校验闭环（架构图）&lt;/h2&gt;&lt;pre class=&quot;ybc-pre-component ybc-pre-component_not-math&quot;&gt;入库QC&amp;nbsp;──►&amp;nbsp;InternalGrade(A/B/C/D)
&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;PlatformGradeMapper&amp;nbsp;──►&amp;nbsp;BackMarket(Premium/Excellent/Good/Fair)
&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;抖音/闲鱼/Mercari/Vinted&amp;nbsp;本地成色词
&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;▼
ListingAssertion&amp;nbsp;(发布闸门)
&amp;nbsp;&amp;nbsp;&amp;nbsp;•&amp;nbsp;claimed&amp;nbsp;&amp;lt;=&amp;nbsp;real
&amp;nbsp;&amp;nbsp;&amp;nbsp;•&amp;nbsp;电池/划痕/维修/实拍图&amp;nbsp;一致性
&amp;nbsp;&amp;nbsp;&amp;nbsp;•&amp;nbsp;平台宪章对齐&amp;nbsp;(BM:&amp;nbsp;功能全过/电池80%/Premium90%)
&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;不通过&amp;nbsp;──►&amp;nbsp;禁止发布&amp;nbsp;+&amp;nbsp;告警&amp;nbsp;+&amp;nbsp;留审计日志
&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;通过&amp;nbsp;&amp;nbsp;&amp;nbsp;──►&amp;nbsp;上架
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;▼
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReturnCases&amp;nbsp;回流
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;▼
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReturnSignalLoop
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(同SKU+同标称等级退货&amp;gt;=N&amp;nbsp;→&amp;nbsp;overgrading警报)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;▼
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AutoTakedownGuard.post_return_heal()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;硬标A的&amp;nbsp;→&amp;nbsp;按实物降级为B/C
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;严重漂移&amp;nbsp;→&amp;nbsp;停发&amp;nbsp;+&amp;nbsp;盲检复评(反向打分)&lt;/pre&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;盲检复评（reverse blind grading）&lt;/strong&gt; 是行业里防 grading drift 最稳的办法：让另一个技师在不看原等级的情况下重新检，和原结果比对。&lt;/div&gt;&lt;/blockquote&gt;&lt;hr/&gt;&lt;h2&gt;五、6 条铁律&lt;/h2&gt;&lt;ol style=&quot;list-style-type: decimal;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;标称等级永远 ≤ 实物等级&lt;/strong&gt;：宁可 undergrade 亏毛利，别 overgrading 丢账户。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;A/B/C 不是形容词，是字段组合&lt;/strong&gt;：划痕、磕碰、电池、功能、维修记录、实拍张数，全进规则引擎。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Back Market 成色只管外观，功能必须全过&lt;/strong&gt;：把“A 级但触屏偶尔失灵”发出去 = 违反 Quality Charter。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;电池数字是高危字段&lt;/strong&gt;：描述写 95%、QC 写 85%，平台/买家一投诉就实锤“描述不符”。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;退货原因码是唯一真相源&lt;/strong&gt;：按 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;SKU × 标称等级&lt;/code&gt; 聚合，退货集中 = 等级标准漂了，不是“买家事多”。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;自动下架防御要双向&lt;/strong&gt;：发布前拦错标 + 售后后自动降级；别等平台算法把店铺流量关了再救。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr/&gt;&lt;h2&gt;六、和前几篇串起来&lt;/h2&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;前篇 &lt;strong&gt;Back Market Compliance Gate&lt;/strong&gt;：主体/VAT/OAuth/Quality Charter 是“能不能卖”；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;本篇 &lt;strong&gt;Grade Integrity Loop&lt;/strong&gt;：成色 A/B 一致性是“卖得久不久”；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;前篇 &lt;strong&gt;Vinted GPSR / Mercari 限流 / eBay ConditionGuard&lt;/strong&gt;：都是“平台替你守买家体验，ERP 必须先把规则内建”；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;前篇 &lt;strong&gt;ModeSelector&lt;/strong&gt;：认证服务商模式值不值——看这种闭环要养多少质检/SOP 就懂了。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;二手跨境电商的底层公式：&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;&lt;strong&gt;可信等级 = QC 证据 × 平台宪章 × 描述一致性&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;ybc-p&quot;&gt;三者任一断，A 级也会变“描述不符”。&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;ybc-p&quot;&gt;要不要我把 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;grade_integrity_loop.py&lt;/code&gt; 合进 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;commerce-mesh/core/&lt;/code&gt;：做成 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;GradeEngine&lt;/code&gt; + &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;QcChecklistRegistry&lt;/code&gt;（按手机/平板/服饰/奢品挂不同清单）+ &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;ReturnDriftDetector&lt;/code&gt;，并和前篇 &lt;code class=&quot;hyc-common-markdown__code__inline&quot;&gt;ObservabilityMiddleware&lt;/code&gt; 出一张 &lt;strong&gt;Overgrading 风险面板&lt;/strong&gt;（按 SKU / 技师 / 班次 / 类目拆分）？&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Tue, 15 Sep 2026 10:37:20 +0800</pubDate></item></channel></rss>