six_001
This commit is contained in:
@@ -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,
|
||||
# )
|
||||
Reference in New Issue
Block a user