AppleInAppPurchaseSubscriptionObject.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. # @Author : linhaohong
  2. # @File : AppleInAppPurchaseSubscriptionObject.py
  3. # @Time : 2024/9/4 11:58
  4. from appstoreserverlibrary.receipt_utility import ReceiptUtility
  5. from Ansjer.config import CONFIG_INFO, CONFIG_TEST, BASE_DIR, IN_APP_CONFIG
  6. from appstoreserverlibrary.api_client import AppStoreServerAPIClient
  7. from appstoreserverlibrary.models.Environment import Environment
  8. from appstoreserverlibrary.signed_data_verifier import SignedDataVerifier
  9. ENV = Environment.SANDBOX if CONFIG_INFO == CONFIG_TEST else Environment.PRODUCTION
  10. class InAppConfig:
  11. def __init__(self, bundle_id: str):
  12. """
  13. 初始化 AppConfig,加载与指定 bundle_id 对应的配置。
  14. :param bundle_id: 应用的 bundle ID,用于检索相关配置。
  15. """
  16. config = IN_APP_CONFIG.get(bundle_id)
  17. if not config:
  18. raise ValueError(f"没有找到与 bundle_id '{bundle_id}' 对应的配置")
  19. self.key_id = config['key_id']
  20. self.issuer_id = config['issuer_id']
  21. self.key_filename = config['key_filename']
  22. self.cert_names = config['cert_names']
  23. self.app_apple_id = config.get("app_apple_id")
  24. self.environment = ENV
  25. class InAppPurchase:
  26. def __init__(self, bundle_id="com.ansjer.zccloud"):
  27. """
  28. 初始化 InAppSubscription,加载私钥并初始化客户端和解码器。
  29. :param app_config: 包含内购相关配置的 AppConfig 实例。
  30. """
  31. app_config = InAppConfig(bundle_id)
  32. self.bundle_id = bundle_id
  33. self.config = app_config
  34. self.private_key = self._load_private_key(self.config.key_filename)
  35. self.client = self._initialize_client()
  36. self.verifier = self._initialize_verifier()
  37. self.receipt_util = self._initialize_receipt_util()
  38. def _load_private_key(self, key_filename: str) -> bytes:
  39. """
  40. 加载私钥文件并返回其内容。
  41. :param key_filename: 私钥文件的名称。
  42. :return: 返回私钥文件的内容,类型为 bytes。
  43. """
  44. key_path = f'{BASE_DIR}/Ansjer/file/in_app_purchase/{key_filename}'
  45. try:
  46. with open(key_path, 'rb') as file:
  47. return file.read()
  48. except FileNotFoundError:
  49. raise ValueError(f"Private key file not found: {key_path}")
  50. def _initialize_client(self) -> AppStoreServerAPIClient:
  51. """
  52. 初始化 AppStoreServerAPIClient 实例,用于与 App Store 进行通信。
  53. :return: 返回初始化后的 AppStoreServerAPIClient 实例。
  54. """
  55. return AppStoreServerAPIClient(
  56. self.private_key,
  57. self.config.key_id,
  58. self.config.issuer_id,
  59. self.bundle_id,
  60. self.config.environment
  61. )
  62. def _initialize_verifier(self) -> SignedDataVerifier:
  63. """
  64. 初始化 SignedDataVerifier 实例,用于内购验证签名数据。
  65. :return: 返回初始化后的 SignedDataVerifier 实例。
  66. """
  67. root_certificates = [
  68. self._load_certificate(cert_name)
  69. for cert_name in self.config.cert_names
  70. ]
  71. enable_online_checks = True # 根据需要设定在线检查是否启用
  72. app_apple_id = None if CONFIG_INFO == CONFIG_TEST else self.config.app_apple_id
  73. return SignedDataVerifier(
  74. root_certificates,
  75. enable_online_checks,
  76. self.config.environment,
  77. self.bundle_id,
  78. app_apple_id
  79. )
  80. def _load_certificate(self, cert_name: str) -> bytes:
  81. """
  82. 加载指定的根证书文件并返回其内容。
  83. :param cert_name: 根证书文件的名称。
  84. :return: 返回根证书文件的内容,类型为 bytes。
  85. """
  86. cert_path = f'{BASE_DIR}/Ansjer/file/in_app_purchase/{cert_name}'
  87. try:
  88. with open(cert_path, 'rb') as file:
  89. return file.read()
  90. except FileNotFoundError:
  91. raise ValueError(f"Certificate file not found: {cert_path}")
  92. def _initialize_receipt_util(self):
  93. receipt_util = ReceiptUtility()
  94. return receipt_util