| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744 | 
							- import datetime as date_time
 
- import json
 
- import logging
 
- import time
 
- import traceback
 
- import paypalrestsdk
 
- from django.db import transaction
 
- from django.db.models import Q, F
 
- from django.http import HttpResponseRedirect, HttpResponse
 
- from django.views.generic.base import View
 
- from Ansjer.config import PAYPAL_CRD, SERVER_DOMAIN_SSL, PAYPAL_WEB_HOOK_ID, PAYPAL_WEB_HOOK_ID_TWO, CONFIG_INFO, \
 
-     CONFIG_US, CONFIG_EUR
 
- from Controller import CloudStorage
 
- from Model.models import PayCycleConfigModel, Store_Meal, UID_Bucket, PromotionRuleModel, \
 
-     Unused_Uid_Meal, Device_Info, CouponModel, Order_Model, PaypalWebHookEvent, CountryModel, AiService
 
- from Object.ResponseObject import ResponseObject
 
- from Object.TokenObject import TokenObject
 
- from Service.CommonService import CommonService
 
- PAY_LOGGER = logging.getLogger('pay')
 
- # 周期扣款相关
 
- class Paypal:
 
-     # 检查是否有重复订阅
 
-     def checkSubscriptions(userID, uid, rank):
 
-         hasOrder = Order_Model.objects.filter(UID=uid)
 
-         hasOrder = hasOrder.filter(~Q(agreement_id='')).values('agreement_id', 'orderID').order_by('-addTime')[0:1]
 
-         if not hasOrder.exists():
 
-             return True
 
-         paypalrestsdk.configure(PAYPAL_CRD)
 
-         billing_agreement = paypalrestsdk.BillingAgreement.find(hasOrder[0]['agreement_id'])
 
-         if billing_agreement.state == 'Active':
 
-             return False
 
-         return True
 
-     def subscriptions(store_info, lang, orderID, price):
 
-         logger = logging.getLogger('pay')
 
-         cycle_config = PayCycleConfigModel.objects.filter(id=store_info['cycle_config_id']).values()
 
-         if not cycle_config:
 
-             logger.info('----创建订阅失败----')
 
-             logger.info('订阅配置失败')
 
-             return False
 
-         cal_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-         if lang != 'cn':
 
-             cal_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-         return_url = "{SERVER_DOMAIN_SSL}payCycle/paypalCycleReturn?lang={lang}". \
 
-             format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL, lang=lang)
 
-         # call_sub_url = "http://binbin.uicp.vip/cloudstorage/dopaypalcallback?orderID={orderID}".format(
 
-         # SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL, orderID=orderID)
 
-         # exit(price)
 
-         BillingPlan = {
 
-             "description": orderID,
 
-             "merchant_preferences": {
 
-                 "auto_bill_amount": "YES",
 
-                 "cancel_url": cal_url,  # 取消协议url
 
-                 "initial_fail_amount_action": "CANCEL",
 
-                 "max_fail_attempts": "1",  # 允许的最大失败付款尝试次数
 
-                 "return_url": return_url,  # 客户批准协议的url
 
-                 # "notify_url": "http://www.notify.com",  #通知客户协议已创建的 URL。只读并保留供将来使用。
 
-                 "setup_fee": {
 
-                     "currency": store_info['currency'],
 
-                     "value": price,
 
-                 }
 
-             },
 
-             "name": store_info['lang__content'],
 
-             "payment_definitions": [
 
-                 {
 
-                     "amount": {
 
-                         "currency": store_info['currency'],
 
-                         "value": store_info['price']
 
-                     },
 
-                     # "charge_models": [
 
-                     #     {
 
-                     #         "amount": {
 
-                     #             "currency": "USD",
 
-                     #             "value": "20"
 
-                     #         },
 
-                     #         "type": "TAX"   #税金
 
-                     #     }
 
-                     # ],
 
-                     "cycles": cycle_config[0]['cycles'],
 
-                     "frequency": cycle_config[0]['frequency'],
 
-                     "frequency_interval": cycle_config[0]['frequencyInterval'],
 
-                     "name": store_info['lang__title'],
 
-                     "type": "REGULAR"
 
-                 },
 
-             ],
 
-             "type": "INFINITE",
 
-         }
 
-         paypalrestsdk.configure(PAYPAL_CRD)
 
-         billing_plan = paypalrestsdk.BillingPlan(BillingPlan)
 
-         if billing_plan.create():
 
-             billing_plan.activate()  # 激活
 
-             plan_id = billing_plan.id
 
-         else:
 
-             logger.info('----创建计划失败----')
 
-             logger.info(billing_plan.error)
 
-             return False
 
-         now_time = int(time.time())
 
-         if cycle_config[0]['frequency'] == "DAY":
 
-             start_date_timestamp = now_time + 86400 - 3600  # 下次扣款为明天,提前1个小时扣款
 
-             start_date_str = CommonService.timestamp_to_str(start_date_timestamp, "%Y-%m-%dT%H:%M:%SZ")
 
-         elif cycle_config[0]['frequency'] == "MONTH":
 
-             start_date_timestamp = CommonService.calcMonthLater(1, now_time) - (5 * 86400)  # 下次扣款为下个月提前5天扣款
 
-             start_date_str = CommonService.timestamp_to_str(start_date_timestamp, "%Y-%m-%dT%H:%M:%SZ")
 
-         # 订阅
 
-         billingAgreement = {
 
-             "name": store_info['lang__content'],
 
-             "description": orderID,
 
-             "start_date": start_date_str,
 
-             "plan": {
 
-                 "id": plan_id
 
-             },
 
-             "payer": {
 
-                 "payment_method": "paypal"
 
-             },
 
-         }
 
-         billing_agreement = paypalrestsdk.BillingAgreement(billingAgreement)
 
-         # print(billing_agreement.create())
 
-         if billing_agreement.create():
 
-             for link in billing_agreement.links:
 
-                 if link.rel == "approval_url":
 
-                     return {"plan_id": plan_id, "url": link.href}
 
-         else:
 
-             logger.info('----创建订阅失败----')
 
-             logger.info(billing_agreement.error)
 
-             return False
 
- class PaypalCycleNotify(View):
 
-     def get(self, request, *args, **kwargs):
 
-         request.encoding = 'utf-8'
 
-         operation = kwargs.get('operation')
 
-         return self.validation(request.GET, request, operation)
 
-     def post(self, request, *args, **kwargs):
 
-         request.encoding = 'utf-8'
 
-         operation = kwargs.get('operation')
 
-         return self.validation(request.POST, request, operation)
 
-     def validation(self, request_dict, request, operation):
 
-         response = ResponseObject()
 
-         if operation is None:
 
-             return response.json(444, 'error path')
 
-         elif operation == 'paypalCycleReturn':  # paypal成功订阅回调
 
-             return self.do_paypal_cycle_return(request_dict, response)
 
-         elif operation == 'paypalCycleNotify':  # paypal 周期付款回调
 
-             return self.do_paypal_webhook_notify(request_dict, request, response)
 
-         elif operation == 'subscriptionBreakNotify':  # paypal 订阅相关回调
 
-             return self.do_subscription_break_notify(request_dict, request, response)
 
-     def do_paypal_cycle_return(self, request_dict, response):
 
-         lang = request_dict.get('lang', 'en')
 
-         token = request_dict.get('token', None)
 
-         logger = logging.getLogger('pay')
 
-         logger.info('--------进入paypay首次订阅付款回调--------')
 
-         logger.info(request_dict)
 
-         paypalrestsdk.configure(PAYPAL_CRD)
 
-         billing_agreement = paypalrestsdk.BillingAgreement()
 
-         billing_agreement_response = billing_agreement.execute(token)
 
-         if billing_agreement_response.error:
 
-             logger.info('----付款失败----')
 
-             logger.info(billing_agreement_response.error)
 
-             red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             if lang != 'cn':
 
-                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             return HttpResponseRedirect(red_url)
 
-         orderID = billing_agreement_response.description
 
-         state = billing_agreement_response.state
 
-         nowTime = int(time.time())
 
-         promotion_rule_id = ''
 
-         logger.info('----订阅详情----')
 
-         logger.info(billing_agreement_response)
 
-         agreement_id = billing_agreement_response.id
 
-         order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
 
-         order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
 
-                                      "userID__userID",
 
-                                      "userID__username", 'coupon_id')
 
-         if not orderID:
 
-             logger.info('----订阅订单号失效----')
 
-             red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             if lang != 'cn':
 
-                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             return HttpResponseRedirect(red_url)
 
-         UID = order_list[0]['UID']
 
-         if state != 'Active':
 
-             order_qs.update(status=2, promotion_rule_id=promotion_rule_id)
 
-             logger.info('----UID:{UID},用户名:{last_time} {first_time}首次订阅付款失败----'.format
 
-                         (UID=UID,
 
-                          last_time=billing_agreement_response.payer.payer_info.last_name,
 
-                          first_time=billing_agreement_response.payer.payer_info.first_time,
 
-                          ))
 
-             logger.info('billing_agreement_state')
 
-             logger.info(state)
 
-             red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             if lang != 'cn':
 
-                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             return HttpResponseRedirect(red_url)
 
-         try:
 
-             userid = order_list[0]['userID__userID']
 
-             username = order_list[0]['userID__username']
 
-             channel = order_list[0]['channel']
 
-             rank = order_list[0]['rank']
 
-             smqs = Store_Meal.objects.filter(id=rank).values("day", "bucket_id", "bucket__storeDay", "expire", "is_ai")
 
-             bucketId = smqs[0]['bucket_id']
 
-             if not smqs.exists():
 
-                 logger.info('----订阅套餐失效----')
 
-                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-                 if lang != 'cn':
 
-                     red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-                 return HttpResponseRedirect(red_url)
 
-             # ##
 
-             ubqs = UID_Bucket.objects.filter(uid=UID).values("id", "bucket_id", "bucket__storeDay", "bucket__region",
 
-                                                              "endTime", "use_status")
 
-             expire = smqs[0]['expire']
 
-             is_ai = smqs[0]['is_ai']
 
-             if order_list[0]['isSelectDiscounts'] == 1:
 
-                 expire = smqs[0]['expire'] * 2
 
-             # 是否有促销
 
-             promotion = PromotionRuleModel.objects.filter(status=1, startTime__lte=nowTime,
 
-                                                           endTime__gte=nowTime).values('id', 'ruleConfig')
 
-             if promotion.exists():
 
-                 promotion_rule_id = promotion[0]['id']
 
-                 expire = expire * 2
 
-             endTime = CommonService.calcMonthLater(expire)
 
-             use_flag = True
 
-             with transaction.atomic():
 
-                 if ubqs.exists():
 
-                     ubq = ubqs[0]
 
-                     uid_bucket_id = ubq['id']
 
-                     if ubq['use_status'] == 1 and ubq['endTime'] > nowTime:  # 套餐使用中并且未过期,加入未使用的关联套餐表
 
-                         Unused_Uid_Meal.objects.create(uid=UID, channel=channel, addTime=nowTime, is_ai=is_ai,
 
-                                                        order_id=orderID, expire=expire, bucket_id=bucketId)
 
-                         update_status = UID_Bucket.objects.filter(id=uid_bucket_id).update(has_unused=1)
 
-                         use_flag = False
 
-                     else:  # 云存服务已过期则重新开通云存服务
 
-                         update_status = UID_Bucket.objects.filter(id=uid_bucket_id).update(uid=UID, channel=channel,
 
-                                                                                            bucket_id=bucketId,
 
-                                                                                            endTime=endTime,
 
-                                                                                            updateTime=nowTime,
 
-                                                                                            use_status=1)
 
-                 else:
 
-                     ub_cqs = UID_Bucket.objects.create \
 
-                         (uid=UID, channel=channel, bucket_id=bucketId, endTime=endTime, addTime=nowTime,
 
-                          updateTime=nowTime, use_status=1)
 
-                     update_status = True
 
-                     uid_bucket_id = ub_cqs.id
 
-                 dvq = Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster='')
 
-                 if dvq.exists():
 
-                     dvq_set_update_dict = {
 
-                         'vodPrimaryUserID': userid,
 
-                         'vodPrimaryMaster': username
 
-                     }
 
-                     dvq.update(**dvq_set_update_dict)
 
-                 # 开通AI服务
 
-                 if is_ai and use_flag:
 
-                     ai_service = AiService.objects.filter(uid=UID, channel=channel)
 
-                     if ai_service.exists():  # 有正在使用的套餐,套餐结束时间保存为套餐有效期
 
-                         ai_service.update(updTime=nowTime, use_status=1, orders_id=orderID, endTime=endTime)
 
-                     else:
 
-                         AiService.objects.create(uid=UID, channel=channel, detect_status=1, addTime=nowTime,
 
-                                                  updTime=nowTime, endTime=endTime, use_status=1, orders_id=orderID)
 
-                 # uid_main_exist = UIDMainUser.objects.filter(UID=UID)
 
-                 # if not uid_main_exist.exists():
 
-                 #     uid_main_dict = {
 
-                 #         'UID': UID,
 
-                 #         'user_id': userid
 
-                 #     }
 
-                 #     UIDMainUser.objects.create(**uid_main_dict)
 
-                 # 核销coupon
 
-                 if order_list[0]['coupon_id']:
 
-                     CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=2, update_time=nowTime)
 
-                 logger.info(
 
-                     'uid:{},uid_bucket_id:{},update_status:{},order_id:{}'.format(UID, uid_bucket_id, update_status,
 
-                                                                                   orderID))
 
-                 order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id,
 
-                                 promotion_rule_id=promotion_rule_id, agreement_id=agreement_id)
 
-                 # 如果存在序列号,消息提示用序列号
 
-                 device_name = CommonService.query_serial_with_uid(uid=UID)
 
-                 datetime = time.strftime("%Y-%m-%d", time.localtime())
 
-                 sys_msg_text_list = [
 
-                     '温馨提示:尊敬的客户,您的' + device_name + '设备在' + datetime + '已成功订阅云存套餐',
 
-                     'Dear customer,you already subscribed the cloud storage package successfully for device ' + device_name + ' on ' + time.strftime(
 
-                         "%b %dth,%Y", time.localtime())]
 
-                 CloudStorage.CloudStorageView().do_vod_msg_notice(UID, channel, userid, lang, sys_msg_text_list,
 
-                                                                   'SMS_219738485')
 
-                 # return response.json(0)
 
-                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/success.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-                 if lang != 'cn':
 
-                     red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_success.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-                 logger.info('{UID}成功开通paypal自动续费:----'.format(UID=UID))
 
-                 return HttpResponseRedirect(red_url)
 
-         except Exception as e:
 
-             print(repr(e))
 
-             logger.info('do_paypal_cycle_return支付失败:----')
 
-             logger.info('{UID}开通paypal自动续费失败'.format(UID=UID))
 
-             logger.info("错误行数:{errLine}".format(errLine=e.__traceback__.tb_lineno))
 
-             logger.info(repr(e))
 
-             if order_qs:
 
-                 order_qs.update(status=10, promotion_rule_id=promotion_rule_id)
 
-             red_url = "{SERVER_DOMAIN_SSL}web/paid2/fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             if lang != 'cn':
 
-                 red_url = "{SERVER_DOMAIN_SSL}web/paid2/en_fail.html".format(SERVER_DOMAIN_SSL=SERVER_DOMAIN_SSL)
 
-             return HttpResponseRedirect(red_url)
 
-     def do_paypal_webhook_notify(self, request_dict, request, response):
 
-         PAY_LOGGER.info('--------进入周期扣款钩子--------')
 
-         if not request.body:
 
-             PAY_LOGGER.info('PayPal周期扣款失败---缺失请求体')
 
-             return HttpResponse('fail', status=500)
 
-         json_agreement_str = request.body.decode("utf-8")
 
-         json_obj = json.loads(json_agreement_str)
 
-         header = request.META
 
-         paypal_body = json_obj.get('resource')
 
-         PAY_LOGGER.info('----请求体数据:{}----'.format(json_agreement_str))
 
-         PAY_LOGGER.info('----请求头数据:{}----'.format(header))
 
-         try:
 
-             transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID', None)
 
-             transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME', None)
 
-             cert_url = header.get('HTTP_PAYPAL_CERT_URL', None)
 
-             transmission_sig = header.get('HTTP_PAYPAL_TRANSMISSION_SIG', None)
 
-             auth_algo = header.get('HTTP_PAYPAL_AUTH_ALGO', None)
 
-             event_type = json_obj.get('event_type')
 
-             summary = json_obj.get('summary')
 
-             resource_type = json_obj.get('resource_type')
 
-             billing_agreement_id = paypal_body.get('billing_agreement_id')
 
-             paypal_transaction_id = paypal_body.get('id')
 
-             amount = paypal_body.get('amount')
 
-             PaypalWebHookEventInsert = {
 
-                 'webhook_event_id': json_obj.get('id'),
 
-                 'resource_type': json_obj.get('resource_type'),
 
-                 'event_type': 1,
 
-                 'summary': summary,
 
-                 'trade_no': paypal_transaction_id,
 
-                 'resource': json_agreement_str,
 
-                 'created_time': int(time.time()),
 
-             }
 
-             if event_type != 'PAYMENT.SALE.COMPLETED':
 
-                 PAY_LOGGER.info('----event_type异常:{}----'.format(event_type))
 
-             if resource_type == 'sale' and paypal_body.get('state') == 'completed':
 
-                 paypalrestsdk.configure(PAYPAL_CRD)
 
-                 response = paypalrestsdk.WebhookEvent.verify(
 
-                     transmission_id, transmission_time, PAYPAL_WEB_HOOK_ID, json_agreement_str, cert_url,
 
-                     transmission_sig, auth_algo)
 
-                 if not response:
 
-                     PAY_LOGGER.info('PayPal周期扣款失败---签名验证失败')
 
-                     return HttpResponse('Fail', status=500)
 
-             else:
 
-                 PAY_LOGGER.info('PayPal周期扣款失败,付款状态有误,resource_type:{},state:{}----'.
 
-                                 format(resource_type, paypal_body.get('state')))
 
-                 return HttpResponse('Fail', status=500)
 
-             nowTime = int(time.time())
 
-             if not billing_agreement_id:
 
-                 # 记录钩子日志
 
-                 PaypalWebHookEvent.objects.create(**PaypalWebHookEventInsert)
 
-                 # 普通支付,更新paypal交易id
 
-                 paymentID = paypal_body.get('parent_payment')
 
-                 if paymentID and paypal_transaction_id:
 
-                     # 查询客户地区信息,地区跟服务器配置不匹配,返回500
 
-                     order_qs = Order_Model.objects.filter(paymentID=paymentID).values('UID', 'userID__region_country')
 
-                     if not order_qs.exists():
 
-                         PAY_LOGGER.info('PayPal周期扣款失败---根据paymentID查询订单数据不存在')
 
-                         return HttpResponse('Fail', status=500)
 
-                     # 更新PayPal交易号
 
-                     order_qs.update(trade_no=paypal_transaction_id)
 
-                     # 判断用户地区是否跟服务器地区匹配
 
-                     uid = order_qs[0]['UID']
 
-                     country_id = order_qs[0]['userID__region_country']
 
-                     if not self.config_match_region(uid, country_id):
 
-                         return HttpResponse('Fail', status=500)
 
-                     order_qs.update(status=1, updTime=nowTime)
 
-                     PAY_LOGGER.info('PayPal周期扣款成功---更新交易id:{}'.format(paypal_transaction_id))
 
-                     return HttpResponse('success')
 
-                 else:
 
-                     PAY_LOGGER.info('PayPal周期扣款失败---paymentID:{}或paypal_transaction_id:{}为空'.
 
-                                     format(paymentID, paypal_transaction_id))
 
-                     return HttpResponse('fail', status=500)
 
-             agreement_id = paypal_body.get('billing_agreement_id')
 
-             billing_agreement = paypalrestsdk.BillingAgreement.find(agreement_id)
 
-             PAY_LOGGER.info('billing_agreement:{}'.format(billing_agreement))
 
-             # 记录钩子日志
 
-             PaypalWebHookEventInsert['agreement_desc'] = repr(billing_agreement)
 
-             PaypalWebHookEventInsert['agreement_id'] = agreement_id
 
-             PaypalWebHookEventInsert['orderID'] = billing_agreement.description
 
-             paypal_webhook_event_qs = PaypalWebHookEvent.objects.create(**PaypalWebHookEventInsert)
 
-             # 查询订单数据
 
-             order_id = billing_agreement.description
 
-             order_qs = Order_Model.objects.filter(orderID=order_id).values('UID', 'channel', 'commodity_code', 'rank',
 
-                                                                            'isSelectDiscounts', 'plan_id', 'desc',
 
-                                                                            'payType', 'currency', 'addTime',
 
-                                                                            'commodity_type', 'updTime', 'order_type',
 
-                                                                            'userID__userID', 'uid_bucket_id',
 
-                                                                            'userID__username', 'userID__region_country'
 
-                                                                            )
 
-             if not order_qs.exists():
 
-                 PAY_LOGGER.info('PayPal周期扣款失败---根据order_id查询订单数据不存在')
 
-                 return HttpResponse('fail', status=500)
 
-             # 判断用户地区是否跟服务器地区匹配
 
-             uid = order_qs[0]['UID']
 
-             country_id = order_qs[0]['userID__region_country']
 
-             if not self.config_match_region(uid, country_id):
 
-                 return HttpResponse('Fail', status=500)
 
-             UID = order_qs[0]['UID']
 
-             # PayPal周期扣款首次扣款
 
-             if billing_agreement.agreement_details.cycles_completed == '0':
 
-                 order_qs.update(status=1, trade_no=paypal_transaction_id, updTime=nowTime)
 
-                 PAY_LOGGER.info('{} PayPal周期扣款首次扣款成功'.format(UID))
 
-                 return HttpResponse('success')
 
-             if order_qs[0]['addTime'] + 9200 > nowTime:  # 避免续费订单重复支付
 
-                 PAY_LOGGER.info('{} PayPal周期扣款失败---续费订单已创建'.format(UID))
 
-                 return HttpResponse('success')
 
-             desc = order_qs[0]['desc']
 
-             pay_type = order_qs[0]['payType']
 
-             currency = order_qs[0]['currency']
 
-             commodity_code = order_qs[0]['commodity_code']
 
-             commodity_type = order_qs[0]['commodity_type']
 
-             plan_id = order_qs[0]['plan_id']
 
-             userid = order_qs[0]['userID__userID']
 
-             username = order_qs[0]['userID__username']
 
-             channel = order_qs[0]['channel']
 
-             rank = order_qs[0]['rank']
 
-             order_type = order_qs[0]['order_type']
 
-             store_meal_qs = Store_Meal.objects.filter(id=rank).values("day", "bucket_id", "bucket__storeDay", "expire",
 
-                                                                       "is_ai")
 
-             if not store_meal_qs.exists():
 
-                 PAY_LOGGER.info('{} PayPal周期扣款失败---套餐数据不存在'.format(UID))
 
-                 return HttpResponse('fail', status=500)
 
-             bucketId = store_meal_qs[0]['bucket_id']
 
-             expire = store_meal_qs[0]['expire']
 
-             is_ai = store_meal_qs[0]['is_ai']
 
-             endTime = CommonService.calcMonthLater(expire)
 
-             use_flag = True
 
-             orderID = CommonService.createOrderID()
 
-             ubqs = UID_Bucket.objects.filter(uid=UID).values("id", "bucket_id", "bucket__storeDay", "bucket__region",
 
-                                                              "endTime", "use_status")
 
-             with transaction.atomic():
 
-                 if ubqs.exists():
 
-                     ubq = ubqs[0]
 
-                     uid_bucket_id = ubq['id']
 
-                     if ubq['use_status'] == 1 and ubq['endTime'] > nowTime:  # 套餐使用中并且未过期
 
-                         Unused_Uid_Meal.objects.create(uid=UID, channel=channel, addTime=nowTime, is_ai=is_ai,
 
-                                                        order_id=orderID, expire=expire, bucket_id=bucketId)
 
-                         update_status = UID_Bucket.objects.filter(id=ubq['id']).update(has_unused=1)
 
-                         use_flag = False
 
-                     else:  # 已过期或者不相同的套餐加入未使用的关联套餐表
 
-                         update_status = UID_Bucket.objects.filter(id=uid_bucket_id).update(uid=UID, channel=channel,
 
-                                                                                            bucket_id=bucketId,
 
-                                                                                            endTime=endTime,
 
-                                                                                            updateTime=nowTime,
 
-                                                                                            use_status=1)
 
-                 else:
 
-                     ub_cqs = UID_Bucket.objects.create(uid=UID, channel=channel, bucket_id=bucketId, endTime=endTime,
 
-                                                        addTime=nowTime, updateTime=nowTime, use_status=1)
 
-                     uid_bucket_id = ub_cqs.id
 
-                     update_status = True
 
-                 PAY_LOGGER.info(
 
-                     'uid:{},uid_bucket_id:{},update_status:{},order_id:{}'.format(UID, uid_bucket_id, update_status,
 
-                                                                                   orderID))
 
-                 dvq = Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster='')
 
-                 if dvq.exists():
 
-                     dvq_set_update_dict = {
 
-                         'vodPrimaryUserID': userid,
 
-                         'vodPrimaryMaster': username
 
-                     }
 
-                     dvq.update(**dvq_set_update_dict)
 
-                 store_meal_qs = Store_Meal.objects.filter(id=rank, 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 = '未知套餐'
 
-                 Order_Model.objects.create(orderID=orderID, UID=UID, channel=channel, userID_id=userid,
 
-                                            desc=desc, payType=pay_type, payTime=nowTime,
 
-                                            price=amount.get('total'),
 
-                                            currency=order_qs[0]['currency'], addTime=nowTime,
 
-                                            updTime=nowTime, order_type=order_type,
 
-                                            pay_url='', isSelectDiscounts=0,
 
-                                            commodity_code=commodity_code,
 
-                                            commodity_type=commodity_type, rank_id=rank, paymentID='',
 
-                                            coupon_id='', uid_bucket_id=uid_bucket_id, status=1,
 
-                                            agreement_id=agreement_id, store_meal_name=store_meal_name,
 
-                                            plan_id=plan_id, ai_rank_id=1, trade_no=paypal_transaction_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=nowTime, use_status=1, orders_id=orderID, endTime=endTime)
 
-                     else:
 
-                         AiService.objects.create(uid=uid, channel=channel, detect_status=1, addTime=nowTime,
 
-                                                  updTime=nowTime, endTime=endTime, use_status=1, orders_id=orderID)
 
-                 # 如果存在序列号,消息提示用序列号
 
-                 device_name = CommonService.query_serial_with_uid(uid=UID)
 
-                 datetime = time.strftime("%Y-%m-%d", time.localtime())
 
-                 sys_msg_text_list = [
 
-                     '温馨提示:尊敬的客户,您的' + device_name + '设备在' + datetime + '已成功续订云存套餐',
 
-                     'Dear customer,you already subscribed the cloud storage package successfully for device ' + device_name + ' on ' + time.strftime(
 
-                         "%b %dth,%Y", time.localtime())]
 
-                 if pay_type == 1:
 
-                     lang = 'en'
 
-                 else:
 
-                     lang = 'cn'
 
-                 CloudStorage.CloudStorageView().do_vod_msg_notice(UID, channel, userid, lang,
 
-                                                                   sys_msg_text_list, 'SMS_219738485')
 
-                 # 更新agreement
 
-                 billing_agreement_update_attributes = [
 
-                     {
 
-                         "op": "replace",
 
-                         "path": "/",
 
-                         "value": {
 
-                             "description": orderID,
 
-                         }
 
-                     }
 
-                 ]
 
-                 update_status = billing_agreement.replace(billing_agreement_update_attributes)
 
-                 # 记录新订单号和更新状态
 
-                 PaypalWebHookEvent.objects.filter(id=paypal_webhook_event_qs.id).update(newOrderID=orderID,
 
-                                                                                         update_status=update_status)
 
-                 PAY_LOGGER.info('{} PayPal周期扣款成功'.format(UID))
 
-                 return HttpResponse('success')
 
-         except Exception as e:
 
-             PAY_LOGGER.info('PayPal周期扣款异常: errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
-             return HttpResponse('fail', status=500)
 
-     @staticmethod
 
-     def config_match_region(uid, country_id):
 
-         """
 
-         判断用户地区是否跟服务器地区匹配
 
-         @param uid: uid
 
-         @param country_id: 国家表id
 
-         @return: bool
 
-         """
 
-         country_qs = CountryModel.objects.filter(id=country_id).values('region_id')
 
-         # 不确定用户地区信息,默认美洲
 
-         if not country_qs.exists():
 
-             if CONFIG_INFO == CONFIG_EUR:
 
-                 PAY_LOGGER.info('PayPal周期扣款失败---不确定地区的用户请求欧洲服,uid:{},country_id:{}'.format(uid, country_id))
 
-                 return False
 
-             else:
 
-                 return True
 
-         region_id = country_qs[0]['region_id']
 
-         PAY_LOGGER.info('uid{}的用户地区信息: country_id:{}, region_id:{}'.format(uid, country_id, region_id))
 
-         if (CONFIG_INFO == CONFIG_US and region_id == 4) or (CONFIG_INFO == CONFIG_EUR and region_id != 4):
 
-             PAY_LOGGER.info('PayPal周期扣款失败---服务器跟用户地区不匹配')
 
-             return False
 
-         return True
 
-     def do_subscription_break_notify(self, request_dict, request, response):
 
-         logger = logging.getLogger('pay')
 
-         logger.info('--------进入订阅失败,付款失败,暂停--------')
 
-         json_agreement_str = request.body.decode("utf-8")
 
-         json_obj = json.loads(json_agreement_str)
 
-         header = request.META
 
-         paypal_body = json_obj.get('resource')
 
-         logger.info('----主体信息----')
 
-         logger.info(json_agreement_str)
 
-         logger.info('----进入订阅失败头部信息----')
 
-         logger.info(header)
 
-         try:
 
-             transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID', None)
 
-             transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME', None)
 
-             cert_url = header.get('HTTP_PAYPAL_CERT_URL', None)
 
-             transmission_sig = header.get('HTTP_PAYPAL_TRANSMISSION_SIG', None)
 
-             auth_algo = header.get('HTTP_PAYPAL_AUTH_ALGO', None)
 
-             event_type = json_obj.get('event_type')
 
-             summary = json_obj.get('summary')
 
-             resource_type = json_obj.get('resource_type')
 
-             paypal_transaction_id = paypal_body.get('id')
 
-             amount = paypal_body.get('amount')
 
-             # self.get_plan_desc('P-4CG284532S612303METMEINY')
 
-             paypalrestsdk.configure(PAYPAL_CRD)
 
-             response = paypalrestsdk.WebhookEvent.verify(
 
-                 transmission_id, transmission_time, PAYPAL_WEB_HOOK_ID_TWO, json_agreement_str, cert_url,
 
-                 transmission_sig, auth_algo)
 
-             logger.info('----验证签名----')
 
-             logger.info(response)
 
-             if not response:
 
-                 return HttpResponse('Fail', status=500)
 
-             event_type_code = 0
 
-             billing_agreement_id = ''
 
-             if event_type == 'PAYMENT.SALE.COMPLETED':
 
-                 event_type_code = 1
 
-                 billing_agreement_id = paypal_body.get('billing_agreement_id')
 
-             elif event_type == 'PAYMENT.SALE.REVERSED':
 
-                 billing_agreement_id = paypal_body.get('billing_agreement_id')
 
-                 event_type_code = 2
 
-             elif event_type == 'BILLING.SUBSCRIPTION.CANCELLED':
 
-                 billing_agreement_id = paypal_body.get('id')
 
-                 event_type_code = 3
 
-             elif event_type == 'BILLING.SUBSCRIPTION.SUSPENDED':
 
-                 billing_agreement_id = paypal_body.get('id')
 
-                 event_type_code = 4
 
-             elif event_type == 'BILLING.SUBSCRIPTION.PAYMENT.FAILED':
 
-                 billing_agreement_id = paypal_body.get('id')
 
-                 event_type_code = 5
 
-             elif event_type == 'PAYMENT.SALE.REFUNDED':
 
-                 billing_agreement_id = paypal_body.get('billing_agreement_id')
 
-                 event_type_code = 6
 
-             PaypalWebHookEventInsert = {
 
-                 'webhook_event_id': json_obj.get('id'),
 
-                 'resource_type': resource_type,
 
-                 'event_type': event_type_code,
 
-                 'summary': summary,
 
-                 'trade_no': paypal_transaction_id,
 
-                 'resource': json_agreement_str,
 
-                 'created_time': int(time.time()),
 
-             }
 
-             if not billing_agreement_id:
 
-                 # 记录钩子日志
 
-                 PaypalWebHookEvent.objects.create(**PaypalWebHookEventInsert)
 
-                 return HttpResponse('success')
 
-             billing_agreement = paypalrestsdk.BillingAgreement.find(billing_agreement_id)
 
-             # 记录钩子日志
 
-             PaypalWebHookEventInsert['agreement_desc'] = repr(billing_agreement)
 
-             PaypalWebHookEventInsert['agreement_id'] = billing_agreement_id
 
-             PaypalWebHookEventInsert['orderID'] = billing_agreement.description
 
-             PaypalWebHookEvent.objects.create(**PaypalWebHookEventInsert)
 
-             return HttpResponse('success')
 
-         except Exception as e:
 
-             print(e)
 
-             logger.info('----进入订阅失败----')
 
-             logger.info('do_paypal_webhook_notify支付失败:----')
 
-             logger.info("错误行数:{errLine}".format(errLine=e.__traceback__.tb_lineno))
 
-             logger.info(repr(e))
 
-             return HttpResponse('fail', status=500)
 
-     def get_plan_desc(self, plan_id):
 
-         paypalrestsdk.configure(PAYPAL_CRD)
 
-         billing_plan = paypalrestsdk.BillingPlan.find(plan_id)
 
-         print("Got Billing Plan Details for Billing Plan[%s]" % (billing_plan.id))
 
-         exit()
 
- class payCycle(View):
 
-     def get(self, request, *args, **kwargs):
 
-         request.encoding = 'utf-8'
 
-         operation = kwargs.get('operation')
 
-         return self.validation(request.GET, request, operation)
 
-     def post(self, request, *args, **kwargs):
 
-         request.encoding = 'utf-8'
 
-         operation = kwargs.get('operation')
 
-         return self.validation(request.POST, request, operation)
 
-     def validation(self, request_dict, request, operation):
 
-         response = ResponseObject()
 
-         token = request_dict.get('token', None)
 
-         # 设备主键uid
 
-         tko = TokenObject(token)
 
-         response.lang = tko.lang
 
-         if tko.code != 0:
 
-             return response.json(tko.code)
 
-         userID = tko.userID
 
-         if operation is None:
 
-             return response.json(444, 'error path')
 
-         elif operation == 'queryPayCycle':  # paypal成功订阅回调
 
-             return self.do_query_pay_cycle(request_dict, userID, response)
 
-         elif operation == 'cancelPayCycle':  # 取消自动续费
 
-             return self.do_cancel_pay_cycle(request_dict, userID, response)
 
-     def do_query_pay_cycle(self, request_dict, userID, response):
 
-         lang = request_dict.get('lang', 'en')
 
-         uid = request_dict.get('uid', None)
 
-         orderObject = Order_Model.objects.filter(userID=userID, status=1, rank__lang__lang=lang).annotate(
 
-             rank__title=F('rank__lang__title'), rank__content=F('rank__lang__content'))
 
-         if uid:
 
-             orderObject = orderObject.filter(UID=uid)
 
-         orderObject = orderObject.filter(~Q(agreement_id=''))
 
-         if not orderObject.exists():
 
-             return response.json(0, {'data': [], 'count': 0})
 
-         orderQuery = orderObject.values("orderID", "UID", "channel", "desc", "price", "currency",
 
-                                         "addTime",
 
-                                         "updTime", "paypal", "rank__day", "payType",
 
-                                         "rank__price", "status",
 
-                                         "rank__lang__content", "rank__lang__title", "rank__currency",
 
-                                         "rank_id", "rank__expire", "agreement_id").order_by('addTime')
 
-         new_data = []
 
-         values = []
 
-         for d in orderQuery:
 
-             if d['agreement_id'] not in values:
 
-                 new_data.append(d)
 
-                 values.append(d['agreement_id'])
 
-         count = len(new_data)
 
-         return response.json(0, {'data': new_data, 'count': count})
 
-     def do_cancel_pay_cycle(self, request_dict, userID, response):
 
-         orderID = request_dict.get('orderID', 'None')
 
-         orderObject = Order_Model.objects.filter(orderID=orderID)
 
-         orderObject = orderObject.filter(~Q(agreement_id='')).values("agreement_id")
 
-         if not orderObject.exists():
 
-             return response.json(800)
 
-         paypalrestsdk.configure(PAYPAL_CRD)
 
-         BILLING_AGREEMENT_ID = orderObject[0]['agreement_id']
 
-         try:
 
-             billing_agreement = paypalrestsdk.BillingAgreement.find(BILLING_AGREEMENT_ID)
 
-             if billing_agreement.state != 'Active':
 
-                 Order_Model.objects.filter(agreement_id=BILLING_AGREEMENT_ID).update(agreement_id='')
 
-                 return response.json(0)
 
-             cancel_note = {"note": "Canceling the agreement"}
 
-             if billing_agreement.cancel(cancel_note):
 
-                 Order_Model.objects.filter(agreement_id=BILLING_AGREEMENT_ID).update(agreement_id='')
 
-                 return response.json(0)
 
-             else:
 
-                 return response.json(10052)
 
-         except Exception as e:
 
-             return response.json(10052)
 
 
  |