This commit is contained in:
doudou201703
2026-09-19 11:51:34 +08:00
parent dd4383130d
commit 922583becb
15 changed files with 223 additions and 124 deletions
+3 -7
View File
@@ -29,30 +29,26 @@ def sync_lock(lock):
class 小程序发优惠券到钱包接口ViewSets(ViewSet): class 小程序发优惠券到钱包接口ViewSets(ViewSet):
lock = threading.Lock() # 所有请求 共享这一个 lock对象 lock = threading.Lock() # 所有请求 共享这一个 lock对象
stock_id_代金券批次号 = "22941326"
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="生成优惠券") @action(detail=False, methods=["get", "post", "put", "delete"], url_path="生成优惠券")
def 生成优惠券(self, request: Request): def 生成优惠券(self, request: Request):
"""这里的接口就是将,券,直接发送给前端用户,""" """这里的接口就是将,券,直接发送给前端用户,"""
self_mini_openid = request.data.get("self_mini_openid", None) self_mini_openid = request.data.get("self_mini_openid", None)
self_mini_unionid = request.data.get("self_mini_unionid", 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() stock查询数据领券成功时的处理: stock券数据表 | None = stock券数据表.objects.filter(mini_unionid=self_mini_unionid, mini_openid=self_mini_openid, stock_use_券状态="已领券").first()
if stock查询数据领券成功时的处理 is not None: if stock查询数据领券成功时的处理 is not None:
return Response(data={"stock券状态": "已领券", "stock领券数据": {}}) return Response(data={"stock券状态": "已领券", "stock领券数据": {}})
stock查询数据: stock券数据表 | None = stock券数据表.objects.filter(mini_unionid=self_mini_unionid, mini_openid=self_mini_openid, stock_use_券状态="待领券").first() 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: if stock查询数据 is None:
# 查询数据库,看看用户当前有没有券已发了但是还没有领取的状态 # 查询数据库,看看用户当前有没有券已发了但是还没有领取的状态
# stock发券数据 = stock发送代金券功能(stock_id_代金券批次号="22512292").send发券并返回前端需要的数据() # 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) stock发券数据 = stock发送代金券功能(stock_id_代金券批次号=self.stock_id_代金券批次号, stock券的状态="待领券").send发券并返回前端需要的数据(self_mini_openid=self_mini_openid, self_mini_unionid=self_mini_unionid)
print(stock发券数据)
# 4. 生成签名 # 4. 生成签名
# return Response(data=stock发券数据) # return Response(data=stock发券数据)
return Response(data={"stock券状态": "待领券", "stock领券数据": stock发券数据}) return Response(data={"stock券状态": "待领券", "stock领券数据": stock发券数据})
else: else:
pass pass
print("查询是这里生效了啦")
print({"stock券状态": stock查询数据.stock_use_券状态, "stock领券数据": stock查询数据.stock_未领取券的数据})
return Response(data={"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="领券后更新当前券的状态") @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) self_mini_unionid = request.data.get("self_mini_unionid", None)
stock券状态 = request.data.get("stock券状态", None) stock券状态 = request.data.get("stock券状态", None)
print("用户领券成功了") 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领券数据": {}}) return Response(data={"stock券状态": stock券状态, "stock领券数据": {}})
+59 -29
View File
@@ -2,15 +2,17 @@ from typing import cast
import pydash import pydash
from channels.layers import BaseChannelLayer, get_channel_layer from channels.layers import BaseChannelLayer, get_channel_layer
from django.db.models import QuerySet
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.viewsets import ViewSet from rest_framework.viewsets import ViewSet
from ulid import ULID from ulid import ULID
from sixGuoDjango import BaseResponse, ResData
from wechat_微信支付证书.江苏六果科技有限公司支付证书.六果公司支付类 import sixWechatPay六果泡泡支付
from wechat_微信支付证书.江苏六果科技有限公司支付证书.江苏六果科技有限公司支付参数 import sixpay六果科技公司 from wechat_微信支付证书.江苏六果科技有限公司支付证书.江苏六果科技有限公司支付参数 import sixpay六果科技公司
from wechat_数据库.用户数据库.小程序积分数据库 import share积分表 from wechat_数据库.用户数据库.小程序积分数据库 import share积分表
from wechat_项目工具包.微信支付工具包.微信支付类 import paymentCategory, wechatPay
from wechat_项目工具包.数据库的工具包.更新用户积分 import miniUser提现状态 from wechat_项目工具包.数据库的工具包.更新用户积分 import miniUser提现状态
default_channel_layer = cast(BaseChannelLayer, get_channel_layer(alias="default")) default_channel_layer = cast(BaseChannelLayer, get_channel_layer(alias="default"))
@@ -33,6 +35,7 @@ def sync_lock(lock):
class 积分提现ViewSets(ViewSet): class 积分提现ViewSets(ViewSet):
lock = threading.Lock() # 所有请求 共享这一个 lock对象 lock = threading.Lock() # 所有请求 共享这一个 lock对象
uri = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills" # 发起提现的接口
@sync_lock(lock=lock) # 锁住这个接口所有并发请求, @sync_lock(lock=lock) # 锁住这个接口所有并发请求,
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="发起提现") @action(detail=False, methods=["get", "post", "put", "delete"], url_path="发起提现")
@@ -43,10 +46,27 @@ class 积分提现ViewSets(ViewSet):
print("用户发起了积分提现在的功能了", self_mini_unionid) print("用户发起了积分提现在的功能了", self_mini_unionid)
# 通地 self_mini_unionid 查询 这个就是分享者的ID # 通地 self_mini_unionid 查询 这个就是分享者的ID
share支付订单商家侧的订单号 = f"{ULID()}" share支付订单商家侧的订单号 = f"{ULID()}"
可提现在的数据 = share积分表.objects.filter(share分享者unionid=self_mini_unionid, share积分是否可以提现的状态=miniUser提现状态().可提现) 可提现在的数据: QuerySet[
print(len(可提现在的数据)) 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 = { transferAccountsBody = {
"appid": sixpay六果科技公司.appid, "out_bill_no": share支付订单商家侧的订单号, # 必填 integer【商户单号】 "appid": sixpay六果科技公司.appid,
"out_bill_no": share支付订单商家侧的订单号, # 必填 integer【商户单号】
# 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一 # 商户系统内部的商家单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
"transfer_scene_id": "1000", "transfer_scene_id": "1000",
# 必填 integer【转账场景ID】 该笔转账使用的转账场景,可前往“商户平台-产品中心-商家转账”中申请。如:1000(现金营销),1006(企业报销)等 # 必填 integer【转账场景ID】 该笔转账使用的转账场景,可前往“商户平台-产品中心-商家转账”中申请。如:1000(现金营销),1006(企业报销)等
@@ -54,9 +74,9 @@ class 积分提现ViewSets(ViewSet):
"openid": self_mini_openid, # 必填 integer【收款用户OpenID】 用户在商户appid下的唯一标识。发起转账前需获取到用户的OpenID,获取方式详见参数说明。 "openid": self_mini_openid, # 必填 integer【收款用户OpenID】 用户在商户appid下的唯一标识。发起转账前需获取到用户的OpenID,获取方式详见参数说明。
# "user_name":"757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45", # 【收款用户姓名】 # "user_name":"757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45", # 【收款用户姓名】
# 收款方真实姓名。需要加密传入,支持标准RSA算法和国密算法,公钥由微信侧提供。 # 收款方真实姓名。需要加密传入,支持标准RSA算法和国密算法,公钥由微信侧提供。
"transfer_amount": 10, # 必填 integer【转账金额】 转账金额单位为“分”。 "transfer_amount": 10000, # 必填 integer【转账金额】 转账金额单位为“分”。
"transfer_remark": "新会员开通有礼", # 必填 string(32)【转账备注】 转账备注,用户收款时可见该备注信息,UTF8编码,最多允许32个字符 "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": "现金奖励", # 选填 【用户收款感知】 用户收款时感知到的收款原因将根据转账场景自动展示默认内容。如有其他展示需求, "user_recv_perception": "现金奖励", # 选填 【用户收款感知】 用户收款时感知到的收款原因将根据转账场景自动展示默认内容。如有其他展示需求,
# 必填 array[TransferSceneReportInfo] 【转账场景报备信息】 各转账场景下需报备的内容,商户需要按照所属转账场景规则传参,详见转账场景报备信息字段说明。 # 必填 array[TransferSceneReportInfo] 【转账场景报备信息】 各转账场景下需报备的内容,商户需要按照所属转账场景规则传参,详见转账场景报备信息字段说明。
"transfer_scene_report_infos": [ "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提现返回数据) 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="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发起提现的时间 = pydash.get(obj=wechat_data提现返回数据, path="create_time")
share提现的数据package_info = pydash.get(obj=wechat_data提现返回数据, path="package_info") share提现的数据package_info = pydash.get(obj=wechat_data提现返回数据, path="package_info")
if share提现微信侧返回的提现状态 == "WAIT_USER_CONFIRM":
arry = [{"age": 100}, {"age": 200}, {"age": 300}, {"age": 400}] for payItem in result:
sum_limit = 900 payItem.share提现微信侧返回的提现状态 = share提现微信侧返回的提现状态
payItem.share提现订单商家侧的订单号 = share提现订单商家侧的订单号
result = [] payItem.share提现订单微信侧订单号 = share支付微信侧提现订单号
total = 0 payItem.share提现用户提现状态 = share提现微信侧返回的提现状态
# payItem.share积分是否可以提现的状态 = share提现微信侧返回的提现状态
for item in arry: payItem.save()
if total + item["age"] <= sum_limit: 前端调用的数据 = {
result.append(item) "mchId": sixpay六果科技公司.mchid, "appId": sixpay六果科技公司.appid, "package": share提现的数据package_info,
total += item["age"] }
else: httpResData = BaseResponse(resData=ResData(listData=[""], dictData=前端调用的数据), ).model_dump()
break return Response(data=httpResData)
httpResData = BaseResponse(resData=ResData(listData=[""], dictData={}, ), code=500).model_dump()
print(result) return Response(data=httpResData)
return Response(data=result)
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="积分提现回调") @action(detail=False, methods=["get", "post", "put", "delete"], url_path="积分提现回调")
def 添加商品数据(self, request: Request): def 积分提现回调(self, request: Request):
pass pass
提现返回数据 = wechatPay(payment=paymentCategory).callBack回调解密(headers=request.headers, response_body=request.data) # 提现返回数据 = 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)
print(提现返回数据) 返回的数据值 = {'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={}) return Response(data={})
+11 -3
View File
@@ -2,6 +2,7 @@ from datetime import datetime
from typing import cast from typing import cast
from channels.layers import BaseChannelLayer, get_channel_layer from channels.layers import BaseChannelLayer, get_channel_layer
from django.db import models
from django.db.models import Case, Count, IntegerField, Sum, When from django.db.models import Case, Count, IntegerField, Sum, When
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.request import Request from rest_framework.request import Request
@@ -52,7 +53,7 @@ class 积分查询接口ViewSets(ViewSet):
share总积分=Sum("share分享者积分值"), share总积分=Sum("share分享者积分值"),
share可提现积分=Sum( share可提现积分=Sum(
Case( Case(
When(share积分是否可以提现的状态=miniUser提现状态().可提现, then="share分享者积分值"), When(models.Q(share积分是否可以提现的状态=miniUser提现状态().可提现) & models.Q(share提现微信侧返回的提现状态__isnull=True), then="share分享者积分值"),
default=0, default=0,
output_field=IntegerField() output_field=IntegerField()
) )
@@ -68,17 +69,23 @@ class 积分查询接口ViewSets(ViewSet):
), ),
share已提现积分=Sum( share已提现积分=Sum(
Case( Case(
When(share积分是否可以提现的状态="已提现", then="share分享者积分值" When(share提现微信侧返回的提现状态="SUCCESS", then="share分享者积分值"
), ),
default=0, default=0,
output_field=IntegerField() output_field=IntegerField()
) )
), ),
share提现中积分=Sum(
Case(
When(models.Q(share提现微信侧返回的提现状态="WAIT_USER_CONFIRM"), then="share分享者积分值", ),
default=0,
output_field=IntegerField()
)
),
share点击次数=Count("id_主键") share点击次数=Count("id_主键")
) )
) )
xiaozizidata["unionid"] = self_mini_unionid xiaozizidata["unionid"] = self_mini_unionid
print(xiaozizidata)
return Response(data=xiaozizidata) return Response(data=xiaozizidata)
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="查询当前用户积列详情列表数据") @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) self_mini_unionid = request.data.get("self_mini_unionid", None)
当前的月份 = datetime.now().month 当前的月份 = datetime.now().month
shareDaat = share积分表.objects.filter(share分享者unionid=self_mini_unionid, ).order_by("-dateAndTime").values() shareDaat = share积分表.objects.filter(share分享者unionid=self_mini_unionid, ).order_by("-dateAndTime").values()
print("shareDaatshareDaatshareDaatshareDaatshareDaatshareDaatshareDaatshareDaat", shareDaat)
return Response(data=shareDaat) return Response(data=shareDaat)
@@ -20,14 +20,10 @@ from wechat_mini_服务端接口目录.用工关系接口列表.用工关系接
from wechat_mini_服务端接口目录.附近小程序.附近小程序接口 import 附近小程序ViewSets from wechat_mini_服务端接口目录.附近小程序.附近小程序接口 import 附近小程序ViewSets
小程序服务端管理接口列表ViewSetsRouter = DefaultRouter() 小程序服务端管理接口列表ViewSetsRouter = DefaultRouter()
小程序服务端管理接口列表ViewSetsRouter.register(prefix="nearby_mini_program", viewset=附近小程序ViewSets, 小程序服务端管理接口列表ViewSetsRouter.register(prefix="nearby_mini_program", viewset=附近小程序ViewSets, basename="附近小程序ViewSets")
basename="附近小程序ViewSets") 小程序服务端管理接口列表ViewSetsRouter.register(prefix="phone", viewset=获取手机号ViewSets, basename="获取手机号ViewSets")
小程序服务端管理接口列表ViewSetsRouter.register(prefix="phone", viewset=获取手机号ViewSets, 小程序服务端管理接口列表ViewSetsRouter.register(prefix="token", viewset=获取稳定版接口调用凭据ViewSets, basename="获取稳定版接口调用凭据ViewSets")
basename="获取手机号ViewSets") 小程序服务端管理接口列表ViewSetsRouter.register(prefix="shipment_information_management", 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="用工关系", viewset=用工关系接口ViewSets, basename="用工关系接口ViewSets")
小程序服务端管理接口列表ViewSetsRouter.register(prefix="qrcode", viewset=小程序码接口ViewSets, basename="小程序码接口ViewSets") 小程序服务端管理接口列表ViewSetsRouter.register(prefix="qrcode", viewset=小程序码接口ViewSets, basename="小程序码接口ViewSets")
小程序服务端管理接口列表ViewSetsRouter.register(prefix="scheme", viewset=Scheme接口ViewSets, basename="Scheme接口ViewSets") 小程序服务端管理接口列表ViewSetsRouter.register(prefix="scheme", viewset=Scheme接口ViewSets, basename="Scheme接口ViewSets")
+5 -8
View File
@@ -1,6 +1,6 @@
import threading import threading
from datetime import datetime from datetime import datetime
from typing import List, Dict, Any, Literal, Optional from typing import Any, Dict, List, Literal, Optional
import redis import redis
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@@ -59,13 +59,8 @@ class RedisClientManager(metaclass=SingletonMetaDefault):
def get_client(self, db_name: Optional[ def get_client(self, db_name: Optional[
Literal[ 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_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: ) -> redis.StrictRedis:
""" """"""
:param db_name:
:type db_name:
:return:
:rtype:
"""
if db_name not in self._clients: if db_name not in self._clients:
with self._client_lock: with self._client_lock:
if db_name not in self._clients: # double-check if db_name not in self._clients: # double-check
@@ -154,6 +149,8 @@ class Timestamp:
def uuid_hex(): def uuid_hex():
return uuid8().hex return uuid8().hex
# 使用示例 # 使用示例
if __name__ == "__main__": if __name__ == "__main__":
pass pass
@@ -42,7 +42,7 @@ class sixWechatPay六果泡泡支付(BaseModel):
# ---------- 商户API密钥对(用于签名请求) ---------- # ---------- 商户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_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") wechatpay_public_key_id: str = Field(default="PUB_KEY_ID_0117003834192026080500181856002000", alias="微信支付公钥ID")
@@ -126,7 +126,7 @@ class sixWechatPay六果泡泡支付(BaseModel):
print(e, "捕获了签名串验证不通过的错误") # 签名验证失败 print(e, "捕获了签名串验证不通过的错误") # 签名验证失败
raise "捕获了签名串验证不通过的错误" raise "捕获了签名串验证不通过的错误"
def gouzhao构造签名串(self, ): def getHeaders构造签名串(self, ):
"""注释""" """注释"""
url_data = re.search(r'/v3.*', string=self.pay_uri).group() url_data = re.search(r'/v3.*', string=self.pay_uri).group()
utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp()) 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) associated_data = pydash.get(obj=response_body, path="resource.associated_data", default=None)
nonce = pydash.get(obj=response_body, path="resource.nonce", default=None) nonce = pydash.get(obj=response_body, path="resource.nonce", default=None)
wei_xin_zhi_fu_hui_diao_data = self.modegmc解密( wei_xin_zhi_fu_hui_diao_data = self.modegmc解密(
nonce=nonce, ciphertext=ciphertext, nonce=nonce, ciphertext=ciphertext, associated_data=associated_data,
associated_data=associated_data,
) )
return wei_xin_zhi_fu_hui_diao_data return wei_xin_zhi_fu_hui_diao_data
def getpay_navite发起二维码支付(self, ): def getpay_navite发起二维码支付(self, ):
""" 二维码支付,可以适用于 网站 的用户扫码支付 """ """ 二维码支付,可以适用于 网站 的用户扫码支付 """
headers = self.gouzhao构造签名串() # headers = self.getHeaders构造签名串()
response = requests.post(url=self.pay_uri, headers=headers, json=self.pay_请求体) response = requests.post(url=self.pay_uri, headers=self.pay_Headers, json=self.pay_请求体)
生成的支付链接 = response.json() 生成的支付链接 = response.json()
return 生成的支付链接 return 生成的支付链接
@@ -313,11 +312,16 @@ class sixWechatPay六果泡泡支付(BaseModel):
def 发起退款(self, ): def 发起退款(self, ):
pass pass
uri = f"https://api.mch.weixin.qq.com/v3/refund/domestic/refunds" uri = f"https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"
heardes = self.gouzhao构造签名串() heardes = self.getHeaders构造签名串()
print(heardes) print(heardes)
response_data = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=heardes) response_data = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=heardes)
print(response_data.json()) 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__": if __name__ == "__main__":
pass pass
@@ -62,35 +62,39 @@ class 商品接口ViewSets(ViewSet):
goods_商品标题="六果泡泡 (超划算) 源自天然酵素迅速渗入衣物,99%除菌🦠一洗即净,守护健康", goods_商品标题="六果泡泡 (超划算) 源自天然酵素迅速渗入衣物,99%除菌🦠一洗即净,守护健康",
goods_商品标签=["99%除菌🦠", "99种污渍🫟", ], goods_商品标签=["99%除菌🦠", "99种污渍🫟", ],
# goods_商品销售场景=goods商品Choices.商城商品.value, # goods_商品销售场景=goods商品Choices.商城商品.value,
goods_商品销售场景=goods商品Choices.赢免单.value, goods_商品销售场景=goods商品Choices.商城商品.value,
goods_商品搜索标签=["20"], goods_商品搜索标签=["20"],
goods_商品销售规格={ goods_商品销售规格={
"goods_商品标题": "六果泡泡 (超划算) 源自天然酵素迅速渗入衣物,99%除菌🦠一洗即净,守护健康", "goods_商品标题": "六果泡泡 (超划算) 源自天然酵素迅速渗入衣物,99%除菌🦠一洗即净,守护健康",
"零售价格": 8000, "会员价": 7000, "销售规格": "20斤装/桶", "零售价格": 8000, "会员价": 7000, "销售规格": "20斤装/桶",
"单个商品订单数量": 1, "单个商品订单总金额": 14200, "商品条码": "", "单个商品实际支付价格": 7000, "单个商品订单数量": 1,
"单个商品订单总金额": 14200,
"商品条码": "",
"单个商品实际支付价格": 7000,
"成本价": 12000, "净利润": 12200, "可选参数": ["苹果香", "熏衣草"], "商品ID": f"GOOD{ULID()}", "成本价": 12000, "净利润": 12200, "可选参数": ["苹果香", "熏衣草"], "商品ID": f"GOOD{ULID()}",
"推荐积分": {"企微员工": 1000, "推广员": 5000}, "推荐积分": {"企微员工": 1000, "推广员": 5000},
"goods_商品详情图片": { "goods_商品详情图片": {
"主图": ["https://hudie.xiao.band/icon/six.png"], "主图": ["https://hudie.sixgou.com/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"],
}, },
"goods_sku": { "goods_sku": {
"goods_select_title": "开启衣物芬芳之旅", "goods_select_title": "规格",
"goods_sku_list": [ "goods_sku_list": [
{ {
"goods_sku_id": f"{ULID()}", "goods_sku_id": f"{ULID()}",
"goods_sku_条形码": f"", "goods_sku_条形码": f"",
"goods_sku_name": "苹果香型", "goods_是否默认选择": True, "goods_sku_name": "通用型",
"goods_sku_主图": ["https://hudie.xiao.band/icon/six.png"], "goods_是否默认选择": True,
"goods_sku_详情图": ["https://hudie.xiao.band/icon/six.png", "https://hudie.xiao.band/icon/six.png"], "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.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.sixgou.com/icon/six.png", "https://hudie.sixgou.com/icon/six.png"],
# },
], ],
}, },
}, },
@@ -42,6 +42,7 @@ class 六果科技小程序用户登陆(ViewSet):
superior_unionid = request.data.get("superior_unionid", 上级分享者的默认值) # 如果上级是默认的值 则说明是没有上级的, superior_unionid = request.data.get("superior_unionid", 上级分享者的默认值) # 如果上级是默认的值 则说明是没有上级的,
scene = request.data.get("scene", None) # 微信用户进入小程的场景值 scene = request.data.get("scene", None) # 微信用户进入小程的场景值
shareTicket = request.data.get("shareTicket", None) # 微信用户的shareTicket值 shareTicket = request.data.get("shareTicket", None) # 微信用户的shareTicket值
print("user_手机设备参数user_手机设备参数", user_手机设备参数)
res = wei小程序服务端工具.获取OPENID(js_code=code, appid=paymentCategory.appid, res = wei小程序服务端工具.获取OPENID(js_code=code, appid=paymentCategory.appid,
secret=paymentCategory.appsecret, ) secret=paymentCategory.appsecret, )
# 代码能往下执行:则说明,已经正确拿到结果; # 代码能往下执行:则说明,已经正确拿到结果;
@@ -32,10 +32,11 @@ class share积分表(models.Model):
share点击者昵称 = models.CharField(max_length=128) share点击者昵称 = models.CharField(max_length=128)
share点击者头像 = models.TextField(null=True, blank=True, ) share点击者头像 = models.TextField(null=True, blank=True, )
share分享的商品ID = models.CharField(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.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.JSONField(null=True, blank=True, default=dict)
share积分是否可以提现的状态 = models.CharField(null=True, blank=True, ) share积分是否可以提现的状态 = models.CharField(null=True, blank=True, )
share日期 = models.DateField(blank=True, null=True) share日期 = models.DateField(blank=True, null=True)
@@ -294,11 +294,11 @@ class ems邮政物流工具(BaseModel):
if __name__ == "__main__": if __name__ == "__main__":
# 当脚本直接运行时执行的代码 # 当脚本直接运行时执行的代码
# ems邮政物流工具().生成运单(out_trade_no商家侧支付订单号="") # ems邮政物流工具().生成运单(out_trade_no商家侧支付订单号="")
order物流公司订单编号 = "EMS01KZBJBPHFR9E924DKDW86CGJT_waybill_id" order物流公司订单编号 = "EMS01M2PY16HXDKY9BMQH6XCWDE3D_waybill_id"
ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=100001, action_msg="揽件成功") ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=100001, action_msg="揽件成功")
time.sleep(30) time.sleep(30)
ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=300002, action_msg="开始派送") ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=300002, action_msg="开始派送")
time.sleep(30) time.sleep(30)
ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=300003, action_msg="签收成功") # ems邮政物流工具().模拟更新订单状态(order物流公司订单编号=order物流公司订单编号, action_type=300003, action_msg="签收成功")
# ems邮政物流工具().更新物流快递数据(order物流公司订单编号="EMS01KZAD94RDQFQBVVX705YNH6SE_waybill_id") # ems邮政物流工具().更新物流快递数据(order物流公司订单编号="EMS01KZAD94RDQFQBVVX705YNH6SE_waybill_id")
@@ -95,6 +95,10 @@ class miniTransaction交易管理服务工具(BaseModel):
更新对象.save() 更新对象.save()
print("发起确认交易调用成功了") print("发起确认交易调用成功了")
@classmethod
def xiaozizi(cls):
pass
if __name__ == "__main__": if __name__ == "__main__":
pass pass
@@ -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
@@ -54,11 +54,8 @@ class paymentCategory(sixpay六果科技公司):
class wechatPay(BaseModel): class wechatPay(BaseModel):
payment: type[sixpay六果科技公司] | type[six六果服务商支付参数] payment: type[sixpay六果科技公司] | type[six六果服务商支付参数]
def 构造签名串(self, uri: str, body_data: dict | bytes | str | None = None, def 构造签名串(self, uri: str, body_data: dict | bytes | str | None = None, method: Optional[Literal["GET", "POST", "PATCH"]] = "POST", ):
method: Optional[Literal["GET", "POST", "PATCH"]] = "POST",
):
""" """
""" """
url_data = re.search(r'/v3.*', string=uri).group() url_data = re.search(r'/v3.*', string=uri).group()
shi_jian_chou = str(int(time.time())) # 时间戳 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()]) str_list = ",".join([f'{key}="{value}"' for key, value in data.items()])
# 生成请求头 # 生成请求头
Authorization = f"{s_with_space}{str_list}" Authorization = f"{s_with_space}{str_list}"
headers = { headers = {"Content-Type": "application/json", "Authorization": Authorization, }
"Content-Type": "application/json", "Authorization": Authorization,
}
# headers.update({"Wechatpay-Serial": self.payment.微信支付公钥ID}) # headers.update({"Wechatpay-Serial": self.payment.微信支付公钥ID})
return headers return headers
def getpay_jsapi(self, uri, body_data: dict | bytes | str | None = None, method: Optional[ def getpay_jsapi(self, uri, body_data: dict | bytes | str | None = None, method: Optional[
Literal["GET", "POST"]] = "POST", Literal["GET", "POST"]] = "POST",
): ):
headers = self.构造签名串(uri=uri, body_data=body_data, method=method) headers = self.构造签名串(uri=uri, body_data=body_data, method=method)
# 发送请求 # 发送请求
response: Response = requests.post(url=uri, json=body_data, headers=headers) response: Response = requests.post(url=uri, json=body_data, headers=headers)
@@ -309,8 +303,8 @@ class wechatPay(BaseModel):
@return: @return:
@rtype: @rtype:
""" """
public_key = RSA.import_key(self.payment.wechat_certificate) # public_key = RSA.import_key(self.payment.wechat_certificate)
# public_key = RSA.import_key(self.payment.pem微信支付公钥) public_key = RSA.import_key(self.payment.pem微信支付公钥)
Wechatpay_Timestamp = pydash.get(response_headers, "Wechatpay-Timestamp") Wechatpay_Timestamp = pydash.get(response_headers, "Wechatpay-Timestamp")
Wechatpay_Nonce = pydash.get(response_headers, "Wechatpay-Nonce") Wechatpay_Nonce = pydash.get(response_headers, "Wechatpay-Nonce")
Wechatpay_Signa = pydash.get(response_headers, "Wechatpay-Signature") Wechatpay_Signa = pydash.get(response_headers, "Wechatpay-Signature")
+10 -7
View File
@@ -1,16 +1,19 @@
import os import os
import django import django
import yarl
from sixGuoDjango.settings import base_dir_name from sixGuoDjango.settings import base_dir_name
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{base_dir_name}.settings") os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{base_dir_name}.settings")
django.setup() django.setup()
from wechat_数据库.用户数据库.小程序积分数据库 import share积分表
import segno 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"}
# segno 直接支持输出为 bytes ) # yarl
qr = segno.make_micro("xiaozizi") print(uri.human_repr())
print(qr.png_data_uri()) print(uri.raw_parts)
code = segno.make('Penny Lane', error='h') 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"
print(code.svg_data_uri()) "%25A5%25E8%25AF%25A2/?key=value")
print(query_url.human_repr())
+7 -4
View File
@@ -18,7 +18,7 @@ from qcloud_cos import CosConfig, CosS3Client
default_config = CosS3Client( default_config = CosS3Client(
CosConfig( CosConfig(
Region="ap-nanjing", SecretId="AKID5FE1e4SjPvFLvLNEvRm8KJ5h86sRXR9e", 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"),
) )
@@ -40,7 +40,8 @@ class oss上传腾讯云图片:
:param file: 文件的bytes类型文件 :param file: 文件的bytes类型文件
""" """
response = cls.client.upload_file_from_buffer(Bucket=cls.Bucket, Key=key, 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) data = cls.批量查询图片链接(Key=key)
src = pydash.get(obj=data, path="src") src = pydash.get(obj=data, path="src")
# print( src ) # print( src )
@@ -77,7 +78,7 @@ class oss上传腾讯云图片:
Key = f"six/app应用/用户头像/{name}.png" Key = f"six/app应用/用户头像/{name}.png"
print(Key) print(Key)
response = cls.client.upload_file_from_buffer(Bucket=cls.Bucket, Key=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) img_response = cls.批量查询图片链接(Key=Key)
src = jmespath.search(data=img_response, expression="src", ) src = jmespath.search(data=img_response, expression="src", )
return src return src
@@ -120,8 +121,10 @@ class oss上传腾讯云图片:
if __name__ == "__main__": if __name__ == "__main__":
pass pass
fileImg = Path("../django_static_directory/media/yanhua.jpg").resolve() fileImg = Path("../django_static_directory/media/扫描 4.png").resolve()
print(fileImg) print(fileImg)
print(fileImg.name) print(fileImg.name)
# default_storage.save(name=fileImg.name, content=fileImg.open(mode="rb")) # default_storage.save(name=fileImg.name, content=fileImg.open(mode="rb"))
fileImgFile = open(file=fileImg, mode="rb")
# oss上传腾讯云图片.删除图片() # oss上传腾讯云图片.删除图片()
# print(oss上传腾讯云图片.上传图片(key=f"/demo/{fileImg.name}", file=fileImg.open(mode="rb")), )