import datetime import threading from datetime import timedelta from typing import cast from zoneinfo import ZoneInfo import jmespath import orjson import pydash import requests from asgiref.sync import async_to_sync from channels.layers import get_channel_layer, BaseChannelLayer from django.forms import model_to_dict from rest_framework import status from rest_framework.decorators import action from rest_framework.request import Request from rest_framework.response import Response from rest_framework.routers import DefaultRouter from rest_framework.viewsets import ViewSet from django_celery.message.tasks import my_task from django_定时器.团购任务 import TwoHourWindowManager from django_定时器.幸运拼团数据库 import lucky拼团对象类型, lucky拼团 from sixGuoDjango import ResData, BaseResponse from wechat_数据库.支付订单数据库.商品订单数据 import order订单 from wechat_数据库.洗衣液商品数据库.六果洗衣液商品 import goods商品, goods商品Choices from wechat_数据库.用户数据库.小程序登陆用户 import weiuser from wechat_数据库.雪花算法.雪花算法工具 import generator from wechat_项目工具包.微信支付工具包.微信支付类 import paymentCategory, wechatPay # window = 0 window = TwoHourWindowManager() default_channel_layer = cast(BaseChannelLayer, get_channel_layer(alias="default")) class 拼团业务接口ViewSets(ViewSet): lock = threading.Lock() def 处理积分方法(self, attach): pass # 将字符串转为换字典 attachData = orjson.loads(attach) # 拿到数据 print("\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n", attachData) share订单分享者ID = pydash.get(obj=attachData, path="share订单分享者ID") out_trade_no = pydash.get(obj=attachData, path="out_trade_no") if share订单分享者ID == "六果": # 说明没有分享都,啥也不需要干 pass else: print("\n🍎 🍏 🍊 有分享者,需要调用添加积分的接口 \n", ) uri = "https://xiao.sixgou.com/integral/pay_add/" requests.post(url=uri, json={"attachData": attachData}) pass @action(detail=False, methods=["post"], url_path="current") def 查询当前的拼团的数据(self, request: Request): """""" self_user_unionid = request.data.get("self_user_unionid", None) self_mini_openid = request.data.get("self_mini_openid", None) 拼团商品 = goods商品.objects.filter(goods商品类型=goods商品Choices.幸运拼团.value).values() print("\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n", 拼团商品) 查询对象 = lucky拼团.objects.get(idKey=window.generate_str_id) 时间戳 = (查询对象.dateAndTime.astimezone(tz=ZoneInfo("Asia/Shanghai")) + timedelta(seconds=7200)).timestamp() 最终时间戳 = int(时间戳) * 1000 - int(datetime.datetime.now(tz=ZoneInfo("Asia/Shanghai")).timestamp()) * 1000 resData = {"idKey": 查询对象.idKey, "lucky拼团详细": 查询对象.lucky拼团详细, "dateAndTime": 最终时间戳} httpResData = BaseResponse(resData=ResData(listData=拼团商品, dictData=resData), ).model_dump() return Response(data=httpResData, status=status.HTTP_200_OK) @action(detail=False, methods=["post"], url_path="join") def 加入拼团支付(self, request: Request): """""" url_pay = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi" # 发起请求的链接 self_mini_openid = request.data.get("self_mini_openid", None) self_mini_unionid = request.data.get("self_mini_unionid", None) order商品数据 = request.data.get("order商品数据", None) order商品数量 = request.data.get("order商品数量", None) order商品总价 = request.data.get("order商品总价", None) order商品ID = request.data.get("order商品ID", None) share订单分享者ID = request.data.get("share订单分享者ID", None) # 当前是否有上级对象 order订单类型 = request.data.get("order订单类型", None) superior_unionid = request.data.get("superior_unionid", None) # 当前是否有上级对象 order用户配送地址 = request.data.get("order用户配送地址", None) print("\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n", share订单分享者ID, "\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n") out_trade_no = generator.generate_str() body = { "mchid": paymentCategory.mchid, # 【直连商户号】 直连商户号 "out_trade_no": out_trade_no, # 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。 "appid": paymentCategory.appid, # 【公众号 或者 小程序ID】 "description": "幸运拼团", # 【商品描述】 商品描述要 "notify_url": "https://xiao.sixgou.com/lucky/update/", # 回调地址要 "amount": { "total": 1, # 【总金额】 订单总金额,单位为分。 "currency": "CNY", # 【货币类型】 CNY:人民币,境内商户号仅支持人民币。 }, # 【支付者】 支付者信息。 "payer": { "openid": self_mini_openid, # 【用户标识】 用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID,详见OpenID获取 # "openid": OPENID测试, # 【用户标识】 用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID,详见OpenID获取 }, "attach": orjson.dumps({"share订单分享者ID": share订单分享者ID}, option=orjson.OPT_SORT_KEYS, ).decode( encoding="utf-8") } # 请求的数据 wechat_data = wechatPay(payment=paymentCategory).getpay_jsapi(uri=url_pay, body_data=body, method="POST") order订单.objects.create(order支付商家侧订单号=out_trade_no, order商品总价=order商品总价, order商品数据=order商品数据, order商品数量=order商品数量, order分享者unionid=share订单分享者ID, order商品ID=order商品ID, order支付数据=body, wai外键lucky拼团表_id=window.generate_str_id, order支付状态="支付中", order支付者openid=self_mini_openid, order用户配送地址=order用户配送地址, order订单类型=order订单类型 ) payData = pydash.get(obj=wechat_data, path="response") httpResData = BaseResponse(resData=ResData(listData=[""], dictData=payData), ).model_dump() return Response(data=httpResData, status=status.HTTP_200_OK) @action(detail=False, methods=["post"], url_path="update") def 更新幸运拼团的支付回调接口(self, request: Request): """ """ with self.lock: wechat_data支付回调数据 = wechatPay(payment=paymentCategory).callBack回调解密(headers=request.headers, response_body=request.data) print("\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n", wechat_data支付回调数据, "返回的结果支付返回", type(wechat_data支付回调数据)) out_trade_no = jmespath.search(data=wechat_data支付回调数据, expression="out_trade_no") trade_state_desc = pydash.get(obj=wechat_data支付回调数据, path="trade_state_desc") self_mini_openid = pydash.get(obj=wechat_data支付回调数据, path="payer.openid") attach = pydash.get(obj=wechat_data支付回调数据, path="attach") self.处理积分方法(attach=attach) # 调用异步方法 : 作用 (发起订单录入接口调用) share订单分享者ID = pydash.get(obj=orjson.loads(pydash.get(obj=wechat_data支付回调数据, path="attach")), path="share订单分享者ID") my_task.apply_async(kwargs={"self_mini_openid": self_mini_openid, "out_trade_no": out_trade_no, "share订单分享者ID": share订单分享者ID}, countdown=30) # 更新 拼团订单的 支付状态 生成物流的订单号 = generator.generate_str() order订单.objects.filter(order支付商家侧订单号=out_trade_no).update(order支付数据=wechat_data支付回调数据, order支付状态=trade_state_desc, order物流状态=order订单.order订单choosies物流状态.待发货.value, order物流订单号=生成物流的订单号 ) 当前用户对象 = weiuser.objects.get(mini_openid=self_mini_openid) 参与拼团的对象 = lucky拼团对象类型(wei_openid=self_mini_openid, pay订单号=window.generate_str_id, avatar=当前用户对象.avatar, nickName=当前用户对象.nickName) # 查询当前的对象,然后进行数据的更新 当前拼团的对象 = lucky拼团.objects.get(idKey=window.generate_str_id) print("🍎 🍏🍎 🍏🍎 🍏🍎 🍏🍎 长度是多少了呢", len(当前拼团的对象.lucky拼团详细)) # 需要判断当前列表的长度,如果大于等于5的话,就需要调用清团重开 if len(当前拼团的对象.lucky拼团详细) >= 4: # 需要清掉重新 print("🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 新开团的ID是否变更了", window.generate_str_id) 当前拼团的对象.lucky拼团详细.append(参与拼团的对象) 当前拼团的对象.lucky开团状态 = lucky拼团.choosies.已开团.value 当前拼团的对象.save() 对象 = model_to_dict(instance=当前拼团的对象, fields=None) async_to_sync(awaitable=default_channel_layer.group_send)(group="default_group_name", message={"lucktyData": 对象, "type": "chat_Lucky拼团"}, ) window.开团重置() else: 当前拼团的对象.lucky拼团详细.append(参与拼团的对象) 当前拼团的对象.save() 对象 = model_to_dict(instance=当前拼团的对象, fields=None) async_to_sync(awaitable=default_channel_layer.group_send)(group="default_group_name", message={"lucktyData": 对象, "type": "chat_Lucky拼团"}, ) httpResData = BaseResponse(resData=ResData(listData=[""], dictData={}), ).model_dump() return Response(data=httpResData, status=status.HTTP_200_OK) @action(detail=False, methods=["get", "post", "put", "delete"], url_path="group_opening_order") def 查询当前开团的最后一个团数据(self, request: Request): """""" self_user_unionid = request.data.get("self_user_unionid", None) self_mini_openid = request.data.get("self_mini_openid", None) 拼团订单号 = window.generate_str_id # 查询结果 = lucky拼团.objects.filter(lucky开团状态=lucky拼团.choosies.已开团.value, lucky拼团订单__order支付都ID=self_mini_openid, # lucky拼团订单__order支付状态="支付成功" # ).order_by("-updateTime") 查询结果 = lucky拼团.objects.filter(lucky开团状态=lucky拼团.choosies.已开团.value, lucky拼团详细__contains=[{"wei_openid": self_mini_openid}]).order_by( "-updateTime").first() print(查询结果, "🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 ") if 查询结果 is None: httpResData = BaseResponse(resData=ResData(listData=[""], dictData={}), ).model_dump() return Response(data=httpResData, status=status.HTTP_200_OK) else: 返回结果数据 = model_to_dict(instance=查询结果, fields=None) print(返回结果数据, "🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 ") httpResData = BaseResponse(resData=ResData(listData=[], dictData=返回结果数据), ).model_dump() return Response(data=httpResData, status=status.HTTP_200_OK) # 拼团业务接口ViewSetsRouter = DefaultRouter() # 拼团业务接口ViewSetsRouter.register(prefix="", viewset=拼团业务接口ViewSets, basename="")