from typing import cast import pydash from channels.layers import BaseChannelLayer, get_channel_layer from django.db.models import QuerySet from rest_framework.decorators import action from rest_framework.request import Request from rest_framework.response import Response from rest_framework.viewsets import ViewSet from ulid import ULID from sixGuoDjango import BaseResponse, ResData from wechat_微信支付证书.江苏六果科技有限公司支付证书.六果公司支付类 import sixWechatPay六果泡泡支付 from wechat_微信支付证书.江苏六果科技有限公司支付证书.江苏六果科技有限公司支付参数 import sixpay六果科技公司 from wechat_数据库.用户数据库.小程序积分数据库 import share积分表 from wechat_项目工具包.数据库的工具包.更新用户积分 import miniUser提现状态 default_channel_layer = cast(BaseChannelLayer, get_channel_layer(alias="default")) from functools import wraps import threading def sync_lock(lock): def decorator(fn): @wraps(fn) def wrapper(*args, **kwargs): with lock: return fn(*args, **kwargs) return wrapper return decorator class 积分提现ViewSets(ViewSet): lock = threading.Lock() # 所有请求 共享这一个 lock对象 uri = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills" # 发起提现的接口 @sync_lock(lock=lock) # 锁住这个接口所有并发请求, @action(detail=False, methods=["get", "post", "put", "delete"], url_path="发起提现") def 前端用户发起可提现积分事件(self, request: Request): """""" self_mini_openid = request.data.get("self_mini_openid", None) self_mini_unionid = request.data.get("self_mini_unionid", None) print("用户发起了积分提现在的功能了", self_mini_unionid) # 通地 self_mini_unionid 查询 这个就是分享者的ID share支付订单商家侧的订单号 = f"{ULID()}" 可提现在的数据: QuerySet[ share积分表] = share积分表.objects.filter(share分享者unionid=self_mini_unionid, share积分是否可以提现的状态=miniUser提现状态().可提现, share提现微信侧返回的提现状态__isnull=True) # print(可提现在的数据) sum_limit = 20000 result: list[share积分表] = [] total = 0 for item in 可提现在的数据: if total + item.share分享者积分值 <= sum_limit: result.append(item) total += item.share分享者积分值 else: break # 生成前端需要的数据类型 transferAccountsBody = { "appid": sixpay六果科技公司.appid, "out_bill_no": share支付订单商家侧的订单号, # 必填 integer【商户单号】 # 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一 "transfer_scene_id": "1000", # 必填 integer【转账场景ID】 该笔转账使用的转账场景,可前往“商户平台-产品中心-商家转账”中申请。如:1000(现金营销),1006(企业报销)等 # "openid":"ohQkD7A-N93kljcFmkCyG6e_D9vg", "openid": self_mini_openid, # 必填 integer【收款用户OpenID】 用户在商户appid下的唯一标识。发起转账前需获取到用户的OpenID,获取方式详见参数说明。 # "user_name":"757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45", # 【收款用户姓名】 # 收款方真实姓名。需要加密传入,支持标准RSA算法和国密算法,公钥由微信侧提供。 "transfer_amount": 10000, # 必填 integer【转账金额】 转账金额单位为“分”。 "transfer_remark": "新会员开通有礼", # 必填 string(32)【转账备注】 转账备注,用户收款时可见该备注信息,UTF8编码,最多允许32个字符 "notify_url": "https://xiao.sixgou.com/wechat_mini/积分提现/积分提现回调/", # 选填【通知地址】 异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的URL,必须为HTTPS,不能携带参数。 "user_recv_perception": "现金奖励", # 选填 【用户收款感知】 用户收款时感知到的收款原因将根据转账场景自动展示默认内容。如有其他展示需求, # 必填 array[TransferSceneReportInfo] 【转账场景报备信息】 各转账场景下需报备的内容,商户需要按照所属转账场景规则传参,详见转账场景报备信息字段说明。 "transfer_scene_report_infos": [ { "info_type": "活动名称", # 必填 string(15)【信息类型】 不能超过15个字符,商户所属转账场景下的信息类型,此字段内容为固定值 "info_content": "新人红包", # 必填 【信息内容】 不能超过32个字符,商户所属转账场景下的信息内容,商户可按实际业务场景自定义传参 }, { "info_type": "奖励说明", "info_content": "新人红包", }, ], } # wechat_data提现返回数据 = wechatPay(payment=sixpay六果科技公司).transferAccounts商家转账到零钱(transferAccountsBody=transferAccountsBody) wechat_data提现返回数据 = sixWechatPay六果泡泡支付(pay_uri=self.uri, pay_请求体=transferAccountsBody, ).getpay_发起提现() print(wechat_data提现返回数据) share提现微信侧返回的提现状态 = pydash.get(obj=wechat_data提现返回数据, path="state") share支付微信侧提现订单号 = pydash.get(obj=wechat_data提现返回数据, path="transfer_bill_no") share提现订单商家侧的订单号 = pydash.get(obj=wechat_data提现返回数据, path="out_bill_no") share发起提现的时间 = pydash.get(obj=wechat_data提现返回数据, path="create_time") share提现的数据package_info = pydash.get(obj=wechat_data提现返回数据, path="package_info") if share提现微信侧返回的提现状态 == "WAIT_USER_CONFIRM": for payItem in result: payItem.share提现微信侧返回的提现状态 = share提现微信侧返回的提现状态 payItem.share提现订单商家侧的订单号 = share提现订单商家侧的订单号 payItem.share提现订单微信侧订单号 = share支付微信侧提现订单号 payItem.share提现用户提现状态 = share提现微信侧返回的提现状态 # payItem.share积分是否可以提现的状态 = share提现微信侧返回的提现状态 payItem.save() 前端调用的数据 = { "mchId": sixpay六果科技公司.mchid, "appId": sixpay六果科技公司.appid, "package": share提现的数据package_info, } httpResData = BaseResponse(resData=ResData(listData=[""], dictData=前端调用的数据), ).model_dump() return Response(data=httpResData) httpResData = BaseResponse(resData=ResData(listData=[""], dictData={}, ), code=500).model_dump() return Response(data=httpResData) @action(detail=False, methods=["get", "post", "put", "delete"], url_path="积分提现回调") def 积分提现回调(self, request: Request): pass # 提现返回数据 = wechatPay(payment=paymentCategory).callBack回调解密(headers=request.headers, response_body=request.data) wechat_data支付回调数据 = sixWechatPay六果泡泡支付(pay_uri=None, pay_请求体={}, pay_methon方法="POST").callBack回调解密(headers=request.headers, response_body=request.data) 返回的数据值 = {'mch_id': '1700383419', 'out_bill_no': '01M14YR7TK7B1V6DJ841TKH7FH', 'transfer_bill_no': '1330007188892932608290032933843939', 'transfer_amount': 10, 'state': 'SUCCESS', 'openid': 'ohQkD7NJ5EASxdh6ajad4QR_6i78', 'create_time': '2026-08-29T03:50:07+08:00', 'update_time': '2026-08-29T03:50:11+08:00', 'mchid': '1700383419' } # 收到回调后,需要更新提现的所有订单列表 share提现订单微信侧订单号 = pydash.get(obj=wechat_data支付回调数据, path="transfer_bill_no") share分享者openid = pydash.get(obj=wechat_data支付回调数据, path="openid") state = pydash.get(obj=wechat_data支付回调数据, path="state") share积分表.objects.filter(share提现微信侧返回的提现状态="WAIT_USER_CONFIRM", share提现订单微信侧订单号=share提现订单微信侧订单号, share分享者openid=share分享者openid).update( share提现微信侧返回的提现状态=state, share提现用户提现状态=state, ) print("提现返回数据提现返回数据提现返回数据提现返回数据提现返回数据提现返回数据", wechat_data支付回调数据) return Response(data={})