在二手數(shù)碼回收業(yè)務(wù)對接中,愛回收商品詳情接口是獲取設(shè)備估價、成色分級、回收方式等核心數(shù)據(jù)的關(guān)鍵入口 —— 不同于普通電商商品,回收類商品需重點處理 “成色編碼映射”“實時估價波動”“回收渠道差異” 等特殊場景。本文參考標(biāo)準(zhǔn)化接口對接邏輯,結(jié)合愛回收平臺特色,拆解從認(rèn)證到數(shù)據(jù)落地的全流程,提供可直接復(fù)用的代碼方案,解決簽名失敗、成色解析混亂、估價數(shù)據(jù)延遲等常見問題。
一、接口對接前置準(zhǔn)備
1. 核心參數(shù)與權(quán)限說明(需平臺申請)
調(diào)用愛回收商品詳情接口前( https://o0b.cn/lin ),需先從平臺獲取專屬憑證,確保請求合法性,關(guān)鍵參數(shù)如下:
| 參數(shù)名 | 類型 | 說明 | 是否必選 |
| app_key | String | 應(yīng)用唯一標(biāo)識,愛回收開放平臺為每個開發(fā)者分配,用于身份識別 | 是 |
| app_secret | String | 接口調(diào)用密鑰,用于生成簽名(嚴(yán)禁泄露,建議通過環(huán)境變量或配置文件存儲) | 是 |
| product_id | String | 回收商品唯一 ID(如手機型號對應(yīng) ID,可從愛回收商品列表接口獲?。?/td> | 是 |
| timestamp | String | 毫秒級時間戳(格式:1719000000000),與平臺服務(wù)器時間差需≤5 分鐘 | 是 |
| condition_type | Integer | 設(shè)備成色類型(可選,1 = 全新未拆封,2=95 新,3=9 新,4=8 新,5=7 新及以下) | 否 |
| sign | String | 簽名信息(按愛回收規(guī)則生成,驗證請求完整性,防止參數(shù)篡改) |
是 |
2. 簽名生成規(guī)則(愛回收特色邏輯)
愛回收采用 HMAC-MD5 簽名機制,相比普通 MD5 增加密鑰二次校驗,步驟如下(少一步都可能失?。?/p>
參數(shù)篩選:僅保留非空的請求參數(shù)(含公共參數(shù)與condition_type等私有參數(shù)),排除sign本身;
字典序排序:按參數(shù)名首字母字典序升序排列(如app_key在condition_type前,product_id在timestamp前);
字符串拼接:按 “key=value&key=value” 格式拼接排序后的參數(shù)(例:app_key=xxx&condition_type=2&product_id=123×tamp=1719000000000);
密鑰拼接:在拼接字符串末尾添加 “&secret=xxx”(xxx 為app_secret,注意前綴有 “&secret=”);
HMAC-MD5 加密:將最終字符串用app_secret作為密鑰進(jìn)行 HMAC-MD5 加密,結(jié)果轉(zhuǎn)為小寫,即為sign值。
二、核心技術(shù)實現(xiàn)(適配回收場景)
1. 接口調(diào)用客戶端(含成色解析 + 緩存)
針對愛回收 “估價實時變”“成色類型多” 的特點,客戶端需額外處理成色編碼映射、估價區(qū)間提取、短時效緩存,代碼如下:
import requestsimport hashlibimport hmacimport timeimport jsonfrom threading import Lockfrom cachetools import TTLCacheclass AihuishouProductClient: """愛回收商品詳情接口客戶端(含簽名、成色解析、短時效緩存)""" # 愛回收成色編碼映射(固定對應(yīng)關(guān)系,避免解析混亂) CONDITION_MAP = { 1: "全新未拆封", 2: "95新(輕微使用痕跡)", 3: "9新(明顯使用痕跡,無功能問題)", 4: "8新(較多使用痕跡,無功能問題)", 5: "7新及以下(明顯磨損或輕微功能瑕疵)" } def __init__(self, app_key, app_secret, timeout=8, max_retries=2, cache_ttl=600): """ 初始化客戶端 :param app_key: 平臺分配app_key :param app_secret: 平臺分配app_secret :param timeout: 請求超時時間(秒),默認(rèn)8秒(回收接口響應(yīng)較快) :param max_retries: 失敗重試次數(shù),默認(rèn)2次 :param cache_ttl: 緩存有效期(秒),默認(rèn)10分鐘(適配估價實時性) """ self.app_key = app_key self.app_secret = app_secret self.base_url = "https://api.aihuishou.com/product/detail" # 接口固定地址 self.timeout = timeout self.max_retries = max_retries # 短時效緩存:避免頻繁調(diào)用導(dǎo)致估價數(shù)據(jù)重復(fù)獲取 self.cache = TTLCache(maxsize=1000, ttl=cache_ttl) self.cache_lock = Lock() # 緩存操作線程鎖 def _generate_sign(self, params): """生成愛回收HMAC-MD5簽名""" # 1. 篩選非空參數(shù)并字典序排序 valid_params = {k: v for k, v in params.items() if v is not None} sorted_params = sorted(valid_params.items(), key=lambda x: x[0]) # 2. 拼接"key=value&key=value"格式 param_str = "&".join([f"{k}={v}" for k, v in sorted_params]) # 3. 追加"&secret=app_secret" sign_str = f"{param_str}&secret={self.app_secret}" # 4. HMAC-MD5加密(密鑰為app_secret) hmac_obj = hmac.new( self.app_secret.encode("utf-8"), sign_str.encode("utf-8"), hashlib.md5 ) return hmac_obj.hexdigest().lower() def _get_cache_key(self, product_id, condition_type=None): """生成緩存鍵(區(qū)分商品ID和成色類型)""" cond_suffix = f"_cond{condition_type}" if condition_type else "_default" return f"aihuishou_{product_id}{cond_suffix}" def get_product_detail(self, product_id, condition_type=None, use_cache=True): """ 核心方法:獲取愛回收商品詳情(含估價、成色、回收方式) :param product_id: 回收商品ID :param condition_type: 設(shè)備成色類型(可選,見CONDITION_MAP) :param use_cache: 是否使用緩存(默認(rèn)啟用,實時場景可關(guān)閉) :return: 結(jié)構(gòu)化商品數(shù)據(jù)(None表示失?。? """ # 1. 先查緩存(避免重復(fù)請求) if use_cache: cache_key = self._get_cache_key(product_id, condition_type) with self.cache_lock: if cache_key in self.cache: print(f"[緩存命中] 商品{product_id}(成色:{condition_type})") return self.cache[cache_key] # 2. 構(gòu)建基礎(chǔ)請求參數(shù) base_params = { "app_key": self.app_key, "product_id": product_id, "timestamp": str(int(time.time() * 1000)), # 毫秒級時間戳 "condition_type": condition_type # 可選參數(shù),非空才傳入 } # 過濾None值(避免參數(shù)格式錯誤) base_params = {k: v for k, v in base_params.items() if v is not None} # 3. 生成簽名并添加到參數(shù) base_params["sign"] = self._generate_sign(base_params) # 4. 發(fā)送請求(帶重試機制) retry_count = 0 while retry_count < self.max_retries: try: response = requests.get( url=self.base_url, params=base_params, headers={"User-Agent": "AihuishouProductClient/1.0"}, timeout=self.timeout ) response.raise_for_status() # 捕獲4xx/5xx錯誤 # 5. 解析JSON響應(yīng) try: result = response.json() except json.JSONDecodeError: print(f"商品{product_id}:響應(yīng)非JSON格式,解析失敗") retry_count += 1 continue # 6. 處理業(yè)務(wù)錯誤(愛回收code=200為成功) if result.get("code") != 200: error_msg = result.get("msg", "未知錯誤") print(f"商品{product_id}:接口錯誤 - {error_msg}(code:{result.get('code')})") # 簽名/參數(shù)錯誤無需重試 if result.get("code") in [401, 402]: # 401=簽名錯,402=參數(shù)錯 return None retry_count += 1 continue # 7. 解析回收特色數(shù)據(jù) parsed_data = self._parse_recycle_data(result.get("data", {}), condition_type) if not parsed_data: print(f"商品{product_id}:數(shù)據(jù)解析為空,跳過") return None # 8. 寫入緩存 if use_cache: with self.cache_lock: self.cache[cache_key] = parsed_data return parsed_data except requests.exceptions.RequestException as e: print(f"商品{product_id}:請求異常 - {str(e)}") retry_count += 1 time.sleep(1) # 重試前休眠1秒 print(f"商品{product_id}:超過{self.max_retries}次重試,獲取失敗") return None def _parse_recycle_data(self, raw_data, condition_type): """解析愛回收回收特色數(shù)據(jù)(核心:估價、成色、回收方式)""" if not isinstance(raw_data, dict): return None # 1. 基礎(chǔ)商品信息(設(shè)備型號、品牌、規(guī)格) base_info = { "product_id": raw_data.get("productId", ""), "brand": raw_data.get("brandName", ""), # 如"蘋果" "model": raw_data.get("modelName", ""), # 如"iPhone 15 Pro" "spec": raw_data.get("specInfo", ""), # 如"256GB·黑色" "release_year": raw_data.get("releaseYear", "") # 發(fā)布年份(回收估價參考) } # 2. 估價信息(區(qū)分不同成色的估價區(qū)間) price_info = self._parse_price(raw_data.get("priceRange", {}), condition_type) # 3. 回收方式與服務(wù)(上門/郵寄、質(zhì)檢周期) service_info = { "recycle_methods": [ "上門回收" if method == 1 else "郵寄回收" for method in raw_data.get("recycleMethods", []) ], "inspection_cycle": raw_data.get("inspectionCycle", "24小時內(nèi)"), # 質(zhì)檢周期 "payment_time": raw_data.get("paymentTime", "質(zhì)檢通過后2小時內(nèi)") # 打款時間 } # 4. 成色說明(當(dāng)前查詢成色+支持的成色列表) condition_info = { "current_condition": self.CONDITION_MAP.get(condition_type, "未指定"), "supported_conditions": [ {"code": k, "name": v} for k, v in self.CONDITION_MAP.items() ] } return { "base_info": base_info, "price_info": price_info, "service_info": service_info, "condition_info": condition_info, "parse_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) } def _parse_price(self, raw_price, condition_type): """解析估價信息(愛回收按成色返回不同估價區(qū)間)""" if not raw_price: return {"price_range": "未知", "currency": "人民幣"} # 若指定成色,優(yōu)先取對應(yīng)成色估價;否則取默認(rèn)區(qū)間 if condition_type and str(condition_type) in raw_price: price = raw_price[str(condition_type)] return { "price_range": f"{price.get('min')}-{price.get('max')}元", "currency": "人民幣", "note": "按指定成色計算" } else: # 默認(rèn)取全成色區(qū)間(min取最小,max取最大) all_prices = list(raw_price.values()) min_total = min([p.get('min', 0) for p in all_prices]) max_total = max([p.get('max', 0) for p in all_prices]) return { "price_range": f"{min_total}-{max_total}元", "currency": "人民幣", "note": "全成色區(qū)間(指定成色可獲取更精準(zhǔn)估價)" }
三、實戰(zhàn)示例(貼合回收業(yè)務(wù)場景)
1. 單商品精準(zhǔn)估價查詢(指定成色)
def single_product_demo(): """單商品查詢示例:查iPhone 15 Pro 256GB的95新估價""" # 1. 替換為自身的app_key和app_secret(從愛回收開放平臺申請) APP_KEY = "your_aihuishou_app_key" APP_SECRET = "your_aihuishou_app_secret" # 2. 目標(biāo)商品ID(假設(shè)iPhone 15 Pro 256GB的product_id為10086) TARGET_PRODUCT_ID = "10086" # 3. 指定成色:95新(對應(yīng)condition_type=2) TARGET_CONDITION = 2 # 4. 初始化客戶端(緩存10分鐘,適配估價實時性) client = AihuishouProductClient( app_key=APP_KEY, app_secret=APP_SECRET, cache_ttl=600 ) # 5. 獲取并打印詳情 print(f"開始查詢商品ID {TARGET_PRODUCT_ID}({client.CONDITION_MAP[TARGET_CONDITION]})...") product_detail = client.get_product_detail( product_id=TARGET_PRODUCT_ID, condition_type=TARGET_CONDITION ) if product_detail: print("n=== 愛回收商品詳情 ===") print(f"設(shè)備型號:{product_detail['base_info']['brand']} {product_detail['base_info']['model']}") print(f"規(guī)格配置:{product_detail['base_info']['spec']}") print(f"查詢成色:{product_detail['condition_info']['current_condition']}") print(f"精準(zhǔn)估價:{product_detail['price_info']['price_range']}") print(f"回收方式:{', '.join(product_detail['service_info']['recycle_methods'])}") print(f"質(zhì)檢周期:{product_detail['service_info']['inspection_cycle']}") else: print(f"n商品{TARGET_PRODUCT_ID}詳情獲取失敗")if __name__ == "__main__": single_product_demo()
2. 批量商品回收數(shù)據(jù)采集(多型號 + 多成色)
from concurrent.futures import ThreadPoolExecutor, as_completeddef batch_product_demo(): """批量采集示例:多型號+多成色組合查詢""" APP_KEY = "your_aihuishou_app_key" APP_SECRET = "your_aihuishou_app_secret" # 批量任務(wù):(product_id, condition_type) 組合 BATCH_TASKS = [ ("10086", 2), # iPhone 15 Pro 256GB - 95新 ("10087", 3), # 華為Mate 60 Pro 512GB - 9新 ("10088", 4), # 小米14 256GB - 8新 ("10089", 1) # 三星S24 Ultra 512GB - 全新 ] MAX_WORKERS = 2 # 并發(fā)數(shù)(愛回收接口建議≤2,避免頻率限制) # 初始化客戶端 client = AihuishouProductClient(APP_KEY, APP_SECRET) batch_result = [] print(f"開始批量采集 {len(BATCH_TASKS)} 個商品回收數(shù)據(jù)(并發(fā):{MAX_WORKERS})...") # 多線程提交任務(wù) with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: future_map = { executor.submit(client.get_product_detail, task[0], task[1]): task for task in BATCH_TASKS } # 處理結(jié)果 for future in as_completed(future_map): product_id, cond_type = future_map[future] try: data = future.result() if data: batch_result.append(data) print(f"? 商品{product_id}({client.CONDITION_MAP[cond_type]})采集成功") else: print(f"? 商品{product_id}({client.CONDITION_MAP[cond_type]})采集失敗") except Exception as e: print(f"?? 商品{product_id}處理異常:{str(e)}") # 輸出批量統(tǒng)計 print(f"n=== 批量采集完成 ===") print(f"總?cè)蝿?wù)數(shù):{len(BATCH_TASKS)}") print(f"成功數(shù):{len(batch_result)}") print(f"失敗數(shù):{len(BATCH_TASKS) - len(batch_result)}")# 運行批量示例# if __name__ == "__main__":# batch_product_demo()
四、回收場景專屬避坑指南
1. 成色編碼別搞混:固定映射是關(guān)鍵
愛回收成色condition_type為整數(shù)編碼(1-5),而非文字,需用CONDITION_MAP映射成可讀文字(如 2→95 新);
若接口返回 “成色類型不支持”,檢查condition_type是否在 1-5 范圍內(nèi)(部分老機型僅支持 3-5 成色)。
2. 估價數(shù)據(jù)別緩存太久:10 分鐘是上限
回收估價受市場波動影響(如新機發(fā)布后舊機估價下跌),緩存時間建議≤10 分鐘,實時場景(如用戶實時查詢)可關(guān)閉緩存;
緩存鍵需包含product_id+condition_type(同一商品不同成色估價不同,避免緩存污染)。
3. 回收方式字段要適配:枚舉值會更新
愛回收recycleMethods返回整數(shù)列表(1 = 上門,2 = 郵寄),若新增 “門店回收”(如 3 = 門店),需及時更新_parse_recycle_data中的映射邏輯;
部分偏遠(yuǎn)地區(qū)不支持上門回收,需在業(yè)務(wù)層判斷recycle_methods是否包含 “上門回收”。
4. 時間戳別踩坑:毫秒級 + 時差控制
愛回收要求時間戳為毫秒級(普通接口多為秒級),需用int(time.time() * 1000)生成;
服務(wù)器時間為 UTC+8,本地時間若偏差超過 5 分鐘,會返回 “時間戳無效”,需同步本地時間。
五、常見問題快速排查
| 問題現(xiàn)象 | 可能原因 | 解決辦法 |
| 簽名錯誤(code=401) | 1. 簽名時漏加 “&secret=xxx”;2. app_secret 錯 | 1. 檢查_generate_sign中是否有&secret={self.app_secret};2. 核對 app_secret |
| 估價區(qū)間為空 | 1. product_id 無效;2. 該機型暫不支持回收 | 1. 在愛回收官網(wǎng)驗證 product_id 是否存在;2. 確認(rèn)機型是否在回收列表中 |
| 緩存不生效 | 1. 緩存鍵未包含 condition_type;2. 緩存鎖未加 | 1. 檢查_get_cache_key是否拼接成色后綴;2. 確保緩存讀寫加cache_lock |
| 批量調(diào)用部分失敗 | 1. 頻率超限;2. 個別商品 ID 無效 |
1. 減少并發(fā)數(shù)至 1-2,或增加請求間隔;2. 單獨測試失敗的 product_id 要是對接時卡殼 —— 不管是成色數(shù)據(jù)解析懵了,還是簽名總踩坑,隨時喊小編嘮!評論區(qū)留個暗號(比如 “愛回收接口求助”),小編秒回,手把手幫你捋明白~畢竟回收接口的 “成色”“估價” 這些小細(xì)節(jié),多聊兩句就能少走彎路呀~ |
審核編輯 黃宇
-
接口
+關(guān)注
關(guān)注
33文章
9603瀏覽量
157661 -
python
+關(guān)注
關(guān)注
58文章
4889瀏覽量
90327
發(fā)布評論請先 登錄
調(diào)用愛回收平臺商品詳情 API 接口指南
獲取Ozon商品詳情數(shù)據(jù)的API接口技術(shù)指南
亞馬遜商品詳情數(shù)據(jù)獲取實戰(zhàn):從商品鏈接提取 ID 到解析詳情
實戰(zhàn)指南:調(diào)用沃爾瑪平臺 API 高效獲取商品詳情數(shù)據(jù)
1688 商品詳情 API 調(diào)用與數(shù)據(jù)解析 Python 實戰(zhàn)
亞馬遜獲取商品詳情API接口指南
淘寶商品詳情API接口技術(shù)解析與實戰(zhàn)應(yīng)用
京東商品詳情接口實戰(zhàn)解析:從調(diào)用優(yōu)化到商業(yè)價值挖掘(附避坑代碼)
別踩分頁坑!京東商品詳情接口實戰(zhàn)指南:從并發(fā)優(yōu)化到數(shù)據(jù)完整性閉環(huán)
當(dāng)當(dāng)網(wǎng)商品詳情接口全方位對接指南:從認(rèn)證機制到數(shù)據(jù)提取最佳實踐
從 0 到 1:用 PHP 爬蟲優(yōu)雅地拿下京東商品詳情
愛回收商品詳情接口全方位對接指南:從認(rèn)證機制到數(shù)據(jù)提取最佳實踐(附 Python 代碼 + 成色數(shù)據(jù)處理)
評論