Bladeren bron

周期付款 - 用户非首次订阅使用App Store服务器通知续订

linhaohong 1 jaar geleden
bovenliggende
commit
d833032011
1 gewijzigde bestanden met toevoegingen van 149 en 7 verwijderingen
  1. 149 7
      Controller/InAppPurchaseController.py

+ 149 - 7
Controller/InAppPurchaseController.py

@@ -105,17 +105,29 @@ class InAppPurchaseView(View):
 
             signed_transaction_info = transaction_info.signedTransactionInfo
 
-            # 处理一台手机多账号登录订阅情况
             if original_transaction_identifier != "":
                 device_apple_package_qs = DeviceApplePackage.objects.filter(
                     original_transaction_id=original_transaction_identifier)
                 if device_apple_package_qs.exists():
-                    if device_apple_package_qs[0].userID != user_id:
-                        pay_result_url = CommonService.get_payment_status_url(lang, 'fail')
+                    # 第一种情况: 套餐已过期再次订阅
+                    if device_apple_package_qs[0].uid == uid and device_apple_package_qs[0].subscription_status == 2:
+                        # 使用App Store服务器通知接口订阅
+                        pay_result_url = CommonService.get_payment_status_url(lang, 'success')
                         return response.json(0, {'url': pay_result_url})
+
+                    # 第二种情况: 套餐未过期已取消再次订阅
                     elif device_apple_package_qs[0].uid == uid and device_apple_package_qs[0].subscription_status == 3:
-                        device_apple_package_qs.update(subscription_status=1)
-                        pay_result_url = CommonService.get_payment_status_url(lang, 'success')
+                        # 使用App Store服务器通知接口修改订阅状态
+                        pay_result_url = CommonService.get_payment_status_url(lang, 'fail')
+                        return response.json(0, {'url': pay_result_url})
+
+                    # 第三种情况: 首次订阅
+                    elif device_apple_package_qs[0].uid == uid and device_apple_package_qs[0].subscription_status == 0:
+                        logger.info(f"首次订阅直接充值,orderID:{order_id}")
+
+                    else:
+                        logger.info(f"错误调用此借口,orderID:{order_id}, uid:{uid}, 订阅状态:{device_apple_package_qs[0].subscription_status}")
+                        pay_result_url = CommonService.get_payment_status_url(lang, 'fail')
                         return response.json(0, {'url': pay_result_url})
 
             # transaction_id相同的情况 ---- 本次订阅未过期,用户在苹果设置中将订阅重新打开时会传上次订阅相同的 transaction_id。
@@ -470,8 +482,128 @@ class InAppPurchaseView(View):
                     cls.do_vod_msg_notice(uid, user_id, lang, sys_msg_text_list)
 
             elif str(decoded_payload.rawNotificationType) == "SUBSCRIBED":
-                # 处理订阅 ---> 充值逻辑写在了认证交易
-                pass
+                # 处理订阅 ---> 首次充值逻辑写在了认证交易
+                if decoded_payload.rawSubtype == "RESUBSCRIBE":
+                    decoded_transaction_information = verifier.verify_and_decode_signed_transaction(
+                        decoded_payload.data.signedTransactionInfo)
+                    # originalTransactionId 原始购买的交易标识符
+                    original_transaction_id = decoded_transaction_information.originalTransactionId
+                    transaction_id = decoded_transaction_information.transactionId
+                    logger.info(
+                        f"App Store服务器通知originalTransactionId原始购买的交易标识符{original_transaction_id}")
+                    if not original_transaction_id:
+                        logger.info(f"App Store服务器通知originalTransactionId原始购买的交易标识符为空, 返回状态 400")
+                        return HttpResponse(status=400)
+                    else:
+                        ord_order = Order_Model.objects.filter(
+                            original_transaction_id=original_transaction_id).order_by('-addTime').values("channel",
+                                                                                                         "UID",
+                                                                                                         "payType",
+                                                                                                         "userID_id")
+                        channel = ord_order[0]["channel"]
+                        uid = ord_order[0]["UID"]
+                        pay_type = ord_order[0]["payType"]
+                        user_id = ord_order[0]["userID_id"]
+                        # 用产品id找到使用的套餐
+                        product_id = decoded_transaction_information.productId
+                        rank_id = InAppPurchasePackage.objects.filter(product_id=product_id).values("rank")[0]["rank"]
+                        store_qs = Store_Meal.objects.filter(id=rank_id). \
+                            values(
+                            'id', 'currency', 'price', 'lang__content', 'day', 'commodity_type', 'lang__title',
+                            'expire', 'lang__lang',
+                            'commodity_code', 'discount_price', 'bucket_id', 'bucket__mold', 'cycle_config_id', 'is_ai')
+                        if not store_qs.exists():
+                            logger.info(f"App Store服务器通知云存套餐不存在, 返回状态 400")
+                            return HttpResponse(status=400)
+
+                        order_id = CommonService.createOrderID()
+                        rank_id = store_qs[0]['id']
+                        bucket_id = store_qs[0]['bucket_id']
+                        currency = store_qs[0]['currency']
+                        price = store_qs[0]['price']
+                        is_ai = store_qs[0]['is_ai']
+                        expire = store_qs[0]['expire']
+                        end_time = CommonService.calcMonthLater(expire)
+                        content = store_qs[0]['lang__content']
+                        commodity_code = store_qs[0]['commodity_code']
+                        commodity_type = store_qs[0]['commodity_type']
+                        lang = store_qs[0]['lang__lang']
+                        order_type = 1 if is_ai else 0
+
+                        store_meal_qs = Store_Meal.objects.filter(id=rank_id, lang__lang='cn', is_show=0). \
+                            values('lang__title', 'lang__content')
+                        if store_meal_qs.exists():
+                            store_meal_name = store_meal_qs[0]['lang__title'] + '-' + store_meal_qs[0]['lang__content']
+                        else:
+                            store_meal_name = '未知套餐'
+
+                        # 查询设备是否已开过云存
+                        use_flag = True
+                        uid_bucket_qs = UID_Bucket.objects.filter(uid=uid). \
+                            values('id', 'bucket_id', 'bucket__region', 'endTime', 'use_status')
+                        now_time = int(time.time())
+                        if uid_bucket_qs.exists():
+                            uid_bucket = uid_bucket_qs.first()
+                            uid_bucket_id = uid_bucket['id']
+                            # 叠加相同套餐的过期时间
+                            if uid_bucket['use_status'] == 1 and uid_bucket['endTime'] > now_time:
+                                Unused_Uid_Meal.objects.create(
+                                    uid=uid, channel=channel, addTime=now_time, order_id=order_id, expire=expire,
+                                    is_ai=is_ai,
+                                    bucket_id=bucket_id)
+                                UID_Bucket.objects.filter(id=uid_bucket_id).update(has_unused=1)
+                                use_flag = False
+                            # 更新套餐的过期时间
+                            else:
+                                UID_Bucket.objects.filter(id=uid_bucket_id).update(
+                                    channel=channel, bucket_id=bucket_id, endTime=end_time, updateTime=now_time,
+                                    use_status=1,
+                                    orderId=order_id)
+                        else:
+                            uid_bucket = UID_Bucket.objects.create(
+                                uid=uid, channel=channel, bucket_id=bucket_id, endTime=end_time, use_status=1,
+                                orderId=order_id,
+                                addTime=now_time, updateTime=now_time)
+                            uid_bucket_id = uid_bucket.id
+
+                        # 开通AI服务
+                        if is_ai and use_flag:
+                            ai_service = AiService.objects.filter(uid=uid, channel=channel)
+                            # 有正在使用的套餐,叠加套餐时间,否则创建
+                            if ai_service.exists():
+                                ai_service.update(updTime=now_time, use_status=1, orders_id=order_id,
+                                                  endTime=end_time)
+                            else:
+                                AiService.objects.create(
+                                    uid=uid, channel=channel, detect_status=1, use_status=1, orders_id=order_id,
+                                    addTime=now_time, updTime=now_time, endTime=end_time)
+
+                        Order_Model.objects.create(
+                            orderID=order_id, UID=uid, channel=channel, userID_id=user_id, desc=content,
+                            payType=pay_type,
+                            payTime=now_time, price=price, currency=currency, addTime=now_time, updTime=now_time,
+                            order_type=order_type, commodity_code=commodity_code, commodity_type=commodity_type,
+                            rank_id=rank_id,
+                            ai_rank_id=1, status=1, create_vod=1, store_meal_name=store_meal_name,
+                            uid_bucket_id=uid_bucket_id, transaction_id=transaction_id,
+                            original_transaction_id=original_transaction_id
+                        )
+
+                        # 发送云存开通信息
+                        date_time = time.strftime("%Y-%m-%d", time.localtime())
+                        # 如果存在序列号,消息提示用序列号
+                        device_info_qs = Device_Info.objects.filter(UID=uid).values('serial_number', 'Type')
+                        serial_number = device_info_qs[0]['serial_number']
+                        device_type = device_info_qs[0]['Type']
+                        if serial_number:
+                            device_name = CommonService.get_full_serial_number(uid, serial_number, device_type)
+                        else:
+                            device_name = uid
+                        sys_msg_text_list = [
+                            '温馨提示:尊敬的客户,您的{}设备在{}已成功续订云存套餐'.format(device_name, date_time),
+                            'Dear customer,you already subscribed the cloud storage package successfully for device {} on '.
+                            format(device_name, time.strftime('%b %dth,%Y', time.localtime()))]
+                        cls.do_vod_msg_notice(uid, user_id, lang, sys_msg_text_list)
 
             elif str(decoded_payload.rawNotificationType) == "EXPIRED":
                 # 一种通知类型,与其子类型一起表示订阅已过期。如果subtype为
@@ -503,6 +635,16 @@ class InAppPurchaseView(View):
                         DeviceApplePackage.objects.filter(original_transaction_id=original_transaction_id).update(
                             subscription_status=3)
 
+                elif decoded_payload.rawSubtype == "AUTO_RENEW_ENABLED":
+                    # 自动续订被开启
+                    decoded_transaction_information = verifier.verify_and_decode_signed_transaction(
+                        decoded_payload.data.signedTransactionInfo)
+                    original_transaction_id = decoded_transaction_information.originalTransactionId
+                    if original_transaction_id:
+                        DeviceApplePackage.objects.filter(original_transaction_id=original_transaction_id).update(
+                            subscription_status=1)
+
+
             elif str(decoded_payload.rawNotificationType) == "REFUND":
                 # 一种通知类型,表示 App Store 成功退还了消耗性应用内购买、非消耗性应用内购买、自动续订或不可续订的交易。
                 # revocationDate 包含退款交易的时间戳。originalTransactionId 和 productId 用于标识原始交易和产品。revocationReason 包含原因。