This commit is contained in:
doudou201703
2026-08-02 14:07:04 +08:00
commit 046fac6dc1
339 changed files with 19435 additions and 0 deletions
@@ -0,0 +1,222 @@
"""
Author: xiao 792282@qq.com
Date: 2025-08-10 11:36:05
LastEditors: xiao 792282@qq.com
LastEditTime: 2025-08-17 13:38:40
FilePath: django_小程序/同城配送工具/同城配送.py
Description: 这是默认设置,可以在设置》工具》File Description中进行配置
"""
import os
import django
from sixGuoDjango.settings import BASE_DIR
from wechat_token.token工具包 import sixToken
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{BASE_DIR.name}.settings")
django.setup()
import json
import time
from dataclasses import dataclass, field
from pathlib import Path
import pydash
from django.conf import settings
from pydantic import BaseModel
import base64
from requests import Response, post
import orjson
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Signature import pss
public_key = Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/public_key.pem").read_text()
# public_key = Path("../../../wechat_微信支付证书/江苏六果科技有限公司支付证书/public_key.pem").resolve().read_text()
private_key = Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/private_key.pem").read_text()
# private_key = Path("../../../wechat_微信支付证书/江苏六果科技有限公司支付证书/private_key.pem").resolve().read_text()
平台证书文本 = Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/开放平台证书.pem").read_text()
# 平台证书文本 = Path("../../../wechat_微信支付证书/江苏六果科技有限公司支付证书/开放平台证书.pem").resolve().read_text()
class postData请求体类型(BaseModel):
iv: str
data: str
authtag: str
@dataclass(kw_only=True)
class six同城加解密工具:
"""同城配送类加签,解密"""
# add数据: bytes
uri_urls: str
data_body: dict
_timestamp: int = field(init=False)
uri_path: str = field(init=False)
mini_token: str = field(init=False)
add_GCM使用的认证数据_ADD数据: bytes = field(init=False)
postData加密后的数据: postData请求体类型 = field(init=False)
heardes_请求头数据: dict = field(init=False)
aes_key对称密钥 = base64.b64decode("CV/RZev/1A1eg7TOgzvEOy5/to2aM8SE6Ab/R9E3BgI=")
aes_str对称密钥 = "CV/RZev/1A1eg7TOgzvEOy5/to2aM8SE6Ab/R9E3BgI="
aes对称密钥编号 = "b02be3855ff9b990b2183505f165317e"
rsa非对称密钥编号 = "442e1b521422ec70844a3272e5c857dd"
api开放平台证书编号 = "5330e9294308d338a5e145fd03d0ea6a"
平台证书对象 = 平台证书文本
rsa_private = private_key
rsa_public = public_key
mini_appid = "wxf612e825377328f0"
mini_AppSecret = "8691f774e3c0c5a876b21a3e84109ef0"
def __post_init__(self):
self.mini_token = sixToken.get_mini_token()
self._timestamp = int(time.time())
# self.本地解密( )
def 加密(self, ):
"""
:return:
:rtype:
"""
iv_random_bytes = Random.get_random_bytes(12)
iv_base64_12 = base64.b64encode(iv_random_bytes).decode()
random_bytes_n = Random.get_random_bytes(16)
_n = base64.b64encode(random_bytes_n).decode() # 随机字符串,_n的值 推荐使用16-32 字节非固定长度随机base64字符串
_appid = self.mini_appid # 当前小程序的Appid
self.add_GCM使用的认证数据_ADD数据 = (f"{self.uri_urls}|{self.mini_appid}|{str(self._timestamp).strip()}|"
f"{self.aes对称密钥编号}").encode(encoding="utf-8")
data明文 = {
"_n": _n, "_appid": self.mini_appid, "_timestamp": self._timestamp,
}
data明文格式 = dict(data明文, **self.data_body)
data明文格式_bytes = orjson.dumps(data明文格式).decode()
cliper = AES.new(key=self.aes_key对称密钥, mode=AES.MODE_GCM, nonce=iv_random_bytes)
"""
AAD
1:攻击者无法修改 AAD 而不被发现(解密时会验证失败)。
2:确保加密数据与特定请求关联(如 API 路径、AppID 等)。
3: 不加密但受保护:AAD 本身不加密,但它的完整性会被 MAC 验证。
"""
cliper.update(assoc_data=self.add_GCM使用的认证数据_ADD数据) #
real_ciphertext, real_authTag = cliper.encrypt_and_digest(data明文格式_bytes.encode())
data_base64 = base64.b64encode(real_ciphertext).decode()
authtag_base64 = base64.b64encode(real_authTag).decode()
self.postData加密后的数据 = postData请求体类型(**{"iv": iv_base64_12, "data": data_base64, "authtag": authtag_base64, })
self.本地解密() # 测试调用一下本地解密,是否有效;
print("这里会报错的吗")
def 本地解密(self, ):
"""
解密功能
:return:
:rtype:
"""
# 将base64字符串解码;
iv_bytes = base64.b64decode(self.postData加密后的数据.iv) # 将base64字符串解码;
ciphertext = base64.b64decode(self.postData加密后的数据.data) # 将base64字符串解码;
cipher = AES.new(self.aes_key对称密钥, AES.MODE_GCM, nonce=iv_bytes)
cipher.update(self.add_GCM使用的认证数据_ADD数据)
try:
padded_data = cipher.decrypt(ciphertext)
return
except ValueError:
raise ValueError("解密出错了")
def 对加密数据进行签名(self, ):
"""
对返回的加密数据进行解密;
"""
# 转换为紧凑 JSON 格式
postdata = json.dumps(self.postData加密后的数据.model_dump(), ensure_ascii=False, )
# 构造签名串
sign_str = f"{self.uri_urls}\n{self.mini_appid}\n{self._timestamp}\n{postdata}"
# RSA 签名
private_key_obj = RSA.import_key(self.rsa_private)
h = SHA256.new(sign_str.encode())
# ✅ 改为 PSS 签名
signature = pss.new(private_key_obj).sign(h)
sig = base64.b64encode(signature).decode()
self.heardes_请求头数据 = {
"Wechatmp-Appid": self.mini_appid,
"Wechatmp-TimeStamp": str(self._timestamp),
"Wechatmp-Signature": sig,
"Content-Type": "application/json",
"Accept": "application/json",
}
def 验证签名串(self, respose: Response):
""""""
# 获取原始响应文本(避免任何自动转换,我们使用response.content然后手动解码为utf-8)
Wechatmp_TimeStamp = pydash.get(obj=respose.headers, path="Wechatmp-TimeStamp", default=None)
Wechatmp_Appid = pydash.get(obj=respose.headers, path="Wechatmp-Appid", default=None)
Wechatmp_Signature = pydash.get(obj=respose.headers, path="Wechatmp-Signature", default=None)
# 2. 获取原始响应体(非常重要)
raw_body = respose.text.strip() # 去除首尾空白,确保无额外\n
创建拼接字答串 = f"{self.uri_urls}\n{Wechatmp_Appid}\n{str(Wechatmp_TimeStamp)}\n{raw_body}"
signature = base64.b64decode(Wechatmp_Signature)
msg_hash = SHA256.new(创建拼接字答串.encode(encoding="utf-8"))
public_obj = RSA.import_key(self.平台证书对象)
# 创建PSS签名验证器
try:
pss.new(rsa_key=public_obj).verify(msg_hash=msg_hash, signature=signature) # type: ignore
print("验证成功了")
return True
except Exception as e:
print(f"❌ 签名验证失败: {str(e)}")
raise e
def 解签(self, respose: Response):
Wechatmp_TimeStamp = pydash.get(obj=respose.headers, path="Wechatmp-TimeStamp", default=None)
Wechatmp_Appid = pydash.get(obj=respose.headers, path="Wechatmp-Appid", default=None)
# Wechatmp_Signature 平台证书签名数据,使用base64编码
self.验证签名串(respose=respose)
# ✅ 强制重新构造 AAD,确保与加密端一致
add_data = f"{self.uri_urls}|{Wechatmp_Appid}|{Wechatmp_TimeStamp}|{self.aes对称密钥编号}"
iv = pydash.get(obj=respose.json(), path="iv", default=None)
authtag = pydash.get(obj=respose.json(), path="authtag", default=None)
data = pydash.get(obj=respose.json(), path="data", default=None)
iv_bytes = base64.b64decode(iv)
ciphertext = base64.b64decode(data)
cipher = AES.new(self.aes_key对称密钥, AES.MODE_GCM, nonce=iv_bytes)
cipher.update(add_data.encode()) # ✅ 使用新构造的 AAD
try:
padded_data = cipher.decrypt(ciphertext) # 只能调用decrypt这个方法()
deciphertext = padded_data.decode()
return deciphertext
except ValueError as e:
raise ValueError("解密出错了,请检查 AAD、IV、密文或密钥一致性") from e
def call(self):
""""""
self.加密()
self.对加密数据进行签名()
data = post(url=self.uri_urls, params={"access_token": self.mini_token, }, headers=self.heardes_请求头数据, json=self.postData加密后的数据.model_dump())
print(data.json(), "请求出错了吗")
return self.解签(respose=data)
if __name__ == "__main__":
# six同城加解密工具.对加密数据进行签名( urlpath="https://api.weixin.qq.com/wxa/getuserriskrank", data_body={ } ) # #
# six = six同城加解密工具(uri_urls="https://api.weixin.qq.com/cgi-bin/express/intracity/querystore",
# data_body={}).call()
# print(six)
查询运费请求数据 = {
"wx_store_id": "4000000000016308013",
"user_lng": "119.893083",
"user_lat": "32.474616",
"user_address": "江苏省泰州市海陵区城西街道任景路U牌美容店",
"user_name": "元宝",
"user_phone": "13372551360",
"cargo": {"cargo_name": "测试商品", "cargo_type": 3, "cargo_num": 7, "cargo_price": 5000, "cargo_weight": 2500}
}
res = six同城加解密工具(uri_urls="https://api.weixin.qq.com/cgi-bin/express/intracity/preaddorder", data_body=查询运费请求数据).call()
print(res)
@@ -0,0 +1,73 @@
"""
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_小程序/同城配送工具/小程序用户授权数据.py
Description: 这是默认设置,可以在设置》工具》File Description中进行配置
"""
from wechat_项目工具包.微信支付工具包.微信支付类 import paymentCategory
"""功能模块"""
import jmespath
from requests import post, get
class wei小程序服务端工具:
"""微信登陆"""
@classmethod
def 获取OPENID(cls, secret: str, js_code: str, appid: str, ) -> dict:
"""
@param secret: 小程序 appSecret
@type secret: string
@param js_code: 登录时获取的 code,可通过wx.login获取
@type js_code: string
@param appid: 小程序的app🆔
@type appid: string
@return:{"session_key":"etC7EOml89Pd8XIhTFyAOA==","expires_in":7200,"openid":"oNTAd0fm1GQAdohfbvywhGstsIPc","unionid":"ojWkM1MnLrdty0S3Vks2pYorp4MY"}
@rtype: dict
"""
url = "https://api.weixin.qq.com/sns/jscode2session"
data = {
"appid": appid,
"secret": secret,
"js_code": js_code,
"grant_type": "authorization_code"
}
res_data = get(url=url, params=data)
res = res_data.json()
errcode = jmespath.search(data=res, expression="errcode", )
if res_data.status_code == 200:
if errcode is None:
return res
else:
raise Exception(f"登陆错误码:{res}")
raise Exception("请求login登陆时出错了")
@classmethod
def 获取手机号(cls, url, code: str):
"""
@param url:
@type url:
@param code:
@type code:
@return: {'session_key': 'etC7EOml89Pd8XIhTFyAOA==', 'expires_in': 7200, 'openid': 'oNTAd0fm1GQAdohfbvywhGstsIPc', 'unionid': 'ojWkM1MnLrdty0S3Vks2pYorp4MY'}
@rtype:
"""
data = {
"code": code
}
res_data = post(url=url, json=data)
res = res_data.json() # type: dict
return res
if __name__ == '__main__':
pass
res = wei小程序服务端工具.获取OPENID(
js_code="0e1sYCkl2bCmhg4DG2ll2kheh10sYCkn", appid=paymentCategory.appid,
secret=paymentCategory.appsecret,
)
@@ -0,0 +1,138 @@
import io
import os
import django
import pydash
from django.core.files.storage import default_storage
from wechat_token.token工具包 import sixToken
django.setup()
from requests import post
class 小程序码与小程序链接:
"""获取所有的小程序码的业务接口"""
def 小程序码_getQRCode(self):
"""
该接口用于获取小程序码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制,详见获取小程序码。
"""
pass
mini_token = sixToken.get_mini_token()
post_url = f"https://api.weixin.qq.com/wxa/getwxacode?access_token={mini_token}"
post_data = {
"path": "tabPage/Home/Home?xiao=zizi",
# 扫码进入的小程序页面路径,最大长度 1024 个字符,不能为空,scancode_time为系统保留参数,不允许配置;对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 "?foo=bar",即可在 wx.getLaunchOptionsSync 接口中的 query 参数获取到 {foo:"bar"}。
"is_hyaline": True, # 默认值false;是否需要透明底色,为 true 时,生成透明底色的小程序码
"env_version": "trial", # 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。
}
data = post(url=post_url, json=post_data)
default_storage.save(name="uploads/xiao.png", content=io.BytesIO(initial_bytes=data.content)) # 作用:是可以自动将图片保存在指定的media目录下的 uploads目录下的图片名 xiao.png
def 小程序码_getUnlimitedQRCode(self):
"""
该接口用于获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。 更多用法详见 获取小程序码。
"""
pass
mini_token = sixToken.get_mini_token()
post_url = f"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={mini_token}"
post_data = {
"path": "tabPage/Home/Home?zizi=xiaozizi", # 非必填 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置
"scene": "abc", # 必填 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符
"is_hyaline": True, # 默认值false;是否需要透明底色,为 true 时,生成透明底色的小程序码
"env_version": "trial", # 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。
}
data = post(url=post_url, json=post_data)
print(data.status_code)
default_storage.save(name="uploads/getUnlimitedQRCode.png", content=io.BytesIO(initial_bytes=data.content)) # 作用:是可以自动将图片保存在指定的media目录下的 uploads目录下的图片名 xiao.png
def 小程序码_createQRCode(self):
"""
该接口用于获取小程序二维码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。 更多用法详见 获取小程序码。
"""
pass
mini_token = sixToken.get_mini_token()
post_url = f"https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token={mini_token}"
post_data = {
"path": "tabPage/Home/Home?foo=bar", # 非必填 默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置
"scene": "abc", # 必填 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符
"is_hyaline": True, # 默认值false;是否需要透明底色,为 true 时,生成透明底色的小程序码
"env_version": "trial", # 要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。
}
data = post(url=post_url, json=post_data)
print(data.status_code)
default_storage.save(name="uploads/createQRCode.png", content=io.BytesIO(initial_bytes=data.content)) # 作用:是可以自动将图片保存在指定的media目录下的 uploads目录下的图片名 xiao.png
def urlScheme_获取加密Scheme(self):
mini_token = sixToken.get_mini_token()
post_url = f"https://api.weixin.qq.com/wxa/generatescheme?access_token={mini_token}"
post_data = {
"jump_wxa":
{
"path": "tabPage/Home/Home", # 通过 scheme 码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带 query。path 为空时会跳转小程序主页。
"query": "foo=bar", # 通过 scheme 码进入小程序时的 query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~%`
"env_version": "trial", # 默认值"release"。要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop",仅在微信外打开时生效
},
"is_expire": True,
"expire_type": 1, # number 否 默认值0,到期失效的 scheme 码失效类型,失效时间:0,失效间隔天数:1
"expire_interval": 1, # number 否到期失效的 scheme 码的失效间隔天数。生成的到期失效 scheme 码在该间隔时间到达前有效。最长间隔天数为30天。is_expire 为 true 且 expire_type 为 1 时必填
}
data = post(url=post_url, json=post_data)
print(data.status_code)
print(data.json())
openlink = pydash.get(obj=data.json(), path="openlink")
print(openlink)
# default_storage.save(name="uploads/urlScheme.png", content=io.BytesIO(initial_bytes=data.content)) # 作用:是可以自动将图片保存在指定的media目录下的 uploads目录下的图片名 xiao.png
def shortLink(self):
"""
获取小程序 Short Link,适用于微信内拉起小程序的业务场景。目前只开放给电商类目(具体包含以下一级类目:电商平台、商家自营、跨境电商)。通过该接口,可以选择生成到期失效和永久有效的小程序短链,详情见获取 Short Link。
:return:
:rtype:
"""
mini_token = sixToken.get_mini_token()
post_url = f"https://api.weixin.qq.com/wxa/genwxashortlink?access_token={mini_token}"
post_data = {
"page_url": "tabPage/Home/Home?q=1", # 通过 Short Link 进入的小程序页面路径,必须是已经发布的小程序存在的页面,可携带 query,最大1024个字符
"page_title": "Homework title", # string 否 页面标题,不能包含违法信息,超过20字符会用... 截断代替
"is_permanent": True, # boolean 否 默认值false。生成的 Short Link 类型,短期有效:false,永久有效:true
}
data = post(url=post_url, json=post_data)
print(data.status_code)
print(data.json())
link = pydash.get(obj=data.json(), path="link")
print(link)
def urlLink(self):
"""
获取小程序 URL Link,适用于短信、邮件、网页、微信内等拉起小程序的业务场景。
:return:
:rtype:
"""
mini_token = sixToken.get_mini_token()
post_url = f"https://api.weixin.qq.com/wxa/generate_urllink?access_token={mini_token}"
post_data = {
"path": "tabPage/Home/Home", # 通过 URL Link 进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带 query 。path 为空时会跳转小程序主页
"query": "aaa=bbb", # 通过 URL Link 进入小程序时的query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~%
}
data = post(url=post_url, json=post_data)
print(data.status_code)
print(data.json())
url_link = pydash.get(obj=data.json(), path="url_link")
print(url_link)
if __name__ == '__main__':
pass
# 小程序码与小程序链接().小程序码_getQRCode() # 生成的是小程序码
# 小程序码与小程序链接().小程序码_getUnlimitedQRCode() #
# 小程序码与小程序链接().小程序码_createQRCode() # 生成的是二维码
小程序码与小程序链接().urlScheme_获取加密Scheme() # weixin://dl/business/?t=vQAOKCN3Shu 生成的链接 必须要有正式版本才可以
小程序码与小程序链接().shortLink() # 小程序://元宝零售/Homeworktitle/Lsr22VT1TDJwlyj 生成的是链接 必须要有正式版本才可以 目前只开放给电商类目(具体包含以下一级类目:电商平台、商家自营、跨境电商)
小程序码与小程序链接().urlLink() # 生成的是链接 必须要有正式版本才可以 https://wxaurl.cn/nJAFXSaIgym
@@ -0,0 +1,89 @@
"""
Author: xiao 792282@qq.com
Date: 2025-08-10 11:36:05
LastEditors: xiao 792282@qq.com
LastEditTime: 2025-08-17 13:38:40
FilePath: django_小程序/同城配送工具/小程序订单管理工具.py
Description: 这是默认设置,可以在设置》工具》File Description中进行配置
"""
from wechat_token.token工具包 import sixToken
"""小程序订单管理工具"""
import os
from zoneinfo import ZoneInfo
import orjson
from datetime import datetime
import requests
class six订单管理:
"""录入订单接口的类"""
@classmethod
def order发货信息录入接口(cls, iso_format_time_inner: str, transaction_id: str, openid: str):
"""
调用 录入订单接口,自动录入订单
"""
mini_token = sixToken.get_mini_token()
uri = f"https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token={mini_token}"
# 订单数据 = {
# "order_key": { # 订单,需要上传物流信息的订单
# "order_number_type": 2, # 是 订单单号类型,用于确认需要上传详情的订单。枚举值1,使用下单商户号和商户侧单号;枚举值2,使用微信支付单号。
# "transaction_id": "4200002639202506141300476684" # 否 原支付交易对应的微信订单号
# },
# "delivery_mode": 2, # 发货模式,发货模式枚举值:1、UNIFIED_DELIVERY(统一发货)2、SPLIT_DELIVERY(分拆发货) 示例值: UNIFIED_DELIVERY
# "logistics_type": 2, # 是 物流模式,发货方式枚举值:1、实体物流配送采用快递公司进行实体物流配送形式 2、同城配送 3、虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式 4、用户自提
# "shipping_list": [ # 是 物流信息列表,发货物流单列表,支持统一发货(单个物流单)和分拆发货(多个物流单)两种模式,多重性: [1, 10]
# {
# # "tracking_no": "fake-trackingno-2022121419042711",
# # 否 tracking_no 物流单号,物流快递发货时必填,示例值: 323244567777 字符字节限制: [1, 128]
# # "express_company": "STO",
# # 否 物流公司编码,快递公司ID,参见「获取运力 id 列表get_delivery_list」,物流快递发货时必填, 示例值: DHL 字符字节限制: [1, 128]
# "item_desc": "卷纸", # 是 商品信息,例如:微信红包抱枕*1个,限120个字以内
# # "contact": { # contact否 联系方式,当发货的物流公司为顺丰时,联系方式为必填,收件人或寄件人联系方式二选一
# # "consignor_contact": "+86-177****1234" # 否 寄件人联系方式,寄件人联系方式,采用掩码传输,最后4位数字不能打掩码 示例值:0, ****123-
# # }
# }
# ],
# "upload_time": iso_format_time, # 是 上传时间,用于标识请求的先后顺序 示例值: `2022-12-15T13:29:35.120+08:00`
# "payer": { # payer 支付者,支付者信息
# "openid": "ohQkD7A-N93kljcFmkCyG6e_D9vg"
# # 用户标识,用户在小程序appid下的唯一标识。 下单前需获取到用户的Openid 示例值: oUpF8uMuAJO_M2pxb1Q9zNjWeS6o 字符字节限制: [1, 128]
# }
# }
订单数据 = {
"order_key": {
"order_number_type": 2,
"transaction_id": transaction_id # 使用真实的微信支付单号
},
"delivery_mode": 1,
"logistics_type": 2,
# "is_all_delivered": True,
"shipping_list": [
{
"item_desc": "卷纸", # 确保中文字符被正确处理
}
],
"upload_time": iso_format_time_inner, # 修正时间格式
"payer": {
"openid": openid # 真实的用户openid
}
}
data = requests.post(url=uri, data=orjson.dumps(订单数据).decode(), )
print(data.json())
if __name__ == '__main__':
rfc_3339_time = datetime.now(tz=ZoneInfo("Asia/Shanghai")).isoformat(timespec="seconds")
print(rfc_3339_time)
# 如果报错:则需要查看一下,是不是手机真实支付的,如果是开发工具并且是扫码支付的则不会出现这个订单;
six订单管理.order发货信息录入接口(iso_format_time_inner=rfc_3339_time,
transaction_id="4200002720202508164227110344",
openid="ohQkD7A-N93kljcFmkCyG6e_D9vg")
@@ -0,0 +1,76 @@
"""
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_小程序/同城配送工具/小程序用户授权数据.py
Description: 这是默认设置,可以在设置》工具》File Description中进行配置
"""
"""功能模块"""
import jmespath
from requests import post, get
class wei小程序服务端工具:
"""微信登陆"""
@classmethod
def 获取OPENID( cls, secret: str, js_code: str, appid: str, ) -> dict:
"""
@param secret: 小程序 appSecret
@type secret: string
@param js_code: 登录时获取的 code,可通过wx.login获取
@type js_code: string
@param appid: 小程序的app🆔
@type appid: string
@return:{"session_key":"etC7EOml89Pd8XIhTFyAOA==","expires_in":7200,"openid":"oNTAd0fm1GQAdohfbvywhGstsIPc","unionid":"ojWkM1MnLrdty0S3Vks2pYorp4MY"}
@rtype: dict
"""
url = "https://api.weixin.qq.com/sns/jscode2session"
data = {
"appid": appid,
"secret": secret,
"js_code": js_code,
"grant_type": "authorization_code"
}
res_data = get( url=url, params=data )
res = res_data.json( )
errcode = jmespath.search( data=res, expression="errcode", )
if res_data.status_code == 200:
if errcode is None:
return res
else:
raise Exception( f"登陆错误码:{res}" )
raise Exception( "请求login登陆时出错了" )
@classmethod
def 获取手机号( cls, url, code: str ):
"""
@param url:
@type url:
@param code:
@type code:
@return: {'session_key': 'etC7EOml89Pd8XIhTFyAOA==', 'expires_in': 7200, 'openid': 'oNTAd0fm1GQAdohfbvywhGstsIPc', 'unionid': 'ojWkM1MnLrdty0S3Vks2pYorp4MY'}
@rtype:
"""
data = {
"code": code
}
res_data = post( url=url, json=data )
res = res_data.json( ) # type: dict
return res
if __name__ == '__main__':
pass
# res = wei小程序服务端工具.获取OPENID(
# js_code="0e1sYCkl2bCmhg4DG2ll2kheh10sYCkn", appid=paymentCategory.appid,
# secret=paymentCategory.appsecret,
# )