This commit is contained in:
doudou201703
2026-08-21 23:48:29 +08:00
parent 0e2fe60253
commit dd4383130d
20 changed files with 179 additions and 241 deletions
+3 -3
View File
@@ -16,7 +16,6 @@ from rest_framework.viewsets import ViewSet
from django_jwt_token.jwt认证接口 import Jwt身份认证
from sixGuoDjango import BaseResponse, ResData, redis_5
from wechat_token.token工具包 import sixToken
default_channel_layer = cast(BaseChannelLayer, get_channel_layer(alias="default"))
@@ -37,7 +36,7 @@ def sync_lock(lock):
class DemoXiaoViewSets(ViewSet):
lock = threading.Lock() # 所有请求 共享这一个 lock对象
lock_sync_lock = threading.Lock() # 所有请求 共享这一个 lock对象
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="zizi")
def 只用于初始化项目测试接口(self, request: Request):
@@ -103,7 +102,8 @@ class DemoXiaoViewSets(ViewSet):
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="中文", )
def 中文(self, request: Request):
xiaozizi = request.data.get("xiaozizi", None)
return Response(data={"msg": xiaozizi})
print(xiaozizi)
return Response(data={"data_uri": "0909090"}, status=status.HTTP_200_OK)
DemoXiaoViewSetsDemoRouter = DefaultRouter()
+2
View File
@@ -45,12 +45,14 @@ class 小程序发优惠券到钱包接口ViewSets(ViewSet):
# 查询数据库,看看用户当前有没有券已发了但是还没有领取的状态
# 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发券数据)
# 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="领券后更新当前券的状态")
@@ -5,5 +5,4 @@ from wechat_mini_服务端接口目录.小程序用户地址定位.小程序用
小程序用户地址定位地图Router = DefaultRouter()
小程序用户地址定位地图Router.register(prefix="delivery", viewset=用户配送地址ViewSets, basename="用户配送地址ViewSets")
小程序用户地址定位地图Router.register(prefix="map", viewset=小程序用户的位置接口ViewSets,
basename="小程序用户的位置接口ViewSets")
小程序用户地址定位地图Router.register(prefix="map", viewset=小程序用户的位置接口ViewSets, basename="小程序用户的位置接口ViewSets")
@@ -42,7 +42,6 @@ class 接收微信的code回调ViewSets(ViewSet):
def jwt_生成token(self, openid, uniond):
# 读取私钥的 bytes字符串
# 创建一个 JWT对象
jwt对象实例 = JWT() # 创建对象
# 创建 payload
@@ -72,6 +71,7 @@ class 接收微信的code回调ViewSets(ViewSet):
openid = pydash.get(obj=postData, path="openid")
scope = pydash.get(obj=postData, path="scope")
unionid = pydash.get(obj=postData, path="unionid")
print(postData, "00000000000000000000")
return postData
def get获取用户个人信息(self, code, state):
@@ -126,7 +126,7 @@ class 接收微信的code回调ViewSets(ViewSet):
openid = pydash.get(obj=user_info_用户信息, path="openid")
unionid = pydash.get(obj=user_info_用户信息, path="unionid")
print("为什么没有值了呢", openid, unionid)
token = self.jwt_生成token(openid=openid, uniond=unionid)
token = self.jwt_生成token(openid=openid, uniond=unionid) # 前端带着code进来,
setData = pydash.set_(obj=user_info_用户信息, path="token", value=token)
query_string = urlencode(setData, )
uri = f"myapp://open/home?{query_string}"
+4 -4
View File
@@ -267,7 +267,7 @@ html = """
# SMTP服务器: smtp.163.com
def send_email_bcc_only(emSubject主题, emBody内容, to_emails):
def send_email_bcc_only(emSubject主题, emBody内容, to_emails_收件人列表):
"""只有 BCC 收件人,TO 字段为空"""
from_email = "792282@qq.com"
password = "epagsnfwzrkrbgfa"
@@ -283,12 +283,12 @@ def send_email_bcc_only(emSubject主题, emBody内容, to_emails):
with smtplib.SMTP_SSL("smtp.qq.com", 465) as emServer:
emServer.login(from_email, password)
# ✅ 所有收件人都在 to_addrs 中,但不会显示在邮件头
emServer.sendmail(from_email, to_emails, msg.as_string())
print(f"邮件已密送给 {len(to_emails)} 位收件人")
emServer.sendmail(from_email, to_emails_收件人列表, msg.as_string())
print(f"邮件已密送给 {len(to_emails_收件人列表)} 位收件人")
except Exception as e:
print(f"发送失败: {e}")
# 使用
recipients = ["xiao@xiao.band", "13382551360@163.com"]
send_email_bcc_only(emSubject主题="数字化", emBody内容="邮件的内容", to_emails=["xiao@xiao.band", ])
send_email_bcc_only(emSubject主题="数字化", emBody内容="邮件的内容", to_emails_收件人列表=["792282@qq.com", ])
+1 -1
View File
@@ -43,7 +43,7 @@ from wechat_项目授权.服务号认证接口 import sixwechat
# 注册子路由
urlpatterns = [
path("api-auth/", include("rest_framework.urls")),
# path("api-auth/", include("rest_framework.urls")),
path(route="six/", view=include(arg=业务订单接口ViewSetsViewSetsRouter.urls)),
path(route="", view=htmlViewSets.as_view({"get": "home"})), # 项目首页
# path( route="lucky/", view=include( arg=拼团业务接口ViewSetsRouter.urls ) ), # 幸运拼团的业务demo接口
@@ -29,7 +29,6 @@ class 小程序用户的位置接口ViewSets(ViewSet):
经度 = pydash.get(obj=result, path="longitude")
print("\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 用户的定位的数据", result)
地图解析结果 = wei地图工具.经纬度转换为地址(location=f"{纬度},{经度}")
print(地图解析结果, "=============")
省 = pydash.get(obj=地图解析结果, path="result.address_component.province")
市 = pydash.get(obj=地图解析结果, path="result.address_component.city")
区 = pydash.get(obj=地图解析结果, path="result.address_component.district")
+3 -15
View File
@@ -1,10 +1,12 @@
"""
Author: xiao 792282@qq.com
Date: 2025-08-10 11:36:05
LastEditors: xiao 792282@qq.com
LastEditTime: 2025-08-17 13:38:39
FilePath: django_公共认证接口/微信TOKEN.py
Description: 这是默认设置,可以在设置》工具》File Description中进行配置
"""
import os
@@ -93,7 +95,6 @@ class sixToken:
:return:
:rtype:
"""
print("是不是每次都在调用的吗")
查询对象, 是否存在 = weitoken.objects.get_or_create(token_name="mini_token")
if 查询对象.token_value is None:
创建的新对象 = cls.mini_token()
@@ -115,10 +116,7 @@ class sixToken:
params = {"appid": cls.wechat_appid, "secret": cls.wechat_appsecret, "grant_type": "client_credential", "force_refresh": False, }
token_data = requests.post(url="https://api.weixin.qq.com/cgi-bin/stable_token", json=params)
token: dict = token_data.json()
print(token)
wechat_token服务号 = token.get("access_token")
print("服务 号的token", wechat_token服务号)
# return wechat_token
jsapo_url = f"https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={wechat_token服务号}&type=jsapi"
json_data = requests.get(url=jsapo_url).json()
ticket服务号 = pydash.get(obj=json_data, path="ticket", default=None)
@@ -216,17 +214,7 @@ class sixToken:
"grant_type": "authorization_code", # "code": code
"code": code, # 填写第一步获取的code参数
}
# 返回值 = """
# {
# "access_token":"ACCESS_TOKEN",
# "expires_in":7200,
# "refresh_token":"REFRESH_TOKEN",
# "openid":"OPENID",
# "scope":"SCOPE",
# "is_snapshotuser": 1,
# "unionid": "UNIONID"
# }
# """
oauth_token_url = f"https://api.weixin.qq.com/sns/oauth2/access_token"
oauth_token_data = requests.get(url=oauth_token_url, params=params)
# oauth_token: dict = oauth_token_data.json()
@@ -6,13 +6,14 @@ import re
import secrets
from datetime import datetime
from pathlib import Path
from typing import Literal, Optional
from typing import Literal
from zoneinfo import ZoneInfo
import django
import orjson
import pydash
import requests
import xmltodict
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
@@ -46,58 +47,101 @@ class sixWechatPay六果泡泡支付(BaseModel):
# ---------- 微信支付公钥(用于验签和加密敏感字段) ----------
wechatpay_public_key_id: str = Field(default="PUB_KEY_ID_0117003834192026080500181856002000", alias="微信支付公钥ID")
wechatpay_public_key_pem: str = Field(default=Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/微信支付公钥.pem").read_text(), alias="微信支付公钥PEM", description="pub_key.pem 内容")
# ---------- 平台证书(灰度过渡期备用) ----------
platform_cert_pem: Optional[
str] = Field(default=Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/sixgou_ping_tai_zheng_shu_cert.pem").read_text(), alias="平台证书PEM", description="wechatpay.pem 内容")
pay_uri: str | None = Field(None, )
pay_请求体: dict | bytes | str | None = Field(None, description="发请求签名时需要的请求体")
platform_cert_pem: str = Field(default=Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/sixgou_ping_tai_zheng_shu_cert.pem").read_text(), alias="平台证书PEM",
description="wechatpay.pem 内容")
platform_cert_pem_id: str = Field(default="11D762828E947104028F2D045DE78FA806D0D4F2", description="平台证书的证收序列号ID")
pay_uri: str | None = Field(default=None, description="请求支付时需要的微信的url地址")
pay_请求体: dict = Field(default=None, description="发请求签名时需要的请求体")
pay_methon方法: Literal["GET", "POST", "PATCH"] = Field(default="POST", description="发请求签名时需要的请求体")
pay_Headers: dict = Field(default={}, description="生成的初始化请求头")
def model_post_init(self, __context):
pass
""""""
if self.pay_uri is None or self.pay_uri == "":
return None
url_data = re.search(r'/v3.*', string=self.pay_uri).group()
utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp())
random_str = secrets.token_hex(nbytes=16) # 随机字符串
if isinstance(self.pay_请求体, str):
body_inner = self.pay_请求体
elif isinstance(self.pay_请求体, dict):
body_inner = json.dumps(self.pay_请求体)
elif self.pay_请求体 is None:
body_inner = ""
elif isinstance(self.pay_请求体, bytes):
body_inner = self.pay_请求体.decode()
else:
raise TypeError(f"不支持的请求体类型: {type(self.pay_请求体)}")
pay_signaturestring创建成功的签名串 = f"{self.pay_methon方法}\n{url_data}\n{utc_unix_timestamp}\n{random_str}\n{body_inner}\n"
# 构造一个哈希对象
hash_obj = SHA256.new(pay_signaturestring创建成功的签名串.encode(encoding="utf-8"))
# 加载商户私钥
# 调用了 RSA.import_key() 方法,它会从字符串或文件中导入一个 PEM 格式的 RSA 私钥,并返回一个 RsaKey 类型的对象
private_key: RsaKey = RSA.import_key(self.merchant_private_key_pem) # 用私钥来加密
# 生成签名 使用商户的 私钥进行签名
signature = pkcs1_15.new(rsa_key=private_key).sign(msg_hash=hash_obj)
# 对签名进行Base64编码,符合微信支付API要求
encoded_signature = base64.b64encode(s=signature).decode(encoding="utf-8")
# 组装成微信官方需要的数据;
data = {
"mchid": self.mchid,
"nonce_str": random_str,
"serial_no": self.serial_no商户证书的序列号,
"timestamp": utc_unix_timestamp,
"signature": encoded_signature,
} # 组装好的字典数据;
ftr = "WECHATPAY2-SHA256-RSA2048"
s_with_space = ftr.ljust(len(ftr) + 1) # 将字符串长度 +1(填充空格)
str_list = pydash.join(array=[f'{key}="{value}"' for key, value in data.items()], separator=",")
# 生成请求头
Authorization = f"{s_with_space}{str_list}"
headers = {"Content-Type": "application/json", "Authorization": Authorization, }
headers.update({"Wechatpay-Serial": self.wechatpay_public_key_id})
self.pay_Headers = headers
return None
def 验证签名串(self, response_headers, response_data: dict, ):
"""
@param response_headers:
@type response_headers:
@param response_data:
@type response_data:
@return:
@rtype:
"""
public_key = RSA.import_key(self.platform_cert_pem)
""" 注释 """
public_key = RSA.import_key(self.wechatpay_public_key_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")
Wechatpay_Serial = pydash.get(response_headers, "Wechatpay-Serial")
response_data_str = orjson.dumps(response_data, ).decode(encoding="utf-8")
string_to_verify = f"{Wechatpay_Timestamp}\n{Wechatpay_Nonce}\n{response_data_str}\n" # 构造验签名串
hash_obj = SHA256.new(string_to_verify.encode())
if Wechatpay_Serial == self.platform_cert_pem_id:
public_key = RSA.import_key(self.platform_cert_pem)
# 6. 验证签名
if Wechatpay_Serial == self.wechatpay_public_key_id:
public_key = RSA.import_key(self.wechatpay_public_key_pem) # 在这里需要使用最新的微信支付公钥证书
try:
pkcs1_15.new(public_key).verify(msg_hash=hash_obj, signature=base64.b64decode(Wechatpay_Signa))
return True # 签名验证成功
except (ValueError, TypeError) as e:
raise e # 签名验证失败
print(e, "捕获了签名串验证不通过的错误") # 签名验证失败
raise "捕获了签名串验证不通过的错误"
def gouzhao构造签名串(self, ):
"""
"""
"""注释"""
url_data = re.search(r'/v3.*', string=self.pay_uri).group()
utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp())
random_str = secrets.token_hex(nbytes=16) # 随机字符串
pay_signaturestring创建成功的签名串 = ""
# 创建签名请求参数
# 统一处理请求体,得到 body_inner 字符串
if isinstance(self.pay_请求体, str):
pay_signaturestring创建成功的签名串 = f"{self.pay_methon方法}\n{url_data}\n{utc_unix_timestamp}\n{random_str}\n{self.pay_请求体}\n"
if isinstance(self.pay_请求体, dict):
body_inner = json.dumps(obj=self.pay_请求体)
pay_signaturestring创建成功的签名串 = f"{self.pay_methon方法}\n{url_data}\n{utc_unix_timestamp}\n{random_str}\n{body_inner}\n"
if self.pay_请求体 is None:
body_inner = self.pay_请求体
elif isinstance(self.pay_请求体, dict):
body_inner = json.dumps(self.pay_请求体)
elif self.pay_请求体 is None:
body_inner = ""
pay_signaturestring创建成功的签名串 = f"{self.pay_methon方法}\n{url_data}\n{utc_unix_timestamp}\n{random_str}\n{body_inner}\n"
if isinstance(self.pay_请求体, bytes):
elif isinstance(self.pay_请求体, bytes):
body_inner = self.pay_请求体.decode()
else:
raise TypeError(f"不支持的请求体类型: {type(self.pay_请求体)}")
pay_signaturestring创建成功的签名串 = f"{self.pay_methon方法}\n{url_data}\n{utc_unix_timestamp}\n{random_str}\n{body_inner}\n"
# 构造一个哈希对象
@@ -160,9 +204,8 @@ class sixWechatPay六果泡泡支付(BaseModel):
}
def getpay_jsapi发起支付(self, ):
headers = self.gouzhao构造签名串()
# 发送请求
response: Response = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=headers)
response: Response = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=self.pay_Headers)
prepay_id = pydash.get(obj=response.json(), path="prepay_id", default=None)
# 验证请求后返回的数据是否为微信官方所发送;
验证签名结果 = self.验证签名串(response_data=response.json(), response_headers=response.headers)
@@ -225,21 +268,29 @@ class sixWechatPay六果泡泡支付(BaseModel):
生成的支付链接 = response.json()
return 生成的支付链接
def v2签名返回XML(self, ):
def v2签名返回XML(self, sign_data):
"""v2版本的签名:将扫码支付的body转换为微信支付所要求的数据类型"""
sorted_dict = dict(pydash.sort_by(collection=self.pay_请求体.items(), iteratee=0))
sorted_dict = dict(pydash.sort_by(collection=sign_data.items(), iteratee=0))
# 拼接字符串: (将密钥添加到最末尾)
params_list_str = pydash.join(array=[f"{k}={v}" for k, v in sorted_dict.items()], separator="&") + "&key=" + self.api_v2_key
# 得到params_str就是需要 参与 签名的字符串
signature = hashlib.md5(string=params_list_str.encode()).hexdigest().upper() # 使用MD5加密模式
update后的数据 = pydash.set_(obj=self.pay_请求体, path="sign", value=signature)
update后的数据 = pydash.set_(obj=sign_data, path="sign", value=signature)
xml = dicttoxml(obj=update后的数据, custom_root="xml", xml_declaration=False, attr_type=False, cdata=True)
print(type(xml))
headers = self.gouzhao构造签名串()
response = requests.post(url=self.pay_uri, data=xml, headers=headers)
print(response.text)
print(response.json())
return
return xml
def getpay_code扫用户付款码(self, body_data, ) -> dict:
""" """
xml = self.v2签名返回XML(sign_data=body_data)
fu_kuan_url = "https://api.mch.weixin.qq.com/pay/micropay"
res = requests.post(url=fu_kuan_url, data=xml)
# 返回的数据 是 ISO-8859-1 类型
responseStr = res.text.encode("ISO-8859-1")
# 将请求得到的数据 转换为字典格式;
xml_dict = xmltodict.parse(responseStr.decode())
# 得到请求结果并进行解密
print(xml_dict)
return xml_dict
def 解密群号(self, encryptedData, iv, sessionKey):
"""
@@ -36,6 +36,7 @@ class 六果科技小程序用户登陆(ViewSet):
""""""
encryptedData = request.data.get("encryptedData", None) # 解密群号所需要的参数
iv = request.data.get("iv", None) # 解密群号所需要的参数 iv
user_手机设备参数 = request.data.get("user_手机设备参数", None)
code: str = request.data.get("code", "")
# superior_openid = request.data.get( "superior_openid", ) # 如果上级是默认的值 则说明是没有上级的,
superior_unionid = request.data.get("superior_unionid", 上级分享者的默认值) # 如果上级是默认的值 则说明是没有上级的,
@@ -52,8 +53,8 @@ class 六果科技小程序用户登陆(ViewSet):
share分享者对象, share分享者对象是新创建 = weiuser.objects.update_or_create(unionid=superior_unionid, )
# 首次进来的用户要全部的添加上默认的 用户 角色
click点击者对象, self_bool = weiuser.objects.update_or_create(unionid=self_unionid,
defaults={"mini_openid": self_openid})
defaults={"mini_openid": self_openid, "user_手机设备参数": user_手机设备参数})
print("-----------------------------------", user_手机设备参数)
six六果对象, sixBool = weiuser.objects.get_or_create(unionid="六果")
if superior_unionid == 上级分享者的默认值:
share分享者对象 = six六果对象
@@ -13,7 +13,7 @@ from ulid import ULID
from sixGuoDjango import BaseResponse, ResData
from wechat_微信支付证书.江苏六果科技有限公司支付证书.六果公司支付类 import sixWechatPay六果泡泡支付
from wechat_数据库.雪花算法.雪花算法工具 import generator
from wechat_项目工具包.微信支付工具包.微信支付类 import paymentCategory, wechatPay
from wechat_项目工具包.微信支付工具包.微信支付类 import paymentCategory
class 微信支付ViewSets(ViewSet):
@@ -41,8 +41,6 @@ class 微信支付ViewSets(ViewSet):
},
} # 请求的数据
wechat_pay_data = sixWechatPay六果泡泡支付(pay_methon方法="POST", pay_请求体=body_支付数据, pay_uri=url_pay).getpay_jsapi发起支付()
print(wechat_pay_data)
httpResData = BaseResponse(resData=ResData(listData=[""], dictData=wechat_pay_data), ).model_dump()
return Response(data=httpResData, status=status.HTTP_200_OK)
@@ -78,7 +76,7 @@ class 微信支付ViewSets(ViewSet):
return Response(data=httpResData, status=status.HTTP_200_OK, )
@action(detail=False, methods=["post"], url_path="qrCode")
def 付款码支付(self, request: Request):
def 扫用户付款码支付(self, request: Request):
"""
扫用户付款码的测试接口
:param request:
@@ -97,41 +95,18 @@ class 微信支付ViewSets(ViewSet):
"auth_code": auth_code,
"total_fee": 1, # 订单总金额,单位为分,只能为整数,详见支付金额(必填)
}
wechat_data = wechatPay(payment=paymentCategory).getpay_code扫用户付款码(body_data=fu_kuan_data)
print(wechat_data)
# return_code 通信返回码:'SUCCESS' 表示与微信服务器通信成功,'FAIL' 表示通信失败(如网络或参数错误)
return_code = jmespath.search(data=wechat_data, expression="xml.return_code")
# return_msg 通信返回信息:当 return_code 为 'FAIL' 时,此字段包含错误描述;成功时通常为 'OK'
return_msg = jmespath.search(data=wechat_data, expression="xml.return_msg")
# result_code 业务结果码:'SUCCESS' 表示支付成功,'FAIL' 表示支付失败(需结合 err_code 分析,但此处未提取)
result_code = jmespath.search(data=wechat_data, expression="xml.result_code")
# mch_id 商户号(MCH ID):微信支付分配给商户的唯一标识
mch_id = jmespath.search(data=wechat_data, expression="xml.mch_id")
# appid 公众号或小程序的 AppID:发起支付的应用身份标识
appid = jmespath.search(data=wechat_data, expression="xml.appid")
# nonce_str 随机字符串:用于防止重放攻击,由商户生成并随请求发送,微信原样返回
nonce_str = jmespath.search(data=wechat_data, expression="xml.nonce_str")
# openid 用户在当前 AppID 下的唯一标识(OpenID):可用于关联用户账户
openid = jmespath.search(data=wechat_data, expression="xml.openid")
# total_fee 订单总金额(单位:分):例如 '1' 表示 0.01 元
total_fee = jmespath.search(data=wechat_data, expression="xml.total_fee")
# cash_fee_type 现金支付币种:目前微信支付仅支持 'CNY'(人民币)
cash_fee_type = jmespath.search(data=wechat_data, expression="xml.cash_fee_type")
# transaction_id 微信支付系统生成的唯一交易单号:用于对账、退款、查询等操作
transaction_id = jmespath.search(data=wechat_data, expression="xml.transaction_id")
# 商户系统内部订单号:由商户在调用支付接口时传入,用于关联自身业务订单
out_trade_no = jmespath.search(data=wechat_data, expression="xml.out_trade_no")
# 附加数据:商户在支付请求中可自定义传入,微信原样返回(常用于传递门店ID、商品类型等)
attach = jmespath.search(data=wechat_data, expression="xml.attach")
# time_end 支付完成时间:格式为 yyyyMMddHHmmss,例如 '20260304233708' 表示 2026年03月04日 23:37:08
time_end = jmespath.search(data=wechat_data, expression="xml.time_end")
# wechat_data = wechatPay(payment=paymentCategory).getpay_code扫用户付款码(body_data=fu_kuan_data)
# print(wechat_data)
wechat_data = sixWechatPay六果泡泡支付().getpay_code扫用户付款码(body_data=fu_kuan_data)
httpResData = BaseResponse(resData=ResData(listData=[""], dictData={"demo": "xiaozizi"}), ).model_dump()
return Response(data=httpResData, status=status.HTTP_200_OK)
@action(detail=False, methods=["post"], url_path="jsapi_callback")
def jsapi支付回调测试接口(self, request: Request) -> Response:
""" 微信支付成功后的回调接口 """
wechat_data支付回调数据 = sixWechatPay六果泡泡支付(pay_uri="", pay_请求体={}, pay_methon方法="POST").callBack回调解密(headers=request.headers, response_body=request.data)
print("回调的请求体", request.data)
print("回调的请求体", request.headers)
wechat_data支付回调数据 = sixWechatPay六果泡泡支付(pay_uri=None, pay_请求体={}, pay_methon方法="POST").callBack回调解密(headers=request.headers, response_body=request.data)
print("\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n", wechat_data支付回调数据, "\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n")
httpResData = BaseResponse(resData=ResData(listData=[""], dictData={"demo": "xiaozizi"}), ).model_dump()
@@ -140,56 +115,10 @@ class 微信支付ViewSets(ViewSet):
@action(detail=False, methods=["post"], url_path="callback_navite")
def 二维码支付回调(self, request: Request):
"""注释"""
wechat_data支付回调数据 = sixWechatPay六果泡泡支付(pay_uri="", pay_请求体={}, pay_methon方法="POST").callBack回调解密(headers=request.headers, response_body=request.data)
wechat_data支付回调数据 = sixWechatPay六果泡泡支付().callBack回调解密(headers=request.headers, response_body=request.data)
print("二维码支付回调二维码支付回调二维码支付回调二维码支付回调二维码支付回调")
return Response(data={"msg": "success"})
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="xml_code")
def 扫用户的付款码收钱(self, request: Request):
pass
auth_code = request.data.get("auth_code", None)
data_扫用户付款码数据 = {
"appid": sixWechatPay六果泡泡支付().appid, # 微信分配的公众账号ID(企业号corpid即为此appId)
"attach": "订单额外描述", # 附加数据,在查询API和支付通知中原样返回,可作为自定义参数
"auth_code": "143893528965089", # 授权码,扫码支付时的付款码(条形码/二维码)
"body": "付款码支付测试", # 商品描述,商品简单描述(如:腾讯充值中心-QQ会员充值)
"device_info": "1000", # 设备号,终端设备号(门店号或收银设备ID),自定义参数
"goods_tag": "", # 商品标记,代金券或立减优惠功能的参数,可为空
"mch_id": "10000100", # 商户号,微信支付分配的商户号
"nonce_str": f"{ULID()}", # 随机字符串,长度不超过32位,保证签名不可预测
"out_trade_no": f"{ULID()}", # 商户订单号,商户系统内部订单号,要求32个字符内,且在同一个商户号下唯一
"total_fee": "1", # 订单总金额,单位为分,只能为整数(此处为1分钱)
}
wechat_pay_data = sixWechatPay六果泡泡支付(pay_methon方法="POST", pay_请求体=data_扫用户付款码数据, pay_uri="https://api.mch.weixin.qq.com/pay/micropay").v2签名返回XML()
print(wechat_pay_data)
return Response(data={})
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="add")
def 添加商品数据(self, request: Request):
pass
out_refund_no商家侧生成的退款订单号 = f"{ULID()}"
refund_request = {
"transaction_id": "1217752501201407033233368018", # 微信支付订单号(与 out_trade_no 二选一)
# "out_trade_no": "1217752501201407033233368018", # 商户订单号(与 transaction_id 二选一)
"out_refund_no": out_refund_no商家侧生成的退款订单号, # 商户退款单号,唯一
"reason": "商品已售完", # 退款原因(选填)
"notify_url": "https://xiao.sixgou.com/demopay/退款/", # 异步接收微信支付退款结果通知的回调地址
"funds_account": "AVAILABLE", # 退款资金来源:AVAILABLE-可用余额,UNSETTLED-未结算资金
"amount": {
"refund": 1, # 退款金额,单位:分
"from": [
{
"account": "AVAILABLE", # 出资账户类型
"amount": 444 # 出资金额
}
],
"total": 1, # 原订单金额
"currency": "CNY" # 货币类型
},
}
return Response(data={})
微信支付ViewSetsRouter = DefaultRouter()
微信支付ViewSetsRouter.register(prefix="", viewset=微信支付ViewSets, basename="微信支付ViewSets")
@@ -1,8 +1,5 @@
"""注释"""
from django.db import models
from uuid6 import uuid8
from wechat_数据库.雪花算法.雪花算法工具 import generator
"""
输入 :当前用户实例(self)
@@ -71,6 +68,7 @@ class weiuser(models.Model):
user_绑定企微usrID账号 = models.CharField(max_length=128, null=True, blank=True, )
user_绑定企微UNIONID = models.CharField(max_length=128, null=True, blank=True, )
user_IP地址 = models.GenericIPAddressField(null=True, blank=True, )
user_手机设备参数 = models.JSONField(null=True, blank=True, )
user_绑定用工关系 = models.CharField(max_length=128, null=True, blank=True, )
codeConfigId = models.TextField(blank=True, null=True, ) # 企微的标签ID
codeQrCode = models.TextField(blank=True, null=True, ) # 企微的二维码
@@ -189,7 +187,6 @@ class weiuser(models.Model):
current = current.parent
return None
# class weiuser用户角色表(models.Model):
# """城市信息表"""
# objects = models.Manager() #
@@ -62,16 +62,6 @@ class wecomData获取客户详情响应(BaseModel):
follow_user: List[wecomData跟进成员信息] = []
six六果对象xiao, six是否新创建值 = weiuser.objects.update_or_create(unionid="六果",
defaults={
"user_IP地址": None, "user_昵称": "六果", "user_用户当前的等级": 0, "user_省份": "六果", "user_城市": "六果", "user_区县": "六果",
"user_街道信息": "六果", "user_头像": "https://hudie.xiao.band/%E6%9C%AA%E5%91%BD%E5%90%8D.png", "user_绑定企微usrID账号": "六果", "user_角色权限": "六果", "external_userid": "六果",
"parent_id": "六果", "mini_openid": "wxf612e825377328f0", "wechat_openid": "六果", "wecom_openid": "wwbe6369dc26a9d83a", "codeConfigId": "六果", "codeRemark": "六果",
"codeQrCode": "https://hudie.xiao.band/mini.jpg",
"user_企微角色权限": "六果", "user_绑定企微UNIONID": "六果"
})
class wecom客户好友管理(BaseModel):
# demo_必填: int = Field(..., description="描述") # 必传属发生
# demo_可选: Optional[int] = None # 可选值
@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA+7fWfsUk5JceJXIG8a3JZu30KdKv3uFVP+vJtYDiTspiOd1z
l2D7fzTeZ3BNLlW29OGNDFlUEUJGoVSVzh9ZgKm4ZCpjQYSy03VH25kJHCjVZLX9
aBy0DuRUN2Jwq/ma1Z9lgrJuo5Kou2oQQJgqXON20030CqNkiQA/bMJJnN1MYJZi
I7eHdW/HIC42wB31YW0ZNACEP1UfQ4o54zJzbi6xNus9OyD2DtjV3Q0ZRjuRRUU5
krBWeV2kK2XQrKJ0T5TF9q0N+QqJETA6iY33ScRqt25SDcpjc4dVuwSveL6fPj5J
zrwfRkTtYwDlwfLz7yChJD4aJQ+NWvmyOMVWxQIDAQABAoIBAGIvDAh4p3JOi6C5
gIHmcqema1Wg6565MAJ120Dj2+I1yOifO4YxewfcPGAGiuRm5K1SCS1m7oao3lnx
X1l+GvA3w0e2zO5ybzpSBcxfPhFw0AOvhP+GKqmgYEUWLbK28rEesn6vUL6W5x/r
OBmqAOQoiWHUhztbDkzt/s9SXVpEpYxoEikg2M8QBGHTY+IuHFWMKSSltWh845zK
MtSARPszxlU10WXH8xZIfTGK5EvZ6U5GHoWlDVnEJjzC5NAvf2tcrFP3suMEjEic
PPEmZXR/FNAr7MNF118hsZ8FckUlt4ngaTwT0dmSqcutCc4ye9v4YpxFOyQPoBB3
SnfsbMUCgYEA/gIWSKt4PBsBpWvDIHBEjwYCMwZM/xOqtjnAe1gVR1SDb/fMOr/6
FDW14841I75ez6/GZxHTDzbkxsJ7NVcRrXxKGyxL0+J50qEPnFairyGVd501Dktd
TghTGP5iffesPtRqs36oFURGCPaKetD8Ar33LjXhIzttsPCoJIs0ZbsCgYEA/bEn
VeUicXqwRdarixCgvihMem9Jm0fSyaQc7aeN1xzbI4OEuwq0tWGwJ6UmZOJcbdxx
lc7Z8Y6/U6Gv6oxFgHcOtB4cTHpBSOsKMzXcJNjVVkXzEuq6cvRIEYHZEdzN82t/
2uMUh9DRyIzNDFJ4/+OEaiRQDT3yS8Z8/KLfLX8CgYEAv1cjIirIr75IRyweGNl5
S6PjFDyy05MlDZADhuabYNgxCq9HkRn8cCzlj21OalaFZT2r3wh2TQe03mSyG0Qz
dNQjnsSHel0oF5psAADjG7nYtfoedV4gMx/iOPmnh+yCO/IXTo8iXqLHfwj41/uF
Wytuf8jmh3vE7XzbrGuQVPECgYAD9cL2bUg3W0HrJSmyVwUbUse21Yvhl6JrsVse
PpJRPEsTZ9cnkEg32JmGVOafhoUI1fsT6pGuWpsT9B8p2xyun60kFKA+dV4VhE25
dOrFzHiwCxF7Rxy39KY3V76Kr9arKQ9q3EaSxCiyJ7h/q73lyKhle8GgI0pn8mY7
D1PKgwKBgCxqlcRlHbQ3pv1NM5efI2bEdg1Dz5zuxL7DU/lBoE10dvlyJgJRbRNZ
x49nykTmM3cWjZStQBvxuqzo8XMOVvZaq9DuR0sDbNUDDI61Og/cAhtyThYsiPpL
HzgEN+3o4mVn5+0w//t1JJNpEpmSA8h4aZ0esa8E3wNe+ZMfZ4ti
-----END RSA PRIVATE KEY-----
@@ -336,13 +336,7 @@ class wechatPay(BaseModel):
return xml
def getpay_code扫用户付款码(self, body_data, ) -> dict:
"""
商家扫用户的付款码,收款
:param body_data:
:type body_data:
:return:
:rtype:
"""
""" """
xml = self.v2签名返回XML(sign_data=body_data)
fu_kuan_url = "https://api.mch.weixin.qq.com/pay/micropay"
res = post(url=fu_kuan_url, data=xml)
@@ -50,9 +50,6 @@ class miniUser积分(BaseModel):
click点击者unionidID: str = Field(..., description="点击者的的openid")
bind绑定的企微unionidID: str = Field(default="", description="click绑定的企微unionidID")
def update更新用户头像(self):
pass
def add添加每日积分(self, share积分类型: Literal["每日签到"], share分享者积分值: int, ):
pass
# 注意,这里的每日签到: 分享者 同时 也是点击者
@@ -114,7 +114,7 @@ class sixwecom(ViewSet):
img_file = requests.get(url=avatar).content
src = oss上传腾讯云图片.上传图片(key=f"{userid}/{name}.png", file=io.BytesIO(img_file), )
avatar = src
企微用户关系对象, 企微用户是否为首次 = wecom企微用户.objects.update_or_create(wecom企微ID=UserID, )
企微用户关系对象, 企微用户是否为首次 = wecom企微用户.objects.update_or_create(wecom企微ID=UserID, wecom好友的ID=ExternalUserID)
企微用户关系对象.wecom企微状态State = State
企微用户关系对象.wecom好友的ID = external_userid
企微用户关系对象.wecom好友UNIONID = unionid
@@ -179,6 +179,9 @@ class sixwecom(ViewSet):
企微用户关系对象, 企微用户是否为首次 = wecom企微用户.objects.get_or_create(wecom企微ID=UserID, wecom好友的ID=ExternalUserID)
if 企微用户是否为首次:
pass
企微用户关系对象.wecom好友关系状态 = ChangeType
企微用户关系对象.wecom好友的ID = ExternalUserID
企微用户关系对象.save()
else:
企微用户关系对象.wecom好友关系状态 = ChangeType
企微用户关系对象.save()
+24
View File
@@ -0,0 +1,24 @@
#
import os
import django
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 weiuser
six六果对象xiao, six是否新创建值 = weiuser.objects.update_or_create(unionid="六果",
defaults={
"user_IP地址": None, "user_昵称": "六果", "user_用户当前的等级": 0, "user_省份": "六果", "user_城市": "六果", "user_区县": "六果",
"user_街道信息": "六果", "user_头像": "https://hudie.xiao.band/%E6%9C%AA%E5%91%BD%E5%90%8D.png", "user_绑定企微usrID账号": "六果", "user_角色权限": "六果", "external_userid": "六果",
"parent_id": "六果", "mini_openid": "wxf612e825377328f0", "wechat_openid": "六果", "wecom_openid": "wwbe6369dc26a9d83a", "codeConfigId": "六果", "codeRemark": "六果",
"codeQrCode": "https://hudie.xiao.band/mini.jpg",
"user_企微角色权限": "六果", "user_绑定企微UNIONID": "六果"
})
if __name__ == "__main__":
pass
+6 -15
View File
@@ -1,25 +1,16 @@
import os
from datetime import datetime
from zoneinfo import ZoneInfo
import django
from pydantic import BaseModel
from sixGuoDjango.settings import base_dir_name
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{base_dir_name}.settings")
django.setup()
utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp())
from wechat_token.token工具包 import sixToken
import segno
class emsParameters(BaseModel):
wecom_token: str = sixToken.get_wecom_token()
def xiao(self):
pass
if __name__ == "__main__":
pass
print(emsParameters().wecom_token)
# segno 直接支持输出为 bytes
qr = segno.make_micro("xiaozizi")
print(qr.png_data_uri())
code = segno.make('Penny Lane', error='h')
print(code.svg_data_uri())