Преглед изворни кода

内购同步正式服代码

linhaohong пре 8 месеци
родитељ
комит
e5f4f8eba4
2 измењених фајлова са 33 додато и 27 уклоњено
  1. 26 23
      Controller/InAppPurchaseController.py
  2. 7 4
      Object/AppleInAppPurchaseSubscriptionObject.py

+ 26 - 23
Controller/InAppPurchaseController.py

@@ -8,7 +8,7 @@ import threading
 
 import requests
 from appstoreserverlibrary.models.Environment import Environment
-from appstoreserverlibrary.api_client import AppStoreServerAPIClient, GetTransactionHistoryVersion
+from appstoreserverlibrary.api_client import AppStoreServerAPIClient, GetTransactionHistoryVersion, APIException
 from appstoreserverlibrary.models.AccountTenure import AccountTenure
 from appstoreserverlibrary.models.ConsumptionRequest import ConsumptionRequest
 from appstoreserverlibrary.models.ConsumptionStatus import ConsumptionStatus
@@ -145,7 +145,8 @@ class InAppPurchaseView(View):
                 logger.info(f"苹果内购认证交易订单orderID:{order_id}, 没有transaction_id")
                 pay_result_url = CommonService.get_payment_status_url(lang, 'fail')
                 return response.json(0, {'url': pay_result_url})
-            logger.info(f"苹果内购认证交易订单orderID:{order_id}, transaction_id:{transaction_id}, 时间戳: {int(time.time())}")
+            logger.info(
+                f"苹果内购认证交易订单orderID:{order_id}, transaction_id:{transaction_id}, 时间戳: {int(time.time())}")
 
             OrderPayLog.objects.create(order_id=order_id, order_no=transaction_id,
                                        business_name=f"内购验单",
@@ -153,22 +154,15 @@ class InAppPurchaseView(View):
                                        access_result="SUCCESS")
 
             # 查询交易信息
-            transaction_info = ""
-            attempts = 0
-            while attempts < 6:
-                try:
-                    transaction_info = client.get_transaction_info(transaction_id)
-                    break
-                except ConnectionError as err:
-                    attempts += 1
-                    if attempts == 5:
-                        OrderPayLog.objects.create(order_id=order_id, order_no=transaction_id,
-                                                   business_name=f"{order_id}获取transactionInfo超时",
-                                                   created_time=int(time.time()), updated_time=int(time.time()),
-                                                   access_result="ERROR")
-                        return response.json(5)
-                    logger.info(
-                        f"订单orderId:{order_id}, transaction_id:{transaction_id}, 第{attempts}次获取支付信息超时")
+            try:
+                transaction_info = client.get_transaction_info(transaction_id)
+            except APIException:
+                in_app_purchase = InAppPurchase(bundle_id=bundle_id, user_id=user_id)
+                # AppStoreServerAPIClient 用于查询交易信息
+                client = in_app_purchase.client
+                # SignedDataVerifier 用于解析查询到的交易信息
+                signed_data_verifier = in_app_purchase.verifier
+                transaction_info = client.get_transaction_info(transaction_id)
 
             signed_transaction_info = transaction_info.signedTransactionInfo
             # 解析交易信息
@@ -241,7 +235,6 @@ class InAppPurchaseView(View):
                 redis_obj.del_data(key_coupon)
                 CouponModel.objects.filter(id=c_id).update(use_status=2, update_time=now_time)
 
-
             # 修改订阅状态
             if payload.rawType == "Auto-Renewable Subscription":
                 original_transaction_id = payload.originalTransactionId
@@ -278,8 +271,11 @@ class InAppPurchaseView(View):
             return response.json(0, {'url': pay_result_url})
         except Exception as e:
             redis_obj.del_data(redis_key)
-            LOGGER.info('苹果内购认证交易接口异常:{}'.
+            logger.info('苹果内购认证交易接口异常:{}'.
                         format('error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e))))
+            OrderPayLog.objects.create(order_id=order_id, business_name=f"内购验单异常",
+                                       created_time=int(time.time()), updated_time=int(time.time()),
+                                       access_result="ERROR")
             pay_result_url = CommonService.get_payment_status_url(lang, 'fail')
             return response.json(0, {'url': pay_result_url})
 
@@ -566,7 +562,8 @@ class InAppPurchaseView(View):
                     # 查旧订单消息
                     ord_order_qs = Order_Model.objects.filter(original_transaction_id=original_transaction_id)
                     if not ord_order_qs.exists():
-                        logger.info(f"App Store服务器通知未查询到旧订单信息, originalTransactionId:{original_transaction_id}, 返回状态 400")
+                        logger.info(
+                            f"App Store服务器通知未查询到旧订单信息, originalTransactionId:{original_transaction_id}, 返回状态 400")
                         return HttpResponse(status=400)
 
                     # 解决云存充值成功, 由于一些原因返回500 导致苹果未扣款的问题
@@ -752,7 +749,7 @@ class InAppPurchaseView(View):
                                                                                  refund_progress=2)
                 return HttpResponse(status=200)
 
-            elif str(decoded_payload.rawNotificationType) == "REFUND_DECLINED":
+            elif str(decoded_payload.rawNotificationType) == "REFUND_REVERSED":
                 # 一种通知类型,表示 App Store 由于客户提出的争议而撤销了先前批准的退款。如果您的应用程序因相关退款而撤销了内容或服务,则需要恢复这些内容或服务。
                 # 此通知类型可适用于任何应用程序内购买类型:消耗品、非消耗品、不可续订订阅和自动续订订阅。对于自动续订,当 App Store 撤销退款时,续订日期保持不变。
                 decoded_transaction_information = signed_data_verifier.verify_and_decode_signed_transaction(
@@ -760,6 +757,7 @@ class InAppPurchaseView(View):
                 transaction_id = decoded_transaction_information.transactionId
                 logger.info(
                     'App Store服务器通知,撤销了批准的退款,不恢复套餐,手动处理 transaction_id:{}'.format(transaction_id))
+                return HttpResponse(status=200)
 
             elif str(decoded_payload.rawNotificationType) == "REFUND_DECLINED":
                 decoded_transaction_information = signed_data_verifier.verify_and_decode_signed_transaction(
@@ -768,7 +766,10 @@ class InAppPurchaseView(View):
                 orders_qs = Order_Model.objects.filter(transaction_id=transaction_id)
                 if not orders_qs.exists():
                     return HttpResponse(status=400)
-                InAppRefund.objects.filter(transaction_id=transaction_id).update(refund_progress=3, updated_time=int(time.time()))
+                logger.info(
+                    'App Store服务器通知, 不批准退款, transaction_id:{}'.format(transaction_id))
+                InAppRefund.objects.filter(transaction_id=transaction_id).update(refund_progress=3,
+                                                                                 updated_time=int(time.time()))
 
             else:
                 logger.info(f"App Store服务器通知decoded_payload.rawNotificationType 未处理")
@@ -936,5 +937,7 @@ class InAppPurchaseView(View):
             client.send_consumption_data(transaction_id, consumption_request)
             logger.info(f'内购退款消费数据提交, 订单orderID:{orderID}, transaction_id:{transaction_id}')
             in_app_refund.refund_progress = 1
+            in_app_refund.updated_time = int(time.time())
+            in_app_refund.put_time = int(time.time())
             in_app_refund.save()
         return HttpResponse(status=200)

+ 7 - 4
Object/AppleInAppPurchaseSubscriptionObject.py

@@ -14,7 +14,7 @@ ENV = Environment.SANDBOX if CONFIG_INFO == CONFIG_TEST else Environment.PRODUCT
 
 
 class InAppConfig:
-    def __init__(self, bundle_id: str):
+    def __init__(self, bundle_id: str, user_id=""):
         """
        初始化 AppConfig,加载与指定 bundle_id 对应的配置。
        :param bundle_id: 应用的 bundle ID,用于检索相关配置。
@@ -27,16 +27,19 @@ class InAppConfig:
         self.key_filename = config['key_filename']
         self.cert_names = config['cert_names']
         self.app_apple_id = config.get("app_apple_id")
-        self.environment = ENV
+        if user_id == "167083887153913800138000":
+            self.environment = Environment.SANDBOX
+        else:
+            self.environment = ENV
 
 
 class InAppPurchase:
-    def __init__(self, bundle_id="com.ansjer.zccloud"):
+    def __init__(self, bundle_id="com.ansjer.zccloud", user_id=""):
         """
         初始化 InAppSubscription,加载私钥并初始化客户端和解码器。
         :param app_config: 包含内购相关配置的 AppConfig 实例。
         """
-        app_config = InAppConfig(bundle_id)
+        app_config = InAppConfig(bundle_id, user_id)
         self.bundle_id = bundle_id
         self.config = app_config
         self.private_key = self._load_private_key(self.config.key_filename)