| @@ -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, '增加摄影师投稿收入成功') | 
| @@ -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 |  | 
| @@ -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() | 
| @@ -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) | 
| @@ -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 { | 
| @@ -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 | }, | 
| @@ -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 | 
| @@ -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) |