|
@@ -36,10 +36,12 @@ from Model.models import Order_Model, Store_Meal, Device_Info, UID_Bucket, Unuse
|
|
|
SysMsgModel, OrderPayLog, InAppRefund
|
|
|
from Object.AWS.S3Email import S3Email
|
|
|
from Object.AliSmsObject import AliSmsObject
|
|
|
+from Object.AppleInAppPurchaseSubscriptionObject import InAppPurchase
|
|
|
from Object.RedisObject import RedisObject
|
|
|
from Service.CommonService import CommonService
|
|
|
|
|
|
ENV = Environment.SANDBOX if CONFIG_INFO == CONFIG_TEST else Environment.PRODUCTION
|
|
|
+logger = logging.getLogger('apple_pay')
|
|
|
|
|
|
|
|
|
class InAppPurchaseView(View):
|
|
@@ -77,7 +79,6 @@ class InAppPurchaseView(View):
|
|
|
uid = request_dict.get('uid', None)
|
|
|
lang = request_dict.get('lang', 'en')
|
|
|
channel = request_dict.get('channel', None)
|
|
|
- logger = logging.getLogger('apple_pay')
|
|
|
logger.info(f"receipt: {receipt}, 订单orderId: {order_id}, uid: {uid}")
|
|
|
|
|
|
if not all([receipt, uid, channel, order_id]):
|
|
@@ -287,7 +288,6 @@ class InAppPurchaseView(View):
|
|
|
|
|
|
@classmethod
|
|
|
def app_store_server_notifications(cls, request):
|
|
|
- logger = logging.getLogger('apple_pay')
|
|
|
logger.info('App Store服务器通知请求类型:{}'.format(request.method))
|
|
|
logger.info('App Store服务器通知参数:{}'.format(request.POST))
|
|
|
logger.info('App Store服务器通知请求body:{}'.format(request.body))
|
|
@@ -334,23 +334,27 @@ class InAppPurchaseView(View):
|
|
|
orders_qs.update(status=5, updTime=int(time.time()))
|
|
|
orderID = orders_qs[0].orderID
|
|
|
uid = orders_qs[0].UID
|
|
|
- user_id = orders_qs[0].userID
|
|
|
- # 3. 未使用则删除未使用套餐表,已使用过则删除设备正在使用套餐,并关闭设备云存
|
|
|
- uid_bucket_qs = UID_Bucket.objects.filter(uid=uid, orderId=orderID, use_status=1, endTime__gt=int(time.time()))
|
|
|
+ uid_bucket_qs = UID_Bucket.objects.filter(uid=uid, orderId=orderID, use_status=1,
|
|
|
+ endTime__gt=int(time.time()))
|
|
|
unused_uid_meal_qs = Unused_Uid_Meal.objects.filter(order_id=orderID)
|
|
|
- ai_service_qs = AiService.objects.filter(uid=uid, orders=orderID, use_status=1, endTime__gt=int(time.time()))
|
|
|
+ ai_service_qs = AiService.objects.filter(uid=uid, orders=orderID, use_status=1,
|
|
|
+ endTime__gt=int(time.time()))
|
|
|
if unused_uid_meal_qs.exists():
|
|
|
unused_uid_meal_qs.delete()
|
|
|
if uid_bucket_qs.exists():
|
|
|
- uid_bucket_qs.update(status=0, use_status=2, endTime=int(time.time()), updateTime=int(time.time()))
|
|
|
+ uid_bucket_qs.update(status=0, use_status=2, endTime=int(time.time()),
|
|
|
+ updateTime=int(time.time()))
|
|
|
if ai_service_qs.exists():
|
|
|
- ai_service_qs.update(detect_status=0, use_status=2, endTime=int(time.time()), updTime=int(time.time()))
|
|
|
+ ai_service_qs.update(detect_status=0, use_status=2, endTime=int(time.time()),
|
|
|
+ updTime=int(time.time()))
|
|
|
# 关闭ai
|
|
|
msg = {'commandType': 'AIDisable'}
|
|
|
thing_name = CommonService.query_serial_with_uid(uid) # 存在序列号则为使用序列号作为物品名
|
|
|
topic_name = 'ansjer/generic/{}'.format(thing_name)
|
|
|
req_success = CommonService.req_publish_mqtt_msg(thing_name, topic_name, msg)
|
|
|
- LOGGER.info(f'App Store服务器通知用户退款, 关闭AI:{req_success}')
|
|
|
+ logger.info(f'App Store服务器通知用户退款, 关闭AI:{req_success}')
|
|
|
+ InAppRefund.objects.filter(transaction_id=transaction_id).update(updated_time=int(time.time()),
|
|
|
+ refund_progress=2)
|
|
|
|
|
|
elif CONFIG_INFO == CONFIG_US:
|
|
|
url = "https://api.zositeche.com/inAppPurchase/AppStoreServerNotifications"
|
|
@@ -358,60 +362,98 @@ class InAppPurchaseView(View):
|
|
|
status_code = eur_response.status_code
|
|
|
|
|
|
elif str(decoded_payload.rawNotificationType) == "CONSUMPTION_REQUEST":
|
|
|
- # 从交易信息中获取product_id
|
|
|
- key_path = '{}/Ansjer/file/in_app_purchase/SubscriptionKey_N42WMFCV6A.p8'.format(BASE_DIR)
|
|
|
- with open(key_path, 'rb') as file:
|
|
|
- # 读取文件内容
|
|
|
- private_key = file.read()
|
|
|
-
|
|
|
- key_id = 'N42WMFCV6A'
|
|
|
- issuer_id = '69a6de8c-789b-47e3-e053-5b8c7c11a4d1'
|
|
|
- bundle_id = 'com.ansjer.zccloud'
|
|
|
- environment = ENV
|
|
|
- client = AppStoreServerAPIClient(private_key, key_id, issuer_id, bundle_id, environment)
|
|
|
decoded_transaction_information = verifier.verify_and_decode_signed_transaction(
|
|
|
decoded_payload.data.signedTransactionInfo)
|
|
|
transaction_id = decoded_transaction_information.transactionId
|
|
|
+ app_account_token = decoded_transaction_information.appAccountToken
|
|
|
orders_qs = Order_Model.objects.filter(transaction_id=transaction_id)
|
|
|
if orders_qs.exists():
|
|
|
orderID = orders_qs[0].orderID
|
|
|
- unused_uid_meal_qs = Unused_Uid_Meal.objects.filter(order_id=orderID)
|
|
|
- uid_bucket_qs = UID_Bucket.objects.filter(orderId=orderID, endTime__gt=int(time.time()))
|
|
|
- if unused_uid_meal_qs.exists():
|
|
|
- consumptionStatus = ConsumptionStatus.NOT_CONSUMED
|
|
|
- deliveryStatus = DeliveryStatus.DELIVERED_AND_WORKING_PROPERLY
|
|
|
- elif uid_bucket_qs.exists():
|
|
|
- consumptionStatus = ConsumptionStatus.PARTIALLY_CONSUMED
|
|
|
- deliveryStatus = DeliveryStatus.DELIVERED_AND_WORKING_PROPERLY
|
|
|
- elif UID_Bucket.objects.filter(orderId=orderID, endTime__lt=int(time.time())):
|
|
|
- consumptionStatus = ConsumptionStatus.FULLY_CONSUMED
|
|
|
- deliveryStatus = DeliveryStatus.DELIVERED_AND_WORKING_PROPERLY
|
|
|
- else:
|
|
|
- consumptionStatus = ConsumptionStatus.UNDECLARED
|
|
|
- deliveryStatus = DeliveryStatus.DID_NOT_DELIVER_FOR_OTHER_REASON
|
|
|
- in_app_refund_qs = InAppRefund.objects.filter(transaction_id=transaction_id).exists()
|
|
|
- refundPreference = RefundPreference.PREFER_DECLINE
|
|
|
+ uid = orders_qs[0].UID
|
|
|
+ now_time = int(time.time())
|
|
|
+ put_time = now_time + 11.5 * 60 * 60
|
|
|
+ in_app_refund_qs = InAppRefund.objects.filter(transaction_id=transaction_id)
|
|
|
if in_app_refund_qs.exists():
|
|
|
- if in_app_refund_qs[0].refund_preference == 1:
|
|
|
- refundPreference = RefundPreference.PREFER_GRANT
|
|
|
- consumption_request = ConsumptionRequest(
|
|
|
- customerConsented=True,
|
|
|
- consumptionStatus=consumptionStatus,
|
|
|
- platform=Platform.UNDECLARED,
|
|
|
- sampleContentProvided=True,
|
|
|
- deliveryStatus=deliveryStatus,
|
|
|
- appAccountToken="",
|
|
|
- accountTenure=AccountTenure.UNDECLARED,
|
|
|
- playTime=PlayTime.UNDECLARED,
|
|
|
- lifetimeDollarsRefunded=LifetimeDollarsRefunded.UNDECLARED,
|
|
|
- lifetimeDollarsPurchased=LifetimeDollarsPurchased.UNDECLARED,
|
|
|
- userStatus=UserStatus.ACTIVE,
|
|
|
- refundPreference=refundPreference,
|
|
|
- )
|
|
|
- client.send_consumption_data(transaction_id, consumption_request)
|
|
|
+ in_app_refund_qs.update(refund_progress=0, updated_time=now_time,
|
|
|
+ put_time=put_time, app_account_token=app_account_token)
|
|
|
+ InAppRefund.objects.create(transaction_id=transaction_id, orderID=orderID,
|
|
|
+ uid=uid, app_type=1, created_time=now_time,
|
|
|
+ updated_time=now_time, put_time=put_time,
|
|
|
+ app_account_token=app_account_token)
|
|
|
elif CONFIG_INFO == CONFIG_US:
|
|
|
- url = "https://api.zositeche.com/inAppPurchase/AppStoreServerNotifications"
|
|
|
- eur_response = requests.post(url=url, json=json.loads(request.body))
|
|
|
- status_code = eur_response.status_code
|
|
|
+ url = "https://api.zositeche.com/inAppPurchase/AppStoreServerNotifications"
|
|
|
+ eur_response = requests.post(url=url, json=json.loads(request.body))
|
|
|
+ status_code = eur_response.status_code
|
|
|
+
|
|
|
+ elif str(decoded_payload.rawNotificationType) == "REFUND_DECLINED":
|
|
|
+ decoded_transaction_information = verifier.verify_and_decode_signed_transaction(
|
|
|
+ decoded_payload.data.signedTransactionInfo)
|
|
|
+ transaction_id = decoded_transaction_information.transactionId
|
|
|
+ orders_qs = Order_Model.objects.filter(transaction_id=transaction_id)
|
|
|
+ if orders_qs.exists():
|
|
|
+ InAppRefund.objects.filter(transaction_id=transaction_id).update(refund_progress=3,
|
|
|
+ updated_time=int(time.time()))
|
|
|
+ elif CONFIG_INFO == CONFIG_US:
|
|
|
+ url = "https://api.zositeche.com/inAppPurchase/AppStoreServerNotifications"
|
|
|
+ eur_response = requests.post(url=url, json=json.loads(request.body))
|
|
|
+ status_code = eur_response.status_code
|
|
|
|
|
|
return HttpResponse(status=status_code)
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def put_refund_order():
|
|
|
+ put_time = int(time.time())
|
|
|
+ in_app_refund_qs = InAppRefund.objects.filter(refund_progress=0, put_time__lt=put_time)
|
|
|
+ for in_app_refund in in_app_refund_qs:
|
|
|
+ transaction_id = in_app_refund.transaction_id
|
|
|
+ app_type = in_app_refund.app_type
|
|
|
+ if app_type == 1:
|
|
|
+ bundle_id = "com.ansjer.zccloud"
|
|
|
+ elif app_type == 2:
|
|
|
+ bundle_id = "com.cloudlife.commissionf"
|
|
|
+ else:
|
|
|
+ return HttpResponse(status=200)
|
|
|
+ in_app_purchase_obj = InAppPurchase(bundle_id=bundle_id)
|
|
|
+ # AppStoreServerAPIClient 用于查询交易信息
|
|
|
+ client = in_app_purchase_obj.client
|
|
|
+ orderID = in_app_refund.orderID
|
|
|
+ app_account_token = in_app_refund.app_account_token
|
|
|
+ unused_uid_meal_qs = Unused_Uid_Meal.objects.filter(order_id=orderID)
|
|
|
+ uid_bucket_qs = UID_Bucket.objects.filter(orderId=orderID, endTime__gt=int(time.time()))
|
|
|
+ if unused_uid_meal_qs.exists():
|
|
|
+ consumptionStatus = ConsumptionStatus.NOT_CONSUMED
|
|
|
+ deliveryStatus = DeliveryStatus.DELIVERED_AND_WORKING_PROPERLY
|
|
|
+ elif uid_bucket_qs.exists():
|
|
|
+ consumptionStatus = ConsumptionStatus.PARTIALLY_CONSUMED
|
|
|
+ deliveryStatus = DeliveryStatus.DELIVERED_AND_WORKING_PROPERLY
|
|
|
+ elif UID_Bucket.objects.filter(orderId=orderID, endTime__lt=int(time.time())):
|
|
|
+ consumptionStatus = ConsumptionStatus.FULLY_CONSUMED
|
|
|
+ deliveryStatus = DeliveryStatus.DELIVERED_AND_WORKING_PROPERLY
|
|
|
+ else:
|
|
|
+ consumptionStatus = ConsumptionStatus.UNDECLARED
|
|
|
+ deliveryStatus = DeliveryStatus.DID_NOT_DELIVER_FOR_OTHER_REASON
|
|
|
+
|
|
|
+ if in_app_refund.refund_preference == 1:
|
|
|
+ refundPreference = RefundPreference.PREFER_GRANT
|
|
|
+ else:
|
|
|
+ refundPreference = RefundPreference.PREFER_DECLINE
|
|
|
+
|
|
|
+ consumption_request = ConsumptionRequest(
|
|
|
+ customerConsented=True,
|
|
|
+ consumptionStatus=consumptionStatus,
|
|
|
+ platform=Platform.UNDECLARED,
|
|
|
+ sampleContentProvided=True,
|
|
|
+ deliveryStatus=deliveryStatus,
|
|
|
+ appAccountToken=app_account_token,
|
|
|
+ accountTenure=AccountTenure.UNDECLARED,
|
|
|
+ playTime=PlayTime.UNDECLARED,
|
|
|
+ lifetimeDollarsRefunded=LifetimeDollarsRefunded.UNDECLARED,
|
|
|
+ lifetimeDollarsPurchased=LifetimeDollarsPurchased.UNDECLARED,
|
|
|
+ userStatus=UserStatus.ACTIVE,
|
|
|
+ refundPreference=refundPreference,
|
|
|
+ )
|
|
|
+ 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.save()
|
|
|
+ return HttpResponse(status=200)
|