:art: Support ess_callback

huangqimin001 9 mois auparavant
Parent
Commettre
5d34bd84b1

+ 4 - 3
api/lensman/activity_admin_views.py

@@ -4,9 +4,10 @@ from django.conf import settings
4 4
 from django_logit import logit
5 5
 from django_response import response
6 6
 
7
-from kodo.decorators import check_admin
8
-from apps.lensman.activity.models import LensmanContributionActivityIncomeExpensesInfo
9 7
 from account.models import LensmanInfo
8
+from apps.lensman.activity.models import LensmanContributionActivityIncomeExpensesInfo
9
+from kodo.decorators import check_admin
10
+
10 11
 
11 12
 @logit(res=True)
12 13
 @check_admin
@@ -21,4 +22,4 @@ def add_lensman_contribution_income_api(request, administrator):
21 22
 
22 23
     LensmanContributionActivityIncomeExpensesInfo.objects.update_or_create(contribution_id=contribution_id, lensman_id=lensman.lensman_id, activity_id=activity_id, user_id=user_id, defaults={'amount': amount})
23 24
 
24
-    return response(200, '增加摄影师投稿收入成功')
25
+    return response(200, '增加摄影师投稿收入成功')

+ 2 - 2
api/lensman/contract_admin_views.py

@@ -4,8 +4,8 @@ from django.conf import settings
4 4
 from django_logit import logit
5 5
 from django_response import response
6 6
 
7
-from kodo.decorators import check_admin
8 7
 from apps.contract.models import LensmanContributionContractInfo
8
+from kodo.decorators import check_admin
9 9
 
10 10
 
11 11
 @logit(res=True)
@@ -16,7 +16,7 @@ def get_signed_contribtion_contract_file_api(request, administrator):
16 16
 
17 17
     contract = LensmanContributionContractInfo.objects.filter(contribution_id=contribution_id, user_id=user_id).first()
18 18
 
19
-    operator =  {
19
+    operator = {
20 20
         "UserId": settings.CONTRACT_LENSMAN_CONTRIBUTION_OPERATOR_ID
21 21
     }
22 22
 

+ 14 - 1
api/lensman/contract_mp_views.py

@@ -1,6 +1,7 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3 3
 import base64
4
+import json
4 5
 
5 6
 import requests
6 7
 from django_logit import logit
@@ -12,7 +13,7 @@ from apps.contract.models import LensmanContributionContractInfo
12 13
 from apps.lensman.activity.models import LensmanContributionActivityIncomeExpensesInfo
13 14
 from member.models import MemberActivityContributionInfo
14 15
 from utils.redis.rimage import get_images_data
15
-from utils.tencentcloud.ess import (create_document, create_flow, create_scheme_url, start_flow,
16
+from utils.tencentcloud.ess import (callback_decode, create_document, create_flow, create_scheme_url, start_flow,
16 17
                                     test_upload_document_files, upload_document_files)
17 18
 
18 19
 
@@ -181,4 +182,16 @@ def get_contribtion_contract_sign_mppath(lensman, FlowId):
181 182
 
182 183
 @logit(body=True, res=True)
183 184
 def ess_callback(request):
185
+    # curl http://127.0.0.1:8888/api/mp/ess/callback -H 'Content-type: application/json' -X POST -d '{"encrypt":"62KE4r5Wz0yHzEpMOwVRbM1KV0"}'
186
+    data = json.loads(request.body)
187
+    data = callback_decode(data['encrypt'])
188
+    MsgType = data.get('MsgType')
189
+    if MsgType == 'FlowStatusChange':
190
+        MsgData = data.get('MsgData', {})
191
+        FlowId = MsgData.get('FlowId')
192
+        # DocumentId = MsgData.get('DocumentId')
193
+        FlowCallbackStatus = MsgData.get('FlowCallbackStatus', -1)
194
+        Approvers = MsgData.get('Approvers') or [{}]
195
+        ApproveCallbackStatus = Approvers[-1].get('ApproveCallbackStatus', -1)
196
+        LensmanContributionContractInfo.objects.filter(flow_id=FlowId).update(tencent_contract_status=FlowCallbackStatus, tencent_approve_status=ApproveCallbackStatus)
184 197
     return response()

+ 11 - 1
apps/contract/admin.py

@@ -1,3 +1,13 @@
1
+# -*- coding: utf-8 -*-
2
+
1 3
 from django.contrib import admin
2 4
 
3
-# Register your models here.
5
+from apps.contract.models import LensmanContributionContractInfo
6
+
7
+
8
+class LensmanContributionContractInfoAdmin(admin.ModelAdmin):
9
+    list_display = ('contract_id', 'user_id', 'lensman_id', 'activity_id', 'contribution_id', 'flow_id', 'document_id', 'tencent_contract_status', 'tencent_approve_status', 'status', 'created_at', 'updated_at')
10
+    list_filter = ('brand_id', 'coupon_expire_type', 'status')
11
+
12
+
13
+admin.site.register(LensmanContributionContractInfo, LensmanContributionContractInfoAdmin)

+ 3 - 3
apps/contract/models.py

@@ -1,4 +1,5 @@
1 1
 # -*- coding: utf-8 -*-
2
+
2 3
 from django.db import models
3 4
 from django.utils.translation import ugettext_lazy as _
4 5
 from django_models_ext import BaseModelMixin, upload_file_path, upload_path
@@ -8,8 +9,6 @@ from TimeConvert import TimeConvert as tc
8 9
 
9 10
 from utils.qiniucdn import qiniu_file_url
10 11
 
11
-# Create your models here.
12
-
13 12
 
14 13
 class LensmanContributionContractInfo(BaseModelMixin):
15 14
     CONTRACT_STATUS_TUPLE = (
@@ -67,13 +66,14 @@ class LensmanContributionContractInfo(BaseModelMixin):
67 66
     @property
68 67
     def contract_file_url(self):
69 68
         return qiniu_file_url(self.contract_file.name, bucket='tamron')
70
-    
69
+
71 70
     @property
72 71
     def contract_status(self):
73 72
         if(self.tencent_approve_status == 3 and self.tencent_contract_status == 4):
74 73
             return 1
75 74
         else:
76 75
             return 0
76
+
77 77
     @property
78 78
     def data(self):
79 79
         return {

+ 1 - 1
kodo/settings.py

@@ -248,8 +248,8 @@ TENCENTCLOUD = {
248 248
         'template_id': '',
249 249
         'secret_id': '',
250 250
         'secret_key': '',
251
-        'callback_secret_id': '',
252 251
         'callback_secret_key': '',
252
+        'callback_secret_token': '',
253 253
         'endpoint': 'ess.tencentcloudapi.com',
254 254
         'file_endpoint': 'file.ess.tencent.cn',
255 255
     },

+ 1 - 0
requirements.txt

@@ -9,6 +9,7 @@ mock==4.0.3
9 9
 monetary==1.0.3
10 10
 mysqlclient==2.1.1
11 11
 pngquant==1.0.8
12
+pycryptodomex==3.20.0
12 13
 pysnippets==1.1.4
13 14
 pyzbar==0.1.9
14 15
 qiniu==7.9.0

+ 32 - 1
utils/tencentcloud/ess.py

@@ -1,7 +1,9 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3
+import base64
3 4
 import json
4 5
 
6
+from Cryptodome.Cipher import AES
5 7
 from django.conf import settings
6 8
 from tencentcloud.common import credential
7 9
 from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
@@ -16,8 +18,8 @@ operator_id = tencentcloud_cfg.get('operator_id')
16 18
 template_id = tencentcloud_cfg.get('template_id')
17 19
 secret_id = tencentcloud_cfg.get('secret_id')
18 20
 secret_key = tencentcloud_cfg.get('secret_key')
19
-callback_secret_id = tencentcloud_cfg.get('callback_secret_id')
20 21
 callback_secret_key = tencentcloud_cfg.get('callback_secret_key')
22
+callback_secret_token = tencentcloud_cfg.get('callback_secret_token')
21 23
 endpoint = tencentcloud_cfg.get('endpoint')
22 24
 file_endpoint = tencentcloud_cfg.get('file_endpoint')
23 25
 
@@ -304,3 +306,32 @@ def create_scheme_url(flow_id=None, name=None, mobile=None, card_type='ID_CARD',
304 306
         resp = {}
305 307
 
306 308
     return resp
309
+
310
+
311
+def decode_aes256(data, encryption_key):
312
+    iv = encryption_key[0:16]
313
+    aes = AES.new(encryption_key, AES.MODE_CBC, iv)
314
+    d = aes.decrypt(data)
315
+    unpad = lambda s: s[0:-ord(d[-1:])]
316
+    return unpad(d)
317
+
318
+
319
+def test_decode():
320
+    # https://qian.tencent.com/developers/company/callback_types_v2
321
+    data = "62KE4r5Wz0yHzEpMOwVRbM1KV0pPjj+cmJkT+i65MMscgfHAdNP+9K0nV/fFw1xriwi08APc/wM0mHprE43Hc91VPhRDnu2Wn0+bjzgjmy/FgZKZATR9oquy0/BCWu4C77AjkpkoU1/E7gGLr8M9u9t7zbS4AkkGK5xL5TtwI0sS+CMygmyV7bRjxebMycI52U3QJiwDRIPxFO+7yqeXYXV9AQrRskpCDBNFGW72bh+Ixw9dtX00kWcwVQ93V+mayrvdQ8oGSsL32m72kbBfahsIvIxSYSdDAEeTyokqKGfaLWD27vm55QG218IFKEsOJFDGdqCF+IBcM/+rOFeOrewvP5ehIO2KjFBecTDn0RQTlIiokXIQ4zJKvu6njePFRFoFCZjd4oiEIVn/OBw+rjXml3qwgVBQjPRtYdvDJFNENlVjlkVVmLWeS8MIdqsFWhm6Sa7O8X57mwc0cLJ22mGbyVEzNTFqeFJ/mkueW0leLcoZdjv/+IxZusqa1cpfwzkZhwi5rY6kJffNkkrxIc6OeRvpU4ECgBe/b+kxX+ObC0z9u7nzoZAOHx4akYviyIU5B1romjdfHQ/wDr5udm4Rl4NBhU/6V06Rvaadw0Ta9oBkZHGNxFWv32MnL7fVA0zVNOFDP8n+kaQiNGFAXLF4F5oIItYc5+Gp/IxfkltEki7ni7LztViE7b/ZiKSM+gzQn6fLsJ/dlUoZmh141Y0V/GPpsbxBOnWCjBZdNkLTKxdKCMScLCTysJxv7l6Swff8nAEurbzx1tvyhJAvUDnIaLyP8pRPRFq8p0xm3ZVpOo9k7A952XxVHSs40g4sr/Dihkn60aVhGtKK9DueCzn8P3cWG4TYc03M1hNlPfF+UAfnvQ1ZYAMKT/XPLqYtgRFpRkK96YfVecIrfUe9MjWl0/g4hYCAAOJurFoeGwkJiyQ8Q7DCI5EaHa3s/vI621yQyytC6D2u86RiDJxMW0PdvkUfayT7iPwC83EsfEzpQXr0yeSCQCSBgNByEuCNnZl8LAhYl05Y9+bgCzSPt6EUvmaXclYL+/EPrEmi+hzIdXUwBfhXgICT8MteJgMSgmJM2FjjGxy6uZtfHKRIzf1wk6OORPkPJtMgjlMtMs6VFC62EEeo5Xy2v1S95WT/WQ0tnGR8KjbNnmjNSRyD8VtS2mjlLXaK0xRb71YGt57O19YxQQ3R/Hq9zGqOjG+Agdl+pcvh47RlF8o3CnlU7Q=="
322
+    encryption_key = 'TencentEssEncryptTestKey12345678'
323
+    return callback_decode(data, encryption_key)
324
+
325
+
326
+def callback_decode(data, encryption_key=None):
327
+    # 此处传入密文,如果接收到的数据是{"encrypt":"base64后的密文"}
328
+    # data = 'base64后的密文'
329
+    data = base64.b64decode(data)
330
+    encryption_key = encryption_key or callback_secret_key
331
+    # encryption_key = bytes(encryption_key or callback_secret_key, encoding="utf8")
332
+    # 此处传入CallbackUrlKey
333
+    e = decode_aes256(data, encryption_key)
334
+    # print(type(e))
335
+    # print(e)
336
+    # print(str(e, encoding="utf8"))
337
+    return json.loads(e)