


import json, requests
def request_to_product_check_receipt(receipt, num=0, shareSecret=None):
"""
苹果订阅支付验单 for 生产环境验单
"""
num += 1
try:
url = 'https://buy.itunes.apple.com/verifyReceipt'
if shareSecret:
data = json.dumps({"receipt-data": receipt, 'password': shareSecret})
else:
data = json.dumps({"receipt-data": receipt})
headers = {"Content-type": "application/json"}
res = requests.post(url=url, data=data, headers=headers, verify=False).text
json_object = json.loads(res)
if json_object["status"] == 21007:
print("检测到sandbox测试环境支付receipt 测试环境receipt验证--start...")
res = request_to_sandbox_check_receipt(receipt, 0, shareSecret)
return res
except:
res = 'fail'
if num < 4:
res = request_to_product_check_receipt(receipt, num=num, shareSecret=shareSecret)
return res
def request_to_sandbox_check_receipt(receipt, num=0, shareSecret=None):
"""
苹果订阅支付验单 for 测试环境验单
"""
num += 1
try:
url = 'https://sandbox.itunes.apple.com/verifyReceipt'
if shareSecret:
data = json.dumps({"receipt-data": receipt, 'password': shareSecret})
else:
data = json.dumps({"receipt-data": receipt})
headers = {"Content-type": "application/json"}
res = requests.post(url=url, data=data, headers=headers, verify=False).text
return res
except:
res = 'fail'
if num < 4:
res = request_to_sandbox_check_receipt(receipt, num=num, password=shareSecret)
return res
from typing import Optional
def verify_appstore_install_receipt(
receipt_data: str,
expected_bundle_id: str,
share_secret: str = None
) -> Optional[str]:
"""
验证app是否App Store官方安装
调用Apple接口验证App收据,并返回App本身的 receipt.download_id 用于跟业务entity做关联关系。
Args:
receipt_data: 从iOS客户端获取的Base64编码的收据字符串。
expected_bundle_id: 你的App的Bundle Identifier,用于安全校验。
share_secret: (可选) App的共享密钥。对于包含自动续订订阅的App是必需的。
Returns:
如果所有验证成功,则返回 receipt.download_id (字符串)。api接口层面用于跟VPNUser做强关联
在任何失败的情况下(网络错误、验证失败、找不到ID等),都返回 None。
"""
apple_response_str = request_to_product_check_receipt(receipt_data, shareSecret=share_secret)
if not apple_response_str or apple_response_str == 'fail':
print("Failed to get a valid response from Apple's verification server.")
return None
try:
apple_response_json = json.loads(apple_response_str)
except json.JSONDecodeError:
print("Failed to parse JSON from Apple's response.")
return None
if apple_response_json.get("status") != 0:
print(f"Apple verification failed with status: {apple_response_json.get('status')}")
return None
receipt_info = apple_response_json.get("receipt", {})
if receipt_info.get("bundle_id") != expected_bundle_id:
print(f"Bundle ID mismatch. Expected: {expected_bundle_id}, Got: {receipt_info.get('bundle_id')}")
return None
return f'{receipt_info.get("download_id")}'