123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- from Ansjer.config import PAYPAL_CRD,SERVER_DOMAIN,SERVER_DOMAIN_SSL
- from Model.models import PayCycleConfigModel,Order_Model, Store_Meal, UID_Bucket, PromotionRuleModel, Unused_Uid_Meal,Device_Info, CouponModel
- from Service.CommonService import CommonService
- from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
- import requests
- import time
- from Object.ResponseObject import ResponseObject
- import paypalrestsdk
- from paypalrestsdk import BillingAgreement
- from django.views.generic.base import View
- from django.db import transaction
- from Controller import CloudStorage
- from django.db.models import Q, F, Count
- from paypalrestsdk.notifications import WebhookEvent
- import logging
- import json
- #周期扣款相关
- class Paypal:
- def subscriptions(store_info,lang,orderID):
- cycle_config = PayCycleConfigModel.objects.filter(id=store_info['cycle_config_id']).values()
- if not cycle_config:
- 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)
- 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": store_info['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:
- print(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:
- print(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 == 'test': # paypal 周期付款回调
- return self.do_test(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)
- paypalrestsdk.configure(PAYPAL_CRD)
- billing_agreement = paypalrestsdk.BillingAgreement()
- billing_agreement_response = billing_agreement.execute(token)
- if billing_agreement_response.error:
- print(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
- agreement_id = billing_agreement_response.id
- promotion_rule_id = ''
- try:
- order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
- if not orderID:
- print("not orderID")
- 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)
- order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
- "userID__userID",
- "userID__username",'coupon_id')
- userid = order_list[0]['userID__userID']
- username = order_list[0]['userID__username']
- UID = order_list[0]['UID']
- channel = order_list[0]['channel']
- rank = order_list[0]['rank']
- smqs = Store_Meal.objects.filter(id=rank). \
- values("day", "bucket_id", "bucket__storeDay", "expire")
- bucketId = smqs[0]['bucket_id']
- if not smqs.exists():
- print("not smqs")
- 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']
- if order_list[0]['isSelectDiscounts'] == 1:
- expire = smqs[0]['expire'] * 2
- # 是否有促销
- nowTime = int(time.time())
- 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
- with transaction.atomic():
- if ubqs.exists():
- ubq = ubqs[0]
- if ubq['use_status'] == 1 and ubq['bucket_id'] == bucketId: #套餐使用中并且相同套餐叠加过期时间
- endTime = CommonService.calcMonthLater(expire, ubq['endTime'])
- UID_Bucket.objects.filter(id=ubq['id']).update \
- (uid=UID, channel=channel, bucket_id=bucketId,
- endTime=endTime, updateTime=nowTime)
- else: #已过期或者不相同的套餐加入未使用的关联套餐表
- has_unused = Unused_Uid_Meal.objects.filter(uid=UID, bucket_id=bucketId).values("id")
- nums = 2 if order_list[0]['isSelectDiscounts'] == 1 else 1
- if promotion.exists():
- nums = nums + 1
- if has_unused.exists():
- Unused_Uid_Meal.objects.filter(id=has_unused[0]['id']).update(num=F('num') + nums)
- else:
- Unused_Uid_Meal.objects.create(uid=UID,channel=channel,addTime=nowTime,num=nums,
- expire=smqs[0]['expire'],bucket_id=bucketId)
- UID_Bucket.objects.filter(id=ubq['id']).update(has_unused=1)
- uid_bucket_id = ubq['id']
- else:
- endTime = CommonService.calcMonthLater(expire)
- 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
- 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)
- # 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=1)
- order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id,
- promotion_rule_id=promotion_rule_id,agreement_id=agreement_id)
- datetime = time.strftime("%Y-%m-%d", time.localtime())
- sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功订阅云存套餐',
- 'Dear customer,you already subscribed the cloud storage package successfully for device ' + UID + ' on ' + time.strftime(
- "%b %dth,%Y", time.localtime())]
- CloudStorage.CloudStorageView.do_vod_msg_Notice(self, 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)
- return HttpResponseRedirect(red_url)
- except Exception as e:
- print(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):
- logger = logging.getLogger('info')
- json_str = request.body.decode("utf-8")
- logger.info('json_str----------------')
- logger.info(json_str)
- header = request.META
- logger.info('json_str----------------')
- logger.info(header)
- # json_str = '{"id":"WH-9K090101YP819052B-3LD205733F387905X","event_version":"1.0","create_time":"2022-01-05T08:17:36.937Z","resource_type":"plan","event_type":"BILLING.PLAN.CREATED","summary":"A billing plan was created","resource":{"merchant_preferences":{"setup_fee":{"currency":"USD","value":"0.02"},"return_url":"http://127.0.0.1:8000/payCycle/paypalCycleReturn?lang=en","cancel_url":"http://127.0.0.1:8000/web/paid2/en_fail.html","auto_bill_amount":"YES","initial_fail_amount_action":"CANCEL","max_fail_attempts":"1"},"update_time":"2022-01-05T08:17:15.829Z","create_time":"2022-01-05T08:17:15.129Z","name":"One year package","description":"20220105161712830917","links":[{"href":"https://api.sandbox.paypal.com/v1/payments/billing-plans/P-4RE38399B6473962EFFIEW6I","rel":"self","method":"GET"}],"payment_definitions":[{"id":"PD-8DC78035HJ0448121FFIEW6I","name":"Video save for 7 day","type":"REGULAR","frequency":"Day","amount":{"currency":"USD","value":"0.02"},"cycles":"0","frequency_interval":"1"}],"id":"P-4RE38399B6473962EFFIEW6I","state":"ACTIVE","type":"INFINITE"},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9K090101YP819052B-3LD205733F387905X","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-9K090101YP819052B-3LD205733F387905X/resend","rel":"resend","method":"POST"}]}'
- json_obj = json.loads(json_str)
- transmission_id = header.get('paypal-transmission-id',None)
- transmission_time = header.get('paypal-transmission-id',None)
- webhook_id = '9RW011891A1707801'
- cert_url = header.get('paypal-cert-url',None)
- transmission_sig = header.get('paypal-transmission-sig',None)
- auth_algo = header.get('paypal-auth-algo',None)
- resource_type = json_obj.get('resource_type')
- json_str = '{"id":"WH-22P96595RY482870W-2B701244WV459014K","event_version":"1.0","create_time":"2022-01-06T05:56:33.126Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.02 USD","resource":{"billing_agreement_id":"I-CR65R6YXS3VA","amount":{"total":"0.02","currency":"USD","details":{"subtotal":"0.02"}},"payment_mode":"INSTANT_TRANSFER","update_time":"2022-01-06T05:56:18Z","create_time":"2022-01-06T05:56:18Z","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee":{"currency":"USD","value":"0.02"},"protection_eligibility":"ELIGIBLE","links":[{"method":"GET","rel":"self","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H/refund"}],"id":"2FE30648Y2273061H","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K/resend","rel":"resend","method":"POST"}]}'
- header = "{'PATH_INFO': '/payCycle/paypalCycleNotify', 'wsgi.file_wrapper': <class 'gunicorn.http.wsgi.FileWrapper'>, 'CONTENT_LENGTH': '1226', 'wsgi.multiprocess': True, 'HTTP_PAYPAL_TRANSMISSION_TIME': '2022-01-06T05:56:36Z', 'wsgi.version': (1, 0), 'SERVER_NAME': '0.0.0.0', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.0', 'REMOTE_PORT': '42322', 'HTTP_HTTP_X_FORWARDED_FOR': '173.0.80.116', 'RAW_URI': '/payCycle/paypalCycleNotify', 'HTTP_X_REAL_IP': '173.0.80.116', 'HTTP_X_B3_SPANID': 'f37d2832010b10f2', 'REMOTE_ADDR': '127.0.0.1', 'wsgi.input': <gunicorn.http.body.Body object at 0x7ff31a5b92b0>, 'HTTP_PAYPAL_TRANSMISSION_SIG': 'JI+rFKqe9YqufExp/aJxkyRWG3II+4t6CSCWLHqNrjcd/FP729G0s8lFMPixnGpUemj4+WsJTbu29G4ZR3zxl+CwrlKhPQxe0fE0mUw+/AaBa6THpnoXEVwz9spI/kbH3dNmSXePfW0D5+HyVmWgkac23icxi4G92ZmmszPBzBdcNIc3BumXGSfJwX19cchta0VY7GnD5ePvW1FstPp9eC7NyhDH11xDpvM2qZZqhxH6hahIywVNA0gyNydkYbkbjnD+hGC+HrKKMx0Tpw8eGxUHReWJIEsiw7YCPLBwZIab5PV/+L4A/LscK/JicOeDealP+SKPJICZvinLHDzK0Q==', 'HTTP_PAYPAL_TRANSMISSION_ID': '688538e0-6eb5-11ec-a473-05e6d85b61e7', 'gunicorn.socket': <socket.socket fd=24, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8082), raddr=('127.0.0.1', 42322)>, 'HTTP_PAYPAL_AUTH_ALGO': 'SHA256withRSA', 'HTTP_PAYPAL_AUTH_VERSION': 'v2', 'wsgi.url_scheme': 'http', 'wsgi.errors': <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7ff31a5b9a58>, 'QUERY_STRING': '', 'wsgi.multithread': False, 'HTTP_CORRELATION_ID': 'b696eaa58ea49', 'HTTP_ACCEPT': '*/*', 'HTTP_USER_AGENT': 'PayPal/AUHD-214.0-56138150', 'CONTENT_TYPE': 'application/json', 'HTTP_PAYPAL_CERT_URL': 'https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-7a8abba8', 'HTTP_CONNECTION': 'close', 'SERVER_PORT': '8082', 'HTTP_HOST': 'test.zositechc.cn:443', 'HTTP_X_FORWARDED_FOR': '173.0.80.116', 'SERVER_SOFTWARE': 'gunicorn/19.7.1', 'wsgi.run_once': False, 'REQUEST_METHOD': 'POST'}"
- if resource_type == 'plan':
- paypalrestsdk.configure(PAYPAL_CRD)
- response = paypalrestsdk.WebhookEvent.verify(
- transmission_id, transmission_time, webhook_id, json_str, cert_url, transmission_sig, auth_algo)
- logger.info('response----------------')
- logger.info(response)
- return HttpResponse(json_obj.get('id'))
- def do_test(self, request_dict, request, response):
- json_str = '{"id":"WH-22P96595RY482870W-2B701244WV459014K","event_version":"1.0","create_time":"2022-01-06T05:56:33.126Z","resource_type":"sale","event_type":"PAYMENT.SALE.COMPLETED","summary":"Payment completed for $ 0.02 USD","resource":{"billing_agreement_id":"I-CR65R6YXS3VA","amount":{"total":"0.02","currency":"USD","details":{"subtotal":"0.02"}},"payment_mode":"INSTANT_TRANSFER","update_time":"2022-01-06T05:56:18Z","create_time":"2022-01-06T05:56:18Z","protection_eligibility_type":"ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE","transaction_fee":{"currency":"USD","value":"0.02"},"protection_eligibility":"ELIGIBLE","links":[{"method":"GET","rel":"self","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H"},{"method":"POST","rel":"refund","href":"https://api.sandbox.paypal.com/v1/payments/sale/2FE30648Y2273061H/refund"}],"id":"2FE30648Y2273061H","state":"completed","invoice_number":""},"links":[{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K","rel":"self","method":"GET"},{"href":"https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-22P96595RY482870W-2B701244WV459014K/resend","rel":"resend","method":"POST"}]}'
- header = "{'PATH_INFO': '/payCycle/paypalCycleNotify', 'wsgi.file_wrapper': <class 'gunicorn.http.wsgi.FileWrapper'>, 'CONTENT_LENGTH': '1226', 'wsgi.multiprocess': True, 'HTTP_PAYPAL_TRANSMISSION_TIME': '2022-01-06T05:56:36Z', 'wsgi.version': (1, 0), 'SERVER_NAME': '0.0.0.0', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.0', 'REMOTE_PORT': '42322', 'HTTP_HTTP_X_FORWARDED_FOR': '173.0.80.116', 'RAW_URI': '/payCycle/paypalCycleNotify', 'HTTP_X_REAL_IP': '173.0.80.116', 'HTTP_X_B3_SPANID': 'f37d2832010b10f2', 'REMOTE_ADDR': '127.0.0.1', 'wsgi.input': <gunicorn.http.body.Body object at 0x7ff31a5b92b0>, 'HTTP_PAYPAL_TRANSMISSION_SIG': 'JI+rFKqe9YqufExp/aJxkyRWG3II+4t6CSCWLHqNrjcd/FP729G0s8lFMPixnGpUemj4+WsJTbu29G4ZR3zxl+CwrlKhPQxe0fE0mUw+/AaBa6THpnoXEVwz9spI/kbH3dNmSXePfW0D5+HyVmWgkac23icxi4G92ZmmszPBzBdcNIc3BumXGSfJwX19cchta0VY7GnD5ePvW1FstPp9eC7NyhDH11xDpvM2qZZqhxH6hahIywVNA0gyNydkYbkbjnD+hGC+HrKKMx0Tpw8eGxUHReWJIEsiw7YCPLBwZIab5PV/+L4A/LscK/JicOeDealP+SKPJICZvinLHDzK0Q==', 'HTTP_PAYPAL_TRANSMISSION_ID': '688538e0-6eb5-11ec-a473-05e6d85b61e7', 'gunicorn.socket': <socket.socket fd=24, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8082), raddr=('127.0.0.1', 42322)>, 'HTTP_PAYPAL_AUTH_ALGO': 'SHA256withRSA', 'HTTP_PAYPAL_AUTH_VERSION': 'v2', 'wsgi.url_scheme': 'http', 'wsgi.errors': <gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7ff31a5b9a58>, 'QUERY_STRING': '', 'wsgi.multithread': False, 'HTTP_CORRELATION_ID': 'b696eaa58ea49', 'HTTP_ACCEPT': '*/*', 'HTTP_USER_AGENT': 'PayPal/AUHD-214.0-56138150', 'CONTENT_TYPE': 'application/json', 'HTTP_PAYPAL_CERT_URL': 'https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-7a8abba8', 'HTTP_CONNECTION': 'close', 'SERVER_PORT': '8082', 'HTTP_HOST': 'test.zositechc.cn:443', 'HTTP_X_FORWARDED_FOR': '173.0.80.116', 'SERVER_SOFTWARE': 'gunicorn/19.7.1', 'wsgi.run_once': False, 'REQUEST_METHOD': 'POST'}"
- json_obj = json.loads(json_str)
- # transmission_id = header.get('HTTP_PAYPAL_TRANSMISSION_ID',None)
- # transmission_time = header.get('HTTP_PAYPAL_TRANSMISSION_TIME',None)
- # webhook_id = '6TS30758D98835230'
- # 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)
- # resource_type = json_obj.get('resource_type')
- transmission_id = '688538e0-6eb5-11ec-a473-05e6d85b61e7'
- transmission_time = '2022-01-06T05:56:36Z'
- webhook_id = '6TS30758D98835230'
- cert_url = 'https://api.sandbox.paypal.com/v1/notifications/certs/CERT-360caa42-fca2a594-7a8abba8'
- transmission_sig = 'JI+rFKqe9YqufExp/aJxkyRWG3II+4t6CSCWLHqNrjcd/FP729G0s8lFMPixnGpUemj4+WsJTbu29G4ZR3zxl+CwrlKhPQxe0fE0mUw+/AaBa6THpnoXEVwz9spI/kbH3dNmSXePfW0D5+HyVmWgkac23icxi4G92ZmmszPBzBdcNIc3BumXGSfJwX19cchta0VY7GnD5ePvW1FstPp9eC7NyhDH11xDpvM2qZZqhxH6hahIywVNA0gyNydkYbkbjnD+hGC+HrKKMx0Tpw8eGxUHReWJIEsiw7YCPLBwZIab5PV/+L4A/LscK/JicOeDealP+SKPJICZvinLHDzK0Q=='
- auth_algo = 'SHA256withRSA'
- resource_type = json_obj.get('resource_type')
- if resource_type == 'sale':
- paypalrestsdk.configure(PAYPAL_CRD)
- response = paypalrestsdk.WebhookEvent.verify(
- transmission_id, transmission_time, webhook_id, json_str, cert_url, transmission_sig, auth_algo)
- if response:
- try:
- agreement_id = json_obj.get('resource')['billing_agreement_id']
- order_qs = Order_Model.objects.filter(agreement_id=agreement_id, status=0)
- if not order_qs:
- return False
- order_list = order_qs.values("UID", "channel", "commodity_code", "rank", "isSelectDiscounts",
- "userID__userID",
- "userID__username")
- return HttpResponse(order_list)
- userid = order_list[0]['userID__userID']
- username = order_list[0]['userID__username']
- UID = order_list[0]['UID']
- channel = order_list[0]['channel']
- rank = order_list[0]['rank']
- smqs = Store_Meal.objects.filter(id=rank). \
- values("day", "bucket_id", "bucket__storeDay", "expire")
- bucketId = smqs[0]['bucket_id']
- if not smqs.exists():
- print("not smqs")
- 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']
- if order_list[0]['isSelectDiscounts'] == 1:
- expire = smqs[0]['expire'] * 2
- # 是否有促销
- nowTime = int(time.time())
- 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
- with transaction.atomic():
- if ubqs.exists():
- ubq = ubqs[0]
- if ubq['use_status'] == 1 and ubq['bucket_id'] == bucketId: # 套餐使用中并且相同套餐叠加过期时间
- endTime = CommonService.calcMonthLater(expire, ubq['endTime'])
- UID_Bucket.objects.filter(id=ubq['id']).update \
- (uid=UID, channel=channel, bucket_id=bucketId,
- endTime=endTime, updateTime=nowTime)
- else: # 已过期或者不相同的套餐加入未使用的关联套餐表
- has_unused = Unused_Uid_Meal.objects.filter(uid=UID, bucket_id=bucketId).values("id")
- nums = 2 if order_list[0]['isSelectDiscounts'] == 1 else 1
- if promotion.exists():
- nums = nums + 1
- if has_unused.exists():
- Unused_Uid_Meal.objects.filter(id=has_unused[0]['id']).update(num=F('num') + nums)
- else:
- Unused_Uid_Meal.objects.create(uid=UID, channel=channel, addTime=nowTime, num=nums,
- expire=smqs[0]['expire'], bucket_id=bucketId)
- UID_Bucket.objects.filter(id=ubq['id']).update(has_unused=1)
- uid_bucket_id = ubq['id']
- else:
- endTime = CommonService.calcMonthLater(expire)
- 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
- 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)
- # 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)
- order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id,
- promotion_rule_id=promotion_rule_id, agreement_id=agreement_id)
- datetime = time.strftime("%Y-%m-%d", time.localtime())
- sys_msg_text_list = ['温馨提示:尊敬的客户,您的' + UID + '设备在' + datetime + '已成功订阅云存套餐',
- 'Dear customer,you already subscribed the cloud storage package successfully for device ' + UID + ' on ' + time.strftime(
- "%b %dth,%Y", time.localtime())]
- CloudStorage.CloudStorageView.do_vod_msg_Notice(self, UID, channel, userid, lang,
- sys_msg_text_list, 'SMS_219738485')
- return True
- except Exception as e:
- print(repr(e))
- if order_qs:
- order_qs.update(status=10, promotion_rule_id=promotion_rule_id)
- return False
- return False
|