test2.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import requests
  2. import json
  3. import datetime
  4. import hashlib
  5. import hmac
  6. import time
  7. from urllib.parse import quote
  8. # ==================== 配置区域 ====================
  9. CLIENT_ID = "amzn1.application-oa2-client.9f775d35077a4c7598116e5a89b60222"
  10. CLIENT_SECRET = "amzn1.oa2-cs.v1.6909777baa82b796555a431cd23709342e8e01434abcad1f8b59cadf048b51c3"
  11. REFRESH_TOKEN = "Atzr|IwEBICh_fojh7qAfrePzSjOZhQxTnHRZCYOuWNvSAHGaBs1WfkjR4qjC1Dmv0uK3oyq_L-R9SRKK4cYmPwF1MQXQdqKlpzOAGItWeXnNzh-SyhHHISv0_vCt3D6hluVmIEmF2kA7ro_XF-PslD41g3Eq6bv0Qq4y4pQbkDj-9dudDuz7nku8UL-nc4EWgJCrHCJTAs8TK48Yvrfi3E35uv97tYhs6qb8D9d4dR9C7daaC49eoDqP88qyUHThQV1Kqon8xukx4AT2_wLqWNcabpADzuK-5w7D-vvFFtvzfkbmtfzoPeEdHPulG6scc59BPFTyBlGU7a3d1JSFg2ROHIlrljRm"
  12. AWS_ACCESS_KEY = "AKIA24CLQSVTW2K4S6RP" # ← 填你的
  13. AWS_SECRET_KEY = "CwBJqlsYATNC920A+U6iv80WnP6Eso+ECfIalQ1W" # ← 填你的
  14. AWS_REGION = "us-east-1"
  15. SELLER_ID = "A1H50Z0WYYLEGQ"
  16. SKU = "sofa table black"
  17. MARKETPLACE_ID = "ATVPDKIKX0DER"
  18. NEW_IMAGE_URL = "https://cunchu.site/temp/f1ae4d03-e59e-45c5-9a3b-15dc3775396a.jpg"
  19. # ==================== 工具函数 ====================
  20. def sha256_hash(data):
  21. return hashlib.sha256(data.encode("utf-8")).hexdigest()
  22. def hmac_sha256(key, msg):
  23. return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
  24. def get_signature_key(secret_key, date_stamp, region, service):
  25. k_date = hmac_sha256(("AWS4" + secret_key).encode("utf-8"), date_stamp)
  26. k_region = hmac_sha256(k_date, region)
  27. k_service = hmac_sha256(k_region, service)
  28. return hmac_sha256(k_service, "aws4_request")
  29. def get_access_token():
  30. url = "https://api.amazon.com/auth/o2/token"
  31. resp = requests.post(url, data={
  32. "grant_type": "refresh_token",
  33. "refresh_token": REFRESH_TOKEN,
  34. "client_id": CLIENT_ID,
  35. "client_secret": CLIENT_SECRET,
  36. })
  37. resp.raise_for_status()
  38. return resp.json()["access_token"]
  39. def spapi_request(method, path, query, body=None, access_token=None):
  40. service = "execute-api"
  41. host = "sellingpartnerapi-na.amazon.com"
  42. payload = json.dumps(body, separators=(",", ":")) if body else ""
  43. t = datetime.datetime.now(datetime.timezone.utc)
  44. amz_date = t.strftime("%Y%m%dT%H%M%SZ")
  45. date_stamp = t.strftime("%Y%m%d")
  46. canonical_headers = (
  47. f"host:{host}\n"
  48. f"x-amz-access-token:{access_token}\n"
  49. f"x-amz-date:{amz_date}\n"
  50. )
  51. signed_headers = "host;x-amz-access-token;x-amz-date"
  52. payload_hash = sha256_hash(payload)
  53. canonical_request = (
  54. f"{method}\n{path}\n{query}\n"
  55. f"{canonical_headers}\n{signed_headers}\n{payload_hash}"
  56. )
  57. algorithm = "AWS4-HMAC-SHA256"
  58. credential_scope = f"{date_stamp}/{AWS_REGION}/{service}/aws4_request"
  59. string_to_sign = (
  60. f"{algorithm}\n{amz_date}\n{credential_scope}\n"
  61. f"{sha256_hash(canonical_request)}"
  62. )
  63. signing_key = get_signature_key(AWS_SECRET_KEY, date_stamp, AWS_REGION, service)
  64. signature = hmac.new(signing_key, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
  65. auth_header = (
  66. f"{algorithm} Credential={AWS_ACCESS_KEY}/{credential_scope}, "
  67. f"SignedHeaders={signed_headers}, Signature={signature}"
  68. )
  69. headers = {
  70. "Host": host,
  71. "x-amz-access-token": access_token,
  72. "x-amz-date": amz_date,
  73. "Authorization": auth_header,
  74. }
  75. if body:
  76. headers["Content-Type"] = "application/json"
  77. url = f"https://{host}{path}?{query}"
  78. return requests.request(method, url, headers=headers, data=payload or None)
  79. # ==================== 通用图片修改函数 ====================
  80. def patch_image(access_token, image_type, image_url):
  81. """
  82. image_type 可选值:
  83. "main" → 主图
  84. "other_1" ~ "other_8" → 副图1~8
  85. "swatch" → 变体图
  86. """
  87. encoded_sku = quote(SKU, safe="")
  88. path = f"/listings/2021-08-01/items/{SELLER_ID}/{encoded_sku}"
  89. query = f"marketplaceIds={MARKETPLACE_ID}"
  90. # 根据类型生成 path
  91. if image_type == "main":
  92. attr_path = "/attributes/main_product_image_locator"
  93. elif image_type.startswith("other_") and 1 <= int(image_type.split("_")[1]) <= 8:
  94. n = image_type.split("_")[1]
  95. attr_path = f"/attributes/other_product_image_locator_{n}"
  96. elif image_type == "swatch":
  97. attr_path = "/attributes/swatch_product_image_locator"
  98. else:
  99. raise ValueError(f"不支持的 image_type: {image_type}")
  100. body = {
  101. "productType": "TABLE",
  102. "patches": [
  103. {
  104. "op": "replace",
  105. "path": attr_path,
  106. "value": [
  107. {
  108. "marketplace_id": MARKETPLACE_ID,
  109. "media_location": image_url
  110. }
  111. ]
  112. }
  113. ]
  114. }
  115. return spapi_request("PATCH", path, query, body=body, access_token=access_token)
  116. # ==================== 主程序 ====================
  117. if __name__ == "__main__":
  118. print("🔑 获取 Access Token...")
  119. token = get_access_token()
  120. print("✅ 令牌获取成功")
  121. # 示例:增加/修改副图第3张
  122. new_images = {
  123. "other_1": "https://cunchu.site/temp/cd3a846e-f3b4-4858-a643-e1edc60cbe95.png"
  124. }
  125. for img_type, img_url in new_images.items():
  126. print(f"\n🖼️ 正在设置 {img_type}: {img_url}")
  127. resp = patch_image(token, img_type, img_url)
  128. print(f"📤 状态码: {resp.status_code}")
  129. try:
  130. timestamp = int(time.time())
  131. print(timestamp)
  132. print(json.dumps(resp.json(), indent=2, ensure_ascii=False))
  133. except Exception:
  134. print(resp.text)
  135. if resp.status_code == 200:
  136. print(f"✅ {img_type} 提交成功")
  137. else:
  138. print(f"⚠️ {img_type} 提交失败")