diff --git a/django_app/小程序发券接口.py b/django_app/小程序发券接口.py index 1f4758c..3beb997 100644 --- a/django_app/小程序发券接口.py +++ b/django_app/小程序发券接口.py @@ -29,30 +29,26 @@ def sync_lock(lock): class 小程序发优惠券到钱包接口ViewSets(ViewSet): lock = threading.Lock() # 所有请求 共享这一个 lock对象 + stock_id_代金券批次号 = "22941326" @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_openid, self_mini_unionid) stock查询数据领券成功时的处理: stock券数据表 | None = stock券数据表.objects.filter(mini_unionid=self_mini_unionid, mini_openid=self_mini_openid, stock_use_券状态="已领券").first() if stock查询数据领券成功时的处理 is not None: return Response(data={"stock券状态": "已领券", "stock领券数据": {}}) stock查询数据: stock券数据表 | None = stock券数据表.objects.filter(mini_unionid=self_mini_unionid, mini_openid=self_mini_openid, stock_use_券状态="待领券").first() - print(stock查询数据, "在这里查询到的结果") if stock查询数据 is None: # 查询数据库,看看用户当前有没有券已发了但是还没有领取的状态 # stock发券数据 = stock发送代金券功能(stock_id_代金券批次号="22512292").send发券并返回前端需要的数据() - stock发券数据 = stock发送代金券功能(stock_id_代金券批次号="22625737", stock券的状态="待领券").send发券并返回前端需要的数据(self_mini_openid=self_mini_openid, self_mini_unionid=self_mini_unionid) - print(stock发券数据) + stock发券数据 = stock发送代金券功能(stock_id_代金券批次号=self.stock_id_代金券批次号, stock券的状态="待领券").send发券并返回前端需要的数据(self_mini_openid=self_mini_openid, self_mini_unionid=self_mini_unionid) # 4. 生成签名 # return Response(data=stock发券数据) return Response(data={"stock券状态": "待领券", "stock领券数据": stock发券数据}) else: pass - print("查询是这里生效了啦") - print({"stock券状态": stock查询数据.stock_use_券状态, "stock领券数据": stock查询数据.stock_未领取券的数据}) return Response(data={"stock券状态": stock查询数据.stock_use_券状态, "stock领券数据": stock查询数据.stock_未领取券的数据}) @action(detail=False, methods=["get", "post", "put", "delete"], url_path="领券后更新当前券的状态") @@ -62,5 +58,5 @@ class 小程序发优惠券到钱包接口ViewSets(ViewSet): self_mini_unionid = request.data.get("self_mini_unionid", None) stock券状态 = request.data.get("stock券状态", None) print("用户领券成功了") - stock发送代金券功能(stock_id_代金券批次号="22625737", stock券的状态=stock券状态, stock券已领券="已领券").领券后更新当前券的状态(self_mini_openid=self_mini_openid, self_mini_unionid=self_mini_unionid) + stock发送代金券功能(stock_id_代金券批次号=self.stock_id_代金券批次号, stock券的状态=stock券状态, stock券已领券="已领券").领券后更新当前券的状态(self_mini_openid=self_mini_openid, self_mini_unionid=self_mini_unionid) return Response(data={"stock券状态": stock券状态, "stock领券数据": {}}) diff --git a/django_app/积分提现接口.py b/django_app/积分提现接口.py index 3d4059a..c2579fc 100644 --- a/django_app/积分提现接口.py +++ b/django_app/积分提现接口.py @@ -2,15 +2,17 @@ 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 paymentCategory, wechatPay from wechat_项目工具包.数据库的工具包.更新用户积分 import miniUser提现状态 default_channel_layer = cast(BaseChannelLayer, get_channel_layer(alias="default")) @@ -33,6 +35,7 @@ def sync_lock(lock): 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="发起提现") @@ -43,10 +46,27 @@ class 积分提现ViewSets(ViewSet): print("用户发起了积分提现在的功能了", self_mini_unionid) # 通地 self_mini_unionid 查询 这个就是分享者的ID share支付订单商家侧的订单号 = f"{ULID()}" - 可提现在的数据 = share积分表.objects.filter(share分享者unionid=self_mini_unionid, share积分是否可以提现的状态=miniUser提现状态().可提现) - print(len(可提现在的数据)) + 可提现在的数据: 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【商户单号】 + "appid": sixpay六果科技公司.appid, + "out_bill_no": share支付订单商家侧的订单号, # 必填 integer【商户单号】 # 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一 "transfer_scene_id": "1000", # 必填 integer【转账场景ID】 该笔转账使用的转账场景,可前往“商户平台-产品中心-商家转账”中申请。如:1000(现金营销),1006(企业报销)等 @@ -54,9 +74,9 @@ class 积分提现ViewSets(ViewSet): "openid": self_mini_openid, # 必填 integer【收款用户OpenID】 用户在商户appid下的唯一标识。发起转账前需获取到用户的OpenID,获取方式详见参数说明。 # "user_name":"757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45", # 【收款用户姓名】 # 收款方真实姓名。需要加密传入,支持标准RSA算法和国密算法,公钥由微信侧提供。 - "transfer_amount": 10, # 必填 integer【转账金额】 转账金额单位为“分”。 + "transfer_amount": 10000, # 必填 integer【转账金额】 转账金额单位为“分”。 "transfer_remark": "新会员开通有礼", # 必填 string(32)【转账备注】 转账备注,用户收款时可见该备注信息,UTF8编码,最多允许32个字符 - "notify_url": "https://six.sixgou.com/wechat_mini/积分提现/积分提现回调/", # 选填【通知地址】 异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的URL,必须为HTTPS,不能携带参数。 + "notify_url": "https://xiao.sixgou.com/wechat_mini/积分提现/积分提现回调/", # 选填【通知地址】 异步接收微信支付结果通知的回调地址,通知url必须为公网可访问的URL,必须为HTTPS,不能携带参数。 "user_recv_perception": "现金奖励", # 选填 【用户收款感知】 用户收款时感知到的收款原因将根据转账场景自动展示默认内容。如有其他展示需求, # 必填 array[TransferSceneReportInfo] 【转账场景报备信息】 各转账场景下需报备的内容,商户需要按照所属转账场景规则传参,详见转账场景报备信息字段说明。 "transfer_scene_report_infos": [ @@ -69,34 +89,44 @@ class 积分提现ViewSets(ViewSet): }, ], } - wechat_data提现返回数据 = wechatPay(payment=paymentCategory).transferAccounts商家转账到零钱(transferAccountsBody=transferAccountsBody) + # 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="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="out_bill_no") share发起提现的时间 = pydash.get(obj=wechat_data提现返回数据, path="create_time") share提现的数据package_info = pydash.get(obj=wechat_data提现返回数据, path="package_info") - - arry = [{"age": 100}, {"age": 200}, {"age": 300}, {"age": 400}] - sum_limit = 900 - - result = [] - total = 0 - - for item in arry: - if total + item["age"] <= sum_limit: - result.append(item) - total += item["age"] - else: - break - - print(result) - return Response(data=result) + 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): + def 积分提现回调(self, request: Request): pass - 提现返回数据 = wechatPay(payment=paymentCategory).callBack回调解密(headers=request.headers, response_body=request.data) - - print(提现返回数据) + # 提现返回数据 = 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={}) diff --git a/django_app/积分查询管理接口.py b/django_app/积分查询管理接口.py index 12a0504..1d51749 100644 --- a/django_app/积分查询管理接口.py +++ b/django_app/积分查询管理接口.py @@ -2,6 +2,7 @@ from datetime import datetime from typing import cast from channels.layers import BaseChannelLayer, get_channel_layer +from django.db import models from django.db.models import Case, Count, IntegerField, Sum, When from rest_framework.decorators import action from rest_framework.request import Request @@ -52,7 +53,7 @@ class 积分查询接口ViewSets(ViewSet): share总积分=Sum("share分享者积分值"), share可提现积分=Sum( Case( - When(share积分是否可以提现的状态=miniUser提现状态().可提现, then="share分享者积分值"), + When(models.Q(share积分是否可以提现的状态=miniUser提现状态().可提现) & models.Q(share提现微信侧返回的提现状态__isnull=True), then="share分享者积分值"), default=0, output_field=IntegerField() ) @@ -68,17 +69,23 @@ class 积分查询接口ViewSets(ViewSet): ), share已提现积分=Sum( Case( - When(share积分是否可以提现的状态="已提现", then="share分享者积分值" + When(share提现微信侧返回的提现状态="SUCCESS", then="share分享者积分值" ), default=0, output_field=IntegerField() ) ), + share提现中积分=Sum( + Case( + When(models.Q(share提现微信侧返回的提现状态="WAIT_USER_CONFIRM"), then="share分享者积分值", ), + default=0, + output_field=IntegerField() + ) + ), share点击次数=Count("id_主键") ) ) xiaozizidata["unionid"] = self_mini_unionid - print(xiaozizidata) return Response(data=xiaozizidata) @action(detail=False, methods=["get", "post", "put", "delete"], url_path="查询当前用户积列详情列表数据") @@ -89,4 +96,5 @@ class 积分查询接口ViewSets(ViewSet): self_mini_unionid = request.data.get("self_mini_unionid", None) 当前的月份 = datetime.now().month shareDaat = share积分表.objects.filter(share分享者unionid=self_mini_unionid, ).order_by("-dateAndTime").values() + print("shareDaatshareDaatshareDaatshareDaatshareDaatshareDaatshareDaatshareDaat", shareDaat) return Response(data=shareDaat) diff --git a/django_routes/小程序服务端接口管理列表.py b/django_routes/小程序服务端接口管理列表.py index 7cc1b4b..cc398f6 100644 --- a/django_routes/小程序服务端接口管理列表.py +++ b/django_routes/小程序服务端接口管理列表.py @@ -20,14 +20,10 @@ from wechat_mini_服务端接口目录.用工关系接口列表.用工关系接 from wechat_mini_服务端接口目录.附近小程序.附近小程序接口 import 附近小程序ViewSets 小程序服务端管理接口列表ViewSetsRouter = DefaultRouter() -小程序服务端管理接口列表ViewSetsRouter.register(prefix="nearby_mini_program", viewset=附近小程序ViewSets, - basename="附近小程序ViewSets") -小程序服务端管理接口列表ViewSetsRouter.register(prefix="phone", viewset=获取手机号ViewSets, - basename="获取手机号ViewSets") -小程序服务端管理接口列表ViewSetsRouter.register(prefix="token", viewset=获取稳定版接口调用凭据ViewSets, - basename="获取稳定版接口调用凭据ViewSets") -小程序服务端管理接口列表ViewSetsRouter.register(prefix="shipment_information_management", viewset=发货信息录入ViewSets, - basename="发货信息录入ViewSets") +小程序服务端管理接口列表ViewSetsRouter.register(prefix="nearby_mini_program", viewset=附近小程序ViewSets, basename="附近小程序ViewSets") +小程序服务端管理接口列表ViewSetsRouter.register(prefix="phone", viewset=获取手机号ViewSets, basename="获取手机号ViewSets") +小程序服务端管理接口列表ViewSetsRouter.register(prefix="token", viewset=获取稳定版接口调用凭据ViewSets, basename="获取稳定版接口调用凭据ViewSets") +小程序服务端管理接口列表ViewSetsRouter.register(prefix="shipment_information_management", viewset=发货信息录入ViewSets, basename="发货信息录入ViewSets") 小程序服务端管理接口列表ViewSetsRouter.register(prefix="用工关系", viewset=用工关系接口ViewSets, basename="用工关系接口ViewSets") 小程序服务端管理接口列表ViewSetsRouter.register(prefix="qrcode", viewset=小程序码接口ViewSets, basename="小程序码接口ViewSets") 小程序服务端管理接口列表ViewSetsRouter.register(prefix="scheme", viewset=Scheme接口ViewSets, basename="Scheme接口ViewSets") diff --git a/sixGuoDjango/__init__.py b/sixGuoDjango/__init__.py index 12a6cfd..115c8fc 100644 --- a/sixGuoDjango/__init__.py +++ b/sixGuoDjango/__init__.py @@ -1,6 +1,6 @@ import threading from datetime import datetime -from typing import List, Dict, Any, Literal, Optional +from typing import Any, Dict, List, Literal, Optional import redis from pydantic import BaseModel, Field @@ -18,7 +18,7 @@ class SingletonMetaDefault(type): """单例类""" _instances: dict = {} _lock = threading.RLock() - + def __call__(cls, *args, **kwargs): # 使用类本身作为 key(因为 RedisClientManager 不需要参数化实例) # 如果你确实需要参数化单例(比如不同 config),才用 args/kwargs 做 key @@ -34,7 +34,7 @@ class RedisClientManager(metaclass=SingletonMetaDefault): """ 单例 Redis 连接客户端管理器,支持按名称获取不同数据库的客户端。 """ - + _config: Dict[str, str] = { "redis_0": "redis://:com792282@127.0.0.1:6379/0", "redis_1": "redis://:com792282@127.0.0.1:6379/1", @@ -50,22 +50,17 @@ class RedisClientManager(metaclass=SingletonMetaDefault): "redis_11": "redis://:com792282@127.0.0.1:6379/11", "redis_12": "redis://:com792282@127.0.0.1:6379/12", } - + def __init__(self): if not hasattr(self, '_clients'): self._clients = {} self._client_lock = threading.Lock() - + def get_client(self, db_name: Optional[ Literal[ "redis_1", "redis_2", "redis_3", "redis_4", "redis_5", "redis_6", "redis_7", "redis_8", "redis_9", "redis_10", "redis_11", "redis_12"]] = "redis_5", - ) -> redis.StrictRedis: - """ - :param db_name: - :type db_name: - :return: - :rtype: - """ + ) -> redis.StrictRedis: + """""" if db_name not in self._clients: with self._client_lock: if db_name not in self._clients: # double-check @@ -74,7 +69,7 @@ class RedisClientManager(metaclass=SingletonMetaDefault): raise ValueError(f"Redis client config for '{db_name}' not found.") self._clients[db_name] = redis.StrictRedis.from_url(url, decode_responses=True) return self._clients[db_name] - + def close_all(self): """关闭所有已创建的 Redis 连接(可选)""" for client in self._clients.values(): @@ -97,17 +92,17 @@ class BaseResponse(BaseModel): class Timestamp: """时间戳获取工具""" - + def __init__(self): self._current_time = None - + def get_int(self, format_type: Optional[Literal["milliseconds", "microseconds"]] = "milliseconds") -> int: """ 获取当前时间的整型时间戳(秒级) 返回: int 类型的时间戳 """ now = datetime.now() - + if format_type == "seconds": return int(now.timestamp()) elif format_type == "milliseconds": @@ -116,7 +111,7 @@ class Timestamp: return int(now.timestamp() * 1000000) else: raise ValueError(f"不支持的格式类型: {format_type},可选值: seconds/milliseconds/microseconds") - + def get_str(self, format_type: Optional[Literal["milliseconds", "microseconds"]] = "milliseconds") -> str: """ 获取当前时间的字符串时间戳 @@ -130,7 +125,7 @@ class Timestamp: 返回: str 类型的时间戳 """ now = datetime.now() - + if format_type == "seconds": return str(int(now.timestamp())) elif format_type == "milliseconds": @@ -139,7 +134,7 @@ class Timestamp: return str(int(now.timestamp() * 1000000)) else: raise ValueError(f"不支持的格式类型: {format_type},可选值: seconds/milliseconds/microseconds") - + def get_both(self) -> dict: """ 同时获取 int 和 str 格式的时间戳 @@ -154,6 +149,8 @@ class Timestamp: def uuid_hex(): return uuid8().hex + + # 使用示例 if __name__ == "__main__": pass diff --git a/wechat_微信支付证书/江苏六果科技有限公司支付证书/六果公司支付类.py b/wechat_微信支付证书/江苏六果科技有限公司支付证书/六果公司支付类.py index 0d0f412..36ee773 100644 --- a/wechat_微信支付证书/江苏六果科技有限公司支付证书/六果公司支付类.py +++ b/wechat_微信支付证书/江苏六果科技有限公司支付证书/六果公司支付类.py @@ -42,7 +42,7 @@ class sixWechatPay六果泡泡支付(BaseModel): # ---------- 商户API密钥对(用于签名请求) ---------- merchant_private_key_pem: str = Field(default=Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/apiclient_key.pem").read_text(), alias="商户私钥PEM", description="apiclient_key.pem 内容") - merchant_public_key_pem: str = Field(default=Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/微信支付公钥.pem").read_text(), alias="商户公钥PEM", description="apiclient_cert.pem 内容(很少用到)") + merchant_public_key_pem: str = Field(default=Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/apiclient_cert.pem").read_text(), alias="商户公钥PEM", description="apiclient_cert.pem 内容(很少用到)") # ---------- 微信支付公钥(用于验签和加密敏感字段) ---------- wechatpay_public_key_id: str = Field(default="PUB_KEY_ID_0117003834192026080500181856002000", alias="微信支付公钥ID") @@ -126,7 +126,7 @@ class sixWechatPay六果泡泡支付(BaseModel): print(e, "捕获了签名串验证不通过的错误") # 签名验证失败 raise "捕获了签名串验证不通过的错误" - def gouzhao构造签名串(self, ): + def getHeaders构造签名串(self, ): """注释""" url_data = re.search(r'/v3.*', string=self.pay_uri).group() utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp()) @@ -256,15 +256,14 @@ class sixWechatPay六果泡泡支付(BaseModel): associated_data = pydash.get(obj=response_body, path="resource.associated_data", default=None) nonce = pydash.get(obj=response_body, path="resource.nonce", default=None) wei_xin_zhi_fu_hui_diao_data = self.modegmc解密( - nonce=nonce, ciphertext=ciphertext, - associated_data=associated_data, + nonce=nonce, ciphertext=ciphertext, associated_data=associated_data, ) return wei_xin_zhi_fu_hui_diao_data def getpay_navite发起二维码支付(self, ): """ 二维码支付,可以适用于 网站 的用户扫码支付 """ - headers = self.gouzhao构造签名串() - response = requests.post(url=self.pay_uri, headers=headers, json=self.pay_请求体) + # headers = self.getHeaders构造签名串() + response = requests.post(url=self.pay_uri, headers=self.pay_Headers, json=self.pay_请求体) 生成的支付链接 = response.json() return 生成的支付链接 @@ -313,10 +312,15 @@ class sixWechatPay六果泡泡支付(BaseModel): def 发起退款(self, ): pass uri = f"https://api.mch.weixin.qq.com/v3/refund/domestic/refunds" - heardes = self.gouzhao构造签名串() + heardes = self.getHeaders构造签名串() print(heardes) response_data = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=heardes) print(response_data.json()) + + def getpay_发起提现(self): + pass + response: Response = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=self.pay_Headers) + return response.json() if __name__ == "__main__": diff --git a/wechat_接口/商品订单模拟接口/商品数据接口.py b/wechat_接口/商品订单模拟接口/商品数据接口.py index f254b90..830f83c 100644 --- a/wechat_接口/商品订单模拟接口/商品数据接口.py +++ b/wechat_接口/商品订单模拟接口/商品数据接口.py @@ -62,35 +62,39 @@ class 商品接口ViewSets(ViewSet): goods_商品标题="六果泡泡 (超划算) 源自天然酵素迅速渗入衣物,99%除菌🦠一洗即净,守护健康", goods_商品标签=["99%除菌🦠", "99种污渍🫟", ], # goods_商品销售场景=goods商品Choices.商城商品.value, - goods_商品销售场景=goods商品Choices.赢免单.value, + goods_商品销售场景=goods商品Choices.商城商品.value, goods_商品搜索标签=["20"], goods_商品销售规格={ "goods_商品标题": "六果泡泡 (超划算) 源自天然酵素迅速渗入衣物,99%除菌🦠一洗即净,守护健康", "零售价格": 8000, "会员价": 7000, "销售规格": "20斤装/桶", - "单个商品订单数量": 1, "单个商品订单总金额": 14200, "商品条码": "", "单个商品实际支付价格": 7000, + "单个商品订单数量": 1, + "单个商品订单总金额": 14200, + "商品条码": "", + "单个商品实际支付价格": 7000, "成本价": 12000, "净利润": 12200, "可选参数": ["苹果香", "熏衣草"], "商品ID": f"GOOD{ULID()}", "推荐积分": {"企微员工": 1000, "推广员": 5000}, "goods_商品详情图片": { - "主图": ["https://hudie.xiao.band/icon/six.png"], - "详情图": ["https://hudie.xiao.band/icon/six.png", "https://hudie.xiao.band/icon/six.png"], + "主图": ["https://hudie.sixgou.com/icon/six.png"], + "详情图": ["https://hudie.sixgou.com/icon/six.png", "https://hudie.sixgou.com/icon/six.png"], }, "goods_sku": { - "goods_select_title": "开启衣物芬芳之旅", + "goods_select_title": "规格", "goods_sku_list": [ { "goods_sku_id": f"{ULID()}", "goods_sku_条形码": f"", - "goods_sku_name": "苹果香型", "goods_是否默认选择": True, - "goods_sku_主图": ["https://hudie.xiao.band/icon/six.png"], - "goods_sku_详情图": ["https://hudie.xiao.band/icon/six.png", "https://hudie.xiao.band/icon/six.png"], - }, - { - "goods_sku_id": f"{ULID()}", - "goods_sku_条形码": f"", - "goods_sku_name": "桔子香型", "goods_是否默认选择": False, - "goods_sku_主图": ["https://hudie.sixgou.com/%E5%85%AD%E6%9E%9C%E6%B3%A1%E6%B3%A1%E4%BA%A7%E5%93%81%E5%9B%BE.png"], - "goods_sku_详情图": ["https://hudie.xiao.band/icon/six.png", "https://hudie.xiao.band/icon/six.png"], + "goods_sku_name": "通用型", + "goods_是否默认选择": True, + "goods_sku_主图": ["https://hudie.sixgou.com/icon/six.png"], + "goods_sku_详情图": ["https://hudie.sixgou.com/icon/six.png", "https://hudie.sixgou.com/icon/six.png"], }, + # { + # "goods_sku_id": f"{ULID()}", + # "goods_sku_条形码": f"", + # "goods_sku_name": "桔子香型", "goods_是否默认选择": False, + # "goods_sku_主图": ["https://hudie.sixgou.com/%E5%85%AD%E6%9E%9C%E6%B3%A1%E6%B3%A1%E4%BA%A7%E5%93%81%E5%9B%BE.png"], + # "goods_sku_详情图": ["https://hudie.sixgou.com/icon/six.png", "https://hudie.sixgou.com/icon/six.png"], + # }, ], }, }, diff --git a/wechat_接口/小程序用户接口/小程序用户登陆接口.py b/wechat_接口/小程序用户接口/小程序用户登陆接口.py index f070bd1..ee0cce0 100644 --- a/wechat_接口/小程序用户接口/小程序用户登陆接口.py +++ b/wechat_接口/小程序用户接口/小程序用户登陆接口.py @@ -42,6 +42,7 @@ class 六果科技小程序用户登陆(ViewSet): superior_unionid = request.data.get("superior_unionid", 上级分享者的默认值) # 如果上级是默认的值 则说明是没有上级的, scene = request.data.get("scene", None) # 微信用户进入小程的场景值 shareTicket = request.data.get("shareTicket", None) # 微信用户的shareTicket值 + print("user_手机设备参数user_手机设备参数", user_手机设备参数) res = wei小程序服务端工具.获取OPENID(js_code=code, appid=paymentCategory.appid, secret=paymentCategory.appsecret, ) # 代码能往下执行:则说明,已经正确拿到结果; diff --git a/wechat_数据库/用户数据库/小程序积分数据库.py b/wechat_数据库/用户数据库/小程序积分数据库.py index 20412a7..91760ff 100644 --- a/wechat_数据库/用户数据库/小程序积分数据库.py +++ b/wechat_数据库/用户数据库/小程序积分数据库.py @@ -32,10 +32,11 @@ class share积分表(models.Model): share点击者昵称 = models.CharField(max_length=128) share点击者头像 = models.TextField(null=True, blank=True, ) share分享的商品ID = models.CharField(null=True, blank=True, ) - share支付订单商家侧的订单号 = models.CharField(max_length=128, null=True, blank=True, ) - share支付用户提现状态 = models.CharField(max_length=128, null=True, blank=True, ) - share支付微信侧返回的提现状态 = models.CharField(max_length=128, null=True, blank=True, ) - share支付提现微信公司生成的转账数据 = models.JSONField(null=True, blank=True, default=dict) + share提现订单商家侧的订单号 = models.CharField(max_length=128, null=True, blank=True, ) + share提现订单微信侧订单号 = models.CharField(max_length=128, null=True, blank=True, ) + share提现用户提现状态 = models.CharField(max_length=128, null=True, blank=True, ) + share提现微信侧返回的提现状态 = models.CharField(max_length=128, null=True, blank=True, ) + share提现微信公司生成的转账数据 = models.JSONField(null=True, blank=True, default=dict) share积分是否可以提现的状态 = models.CharField(null=True, blank=True, ) share日期 = models.DateField(blank=True, null=True) diff --git a/wechat_项目工具包/EMS中国邮政/ems邮政.py b/wechat_项目工具包/EMS中国邮政/ems邮政.py index fcef575..a06b836 100644 --- a/wechat_项目工具包/EMS中国邮政/ems邮政.py +++ b/wechat_项目工具包/EMS中国邮政/ems邮政.py @@ -294,11 +294,11 @@ class ems邮政物流工具(BaseModel): if __name__ == "__main__": # 当脚本直接运行时执行的代码 # ems邮政物流工具().生成运单(out_trade_no商家侧支付订单号="") - order物流公司订单编号 = "EMS01KZBJBPHFR9E924DKDW86CGJT_waybill_id" + order物流公司订单编号 = "EMS01M2PY16HXDKY9BMQH6XCWDE3D_waybill_id" ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=100001, action_msg="揽件成功") time.sleep(30) ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=300002, action_msg="开始派送") time.sleep(30) - ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=300003, action_msg="签收成功") + # ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=300003, action_msg="签收成功") # ems邮政物流工具().更新物流快递数据(order物流公司订单编号="EMS01KZAD94RDQFQBVVX705YNH6SE_waybill_id") diff --git a/wechat_项目工具包/小程序交易管理服务/小程序交易订单管理工具.py b/wechat_项目工具包/小程序交易管理服务/小程序交易订单管理工具.py index 87559ea..2e53417 100644 --- a/wechat_项目工具包/小程序交易管理服务/小程序交易订单管理工具.py +++ b/wechat_项目工具包/小程序交易管理服务/小程序交易订单管理工具.py @@ -94,6 +94,10 @@ class miniTransaction交易管理服务工具(BaseModel): 更新对象.order物流状态 = "待用户确认收货" 更新对象.save() print("发起确认交易调用成功了") + + @classmethod + def xiaozizi(cls): + pass if __name__ == "__main__": diff --git a/wechat_项目工具包/微信支付工具包/代金券后端发放券.py b/wechat_项目工具包/微信支付工具包/代金券后端发放券.py new file mode 100644 index 0000000..56ef8b1 --- /dev/null +++ b/wechat_项目工具包/微信支付工具包/代金券后端发放券.py @@ -0,0 +1,58 @@ +from datetime import datetime +from zoneinfo import ZoneInfo + +import requests +import yarl +from pydantic import BaseModel +from ulid import ULID + +from wechat_微信支付证书.江苏六果科技有限公司支付证书.六果公司支付类 import sixWechatPay六果泡泡支付 + + +class MerchantCoupon代金券API(BaseModel): + # demo_必填: int = Field(..., description="描述") # 必传属发生 + + # demo_可选: Optional[int] = None # 可选值 + # demo_默认值: int = Field(default=100001, description="描述") # 有默认值 + # demo_联合类型: Literal["xiao", "zizi"] = Field(..., description="描述") 商家券 + + def model_post_init(self, __context): + print("初始化完成,自动调用 model_post_init") + + def 发放指定批次的代金券(self, mini_openid): + pass + uri = f"https://api.mch.weixin.qq.com/v3/marketing/favor/users/{mini_openid}/coupons" + out_request_no = str(ULID()) + body = { + "stock_id": "22941326", # 必须为代金券(全场券或单品券)批次号 + "out_request_no": out_request_no, # 【商户单据号】商户此次发放凭据号(格式:商户id+日期+流水号),商户侧需保持唯一性 + "appid": sixWechatPay六果泡泡支付().appid, # 公众账号ID】微信为发券方商户分配的公众账号ID + "stock_creator_mchid": sixWechatPay六果泡泡支付().mchid, # 创建方商户号。 + } + header = sixWechatPay六果泡泡支付(pay_uri=uri, pay_请求体=body, ).pay_Headers + print(header) + postData = requests.post(url=uri, json=body, headers=header).json() + print(postData) + + def 根据商户号查用户的券(self, mini_openid): + pass + uri = "" + uri = yarl.URL.build(scheme='https', host="api.mch.weixin.qq.com", path=f"/v3/marketing/favor/users/{mini_openid}/coupons", + query={"appid": sixWechatPay六果泡泡支付().appid, "creator_mchid": sixWechatPay六果泡泡支付().mchid} + ) # yarl + print(uri.human_repr()) + headers = sixWechatPay六果泡泡支付(pay_uri=uri.human_repr(), pay_methon方法="GET").pay_Headers + print(headers) + postData = requests.get(url=uri.human_repr(), headers=headers).json() + print(postData) + + +if __name__ == "__main__": + pass + print(ULID(), type(ULID())) + # MerchantCoupon代金券API().发放指定批次的代金券(mini_openid="ohQkD7NMWkO2aehP9wjBTUXtN7Y0") + MerchantCoupon代金券API().根据商户号查用户的券(mini_openid="ohQkD7NMWkO2aehP9wjBTUXtN7Y0") + utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp()) + uri = yarl.URL.build(scheme='https', host="xiao.sixgou.com", path="/开票/开票回调接口/", + query={"key": "value"} + ) # yarl diff --git a/wechat_项目工具包/微信支付工具包/微信支付类.py b/wechat_项目工具包/微信支付工具包/微信支付类.py index 1886726..49621fd 100644 --- a/wechat_项目工具包/微信支付工具包/微信支付类.py +++ b/wechat_项目工具包/微信支付工具包/微信支付类.py @@ -54,11 +54,8 @@ class paymentCategory(sixpay六果科技公司): class wechatPay(BaseModel): payment: type[sixpay六果科技公司] | type[six六果服务商支付参数] - def 构造签名串(self, uri: str, body_data: dict | bytes | str | None = None, - method: Optional[Literal["GET", "POST", "PATCH"]] = "POST", - ): + def 构造签名串(self, uri: str, body_data: dict | bytes | str | None = None, method: Optional[Literal["GET", "POST", "PATCH"]] = "POST", ): """ - """ url_data = re.search(r'/v3.*', string=uri).group() shi_jian_chou = str(int(time.time())) # 时间戳 @@ -101,16 +98,13 @@ class wechatPay(BaseModel): str_list = ",".join([f'{key}="{value}"' for key, value in data.items()]) # 生成请求头 Authorization = f"{s_with_space}{str_list}" - headers = { - "Content-Type": "application/json", "Authorization": Authorization, - } + headers = {"Content-Type": "application/json", "Authorization": Authorization, } # headers.update({"Wechatpay-Serial": self.payment.微信支付公钥ID}) return headers def getpay_jsapi(self, uri, body_data: dict | bytes | str | None = None, method: Optional[ Literal["GET", "POST"]] = "POST", ): - headers = self.构造签名串(uri=uri, body_data=body_data, method=method) # 发送请求 response: Response = requests.post(url=uri, json=body_data, headers=headers) @@ -309,8 +303,8 @@ class wechatPay(BaseModel): @return: @rtype: """ - public_key = RSA.import_key(self.payment.wechat_certificate) - # public_key = RSA.import_key(self.payment.pem微信支付公钥) + # public_key = RSA.import_key(self.payment.wechat_certificate) + public_key = RSA.import_key(self.payment.pem微信支付公钥) Wechatpay_Timestamp = pydash.get(response_headers, "Wechatpay-Timestamp") Wechatpay_Nonce = pydash.get(response_headers, "Wechatpay-Nonce") Wechatpay_Signa = pydash.get(response_headers, "Wechatpay-Signature") diff --git a/测试数据库.py b/测试数据库.py index 91862b0..9330c3c 100644 --- a/测试数据库.py +++ b/测试数据库.py @@ -1,16 +1,19 @@ import os import django +import yarl from sixGuoDjango.settings import base_dir_name os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{base_dir_name}.settings") django.setup() +from wechat_数据库.用户数据库.小程序积分数据库 import share积分表 -import segno - -# segno 直接支持输出为 bytes -qr = segno.make_micro("xiaozizi") -print(qr.png_data_uri()) -code = segno.make('Penny Lane', error='h') -print(code.svg_data_uri()) +uri = yarl.URL.build(scheme='https', host="xiao.sixgou.com", path="/wechat_mini/%E7%A7%AF%E5%88%86%E6%9F%A5%E8%AF%A2/%E7%BB%9F%E8%AE%A1%E7%A7%AF%E5%88%86%E6%9F%A5%E8%AF%A2/", + query={"key": "value"} + ) # yarl +print(uri.human_repr()) +print(uri.raw_parts) +query_url = yarl.URL(val="https://xiao.sixgou.com/wechat_mini/%25E7%25A7%25AF%25E5%2588%2586%25E6%259F%25A5%25E8%25AF%25A2/%25E7%25BB%259F%25E8%25AE%25A1%25E7%25A7%25AF%25E5%2588%2586%25E6%259F" + "%25A5%25E8%25AF%25A2/?key=value") +print(query_url.human_repr()) diff --git a/第三方工具目录/腾讯云.py b/第三方工具目录/腾讯云.py index d88c554..40b1250 100644 --- a/第三方工具目录/腾讯云.py +++ b/第三方工具目录/腾讯云.py @@ -18,7 +18,7 @@ from qcloud_cos import CosConfig, CosS3Client default_config = CosS3Client( CosConfig( Region="ap-nanjing", SecretId="AKID5FE1e4SjPvFLvLNEvRm8KJ5h86sRXR9e", - SecretKey="NWTFoDUaWHvOhrriMo4FG7pOmxwxpY7V", Token=None, Scheme="https", Domain="hudie.xiao.band", ), + SecretKey="NWTFoDUaWHvOhrriMo4FG7pOmxwxpY7V", Token=None, Scheme="https", Domain="hudie.xiao.band"), ) @@ -30,9 +30,9 @@ class oss上传腾讯云图片: # key: str # Bucket: str = "sixgou-1320557642" # 腾讯云配置(元宝) Bucket: str = "six-1407732583" # 蝴蝶云配置 - + client: CosS3Client = default_config - + @classmethod def 上传图片(cls, key: str, file, ): """ @@ -40,12 +40,13 @@ class oss上传腾讯云图片: :param file: 文件的bytes类型文件 """ response = cls.client.upload_file_from_buffer(Bucket=cls.Bucket, Key=key, - Body=file, ) # Body: 文件的 bytes 类型数据 必须要是一个可以调用read()方法的对象 + Body=file, ) # Body: 文件的 bytes 类型数据 必须要是一个可以调用read()方法的对象 + print(response) data = cls.批量查询图片链接(Key=key) src = pydash.get(obj=data, path="src") # print( src ) return src - + @classmethod def update本地图片文件(cls, key: str, filename: str, path_name: Path): """ @@ -60,7 +61,7 @@ class oss上传腾讯云图片: progress_callback=None, # progress_callback: 上传进度回调函数,None 表示不使用回调函数 ) cls.批量查询图片链接(Key=Key) - + @classmethod def 批量查询图片链接(cls, Key): """ @@ -69,7 +70,7 @@ class oss上传腾讯云图片: url = cls.client.get_object_url(Bucket=cls.Bucket, Key=Key, ) data = {"type": "image", "src": url, } return data - + @classmethod def 处理用户头像(cls, content: bytes, name: str): """""" @@ -77,21 +78,21 @@ class oss上传腾讯云图片: Key = f"six/app应用/用户头像/{name}.png" print(Key) response = cls.client.upload_file_from_buffer(Bucket=cls.Bucket, Key=Key, - Body=image, ) # Body: 文件的 bytes 类型数据 必须要是一个可以调用read()方法的对象 + Body=image, ) # Body: 文件的 bytes 类型数据 必须要是一个可以调用read()方法的对象 img_response = cls.批量查询图片链接(Key=Key) src = jmespath.search(data=img_response, expression="src", ) return src - + @classmethod def 删除图片(cls): data = cls.client.delete_object(Bucket=cls.Bucket, Key="六果项目/app/加.png") print(data) - + @classmethod def xiaozizi(cls): data = cls.client.delete_object(Bucket=cls.Bucket, Key="zizi/") print(data) - + @classmethod def 删除目录(cls): pass @@ -106,7 +107,7 @@ class oss上传腾讯云图片: # 删除 res = cls.client.delete_object(Bucket=cls.Bucket, Key=Key) print(res) - + @classmethod def 查询所有的图片(cls): pass @@ -120,8 +121,10 @@ class oss上传腾讯云图片: if __name__ == "__main__": pass - fileImg = Path("../django_static_directory/media/yanhua.jpg").resolve() + fileImg = Path("../django_static_directory/media/扫描 4.png").resolve() print(fileImg) print(fileImg.name) # default_storage.save(name=fileImg.name, content=fileImg.open(mode="rb")) + fileImgFile = open(file=fileImg, mode="rb") # oss上传腾讯云图片.删除图片() + # print(oss上传腾讯云图片.上传图片(key=f"/demo/{fileImg.name}", file=fileImg.open(mode="rb")), )