six_002
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
||||
# Generated by Django 6.0.2 on 2026-08-04 01:28
|
||||
|
||||
import ulid
|
||||
import wechat_数据库.雪花算法.雪花算法工具
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_app', '0053_alter_goods商品_id_str_alter_lucky拼团_idkey_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='wei客服账号',
|
||||
fields=[
|
||||
('kefu_id', models.UUIDField(default=ulid.ULID, primary_key=True, serialize=False)),
|
||||
('extInfo_推广员账号链接', models.CharField(db_comment='企微客服账号链接', max_length=128)),
|
||||
('extInfo_企微员工绑定的UNIONID', models.CharField(db_comment='企微客服绑定的小程序unionid', max_length=128)),
|
||||
('extInfo_企微员工的名称', models.CharField(blank=True, max_length=128, null=True)),
|
||||
('dateAndTime', models.DateTimeField(auto_now_add=True, db_comment='创建时间')),
|
||||
('updateTime', models.DateTimeField(auto_now=True, db_comment='更新时间')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'wei客服账号',
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='goods商品',
|
||||
name='id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='lucky拼团',
|
||||
name='idKey',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='lucky拼团订单',
|
||||
name='idKey',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='map地图ip转地址',
|
||||
name='id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='minisub订阅消息模板',
|
||||
name='idKey',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='order订单',
|
||||
name='id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='order订单商品数据',
|
||||
name='order_id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='order订单商品数据',
|
||||
name='order_id商品',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wechattransferorder',
|
||||
name='id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wecom企微用户',
|
||||
name='idKeyWecom企微用户',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wecom企微群',
|
||||
name='idKeyWecom企微群',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wecom推广码',
|
||||
name='id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='weiuser地图定位',
|
||||
name='id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='weiuser微信用户地址',
|
||||
name='id_str',
|
||||
field=models.CharField(default=wechat_数据库.雪花算法.雪花算法工具.SnowflakeIDGenerator.generate_str, max_length=128),
|
||||
),
|
||||
]
|
||||
@@ -1,14 +1,12 @@
|
||||
from django.db import models
|
||||
|
||||
from django_定时器 import 幸运拼团数据库
|
||||
from wechat_wecom_企业微信管理.企微通讯录管理.企微通讯录管理数据库 import 企微员工数据
|
||||
from wechat_数据库.企业微信数据库 import 推广二维码数据表, 企微用户表, 企微群数据库
|
||||
from wechat_token import token数据库
|
||||
from wechat_数据库.地图定位 import 用户定位数据库, 腾讯地图解析数据库
|
||||
from wechat_数据库.小程序后端数据库 import 订阅消息
|
||||
from wechat_数据库.支付数据库 import 商家转账数据库
|
||||
from wechat_数据库.支付订单数据库 import 商品订单数据
|
||||
from wechat_数据库.洗衣液商品数据库 import 六果洗衣液商品
|
||||
from wechat_数据库.测试数据库 import 测试数据表
|
||||
from wechat_数据库.用户数据库 import 小程序登陆用户, 小程序用户地址, 小程序积分数据库
|
||||
from wechat_数据库.用户数据库 import 小程序登陆用户, 小程序用户地址, 小程序积分数据库,企微客服数据库
|
||||
# Create your models here.
|
||||
+40
-4
@@ -1,3 +1,6 @@
|
||||
import threading
|
||||
from functools import wraps
|
||||
|
||||
import emoji
|
||||
import orjson
|
||||
import pydash
|
||||
@@ -18,7 +21,20 @@ from wechat_项目工具包.微信支付工具包.微信支付类 import payment
|
||||
from wechat_项目工具包.数据库的工具包.更新用户积分 import miniUser用户角色, miniUser积分
|
||||
|
||||
|
||||
def sync_lock_接口线程锁(lock):
|
||||
def decorator(fn):
|
||||
@wraps(fn)
|
||||
def wrapper(*args, **kwargs):
|
||||
with lock:
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class 业务订单接口ViewSets(ViewSet):
|
||||
lock_接口线程锁 = threading.Lock() # 所有请求 共享这一个 lock对象
|
||||
|
||||
def 处理积分方法(self, 商家订单号):
|
||||
pass
|
||||
@@ -30,7 +46,6 @@ class 业务订单接口ViewSets(ViewSet):
|
||||
def 首单自动注册成为推广员(self, out_trade_no):
|
||||
pass
|
||||
order对象 = order订单.objects.get(order支付商家侧订单号=out_trade_no)
|
||||
|
||||
user用户对象 = weiuser.objects.get(unionid=order对象.order支付者unionid)
|
||||
six绑定的企微员工对象, sixBool = weiuser.objects.get_or_create(unionid=user用户对象.user_绑定企微UNIONID)
|
||||
# 判断用户成为推广员的标准 成为的条件,当前用户绑定的企微员工账号, 必须是同一个区县的
|
||||
@@ -40,6 +55,21 @@ class 业务订单接口ViewSets(ViewSet):
|
||||
user用户对象.user_角色权限 = miniUser用户角色().推广员
|
||||
user用户对象.save()
|
||||
|
||||
def 生成单品优惠券的数据(self, order购物车商品数据: list[dict]):
|
||||
pass
|
||||
准备一个空列表 = []
|
||||
# 循环传递进来的数据
|
||||
for item in order购物车商品数据:
|
||||
# 创建对象
|
||||
data_dict = {
|
||||
"merchant_goods_id": "01KYNDT2KKKPZCR5G1TVG9GZ7G",
|
||||
"goods_name": emoji.replace_emoji(pydash.get(obj=item, path="goods_商品标题")),
|
||||
"quantity": pydash.get(obj=item, path="单个商品订单数量"),
|
||||
"unit_price": pydash.get(obj=item, path="单个商品实际支付价格")
|
||||
}
|
||||
准备一个空列表.append(data_dict)
|
||||
return 准备一个空列表
|
||||
|
||||
@action(detail=False, methods=["post"], url_path="mall")
|
||||
def 商城订单支付接口(self, request: Request) -> Response:
|
||||
"""前端小程序的用户: 发起支付订单的请求接口"""
|
||||
@@ -53,13 +83,15 @@ class 业务订单接口ViewSets(ViewSet):
|
||||
share订单分享者ID = request.data.get("share订单分享者ID", "六果") # 当前是否有上级对象
|
||||
order订单类型 = request.data.get("order订单类型", None)
|
||||
goods标题 = emoji.replace_emoji(pydash.get(obj=pydash.head(order购物车商品数据), path="goods_商品标题"))
|
||||
goods_detail_支付优惠券的数据 = self.生成单品优惠券的数据(order购物车商品数据=order购物车商品数据)
|
||||
print("打印一下哪里出问题了", order购物车商品数据)
|
||||
out_trade_no商家侧的订单号 = f"OAT{ULID()}" # 生成商家侧的订单号
|
||||
body = {
|
||||
"mchid": paymentCategory.mchid, # 【直连商户号】 直连商户号
|
||||
"out_trade_no": out_trade_no商家侧的订单号, # 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
|
||||
"appid": paymentCategory.appid, # 【公众号 或者 小程序ID】
|
||||
"description": goods标题, # 【商品描述】 商品描述要
|
||||
"notify_url": "https://six.sixgou.com/six/mall_callbakc/", # 回调地址要
|
||||
"notify_url": "https://xiao.sixgou.com/six/mall_callbakc/", # 回调地址要
|
||||
"amount": {
|
||||
# "total": order购物车商品总价, # 【总金额】 订单总金额,单位为分。
|
||||
"total": 1, # 【总金额】 订单总金额,单位为分。
|
||||
@@ -71,6 +103,11 @@ class 业务订单接口ViewSets(ViewSet):
|
||||
# "openid": "ohQkD7A-N93kljcFmkCyG6e_D9vg", # 【用户标识】 用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID,详见OpenID获取
|
||||
"openid": self_mini_openid, # 【用户标识】 用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID,详见OpenID获取
|
||||
},
|
||||
"detail": {
|
||||
# 【商品详情】 商品详情描述,该结构去除多余空格换行压缩后,总长度不能超过6144字节。
|
||||
"goods_detail": goods_detail_支付优惠券的数据
|
||||
},
|
||||
"support_fapiao": True, # 【电子发票入口开放标识】 传入true时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效。
|
||||
} # 请求的数据
|
||||
wechat_data = wechatPay(payment=sixpay六果科技公司).getpay_jsapi(uri=url_pay, body_data=body, method="POST")
|
||||
payData = pydash.get(obj=wechat_data, path="response")
|
||||
@@ -88,13 +125,13 @@ class 业务订单接口ViewSets(ViewSet):
|
||||
# httpResData = BaseResponse(resData=ResData(listData=[""], dictData={}), ).model_dump()
|
||||
return Response(data=httpResData, status=status.HTTP_200_OK)
|
||||
|
||||
@sync_lock_接口线程锁(lock=lock_接口线程锁) # 锁住这个接口所有并发请求,
|
||||
@action(detail=False, methods=["post"], url_path="mall_callbakc")
|
||||
def jsapi支付回调测试接口(self, request: Request) -> Response:
|
||||
""" 微信支付成功后的回调接口 """
|
||||
dict_body = request.data
|
||||
wechat_data支付回调数据 = wechatPay(payment=paymentCategory).callBack回调解密(headers=request.headers,
|
||||
response_body=dict_body, )
|
||||
print("\n 🍎 🍏 🍊 🍎 🍏 \n", wechat_data支付回调数据, )
|
||||
out_trade_no商家侧支付订单号 = pydash.get(obj=wechat_data支付回调数据, path="out_trade_no") # 商家侧的订单号
|
||||
trade_state_desc = pydash.get(obj=wechat_data支付回调数据, path="trade_state_desc") # 支付回调的支付状态
|
||||
transaction_id = pydash.get(obj=wechat_data支付回调数据, path="transaction_id")
|
||||
@@ -106,7 +143,6 @@ class 业务订单接口ViewSets(ViewSet):
|
||||
order物流订单号=生成商家侧物流的订单号,
|
||||
order支付微信官方订单号=transaction_id,
|
||||
)
|
||||
print("打印一下商家的订单号", out_trade_no商家侧支付订单号, transaction_id)
|
||||
(miniUser积分(share分享者unionidID="", click点击者unionidID="")
|
||||
.add添加好友助力下单返利积分(order支付商家侧订单号=out_trade_no商家侧支付订单号, share积分类型="好友下单"))
|
||||
ems邮政物流工具().生成运单(out_trade_no商家侧支付订单号=out_trade_no商家侧支付订单号) # 调用方法,生成真实的物流订单号码;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
from typing import cast
|
||||
|
||||
import pydash
|
||||
from channels.layers import BaseChannelLayer, get_channel_layer
|
||||
from django.http.response import HttpResponse
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.viewsets import ViewSet
|
||||
|
||||
from wechat_微信支付证书.江苏六果科技有限公司支付证书.江苏六果科技有限公司支付参数 import sixpay六果科技公司
|
||||
from wechat_项目工具包.微信支付工具包.微信支付类 import wechatPay
|
||||
|
||||
default_channel_layer = cast(BaseChannelLayer, get_channel_layer(alias="default"))
|
||||
|
||||
from functools import wraps
|
||||
import threading
|
||||
|
||||
|
||||
def sync_lock(lock):
|
||||
def decorator(fn):
|
||||
@wraps(fn)
|
||||
def wrapper(*args, **kwargs):
|
||||
with lock:
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class 电子发票管理接口ViewSets(ViewSet):
|
||||
lock = threading.Lock() # 所有请求 共享这一个 lock对象
|
||||
|
||||
@sync_lock(lock=lock) # 锁住这个接口所有并发请求,
|
||||
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="callback")
|
||||
def 电子发票回调接口(self, request: Request):
|
||||
""""""
|
||||
print("电子发票请求进来了没有")
|
||||
print(request.data)
|
||||
print(request.query_params)
|
||||
电子发票回调解密后的数据 = wechatPay(payment=sixpay六果科技公司).callBack回调解密(headers=request.headers, response_body=request.data)
|
||||
|
||||
print(电子发票回调解密后的数据, "=======================")
|
||||
fapiao_apply_id = pydash.get(obj=电子发票回调解密后的数据, path="fapiao_apply_id")
|
||||
return HttpResponse(content="OK")
|
||||
@@ -38,6 +38,6 @@ class 实时更新物流数据ViewSets(ViewSet):
|
||||
order物流公司订单编号 = request.data.get("order物流公司订单编号", None)
|
||||
order物流订单号 = request.data.get("order物流订单号", None)
|
||||
print("实时更新数据请求进来了吗")
|
||||
ems邮政物流工具().更新物流快递数据(order物流公司订单编号=order物流公司订单编号, order物流订单号=order物流订单号)
|
||||
ems邮政物流工具().更新物流快递数据(order物流公司订单编号=order物流公司订单编号, )
|
||||
httpResData = BaseResponse(resData=ResData(listData=[""], dictData={}), ).model_dump()
|
||||
return Response(data=httpResData, status=status.HTTP_200_OK)
|
||||
|
||||
@@ -32,7 +32,8 @@ class 小程序发优惠券到钱包接口ViewSets(ViewSet):
|
||||
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="生成优惠券")
|
||||
def 生成优惠券(self, request: Request):
|
||||
""""""
|
||||
stock发券数据 = stock发送代金券功能(stock_id_代金券批次号="22512292").send发券并返回前端需要的数据()
|
||||
# stock发券数据 = stock发送代金券功能(stock_id_代金券批次号="22512292").send发券并返回前端需要的数据()
|
||||
stock发券数据 = stock发送代金券功能(stock_id_代金券批次号="22625737").send发券并返回前端需要的数据()
|
||||
# 4. 生成签名
|
||||
return Response(data=stock发券数据)
|
||||
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from wechat_wecom_企业微信管理.企微通讯录管理.通讯录管理接口 import 企微员工通讯录管理接口ViewSets
|
||||
from wechat_wecom_企业微信管理.客户管理.客户管理接口 import 客户管理接口ViewSets
|
||||
from wechat_wecom_企业微信管理.客服账号管理.客服账号管理接口 import 客服账号管理接口ViewSets
|
||||
from wechat_wecom_企业微信管理.素材管理.素材管理接口 import 素材管理接口列表ViewSets
|
||||
from wechat_wecom_企业微信管理.联系我与客户群管理.加入群聊管理接口 import 加入群聊管理ViewSets
|
||||
from wechat_wecom_企业微信管理.联系我与客户群管理.联系我管理接口 import 联系我管理ViewSets
|
||||
|
||||
|
||||
企业微信管理端接口列表Router = DefaultRouter()
|
||||
企业微信管理端接口列表Router.register(prefix="企微客户好友管理", viewset=客户管理接口ViewSets, basename="客户管理接口ViewSets")
|
||||
企业微信管理端接口列表Router.register(prefix="chat", viewset=加入群聊管理ViewSets, basename="加入群聊管理ViewSets")
|
||||
企业微信管理端接口列表Router.register(prefix="素材管理接口", viewset=素材管理接口列表ViewSets, basename="素材管理接口列表ViewSets")
|
||||
企业微信管理端接口列表Router.register(prefix="contact", viewset=联系我管理ViewSets, basename="联系我管理ViewSets")
|
||||
企业微信管理端接口列表Router.register(prefix="kefu", viewset=客服账号管理接口ViewSets, basename="客服账号管理接口ViewSets")
|
||||
企业微信管理端接口列表Router.register( prefix="员工", viewset=企微员工通讯录管理接口ViewSets, basename="企微员工通讯录管理接口ViewSets" )
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
from django_app.发票回调管理接口 import 电子发票管理接口ViewSets
|
||||
from django_app.实时更新物流数据接口 import 实时更新物流数据ViewSets
|
||||
from django_app.小程序发券接口 import 小程序发优惠券到钱包接口ViewSets
|
||||
from django_app.添加各类型积分接口 import 添加积分接口ViewSets
|
||||
@@ -41,3 +42,4 @@ from wechat_mini_服务端接口目录.附近小程序.附近小程序接口 imp
|
||||
小程序服务端管理接口列表ViewSetsRouter.register(prefix="积分查询", viewset=积分查询接口ViewSets, basename="积分查询接口ViewSets")
|
||||
小程序服务端管理接口列表ViewSetsRouter.register(prefix="积分提现", viewset=积分提现ViewSets, basename="积分提现ViewSets")
|
||||
小程序服务端管理接口列表ViewSetsRouter.register(prefix="项目初始化接口", viewset=项目初始化功能接口ViewSets, basename="项目初始化接口")
|
||||
小程序服务端管理接口列表ViewSetsRouter.register(prefix="invoice", viewset=电子发票管理接口ViewSets, basename="电子发票管理接口ViewSets")
|
||||
|
||||
@@ -27,7 +27,7 @@ base_dir_name = "sixGuoDjango"
|
||||
# DEBUG = SECRET_KEY_DJANGO
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = ["xiao.sixgou.com", "127.0.0.1"]
|
||||
ALLOWED_HOSTS = ["xiao.sixgou.com", "127.0.0.1", "wechat.sixgou.com"]
|
||||
|
||||
# Application definition
|
||||
|
||||
@@ -53,7 +53,7 @@ INSTALLED_APPS = [
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
'corsheaders.middleware.CorsMiddleware', # 👈 添加这一行
|
||||
# 'corsheaders.middleware.CorsMiddleware', # 👈 添加这一行
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
|
||||
@@ -22,12 +22,14 @@ class 小程序用户的位置接口ViewSets(ViewSet):
|
||||
# 判断 当前用户,是否已经拿有位置的信息数据了
|
||||
if six六果对象.user_区县:
|
||||
# 当这里为true的时候就可以直接返回了
|
||||
print("判断当前的用户区县不为None")
|
||||
return Response()
|
||||
else:
|
||||
纬度 = pydash.get(obj=result, path="latitude")
|
||||
经度 = 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")
|
||||
@@ -38,6 +40,7 @@ class 小程序用户的位置接口ViewSets(ViewSet):
|
||||
six六果对象.user_省份 = 省
|
||||
six六果对象.user_城市 = 市
|
||||
six六果对象.user_街道信息 = 街道
|
||||
six六果对象.save()
|
||||
httpResData = BaseResponse(resData=ResData(listData=[""], dictData={"demo": "xiaozizi"}), ).model_dump()
|
||||
return Response(data=httpResData, status=status.HTTP_200_OK)
|
||||
|
||||
@@ -49,7 +52,7 @@ class 小程序用户的位置接口ViewSets(ViewSet):
|
||||
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', False)
|
||||
ip = pydash.head(x_forwarded_for.split(','))
|
||||
mini_unionid_user = weiuser.objects.get(unionid=self_mini_unionid, )
|
||||
if mini_unionid_user.user_省份 is None or mini_unionid_user.user_区县 is None or mini_unionid_user.user_城市 is None:
|
||||
if mini_unionid_user.user_省份 is None or mini_unionid_user.user_城市 is None:
|
||||
weiData = wei地图工具.ip地址转为地址(x_forwarded_for=ip, )
|
||||
province_省份 = pydash.get(obj=weiData, path="result.ad_info.province")
|
||||
city_城市 = pydash.get(obj=weiData, path="result.ad_info.city")
|
||||
|
||||
@@ -43,9 +43,14 @@ class 用户配送地址ViewSets(ViewSet):
|
||||
用户所在街道 = pydash.get(obj=address, path="detailInfo")
|
||||
weiuser.objects.filter(unionid=self_user_unionid).update(
|
||||
uesr_手机号码=用户手机号码, user_昵称=用户昵称,
|
||||
user_省份=用户所在省, user_城市=用户所在市, user_区县=用户所在区县,
|
||||
user_街道信息=用户所在街道
|
||||
)
|
||||
six_user六果对象 = weiuser.objects.get(unionid=self_user_unionid)
|
||||
if not six_user六果对象.user_区县 or not six_user六果对象.user_城市 or not six_user六果对象.user_省份:
|
||||
six_user六果对象.user_省份 = 用户所在省
|
||||
six_user六果对象.user_城市 = 用户所在市
|
||||
six_user六果对象.user_区县 = 用户所在区县,
|
||||
six_user六果对象.user_街道信息 = 用户所在街道
|
||||
six_user六果对象.save()
|
||||
|
||||
@action(detail=False, methods=["post"], url_path="first_add")
|
||||
def 首次添加用户收件地址(self, request: Request):
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import requests
|
||||
from django.core.files.storage import default_storage
|
||||
from django.core.files.uploadedfile import InMemoryUploadedFile
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.routers import SimpleRouter, DefaultRouter
|
||||
from rest_framework.viewsets import ViewSet
|
||||
|
||||
from sixGuoDjango import ResData, BaseResponse
|
||||
from sixGuoDjango import BaseResponse, ResData
|
||||
from wechat_token.token工具包 import sixToken
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from ulid import ULID
|
||||
|
||||
from sixGuoDjango import BaseResponse, ResData
|
||||
from wechat_token.token工具包 import sixToken
|
||||
from wechat_数据库.支付订单数据库.商品订单数据 import order订单, order订单商品数据
|
||||
from wechat_数据库.支付订单数据库.商品订单数据 import order订单
|
||||
|
||||
|
||||
class ems物流状态更新模型(BaseModel):
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
from django.db import models
|
||||
from uuid6 import uuid8
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class wecom企微员工( models.Model ):
|
||||
"""城市信息表"""
|
||||
objects = models.Manager( ) #
|
||||
wecom企微员工_id = models.UUIDField( primary_key=True, default=uuid8 )
|
||||
# id_str = models.CharField(max_length=128, default=generator.generate_str)
|
||||
wecom_userid = models.CharField( max_length=128, )
|
||||
wecom_department = models.CharField( max_length=128, null=True, blank=True )
|
||||
dateAndTime = models.DateTimeField( auto_now_add=True, db_comment="创建时间" ) # 数据创建时间
|
||||
updateTime = models.DateTimeField( auto_now=True, db_comment="更新时间" ) # 更新时间(需要用 save() )
|
||||
|
||||
|
||||
|
||||
class Meta:
|
||||
db_table = "wecom企微员工" # 给数据表自定义一个名称;默认的会是在 应用名+类名
|
||||
app_label = "django_app"
|
||||
@@ -1,41 +0,0 @@
|
||||
import threading
|
||||
|
||||
import pydash
|
||||
import requests
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ViewSet
|
||||
|
||||
from sixGuoDjango import BaseResponse, ResData
|
||||
from wechat_token.token工具包 import sixToken
|
||||
from wechat_wecom_企业微信管理.企微通讯录管理.企微通讯录管理数据库.企微员工数据 import wecom企微员工
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class 企微员工通讯录管理接口ViewSets( ViewSet ):
|
||||
lock = threading.Lock( )
|
||||
|
||||
|
||||
|
||||
@action( detail=False, methods=[ "get", "post", "put", "delete" ], url_path="获取成员ID列表" )
|
||||
def 获取成员ID列表( self, request: Request ):
|
||||
pass
|
||||
wecom_phone_token = sixToken.get_weom_phone_token( )
|
||||
uri = f"https://qyapi.weixin.qq.com/cgi-bin/user/list_id?access_token={wecom_phone_token}"
|
||||
postData = requests.post( url=uri, json={
|
||||
"limit": 10000
|
||||
} )
|
||||
|
||||
企微员工列表数据 = pydash.get( obj=postData.json( ), path="dept_user" )
|
||||
print( 企微员工列表数据 )
|
||||
for 员工 in 企微员工列表数据:
|
||||
print( 员工 )
|
||||
userid = pydash.get( obj=员工, path="userid" )
|
||||
department = pydash.get( obj=员工, path="department" )
|
||||
wecom企微员工.objects.get_or_create( wecom_userid=userid, wecom_department=department )
|
||||
httpResData = BaseResponse( resData=ResData( listData=[ ], dictData={ } ), ).model_dump( )
|
||||
return Response( data=httpResData, status=status.HTTP_200_OK )
|
||||
@@ -38,9 +38,6 @@ class 客户管理接口ViewSets(ViewSet):
|
||||
@action(detail=False, methods=["post"], url_path="批量获取客户详情并存储到数据库")
|
||||
def 批量获取客户详情并存储到数据库(self, request: Request):
|
||||
""""""
|
||||
self_user_unionid = request.data.get("self_user_unionid", None)
|
||||
self_mini_openid = request.data.get("self_mini_openid", None)
|
||||
userid = request.data.get("userid", "YuanBao1975")
|
||||
state企微员工创建时添加的唯一值 = request.data.get("state企微员工创建时添加的唯一值", None)
|
||||
userid企微员工账号ID = request.data.get("userid企微员工账号ID", None)
|
||||
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import secrets
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Literal, Optional
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import django
|
||||
import orjson
|
||||
import pydash
|
||||
import requests
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.PublicKey.RSA import RsaKey
|
||||
from Crypto.Signature import pkcs1_15
|
||||
from Crypto.Util.Padding import unpad
|
||||
from dicttoxml import dicttoxml
|
||||
from django.conf import settings
|
||||
from pydantic import BaseModel, Field, SecretStr
|
||||
from requests import Response
|
||||
|
||||
from sixGuoDjango.settings import base_dir_name
|
||||
|
||||
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{base_dir_name}.settings")
|
||||
django.setup()
|
||||
|
||||
|
||||
class sixWechatPay六果泡泡支付(BaseModel):
|
||||
mchid: str = Field("1700383419", alias="商户号", description="微信支付商户号")
|
||||
appid: str = Field("wxf612e825377328f0", alias="商户号", description="微信支付商户号")
|
||||
api_v3_key: str = Field("YWMGAIPTJTWZN4YB3YUTHWK34K9U9M1W", alias="APIv3密钥", description="用于回调解密")
|
||||
api_v2_key: Optional[SecretStr] = Field("OXRNKGGUYHGNJSSIHKFGVMAAOHRPXJAT", alias="APIv2密钥", description="仅老接口需要")
|
||||
serial_no商户证书的序列号: str = Field("530160D54E8F56726F506DEE40D7FA49A558E8E0", description="商户证书的序列号")
|
||||
# ---------- 小程序密钥 ----------
|
||||
mini_program_app_secret: SecretStr = Field("8691f774e3c0c5a876b21a3e84109ef0", alias="小程序AppSecret")
|
||||
|
||||
# ---------- 商户API密钥对(用于签名请求) ----------
|
||||
merchant_private_key_pem: str = Field(Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/apiclient_key.pem").read_text(), alias="商户私钥PEM", description="apiclient_key.pem 内容")
|
||||
merchant_public_key_pem: str = Field(Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/微信支付公钥.pem").read_text(), alias="商户公钥PEM", description="apiclient_cert.pem 内容(很少用到)")
|
||||
|
||||
# ---------- 微信支付公钥(用于验签和加密敏感字段) ----------
|
||||
wechatpay_public_key_id: str = Field("PUB_KEY_ID_0117003834192026080500181856002000", alias="微信支付公钥ID")
|
||||
wechatpay_public_key_pem: str = Field(Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/微信支付公钥.pem").read_text(), alias="微信支付公钥PEM", description="pub_key.pem 内容")
|
||||
# ---------- 平台证书(灰度过渡期备用) ----------
|
||||
platform_cert_pem: Optional[
|
||||
str] = Field(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="发请求签名时需要的请求体")
|
||||
pay_methon方法: Literal["GET", "POST", "PATCH"] = Field("POST", description="发请求签名时需要的请求体")
|
||||
|
||||
def model_post_init(self, __context):
|
||||
print("初始化完成,自动调用 model_post_init")
|
||||
|
||||
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)
|
||||
Wechatpay_Timestamp = pydash.get(response_headers, "Wechatpay-Timestamp")
|
||||
Wechatpay_Nonce = pydash.get(response_headers, "Wechatpay-Nonce")
|
||||
Wechatpay_Signa = pydash.get(response_headers, "Wechatpay-Signature")
|
||||
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" # 构造验签名串
|
||||
print("最终验证的请求字符串", string_to_verify)
|
||||
hash_obj = SHA256.new(string_to_verify.encode())
|
||||
# 6. 验证签名
|
||||
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 # 签名验证失败
|
||||
|
||||
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创建成功的签名串 = ""
|
||||
# 创建签名请求参数
|
||||
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 = ""
|
||||
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):
|
||||
body_inner = self.pay_请求体.decode()
|
||||
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.payment.微信支付公钥ID})
|
||||
return headers
|
||||
|
||||
def 返回前端支付数据(self, prepay_id: str, wechat_appid: str):
|
||||
"""
|
||||
小程序调起支付
|
||||
通过JSAPI下单接口获取到发起支付的必要参数prepay_id,然后使用微信支付提供的小程序方法调起小程序支付。
|
||||
@param prepay_ids
|
||||
@type prepay_id:
|
||||
@return:
|
||||
@rtype:
|
||||
"""
|
||||
|
||||
utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp())
|
||||
random_string = secrets.token_hex(nbytes=30) # 随机字符串
|
||||
# 组装微信官方要求的格式;
|
||||
qian_mian_chuan = f"{wechat_appid}\n{utc_unix_timestamp}\n{random_string}\n{prepay_id}\n"
|
||||
# # 使用组装好地签名串,进行sha256 哈希生成哈希对象
|
||||
hash_obj = SHA256.new(qian_mian_chuan.encode())
|
||||
# 生成商户私钥对象
|
||||
# private_key = RSA.import_key( wechat_config.wechat私钥 )
|
||||
private_key = RSA.import_key(self.merchant_private_key_pem)
|
||||
# 生成签名
|
||||
signature = pkcs1_15.new(private_key).sign(hash_obj)
|
||||
# 将生成的签名串,转换为base格式
|
||||
encoded_signature = base64.b64encode(signature).decode()
|
||||
|
||||
return {
|
||||
"appId": self.appid,
|
||||
"timeStamp": str(utc_unix_timestamp),
|
||||
"nonceStr": random_string,
|
||||
"package": prepay_id,
|
||||
"signType": "RSA",
|
||||
"paySign": encoded_signature,
|
||||
}
|
||||
|
||||
def getpay_jsapi发起支付(self, ):
|
||||
headers = self.gouzhao构造签名串()
|
||||
# 发送请求
|
||||
response: Response = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=headers)
|
||||
prepay_id = pydash.get(obj=response.json(), path="prepay_id", default=None)
|
||||
# 验证请求后返回的数据是否为微信官方所发送;
|
||||
验证签名结果 = self.验证签名串(response_data=response.json(), response_headers=response.headers)
|
||||
if 验证签名结果:
|
||||
prepay_id = f"prepay_id={prepay_id}"
|
||||
# 调用方法生成返回给前端的对象
|
||||
return self.返回前端支付数据(prepay_id=prepay_id, wechat_appid=self.appid, ) # 调用 返回前端支付数据()方法生成返回前端的支付字典
|
||||
else:
|
||||
raise "验证不通过"
|
||||
|
||||
def modegmc解密(self, nonce: str, ciphertext: str, associated_data: str, ) -> dict:
|
||||
"""
|
||||
支付成功或者退款回调时需要解密参数,微信返回的响应体.解密后可以获取支付成功或者退款的详细的数据;
|
||||
@param nonce: // 加密使用的随机串初始化向量
|
||||
@type nonce:
|
||||
@param ciphertext: // Base64编码后的密文(需要解密)
|
||||
@type ciphertext: (需要解密)
|
||||
@param associated_data: // 附加数据包(可能为空)
|
||||
@type associated_data:
|
||||
@return:
|
||||
@rtype:
|
||||
"""
|
||||
nonce_bytes = nonce.encode(encoding="utf-8")
|
||||
ad_bytes = associated_data.encode(encoding="utf-8")
|
||||
encrypted_data = base64.b64decode(ciphertext)
|
||||
|
||||
cipher = AES.new(key=self.api_v3_key.encode(), mode=AES.MODE_GCM, nonce=nonce_bytes)
|
||||
# 处理附加关联数据(AAD) - 微信支付中通常是"transaction"
|
||||
# 这部分数据在加密过程中被验证但未被加密
|
||||
# 必须与加密时使用的附加数据完全一致
|
||||
cipher.update(assoc_data=ad_bytes)
|
||||
auth_tag = encrypted_data[-16:] # 提取认证标签(最后16 字节)
|
||||
# 提取实际加密内容
|
||||
ciphertext_bytes = encrypted_data[:-16] # 提取实际加密内容
|
||||
decrypted_data = cipher.decrypt_and_verify(ciphertext=ciphertext_bytes, received_mac_tag=auth_tag)
|
||||
# 回调解密数据: dict = json.loads(decrypted_data.decode())
|
||||
回调解密数据: dict = orjson.loads(decrypted_data.decode(encoding="utf-8"))
|
||||
return 回调解密数据
|
||||
|
||||
def callBack回调解密(self, headers, response_body: dict) -> dict:
|
||||
"""
|
||||
执行微信支付回调方法(获取返回的参数数据)
|
||||
@param request:
|
||||
@type request:
|
||||
"""
|
||||
self.验证签名串(response_headers=headers, response_data=response_body)
|
||||
ciphertext = pydash.get(obj=response_body, path="resource.ciphertext", 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)
|
||||
wei_xin_zhi_fu_hui_diao_data = self.modegmc解密(
|
||||
nonce=nonce, ciphertext=ciphertext,
|
||||
associated_data=associated_data,
|
||||
)
|
||||
return wei_xin_zhi_fu_hui_diao_data
|
||||
|
||||
def getpay_navite发起二维码支付(self, ):
|
||||
""" 二维码支付,可以适用于 网站 的用户扫码支付 """
|
||||
headers = self.gouzhao构造签名串()
|
||||
response = requests.post(url=self.pay_uri, headers=headers, json=self.pay_请求体)
|
||||
生成的支付链接 = response.json()
|
||||
return 生成的支付链接
|
||||
|
||||
def v2签名返回XML(self, ):
|
||||
"""v2版本的签名:将扫码支付的body转换为微信支付所要求的数据类型"""
|
||||
sorted_dict = dict(pydash.sort_by(collection=self.pay_请求体.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)
|
||||
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
|
||||
|
||||
def 解密群号(self, encryptedData, iv, sessionKey):
|
||||
"""
|
||||
"""
|
||||
try:
|
||||
session_key_bytes = base64.b64decode(sessionKey)
|
||||
encrypted_data_bytes = base64.b64decode(encryptedData)
|
||||
iv_bytes = base64.b64decode(iv)
|
||||
cipher = AES.new(key=session_key_bytes, mode=AES.MODE_CBC, iv=iv_bytes)
|
||||
# 解密并去除填充
|
||||
decrypted_data = unpad(cipher.decrypt(encrypted_data_bytes), AES.block_size).decode()
|
||||
data_dict = orjson.loads(decrypted_data)
|
||||
openGId = pydash.get(obj=data_dict, path="openGId")
|
||||
timestamp = pydash.get(obj=data_dict, path="watermark.timestamp")
|
||||
appid = pydash.get(obj=data_dict, path="watermark.appid")
|
||||
return openGId, timestamp, appid
|
||||
except Exception as e:
|
||||
raise Exception(f"解密失败: {str(e)}")
|
||||
|
||||
def 发起退款(self, ):
|
||||
pass
|
||||
uri = f"https://api.mch.weixin.qq.com/v3/refund/domestic/refunds"
|
||||
heardes = self.gouzhao构造签名串()
|
||||
print(heardes)
|
||||
response_data = requests.post(url=self.pay_uri, json=self.pay_请求体, headers=heardes)
|
||||
print(response_data.json())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsWs1Fz9kzTOal/tazXiD
|
||||
7TZ33lFJ9bq+AW7LXVO5gXJY68DtvAv2LTFBjEMOQCyGmzNE9v2nEJJ/ZGVERrfo
|
||||
MC5nVnzQBs+mL6QNOu90/g7TFzls/0+wNxf0usbbzXmU6hLKxWMnr2CPHcNnJIHJ
|
||||
rA4opkv0AwW125Ap60UChV7ocJeZ25yqJuEg1so/7dp/h1ivTjGF5AJvfFbIFwzK
|
||||
uQe+qCKi3GsCW5aWv4q9CpKyA3oy3hUjlgWiUMUEfVUia3gfrTDJeggJYi7MjBeZ
|
||||
zfu2b90JUzryko3vi9L8GWhKI1qMSFNcy24Lf7XVreryt+LwBqvy9F9nx1U90CXY
|
||||
bQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -17,12 +17,15 @@ from django.conf import settings
|
||||
|
||||
平台证书 = Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/sixgou_ping_tai_zheng_shu_cert.pem").read_text()
|
||||
|
||||
微信支付公钥 = Path(settings.BASE_DIR).joinpath("wechat_微信支付证书/江苏六果科技有限公司支付证书/微信支付公钥.pem").read_text()
|
||||
|
||||
|
||||
class sixpay六果科技公司:
|
||||
"""微信支付参数:江苏六果科技有限公司 信息"""
|
||||
public_key = 公钥证书 # 公钥
|
||||
private_key = 私钥证书 # 钥私
|
||||
wechat_certificate = 平台证书 # 平台证书
|
||||
pem微信支付公钥 = 微信支付公钥
|
||||
mchid = "1700383419" # 江苏六果科技有限公司商户号(微信支付商户号)
|
||||
serial_no = "530160D54E8F56726F506DEE40D7FA49A558E8E0" # 江苏六果科技有限公司 商户证书序列号
|
||||
appsecret = "8691f774e3c0c5a876b21a3e84109ef0" # 未生成 微信支付=>小程序密钥(小程序注册)
|
||||
@@ -31,6 +34,7 @@ class sixpay六果科技公司:
|
||||
appid = "wxf612e825377328f0"
|
||||
get_method = "GET" # 请求方法常量
|
||||
post_method = "POST" # 请求方法常量 wechatPay
|
||||
微信支付公钥ID = "PUB_KEY_ID_0117003834192026080500181856002000"
|
||||
|
||||
|
||||
class sixWeCom企业微信:
|
||||
@@ -43,4 +47,3 @@ class sixWeCom企业微信:
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
print(私钥证书)
|
||||
|
||||
@@ -4,18 +4,14 @@ import django
|
||||
|
||||
from sixGuoDjango.settings import 项目名称
|
||||
|
||||
|
||||
|
||||
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{项目名称}.settings")
|
||||
django.setup()
|
||||
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
from django.conf import settings
|
||||
|
||||
六果服务商平台证书 = Path(settings.BASE_DIR).joinpath(
|
||||
"wechat_微信支付证书/江苏六果科技服务商支付证书/江苏六果科技服务商平台证书.pem").read_text()
|
||||
"wechat_微信支付证书/江苏六果科技服务商支付证书/六果服务商平台证书.pem").read_text()
|
||||
六果服务商商户公钥证书 = Path(settings.BASE_DIR).joinpath(
|
||||
"wechat_微信支付证书/江苏六果科技服务商支付证书/商户公钥.pem").read_text()
|
||||
六果服务商商户私钥证书 = Path(settings.BASE_DIR).joinpath(
|
||||
|
||||
@@ -22,11 +22,12 @@ class 商品接口ViewSets(ViewSet):
|
||||
httpResData = BaseResponse(resData=ResData(listData=goodsDataList, dictData={}), ).model_dump()
|
||||
return Response(data=httpResData, status=status.HTTP_200_OK)
|
||||
|
||||
@action(detail=False, methods=["get", "post", "put", "delete"], url_path="赢免单商品")
|
||||
def 添加商品数据(self, request: Request):
|
||||
@action(detail=False, methods=["post", ], url_path="赢免单商品")
|
||||
def 赢免单商品(self, request: Request):
|
||||
pass
|
||||
赢免单商品数据 = Goods.objects.filter(goods_商品销售场景=goods商品Choices.赢免单.value).first()
|
||||
data = model_to_dict(instance=赢免单商品数据, fields=None, exclude=None)
|
||||
print("赢免单,商品查询没有结果了吗", data)
|
||||
return Response(data=data)
|
||||
|
||||
@action(detail=False, methods=["post"], url_path="query")
|
||||
@@ -50,9 +51,6 @@ class 商品接口ViewSets(ViewSet):
|
||||
@action(detail=False, methods=["post"], url_path="add_goods")
|
||||
def 添加商品接口(self, request: Request):
|
||||
""""""
|
||||
return
|
||||
self_user_unionid = request.data.get("self_user_unionid", None)
|
||||
self_mini_openid = request.data.get("self_mini_openid", None)
|
||||
Goods.objects.update_or_create(
|
||||
goods_商品品牌="六果泡泡",
|
||||
goods_商品信息={
|
||||
@@ -67,37 +65,36 @@ class 商品接口ViewSets(ViewSet):
|
||||
# goods_商品销售场景=goods商品Choices.商城商品.value,
|
||||
goods_商品销售场景=goods商品Choices.赢免单.value,
|
||||
goods_商品搜索标签=["20"],
|
||||
goods_商品销售规格=[
|
||||
{
|
||||
goods_商品销售规格={
|
||||
"goods_商品标题": "六果泡泡 (超划算) 源自天然酵素迅速渗入衣物,99%除菌🦠一洗即净,守护健康",
|
||||
"零售价格": 15200, "会员价": 14200, "销售规格": "20斤装/桶",
|
||||
"单个商品订单数量": 1, "单个商品订单总金额": 14200, "商品条码": "", "单个商品实际支付价格": 14200,
|
||||
"零售价格": 8000, "会员价": 7000, "销售规格": "20斤装/桶",
|
||||
"单个商品订单数量": 1, "单个商品订单总金额": 14200, "商品条码": "", "单个商品实际支付价格": 7000,
|
||||
"成本价": 12000, "净利润": 12200, "可选参数": ["苹果香", "熏衣草"], "商品ID": f"GOOD{ULID()}",
|
||||
"推荐积分": {"企微员工": 200, "推广员": 1000},
|
||||
"推荐积分": {"企微员工": 1000, "推广员": 5000},
|
||||
"goods_商品详情图片": {
|
||||
"主图": ["https://hudie.xiao.band/icon/six.png"],
|
||||
"详情图": ["https://hudie.xiao.band/icon/six.png", "https://hudie.xiao.band/icon/six.png"],
|
||||
},
|
||||
"goods_sku": [
|
||||
{
|
||||
"goods_sku_id": f"{ULID()}",
|
||||
"goods_sku": {
|
||||
"goods_select_title": "开启衣物芬芳之旅",
|
||||
"goods_sku_list": [
|
||||
{
|
||||
"goods_sku_name": "西瓜", "goods_是否默认选择": True,
|
||||
"goods_sku_id": f"{ULID()}",
|
||||
"goods_sku_条形码": f"",
|
||||
"goods_sku_name": "苹果香型", "goods_是否默认选择": True,
|
||||
"goods_sku_主图": ["https://hudie.xiao.band/icon/six.png"],
|
||||
"goods_sku_详情图": ["https://hudie.xiao.band/icon/six.png", "https://hudie.xiao.band/icon/six.png"],
|
||||
},
|
||||
{
|
||||
"goods_sku_name": "桔子", "goods_是否默认选择": False,
|
||||
"goods_sku_主图": ["https://hudie.xiao.band/icon/six.png"],
|
||||
"goods_sku_id": f"{ULID()}",
|
||||
"goods_sku_条形码": f"",
|
||||
"goods_sku_name": "桔子香型", "goods_是否默认选择": False,
|
||||
"goods_sku_主图": ["https://hudie.sixgou.com/%E5%85%AD%E6%9E%9C%E6%B3%A1%E6%B3%A1%E4%BA%A7%E5%93%81%E5%9B%BE.png"],
|
||||
"goods_sku_详情图": ["https://hudie.xiao.band/icon/six.png", "https://hudie.xiao.band/icon/six.png"],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
goods_商家推荐标签=["厂家直销", "独家配方", "自产自销", "量大实惠", "品质保证"],
|
||||
)
|
||||
httpResData = BaseResponse(resData=ResData(listData=[""], dictData={"demo": "xiaozizi"}), ).model_dump()
|
||||
@@ -105,4 +102,4 @@ class 商品接口ViewSets(ViewSet):
|
||||
|
||||
|
||||
商品接口ViewSetsRouter = DefaultRouter()
|
||||
商品接口ViewSetsRouter.register(prefix="", viewset=商品接口ViewSets, basename="")
|
||||
商品接口ViewSetsRouter.register(prefix="", viewset=商品接口ViewSets, basename="商品接口ViewSets")
|
||||
|
||||
@@ -1,72 +1,50 @@
|
||||
import secrets
|
||||
|
||||
import jmespath
|
||||
import orjson
|
||||
import pydash
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from rest_framework import status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from rest_framework.viewsets import ViewSet
|
||||
from ulid import ULID
|
||||
|
||||
from sixGuoDjango import ResData, BaseResponse
|
||||
from wechat_数据库.支付订单数据库.商品订单数据 import order订单
|
||||
from sixGuoDjango import BaseResponse, ResData
|
||||
from wechat_微信支付证书.江苏六果科技有限公司支付证书.六果公司支付类 import sixWechatPay六果泡泡支付
|
||||
from wechat_数据库.雪花算法.雪花算法工具 import generator
|
||||
from wechat_项目工具包.微信支付工具包.微信支付类 import paymentCategory, wechatPay
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class 微信支付ViewSets(ViewSet):
|
||||
|
||||
notify_url回调地址 = "https://xiao.sixgou.com/demopay/jsapi_callback/"
|
||||
|
||||
@action(detail=False, methods=["post"], url_path="jsapi")
|
||||
def 小程序支付jsapi(self, request: Request) -> Response:
|
||||
""""""
|
||||
url_pay = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi" # 发起请求的链接
|
||||
self_mini_openid = request.data.get("self_mini_openid", False) #
|
||||
order商品数据 = request.data.get( "order商品数据", None )
|
||||
order用户配送地址 = request.data.get( "order用户配送地址", None )
|
||||
order商品数量 = request.data.get( "order商品数量", None )
|
||||
order商品总价 = request.data.get( "order商品总价", None )
|
||||
order商品ID = request.data.get( "order商品ID", None )
|
||||
share订单分享者ID = request.data.get( "share订单分享者ID", None ) # 当前是否有上级对象
|
||||
order订单类型 = request.data.get( "order订单类型", None )
|
||||
superior_unionid = request.data.get( "superior_unionid", None ) # 当前是否有上级对象
|
||||
out_trade_no = f"{generator.generate_id( )}"
|
||||
print( self_mini_openid, "我的id拿不到了吗", order商品数据 )
|
||||
body = {
|
||||
"mchid": paymentCategory.mchid, # 【直连商户号】 直连商户号
|
||||
out_trade_no = f"{ULID()}"
|
||||
body_支付数据 = {
|
||||
"mchid": sixWechatPay六果泡泡支付().mchid, # 【直连商户号】 直连商户号
|
||||
"out_trade_no": out_trade_no, # 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
|
||||
"appid": paymentCategory.appid, # 【公众号 或者 小程序ID】
|
||||
"appid": sixWechatPay六果泡泡支付().appid, # 【公众号 或者 小程序ID】
|
||||
"description": "测试支付接口", # 【商品描述】 商品描述要
|
||||
"notify_url": "https://xiao.sixgou.com/demopay/jsapi_callback/", # 回调地址要
|
||||
"amount": {
|
||||
"total": 1, # 【总金额】 订单总金额,单位为分。
|
||||
"currency": "CNY", # 【货币类型】 CNY:人民币,境内商户号仅支持人民币。
|
||||
}, # 【支付者】 支付者信息。
|
||||
"attach": orjson.dumps( { "share订单分享者ID": share订单分享者ID }, option=orjson.OPT_SORT_KEYS, ).decode( encoding="utf-8" ),
|
||||
"payer": {
|
||||
# "openid": "ohQkD7A-N93kljcFmkCyG6e_D9vg", # 【用户标识】 用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID,详见OpenID获取
|
||||
"openid": self_mini_openid, # 【用户标识】 用户在普通商户AppID下的唯一标识。 下单前需获取到用户的OpenID,详见OpenID获取
|
||||
},
|
||||
} # 请求的数据
|
||||
wechat_data = wechatPay( payment=paymentCategory ).getpay_jsapi( uri=url_pay, body_data=body, method="POST" )
|
||||
print( wechat_data )
|
||||
payData = jmespath.search( data=wechat_data, expression="response" )
|
||||
order订单.objects.create( order支付商家侧订单号=out_trade_no,
|
||||
order商品总价=order商品总价, order商品数据=order商品数据, order商品数量=order商品数量,
|
||||
order商品ID=order商品ID, order支付数据=body, order支付状态="支付中", order订单类型=order订单类型,
|
||||
order支付都ID=self_mini_openid, order用户配送地址=order用户配送地址,
|
||||
)
|
||||
httpResData = BaseResponse( resData=ResData( listData=[ "" ], dictData=payData ), ).model_dump( )
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@action(detail=False, methods=["post"], url_path="navite")
|
||||
def 二维码支付(self, request: WSGIRequest | Request) -> Response:
|
||||
"""
|
||||
@@ -74,30 +52,30 @@ class 微信支付ViewSets( ViewSet ):
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
out_trade_no = f"{generator.generate_id( )}"
|
||||
out_trade_no商家侧订单号 = f"{ULID()}"
|
||||
native_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/native"
|
||||
native_body = {
|
||||
"mchid": paymentCategory.mchid, # 服务商户号
|
||||
"out_trade_no": out_trade_no, # 商户系统内部订单号
|
||||
"appid": paymentCategory.appid, # 服务商应用ID
|
||||
"mchid": sixWechatPay六果泡泡支付().mchid, # 服务商户号
|
||||
"out_trade_no": out_trade_no商家侧订单号, # 商户系统内部订单号
|
||||
"appid": sixWechatPay六果泡泡支付().appid, # 服务商应用ID
|
||||
"description": "测试", # 商品的描述信息
|
||||
"notify_url": "https://server.xiao.band/demopay/callback_navite/", # 回调地址
|
||||
"notify_url": "https://xiao.sixgou.com/demopay/callback_navite/", # 回调地址
|
||||
"amount": {"total": 1, "currency": "CNY"},
|
||||
}
|
||||
res_data = wechatPay( payment=paymentCategory ).getpay_navite( navite_body=native_body )
|
||||
print( res_data )
|
||||
code_url = jmespath.search( data=res_data, expression="code_url" )
|
||||
print( code_url )
|
||||
wechat_pay_data = sixWechatPay六果泡泡支付(pay_methon方法="POST", pay_请求体=native_body, pay_uri=native_url).getpay_navite发起二维码支付()
|
||||
print(wechat_pay_data)
|
||||
# res_data = wechatPay(payment=paymentCategory).getpay_navite(navite_body=native_body)
|
||||
# print(res_data)
|
||||
code_url = jmespath.search(data=wechat_pay_data, expression="code_url")
|
||||
# print(code_url)
|
||||
import segno
|
||||
|
||||
|
||||
qr = segno.make_qr( content="------", )
|
||||
qr = segno.make_qr(content=code_url, )
|
||||
data = qr.png_data_uri(scale=5)
|
||||
qr.save(out="myqr.png")
|
||||
httpResData = BaseResponse(resData=ResData(listData=[""], dictData={"demo": data}), ).model_dump()
|
||||
return Response(data=httpResData, status=status.HTTP_200_OK, )
|
||||
|
||||
|
||||
|
||||
@action(detail=False, methods=["post"], url_path="qrCode")
|
||||
def 付款码支付(self, request: Request):
|
||||
"""
|
||||
@@ -149,41 +127,64 @@ class 微信支付ViewSets( ViewSet ):
|
||||
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:
|
||||
""" 微信支付成功后的回调接口 """
|
||||
dict_body = request.data
|
||||
wechat_data支付回调数据 = wechatPay( payment=paymentCategory ).callBack回调解密( headers=request.headers, response_body=dict_body, )
|
||||
wechat_data支付回调数据 = sixWechatPay六果泡泡支付(pay_uri="", pay_请求体={}, pay_methon方法="POST").callBack回调解密(headers=request.headers, response_body=request.data)
|
||||
print("\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n", wechat_data支付回调数据, "\n🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 \n")
|
||||
out_trade_no = jmespath.search( data=wechat_data支付回调数据, expression="out_trade_no" )
|
||||
trade_state_desc = pydash.get( obj=wechat_data支付回调数据, path="trade_state_desc" )
|
||||
self_mini_openid = pydash.get( obj=wechat_data支付回调数据, path="payer.openid" )
|
||||
# 调用异步方法 : 作用 (发起订单录入接口调用)
|
||||
# 更新 拼团订单的 支付状态
|
||||
生成物流的订单号 = generator.generate_str( )
|
||||
order订单.objects.filter( order支付商家侧订单号=out_trade_no ).update( order支付数据=wechat_data支付回调数据, order支付状态=trade_state_desc,
|
||||
order物流状态=order订单.order订单choosies物流状态.待发货.value, order物流订单号=生成物流的订单号
|
||||
)
|
||||
# 在这里还需要处理是否给上级添加积分
|
||||
share订单分享者ID = pydash.get( obj=orjson.loads( pydash.get( obj=wechat_data支付回调数据, path="attach" ) ), path="share订单分享者ID" )
|
||||
|
||||
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="callback_navite")
|
||||
def 二维码支付回调( self, request: WSGIRequest | Request ):
|
||||
def 二维码支付回调(self, request: Request):
|
||||
"""注释"""
|
||||
二维码支付回调数据 = wechatPay( payment=paymentCategory ).callBack回调解密( headers=request.headers, response_body=request.body, )
|
||||
print( "二维码支付回调数据=>::", 二维码支付回调数据 )
|
||||
wechat_data支付回调数据 = sixWechatPay六果泡泡支付(pay_uri="", pay_请求体={}, pay_methon方法="POST").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={})
|
||||
|
||||
|
||||
|
||||
微信支付ViewSetsRouter = DefaultRouter( )
|
||||
微信支付ViewSetsRouter.register( prefix="", viewset=微信支付ViewSets, basename="" )
|
||||
@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={})
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from uuid6 import uuid8
|
||||
|
||||
from wechat_数据库.用户数据库.小程序登陆用户 import models_app_name
|
||||
from wechat_数据库.雪花算法.雪花算法工具 import generator
|
||||
|
||||
|
||||
class WechatTransferOrder(models.Model):
|
||||
"""
|
||||
微信商家转账订单记录表
|
||||
用于存储发起请求参数、微信返回的中间状态以及最终回调结果
|
||||
"""
|
||||
|
||||
# === 核心业务字段 ===
|
||||
|
||||
# 商户单据号 (发起时生成,全局唯一)
|
||||
class TransferOrderState(models.TextChoices):
|
||||
"""
|
||||
商家转账订单状态枚举
|
||||
涵盖发起时的中间状态和回调时的终态
|
||||
"""
|
||||
# --- 中间状态 (非终态) ---
|
||||
ACCEPTED = "ACCEPTED", _("已受理 (可原单重试)")
|
||||
PROCESSING = "PROCESSING", _("资金锁定中")
|
||||
WAIT_USER_CONFIRM = "WAIT_USER_CONFIRM", _("待用户确认")
|
||||
TRANSFERING = "TRANSFERING", _("转账中")
|
||||
CANCELING = "CANCELING", _("撤销中")
|
||||
# --- 终态 ---
|
||||
SUCCESS = "SUCCESS", _("转账成功")
|
||||
FAIL = "FAIL", _("转账失败")
|
||||
CANCELLED = "CANCELLED", _("已撤销")
|
||||
|
||||
id_主键_转账 = models.UUIDField(primary_key=True, default=uuid8, editable=True, )
|
||||
id_str = models.CharField(max_length=128, default=generator.generate_str)
|
||||
out_bill_no = models.CharField(max_length=120)
|
||||
# 微信转账单号 (回调时返回,发起时可能为空或为预生成值)
|
||||
transfer_bill_no = models.CharField(max_length=64, db_comment="微信转账单号", blank=True, null=True, )
|
||||
|
||||
# 订单状态
|
||||
state = models.CharField(max_length=32, choices=TransferOrderState, )
|
||||
|
||||
# 转账金额 (单位:分)
|
||||
transfer_amount = models.IntegerField(db_comment="转账金额(分)", )
|
||||
|
||||
# 收款用户 OpenID
|
||||
openid = models.CharField(max_length=64, db_comment="收款用户OpenID", blank=True, null=True, )
|
||||
|
||||
# 商户号
|
||||
mch_id = models.CharField(max_length=32, db_comment="商户号", blank=True, null=True, )
|
||||
|
||||
# === 异常与扩展字段 ===
|
||||
|
||||
# 失败原因 (仅在 state=FAIL 时有值)
|
||||
fail_reason = models.CharField(max_length=128, db_comment="失败原因代码", blank=True, null=True, )
|
||||
|
||||
# 失败详细描述 (可选,如果需要存储更详细的错误信息)
|
||||
fail_message = models.TextField(db_comment="失败详细描述", blank=True, null=True)
|
||||
|
||||
# 加密包信息 (发起时返回,用于特定场景下的重试或解密)
|
||||
package_info = models.TextField(db_comment="加密包信息", blank=True, null=True, )
|
||||
|
||||
# === 时间字段 ===
|
||||
|
||||
# 微信返回的创建时间 (发起接口返回的 create_time)
|
||||
wx_create_time = models.DateTimeField(db_comment="微信单据创建时间", null=True, blank=True)
|
||||
|
||||
# 微信返回的更新时间 (回调接口返回的 update_time)
|
||||
wx_update_time = models.DateTimeField(db_comment="微信单据更新时间", null=True, blank=True)
|
||||
|
||||
# 业务创建时间 (本地记录创建时间)
|
||||
created_at = models.DateTimeField(auto_now_add=True, db_comment="本地创建时间")
|
||||
|
||||
# 本地最后更新时间 (每次状态变更自动更新)
|
||||
updated_at = models.DateTimeField(auto_now=True, db_comment="本地最后更新时间")
|
||||
|
||||
class Meta:
|
||||
db_table = "WechatTransferOrder" # 给数据表自定义一个名称;默认的会是在 应用名+类名
|
||||
# 联合索引优化查询:常按状态和创建时间查询
|
||||
app_label = models_app_name
|
||||
@@ -49,31 +49,3 @@ class order订单(models.Model):
|
||||
ordering = ["-id_主键_order订单"]
|
||||
|
||||
|
||||
class order订单商品数据(models.Model):
|
||||
"""城市信息表"""
|
||||
objects = models.Manager() #
|
||||
|
||||
order订单商品数_id = models.UUIDField(primary_key=True, default=uuid8)
|
||||
order_id_str = models.CharField(max_length=128, default=generator.generate_str)
|
||||
order_id商品 = models.CharField(max_length=128, default=generator.generate_str)
|
||||
order_订单数量 = models.IntegerField(null=True, blank=True)
|
||||
order订单总金额 = models.IntegerField(null=True, blank=True)
|
||||
order_商品品牌 = models.CharField(max_length=128, )
|
||||
order_商品标题 = models.CharField(max_length=128, )
|
||||
order_商品信息 = models.JSONField(null=True, blank=True)
|
||||
order_商品标签 = models.JSONField(null=True, blank=True)
|
||||
order_商品详情图片 = models.JSONField(null=True, blank=True)
|
||||
order_商品销售规格 = models.JSONField(null=True, blank=True, )
|
||||
order_商品销售场景 = models.CharField(max_length=128, choices=goods商品Choices, null=True, blank=True,
|
||||
default=goods商品Choices.商城商品.value)
|
||||
order_分享积分 = models.JSONField(null=True, blank=True, )
|
||||
order_商品搜索标签 = models.JSONField(null=True, blank=True, )
|
||||
order_商家推荐标签 = models.JSONField(null=True, blank=True, )
|
||||
order_其它参数 = models.JSONField(null=True, blank=True)
|
||||
wai_订单 = models.ForeignKey(to=order订单, on_delete=models.CASCADE, null=True, blank=True)
|
||||
dateAndTime = models.DateTimeField(auto_now_add=True, db_comment="创建时间") # 数据创建时间
|
||||
updateTime = models.DateTimeField(auto_now=True, db_comment="更新时间") # 更新时间(需要用 save() )
|
||||
|
||||
class Meta:
|
||||
db_table = "order订单商品数据" # 给数据表自定义一个名称;默认的会是在 应用名+类名
|
||||
app_label = models_app_name
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from django.db import models
|
||||
from ulid import ULID
|
||||
from uuid6 import uuid8
|
||||
|
||||
from wechat_数据库.用户数据库.小程序登陆用户 import models_app_name
|
||||
|
||||
|
||||
class wei客服账号(models.Model):
|
||||
"""城市信息表"""
|
||||
objects = models.Manager() #
|
||||
|
||||
kefu_id = models.UUIDField(primary_key=True, default=uuid8)
|
||||
extInfo_推广员账号链接 = models.CharField(max_length=128, db_comment="企微客服账号链接")
|
||||
extInfo_企微员工绑定的UNIONID = models.CharField(max_length=128, db_comment="企微客服绑定的小程序unionid")
|
||||
extInfo_企微员工的名称 = models.CharField(max_length=128, null=True, blank=True, )
|
||||
dateAndTime = models.DateTimeField(auto_now_add=True, db_comment="创建时间") # 数据创建时间
|
||||
updateTime = models.DateTimeField(auto_now=True, db_comment="更新时间") # 更新时间(需要用 save() )
|
||||
|
||||
class Meta:
|
||||
db_table = "wei客服账号" # 给数据表自定义一个名称;默认的会是在 应用名+类名
|
||||
app_label = models_app_name
|
||||
@@ -1,4 +1,7 @@
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Literal, Optional
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import emoji
|
||||
import orjson
|
||||
@@ -6,7 +9,6 @@ import pydash
|
||||
import requests
|
||||
from django.forms import model_to_dict
|
||||
from pydantic import BaseModel, Field
|
||||
from ulid import ULID
|
||||
|
||||
from django_celery.message.tasks import mini调用微信小程序交易管理服务录入订单接口
|
||||
from wechat_token.token工具包 import sixToken
|
||||
@@ -192,43 +194,43 @@ class ems邮政物流工具(BaseModel):
|
||||
order当前订单对象.order物流订单号 = order订单对象.order物流订单号
|
||||
order当前订单对象.order物流公司订单编号 = waybill_id
|
||||
order当前订单对象.save()
|
||||
print(data.json())
|
||||
print("生成运单成功时的打印", data.json())
|
||||
# 这里的作用是, 当订单生成了 就调用 小程序交易管理的发货管理接口, 自动录入订单号
|
||||
mini调用微信小程序交易管理服务录入订单接口.apply_async(kwargs={"order支付商家侧订单号": order当前订单对象.order支付商家侧订单号}, countdown=30)
|
||||
|
||||
def 模拟更新订单状态(self, order物流商家侧订单号):
|
||||
def 模拟更新订单状态(self, order物流公司订单编号, action_type, action_msg):
|
||||
""""""
|
||||
|
||||
order物流对象 = order订单.objects.get(order物流公司订单编号=order物流公司订单编号)
|
||||
mini_token = sixToken.get_mini_token()
|
||||
milliseconds_int = ULID().milliseconds
|
||||
模拟更新物流状态 = f"https://api.weixin.qq.com/cgi-bin/express/business/test_update_order?access_token={mini_token}"
|
||||
utc_unix_timestamp = int(datetime.now(tz=ZoneInfo("utc")).timestamp())
|
||||
模拟数据 = {
|
||||
"biz_id": self.ems_biz_id,
|
||||
"order_id": order物流商家侧订单号, # 商家生成的订单号
|
||||
"order_id": order物流对象.order物流订单号, # 商家生成的订单号
|
||||
"delivery_id": self.ems_delivery_id, #
|
||||
"waybill_id": "", # 物流订单号
|
||||
"action_time": milliseconds_int, # 这里是更新发的时间戳
|
||||
"action_type": 100001,
|
||||
"action_msg": "揽件成功",
|
||||
"waybill_id": order物流公司订单编号, # 物流订单号
|
||||
"action_time": utc_unix_timestamp, # 这里是更新发的时间戳
|
||||
"action_type": action_type,
|
||||
"action_msg": action_msg,
|
||||
}
|
||||
print("打印 一下模拟的数据,主要就是看一下时间戳的问题", 模拟数据)
|
||||
data = requests.post(url=模拟更新物流状态,
|
||||
data=orjson.dumps(模拟数据, option=orjson.OPT_SORT_KEYS, ).decode(encoding="utf-8"))
|
||||
print("🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 ", data.json())
|
||||
|
||||
def 查询运单轨迹(self, order物流商家侧订单号):
|
||||
""""""
|
||||
查询对象 = order订单.objects.get(order物流订单号=order物流商家侧订单号, )
|
||||
print(查询对象)
|
||||
mini_token = sixToken.get_mini_token()
|
||||
|
||||
def 更新物流快递数据(self, order物流公司订单编号, order物流订单号):
|
||||
def 更新物流快递数据(self, order物流公司订单编号, ):
|
||||
""""""
|
||||
查询对象 = order订单.objects.get(order物流公司订单编号=order物流公司订单编号, order物流订单号=order物流订单号)
|
||||
查询对象 = order订单.objects.get(order物流公司订单编号=order物流公司订单编号, )
|
||||
mini_token = sixToken.get_mini_token()
|
||||
emsGetPathData = requests.post(url="https://api.weixin.qq.com/cgi-bin/express/business/path/get",
|
||||
params={"access_token": mini_token, },
|
||||
json={
|
||||
"openid": 查询对象.order支付者openid,
|
||||
"delivery_id": self.ems_delivery_id, "waybill_id": 查询对象.order物流公司订单编号,
|
||||
"delivery_id": self.ems_delivery_id, "waybill_id": order物流公司订单编号,
|
||||
},
|
||||
)
|
||||
resData = orjson.loads(emsGetPathData.content.decode(encoding="utf-8"))
|
||||
@@ -299,4 +301,11 @@ class ems邮政物流工具(BaseModel):
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 当脚本直接运行时执行的代码
|
||||
ems邮政物流工具().生成运单(out_trade_no商家侧支付订单号="")
|
||||
# ems邮政物流工具().生成运单(out_trade_no商家侧支付订单号="")
|
||||
ems邮政物流工具().模拟更新订单状态(order物流公司订单编号="EMS01KZAH47JZA3HCY2R5NS0WD3VN_waybill_id", action_type=100001, action_msg="揽件成功")
|
||||
time.sleep(30)
|
||||
ems邮政物流工具().模拟更新订单状态(order物流公司订单编号="EMS01KZAH47JZA3HCY2R5NS0WD3VN_waybill_id", action_type=300002, action_msg="开始派送")
|
||||
time.sleep(30)
|
||||
|
||||
ems邮政物流工具().模拟更新订单状态(order物流公司订单编号="EMS01KZAH47JZA3HCY2R5NS0WD3VN_waybill_id", action_type=300003, action_msg="签收成功")
|
||||
# ems邮政物流工具().更新物流快递数据(order物流公司订单编号="EMS01KZAD94RDQFQBVVX705YNH6SE_waybill_id")
|
||||
|
||||
@@ -5,7 +5,6 @@ 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()
|
||||
|
||||
@@ -15,11 +14,6 @@ import pydash
|
||||
import requests
|
||||
from django.conf import settings
|
||||
|
||||
from requests import post
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class wecom消息推送:
|
||||
pass
|
||||
@@ -106,11 +100,7 @@ class wecom消息推送:
|
||||
},
|
||||
],
|
||||
}
|
||||
data = post(
|
||||
url=url, json=json_data, params={
|
||||
"access_token": wecom_token,
|
||||
},
|
||||
)
|
||||
data = requests.post(url=url, json=json_data, params={"access_token": wecom_token, }, )
|
||||
print(data.json())
|
||||
|
||||
@classmethod
|
||||
@@ -126,7 +116,7 @@ class wecom消息推送:
|
||||
|
||||
@classmethod
|
||||
def 发送新客户欢迎语(cls, CALLBACK_CODE: str):
|
||||
""""""
|
||||
"""发送客户添加好友时的 欢迎语 """
|
||||
wecom_token = sixToken.get_wecom_token()
|
||||
url = f"https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token={wecom_token}"
|
||||
miniprogram = cls.欢迎语类型小程序()
|
||||
@@ -150,7 +140,7 @@ class wecom消息推送:
|
||||
""",
|
||||
},
|
||||
}
|
||||
data = post( url=url, json=json_data )
|
||||
data = requests.post(url=url, json=json_data)
|
||||
print("客户欢迎语发送成功了:", data.json())
|
||||
errcode = pydash.get(obj=data.json(), path="errcode")
|
||||
if errcode == 41051:
|
||||
@@ -158,9 +148,6 @@ class wecom消息推送:
|
||||
return data.json().get("errmsg")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class wecom获取企业的全部群发记录:
|
||||
"""
|
||||
企业跟第三方应用可通过该接口获取群发给客户的消息和群发到客户群的消息
|
||||
@@ -191,7 +178,7 @@ class wecom获取企业的全部群发记录:
|
||||
"limit": 50,
|
||||
"cursor": "CURSOR"
|
||||
}
|
||||
data = post( url=url, json=请求数据示例 ).json( )
|
||||
data = requests.post(url=url, json=请求数据示例).json()
|
||||
print(data)
|
||||
|
||||
@classmethod
|
||||
@@ -203,13 +190,12 @@ class wecom获取企业的全部群发记录:
|
||||
wecom_token = sixToken.get_wecom_token()
|
||||
url = f"https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_groupmsg_task?access_token={wecom_token}"
|
||||
请求数据示例 = {"msgid": "msgGCAAAXtWyujaWJHDDGi0mACAAAA", "limit": 50, "cursor": "CURSOR"}
|
||||
data = post( url=url, json=请求数据示例 ).json( )
|
||||
data = requests.post(url=url, json=请求数据示例).json()
|
||||
print(data)
|
||||
|
||||
@classmethod
|
||||
def 获取企业群发成员执行结果(cls):
|
||||
"""
|
||||
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
@@ -221,13 +207,10 @@ class wecom获取企业的全部群发记录:
|
||||
"limit": 50,
|
||||
"cursor": "CURSOR"
|
||||
}
|
||||
data = post( url=url, json=请求数据示例 ).json( )
|
||||
data = requests.post(url=url, json=请求数据示例).json()
|
||||
print(data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class wecom入群欢迎语素材管理:
|
||||
"""
|
||||
添加入群欢迎语素材
|
||||
@@ -267,7 +250,7 @@ class wecom入群欢迎语素材管理:
|
||||
"agentid": 1000014,
|
||||
"notify": 1
|
||||
}
|
||||
data = post( url=url, json=请求数据示例 ).json( )
|
||||
data = requests.post(url=url, json=请求数据示例).json()
|
||||
print(data)
|
||||
|
||||
@classmethod
|
||||
@@ -303,7 +286,7 @@ class wecom入群欢迎语素材管理:
|
||||
},
|
||||
"agentid": 1000014
|
||||
}
|
||||
data = post( url=uri, json=请求数据示例 ).json( )
|
||||
data = requests.post(url=uri, json=请求数据示例).json()
|
||||
print(data)
|
||||
|
||||
@classmethod
|
||||
@@ -313,7 +296,7 @@ class wecom入群欢迎语素材管理:
|
||||
请求数据示例 = {
|
||||
"template_id": "msgXXXXXXX"
|
||||
}
|
||||
data = post( url=uri, json=请求数据示例 ).json( )
|
||||
data = requests.post(url=uri, json=请求数据示例).json()
|
||||
print(data)
|
||||
|
||||
@classmethod
|
||||
@@ -327,13 +310,10 @@ class wecom入群欢迎语素材管理:
|
||||
"template_id": "msgXXXXXXX",
|
||||
"agentid": 1000014
|
||||
}
|
||||
data = post( url=uri, json=请求数据示例 ).json( )
|
||||
data = requests.post(url=uri, json=请求数据示例).json()
|
||||
print(data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class uploadTempMedia上传附件资源:
|
||||
|
||||
@classmethod
|
||||
@@ -353,7 +333,7 @@ class uploadTempMedia上传附件资源:
|
||||
print(file_path)
|
||||
file = {"media": open(file=file_path, mode="rb", )}
|
||||
|
||||
data = post( url=uri, files=file )
|
||||
data = requests.post(url=uri, files=file)
|
||||
media_id = pydash.get(obj=data.json(), path="media_id")
|
||||
print(media_id)
|
||||
|
||||
@@ -361,20 +341,14 @@ class uploadTempMedia上传附件资源:
|
||||
def 上传临时素材(cls):
|
||||
wecom_token = sixToken.get_wecom_token()
|
||||
uri = f"https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token={wecom_token}&type=image"
|
||||
# file_path = Path(settings.BASE_DIR).joinpath("django_环境/常用类/xiao小程序项目图片/ico运力管理系统.png")
|
||||
file_path = Path( settings.BASE_DIR ).joinpath( "django_环境//常用类/xiao小程序项目图片/莫大帅分享主图.png" )
|
||||
print( file_path )
|
||||
file_path = Path(settings.BASE_DIR).joinpath("django_环境/常用类/xiao小程序项目图片/莫大帅分享主图.png")
|
||||
file = {"media": open(file=file_path, mode="rb", )}
|
||||
|
||||
data = post( url=uri, files=file )
|
||||
data = requests.post(url=uri, files=file)
|
||||
media_id = pydash.get(obj=data.json(), path="media_id")
|
||||
print(data.json())
|
||||
print(media_id)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
uploadTempMedia上传附件资源.上传临时素材()
|
||||
|
||||
@@ -16,6 +16,13 @@ class miniTransaction交易管理服务工具(BaseModel):
|
||||
# demo_可选: Optional[int] = None # 可选值
|
||||
# demo_默认值: int = Field(default=100001, description="描述") # 有默认值
|
||||
# demo_联合类型: Literal["xiao", "zizi"] = Field(..., description="描述")
|
||||
def 消息跳转路径设置(self, ):
|
||||
"""如你已经在小程序内接入平台提供的确认收货组件,可以通过该接口设置发货消息及确认收货消息的跳转动作,
|
||||
用户点击发货消息时会直接进入你的小程序订单列表页面或详情页面进行确认收货,进一步优化用户体验"""
|
||||
pass
|
||||
mini_token = sixToken.get_mini_token()
|
||||
uri = f"https://api.weixin.qq.com/wxa/sec/order/set_msg_jump_path?access_token={mini_token}"
|
||||
|
||||
def 发货信息录入(self, order支付商家侧订单号, ):
|
||||
pass
|
||||
print("开始调用录入订单信息了")
|
||||
@@ -73,6 +80,7 @@ class miniTransaction交易管理服务工具(BaseModel):
|
||||
"""这里的调用的时机为: 目前的业务逻辑是,物流的状态更新用户已签收了 , 我会在此时调用户确认接口 用户会收得到一个 确认收货的提示"""
|
||||
mini_token = sixToken.get_mini_token()
|
||||
uri = f"https://api.weixin.qq.com/wxa/sec/order/notify_confirm_receive?access_token={mini_token}"
|
||||
print("发起确认交易调用了")
|
||||
# 快递签收时间设定为 2026-07-24 04:11:24
|
||||
action_time_签收时间戳 = pydash.get(obj=pydash.head(order物流数据), path="action_time")
|
||||
data = {
|
||||
@@ -80,10 +88,12 @@ class miniTransaction交易管理服务工具(BaseModel):
|
||||
"received_time": action_time_签收时间戳, # 快递签收时间,时间戳形式,必传
|
||||
}
|
||||
postData = requests.post(url=uri, json=data)
|
||||
print(postData.json())
|
||||
# 当请求发送后, 因为只能发送一次,所以需要直接更新状态,
|
||||
更新对象 = order订单.objects.get(order支付微信官方订单号=order支付微信官方订单号)
|
||||
更新对象.order物流状态 = "待用户确认收货"
|
||||
更新对象.save()
|
||||
print("发起确认交易调用成功了")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -11,6 +11,7 @@ import os
|
||||
import django
|
||||
|
||||
from sixGuoDjango.settings import base_dir_name
|
||||
from wechat_微信支付证书.江苏六果科技服务商支付证书.江苏六果科技有限公司服务商支付参数 import six六果服务商支付参数
|
||||
|
||||
os.environ.setdefault(key="DJANGO_SETTINGS_MODULE", value=f"{base_dir_name}.settings")
|
||||
django.setup()
|
||||
@@ -35,8 +36,8 @@ from typing import Optional, Literal
|
||||
|
||||
import pydash
|
||||
import xmltodict
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.Cipher import AES, PKCS1_OAEP
|
||||
from Crypto.Hash import SHA1, SHA256
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.PublicKey.RSA import RsaKey
|
||||
from Crypto.Signature import pkcs1_15
|
||||
@@ -51,21 +52,13 @@ class paymentCategory(sixpay六果科技公司):
|
||||
|
||||
|
||||
class wechatPay(BaseModel):
|
||||
payment: type[paymentCategory] | type[sixpay六果科技公司]
|
||||
payment: type[sixpay六果科技公司] | type[six六果服务商支付参数]
|
||||
|
||||
def 构造签名串(self, uri: str, body_data: dict | bytes | str | None = None,
|
||||
method: Optional[Literal["GET", "POST"]] = "POST",
|
||||
method: Optional[Literal["GET", "POST", "PATCH"]] = "POST",
|
||||
):
|
||||
"""
|
||||
构造签名串
|
||||
@param url:
|
||||
@type url:
|
||||
@param body:
|
||||
@type body:
|
||||
@param method:
|
||||
@type method:
|
||||
@return: 返回已经加密后并组装好的请求头;
|
||||
@rtype:
|
||||
|
||||
"""
|
||||
url_data = re.search(r'/v3.*', string=uri).group()
|
||||
shi_jian_chou = str(int(time.time())) # 时间戳
|
||||
@@ -91,7 +84,7 @@ class wechatPay(BaseModel):
|
||||
# 加载商户私钥
|
||||
# 调用了 RSA.import_key() 方法,它会从字符串或文件中导入一个 PEM 格式的 RSA 私钥,并返回一个 RsaKey 类型的对象
|
||||
private_key: RsaKey = RSA.import_key(self.payment.private_key)
|
||||
# 生成签名
|
||||
# 生成签名 使用商户的 私钥进行签名
|
||||
signature = pkcs1_15.new(rsa_key=private_key).sign(msg_hash=hash_obj)
|
||||
# 对签名进行Base64编码,符合微信支付API要求
|
||||
encoded_signature = base64.b64encode(s=signature).decode()
|
||||
@@ -111,24 +104,16 @@ class wechatPay(BaseModel):
|
||||
headers = {
|
||||
"Content-Type": "application/json", "Authorization": Authorization,
|
||||
}
|
||||
# headers.update({"Wechatpay-Serial": self.payment.微信支付公钥ID})
|
||||
return headers
|
||||
|
||||
def getpay_jsapi(self, uri, body_data: dict | bytes | str | None = None, method: Optional[
|
||||
Literal["GET", "POST"]] = "POST",
|
||||
):
|
||||
"""
|
||||
@param url: 请求支付的微信官方地址
|
||||
@type url: str
|
||||
@param pay_body: 小程序下单接口获取到发起支付的必要参数prepay_id
|
||||
@type pay_body: str
|
||||
@return:
|
||||
@rtype:
|
||||
"""
|
||||
|
||||
headers = self.构造签名串(uri=uri, body_data=body_data, method=method)
|
||||
# 发送请求
|
||||
response: Response = requests.post(url=uri, json=body_data, headers=headers)
|
||||
print(response.json())
|
||||
prepay_id = pydash.get(obj=response.json(), path="prepay_id", default=None)
|
||||
# 验证请求后返回的数据是否为微信官方所发送;
|
||||
验证签名结果 = self.验证签名串(response_data=response.json(), response_headers=response.headers)
|
||||
@@ -170,6 +155,15 @@ class wechatPay(BaseModel):
|
||||
回调解密数据: dict = orjson.loads(decrypted_data.decode(encoding="utf-8"))
|
||||
return 回调解密数据
|
||||
|
||||
def modegmc解密电子发票邮箱账号(self, ciphertext):
|
||||
pass
|
||||
encrypted_bytes = base64.b64decode(ciphertext)
|
||||
# 3. 构建 OAEP 解密器(SHA-1)
|
||||
private_key: RsaKey = RSA.import_key(self.payment.private_key)
|
||||
cipher = PKCS1_OAEP.new(key=private_key, hashAlgo=SHA1)
|
||||
plaintext_bytes = cipher.decrypt(encrypted_bytes)
|
||||
return plaintext_bytes.decode("utf-8")
|
||||
|
||||
def getpay_navite(self, navite_body: dict, ):
|
||||
"""
|
||||
@param navite_body:
|
||||
@@ -316,6 +310,7 @@ class wechatPay(BaseModel):
|
||||
@rtype:
|
||||
"""
|
||||
public_key = RSA.import_key(self.payment.wechat_certificate)
|
||||
# public_key = RSA.import_key(self.payment.pem微信支付公钥)
|
||||
Wechatpay_Timestamp = pydash.get(response_headers, "Wechatpay-Timestamp")
|
||||
Wechatpay_Nonce = pydash.get(response_headers, "Wechatpay-Nonce")
|
||||
Wechatpay_Signa = pydash.get(response_headers, "Wechatpay-Signature")
|
||||
@@ -331,7 +326,6 @@ class wechatPay(BaseModel):
|
||||
|
||||
def v2签名返回XML(self, sign_data: dict):
|
||||
"""v2版本的签名:将扫码支付的body转换为微信支付所要求的数据类型"""
|
||||
# sorted_dict = dict(sorted(sign_data.items(), key=lambda item: item[0], reverse=False))
|
||||
sorted_dict = dict(pydash.sort_by(collection=sign_data.items(), iteratee=0))
|
||||
# 拼接字符串: (将密钥添加到最末尾)
|
||||
params_str = "&".join(f"{k}={v}" for k, v in sorted_dict.items()) + '&key=' + self.payment.apiv2
|
||||
@@ -397,14 +391,6 @@ class wechatPay(BaseModel):
|
||||
|
||||
def 解密群号(self, encryptedData, iv, sessionKey):
|
||||
"""
|
||||
对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
|
||||
对称解密的目标密文为 Base64_Decode(encryptedData)。
|
||||
对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
|
||||
对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
|
||||
:param sessionKey:
|
||||
:param encryptedData:
|
||||
:param iv:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
session_key_bytes = base64.b64decode(sessionKey)
|
||||
@@ -447,7 +433,7 @@ class wechatPay(BaseModel):
|
||||
|
||||
def 发起退款(self, body):
|
||||
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.构造签名串(body_data=body, uri=uri, method="POST")
|
||||
print(heardes)
|
||||
response_data = requests.post(url=uri, json=body, headers=heardes)
|
||||
|
||||
@@ -29,7 +29,7 @@ class stock发送代金券功能(BaseModel):
|
||||
# 第二步: 创建好需要的数据并验名
|
||||
params每一张券需要验名的数据格式 = {
|
||||
"out_request_no0": out_request_no, # 商家侧的发券订单号
|
||||
"stock_id0": "22512292", # 代金券创建的批次号
|
||||
"stock_id0": self.stock_id_代金券批次号, # 代金券创建的批次号
|
||||
"send_coupon_merchant": mchid, # 发券的商家商户号
|
||||
# 如果是支付券,必须包含此项并参与签名;商家券则去掉
|
||||
"create_coupon_merchant0": mchid, # 发券的商家商户号
|
||||
@@ -46,7 +46,7 @@ class stock发送代金券功能(BaseModel):
|
||||
# 3. 拼接参数串
|
||||
params = {
|
||||
"out_request_no": out_request_no,
|
||||
"stock_id": "22512292",
|
||||
"stock_id": self.stock_id_代金券批次号,
|
||||
"create_coupon_merchant": sixpay六果科技公司.mchid,
|
||||
"customize_send_time": rfc3339,
|
||||
"send_coupon_merchant": sixpay六果科技公司.mchid,
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import requests
|
||||
from pydantic import BaseModel
|
||||
from yarl import URL
|
||||
|
||||
from wechat_微信支付证书.江苏六果科技服务商支付证书.江苏六果科技有限公司服务商支付参数 import six六果服务商支付参数
|
||||
from wechat_项目工具包.微信支付工具包.微信支付类 import wechatPay
|
||||
|
||||
|
||||
class weiPay服务商电子发票(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):
|
||||
pass
|
||||
uri = URL.build(
|
||||
scheme='https',
|
||||
host="api.mch.weixin.qq.com",
|
||||
path="/v3/new-tax-control-fapiao/fapiaomerchant/getspinviteurl",
|
||||
query={
|
||||
"operation_type": "AUTH_BINDING",
|
||||
"fapiao_mode": ["TENCENT_DIGITAL_TAX"], # 【开票模式】 邀请商户开通服务商电子发票的可选开票模式
|
||||
"fapiao_ability_type_list": ["BASE_ABILITY"],
|
||||
"invite_code": "code_20260805_123", # 必填 【服务商邀请code】 服务商邀请的唯一标识,由服务商生成,可根据邀请code查询邀请开通情况
|
||||
# "sub_mchid": "1700383419"
|
||||
"taxpayer_id":"91321202MAE608K31Q"
|
||||
}
|
||||
)
|
||||
print(uri)
|
||||
headers = wechatPay(payment=six六果服务商支付参数).构造签名串(uri=str(uri), method="GET")
|
||||
headers.update({"Wechatpay-Serial":"1880A972F4400AF653A108F5F0C7A71585A4338E"})
|
||||
getData = requests.get(url=uri, headers=headers)
|
||||
print(getData.text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
weiPay服务商电子发票().获取开通服务商电子发票能力邀请链接()
|
||||
@@ -0,0 +1,135 @@
|
||||
import emoji
|
||||
import pydash
|
||||
import requests
|
||||
from pydantic import BaseModel
|
||||
from ulid import ULID
|
||||
|
||||
from wechat_微信支付证书.江苏六果科技有限公司支付证书.江苏六果科技有限公司支付参数 import sixpay六果科技公司
|
||||
from wechat_数据库.支付订单数据库.商品订单数据 import order订单
|
||||
from wechat_项目工具包.微信支付工具包.微信支付类 import wechatPay
|
||||
|
||||
|
||||
class weiPay电子发票(BaseModel):
|
||||
# demo_可选: Optional[int] = None # 可选值
|
||||
# demo_默认值: int = Field(default=100001, description="描述") # 有默认值
|
||||
# demo_联合类型: Literal["xiao", "zizi"] = Field(..., description="描述")
|
||||
|
||||
def model_post_init(self, __context):
|
||||
print("")
|
||||
|
||||
def 配置开发选项(self):
|
||||
"""配置,小程序用户申请开票时的回调请求地址URL"""
|
||||
pass
|
||||
uri = f"https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/merchant/development-config"
|
||||
http_uri = "https://xiao.sixgou.com/wechat_mini/invoice/callback/"
|
||||
请求体 = {
|
||||
"callback_url": http_uri,
|
||||
"show_fapiao_cell": True
|
||||
}
|
||||
header电子发票请求头 = wechatPay(payment=sixpay六果科技公司).构造签名串(uri=uri, body_data=请求体, method="PATCH")
|
||||
postData = requests.patch(url=uri, json=请求体, headers=header电子发票请求头)
|
||||
|
||||
def 获取商户开票基础信息(self):
|
||||
pass
|
||||
uri = f"https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/merchant/base-information"
|
||||
heardes_data = wechatPay(payment=sixpay六果科技公司).构造签名串(uri=uri, method="GET")
|
||||
getData = requests.get(url=uri, headers=heardes_data)
|
||||
print(getData)
|
||||
print(getData.text)
|
||||
|
||||
@classmethod
|
||||
def 查询电子发票的数据(cls, fapiao_apply_id: str):
|
||||
fapiao_apply_id = "4500000249202608055531280227"
|
||||
uri = f"https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/fapiao-applications/{fapiao_apply_id}"
|
||||
headers = wechatPay(payment=sixpay六果科技公司).构造签名串(uri=uri, method="GET")
|
||||
postData = requests.get(url=uri, headers=headers)
|
||||
|
||||
print(postData)
|
||||
print(postData.json())
|
||||
|
||||
@classmethod
|
||||
def 开具电子发票(cls, fapiao_apply_id, 用户填写的开票):
|
||||
pass
|
||||
|
||||
uri = f"https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/fapiao-applications"
|
||||
发起开票的数据 = {
|
||||
"scene": "WITH_WECHATPAY", # 开票场景,固定值 "WITH_WECHATPAY" 表示该开票申请来源于微信支付订单
|
||||
"fapiao_apply_id": fapiao_apply_id, # 发票申请单号,从"获取用户填写抬头信息"接口返回的 fapiao_apply_id
|
||||
|
||||
"fapiao_information": [ # 发票信息列表(本次只开一张票,故只有一个元素)
|
||||
{
|
||||
"fapiao_id": "20200701123456", # 商户侧发票单号,由商户自行生成,保证唯一
|
||||
"total_amount": 1, # 总价税合计,单位为分(整数)
|
||||
"need_list": False, # 是否需要发票明细清单,false 表示不需要(即只在票面显示总金额)
|
||||
"remark": "微信电子发票测试备注", # 发票备注(选填)
|
||||
"items": [ # 发票行项目列表
|
||||
{
|
||||
"tax_code": "3010101020203000000", # 税收分类编码(需从"获取商品和服务税收分类对照表"接口获取)
|
||||
"goods_category": "洗化用品", # 商品类别(选填,用于辅助分类)
|
||||
"goods_name": "六果洗衣液", # 商品名称(必填,显示在发票明细上)
|
||||
"goods_id": 1, # 商品编号(商户自定义,选填
|
||||
"specification": "A4", # 规格型号(选填)
|
||||
"unit": "根", # 计量单位(选填,如“次”“个”“件”)
|
||||
"quantity": 1, # 数量(整数,此处数量极大,实际应根据订单合理设置)
|
||||
"total_amount": 1, # 该行项目的总价税合计,单位为分(应与 total_amount 逻辑一致)
|
||||
"tax_rate": 1300, # 税率,单位为万分比(如 13% 填 1300)
|
||||
"tax_prefer_mark": "NO_FAVORABLE", # 税收优惠政策标识:NO_FAVORABLE 表示不享受优惠
|
||||
"discount": False, # 是否享受折扣,false 表示不折扣
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
发起开票的数据.update({"buyer_information": 用户填写的开票})
|
||||
商家侧生成的发票单号 = f"{ULID()}"
|
||||
发票对象 = order订单.objects.get(order支付微信官方订单号=fapiao_apply_id)
|
||||
print(发票对象.order购物车商品总价)
|
||||
总价税合计 = 发票对象.order购物车商品总价
|
||||
goods_name = emoji.replace_emoji(pydash.get(obj=pydash.head(发票对象.order购物车商品数据), path="goods_商品标题"))
|
||||
销售规格 = pydash.get(obj=pydash.head(发票对象.order购物车商品数据), path="销售规格")
|
||||
单个商品订单数量 = pydash.get(obj=pydash.head(发票对象.order购物车商品数据), path="单个商品订单数量")
|
||||
fapiao_information = [
|
||||
{
|
||||
"fapiao_id": 商家侧生成的发票单号, # 商户侧发票单号,由商户自行生成,保证唯一
|
||||
"total_amount": 总价税合计, # 总价税合计,单位为分(整数)
|
||||
"need_list": False, # 是否需要发票明细清单,false 表示不需要(即只在票面显示总金额)
|
||||
"remark": "微信电子发票", # 发票备注(选填)
|
||||
"items": [ # 发票行项目列表
|
||||
{
|
||||
"tax_code": "3010101020203000000", # 税收分类编码(需从"获取商品和服务税收分类对照表"接口获取)
|
||||
"goods_category": "洗化用品", # 商品类别(选填,用于辅助分类)
|
||||
"goods_name": goods_name, # 商品名称(必填,显示在发票明细上)
|
||||
"goods_id": 1, # 商品编号(商户自定义,选填)
|
||||
"specification": 销售规格, # 规格型号(选填)
|
||||
"unit": "根", # 计量单位(选填,如“次”“个”“件”)
|
||||
"quantity": 单个商品订单数量, # 数量(整数,此处数量极大,实际应根据订单合理设置)
|
||||
"total_amount": 总价税合计, # 该行项目的总价税合计,单位为分(应与 total_amount 逻辑一致)
|
||||
"tax_rate": 1300, # 税率,单位为万分比(如 13% 填 1300)
|
||||
"tax_prefer_mark": "NO_FAVORABLE", # 税收优惠政策标识:NO_FAVORABLE 表示不享受优惠
|
||||
"discount": False, # 是否享受折扣,false 表示不折扣
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
发起开票的数据.update({"fapiao_information": fapiao_information})
|
||||
print(发起开票的数据)
|
||||
headers = wechatPay(payment=sixpay六果科技公司).构造签名串(uri=uri, body_data=发起开票的数据, method="POST")
|
||||
headers.update({"Wechatpay-Serial": "11D762828E947104028F2D045DE78FA806D0D4F2"})
|
||||
print("打印一下请求头", headers)
|
||||
postData = requests.post(url=uri, json=发起开票的数据, headers=headers)
|
||||
|
||||
print(postData.text)
|
||||
|
||||
@classmethod
|
||||
def 获取用户填写的开票(cls, fapiao_apply_id):
|
||||
uri = f"https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/user-title?fapiao_apply_id={fapiao_apply_id}&scene=WITH_WECHATPAY"
|
||||
headers = wechatPay(payment=sixpay六果科技公司).构造签名串(uri=uri, method="GET")
|
||||
postData = requests.get(url=uri, headers=headers)
|
||||
|
||||
return postData.json()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
用户填写的开票 = weiPay电子发票.获取用户填写的开票(fapiao_apply_id="4500000272202608055614870626")
|
||||
weiPay电子发票.开具电子发票(fapiao_apply_id="4500000272202608055614870626", 用户填写的开票=用户填写的开票)
|
||||
@@ -137,6 +137,7 @@ class miniUser积分(BaseModel):
|
||||
order好友下单企微员工需要添加的积分值 = int(order好友下单商品数量) * int(order购物车商品好友下单助力的企微员工的的积分值)
|
||||
if share分享者unionidID == click点击者unionidID or share分享者对象.parent == six六果对象:
|
||||
print("自己点了自己,不需要添加积分了")
|
||||
return
|
||||
if share分享者对象.user_角色权限 == miniUser用户角色().推广员:
|
||||
pass # 如果是推广员则添加
|
||||
share对象, share布尔值 = share积分表.objects.update_or_create(
|
||||
|
||||
+45
-45
@@ -95,14 +95,14 @@ class wei地图工具:
|
||||
print(res_data.json())
|
||||
res_json = res_data.json() # type: dict
|
||||
d = {
|
||||
'status': 0,
|
||||
'message': 'Success',
|
||||
'request_id': '9435209f1ee84219ae7826e65f577331',
|
||||
'result': {
|
||||
'rows': [{
|
||||
'elements': [{
|
||||
'distance': 3550, # 起点到终点的距离,单位:米
|
||||
'duration': 651, # 表示从起点到终点的结合路况的时间,秒为单位注:步行/骑行方式(不计算耗时)以及起终点附近没有道路造成无法计算时,不返回本此节点
|
||||
"status": 0,
|
||||
"message": "Success",
|
||||
"request_id": "9435209f1ee84219ae7826e65f577331",
|
||||
"result": {
|
||||
"rows": [{
|
||||
"elements": [{
|
||||
"distance": 3550, # 起点到终点的距离,单位:米
|
||||
"duration": 651, # 表示从起点到终点的结合路况的时间,秒为单位注:步行/骑行方式(不计算耗时)以及起终点附近没有道路造成无法计算时,不返回本此节点
|
||||
}],
|
||||
}],
|
||||
},
|
||||
@@ -116,29 +116,29 @@ class wei地图工具:
|
||||
url = f"https://apis.map.qq.com/ws/geocoder/v1/?address={address}"
|
||||
res = requests.get(url=url, params={"key": cls.key}, )
|
||||
d = {
|
||||
'status': 0,
|
||||
'message': 'Success',
|
||||
'request_id': '9b049a3ff13c4ac3bda3bb5a9fe0c0a8',
|
||||
'result': {
|
||||
'title': '泰州海陵万达广场',
|
||||
'location': { # 解析到的坐标(GCJ02坐标系)
|
||||
'lng': 119.917068, # 经度
|
||||
'lat': 32.471578, # 纬度
|
||||
"status": 0,
|
||||
"message": "Success",
|
||||
"request_id": "9b049a3ff13c4ac3bda3bb5a9fe0c0a8",
|
||||
"result": {
|
||||
"title": "泰州海陵万达广场",
|
||||
"location": { # 解析到的坐标(GCJ02坐标系)
|
||||
"lng": 119.917068, # 经度
|
||||
"lat": 32.471578, # 纬度
|
||||
},
|
||||
'ad_info': { # 行政区划信息 object 是
|
||||
'adcode': '321202', # string 是 行政区划代码,规则详见:行政区划代码说明
|
||||
"ad_info": { # 行政区划信息 object 是
|
||||
"adcode": "321202", # string 是 行政区划代码,规则详见:行政区划代码说明
|
||||
},
|
||||
'address_components': {
|
||||
'province': '江苏省',
|
||||
'city': '泰州市',
|
||||
'district': '海陵区',
|
||||
'street': '济川东路',
|
||||
'street_number': '',
|
||||
"address_components": {
|
||||
"province": "江苏省",
|
||||
"city": "泰州市",
|
||||
"district": "海陵区",
|
||||
"street": "济川东路",
|
||||
"street_number": "",
|
||||
},
|
||||
'similarity': 0.99,
|
||||
'deviation': 1000,
|
||||
'reliability': 7, # 可信度参考:值范围 1 <低可信> - 10 <高可信>
|
||||
'level': 11, # 解析精度级别,分为11个级别,一般>=9即可采用(定位到点,精度较高) 也可根据实际业务需求自行调整,完整取值表见下文。
|
||||
"similarity": 0.99,
|
||||
"deviation": 1000,
|
||||
"reliability": 7, # 可信度参考:值范围 1 <低可信> - 10 <高可信>
|
||||
"level": 11, # 解析精度级别,分为11个级别,一般>=9即可采用(定位到点,精度较高) 也可根据实际业务需求自行调整,完整取值表见下文。
|
||||
},
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ class wei地图工具:
|
||||
def 经纬度转换为地址(cls, location):
|
||||
""""""
|
||||
pass
|
||||
url = f'https://apis.map.qq.com/ws/geocoder/v1/?location={location}'
|
||||
url = f"https://apis.map.qq.com/ws/geocoder/v1/?location={location}"
|
||||
res = requests.get(url=url, params={"key": cls.key}, )
|
||||
return res.json()
|
||||
|
||||
@@ -159,22 +159,22 @@ class wei地图工具:
|
||||
print(data)
|
||||
resData = pydash.omit(data, "request_id")
|
||||
d = {
|
||||
'status': 0,
|
||||
'message': 'Success',
|
||||
'request_id': '8805bff3303f42dd8a1cbcca3701cf63',
|
||||
'result': {
|
||||
'ip': '240e:3a3:b201:3f10:185c:efdb:c5b0:b95c',
|
||||
'location': {
|
||||
'lat': 32.49098,
|
||||
'lng': 119.91956,
|
||||
"status": 0,
|
||||
"message": "Success",
|
||||
"request_id": "8805bff3303f42dd8a1cbcca3701cf63",
|
||||
"result": {
|
||||
"ip": "240e:3a3:b201:3f10:185c:efdb:c5b0:b95c",
|
||||
"location": {
|
||||
"lat": 32.49098,
|
||||
"lng": 119.91956,
|
||||
},
|
||||
'ad_info': {
|
||||
'nation': '中国',
|
||||
'province': '江苏省',
|
||||
'city': '泰州市',
|
||||
'district': '海陵区',
|
||||
'adcode': 321202,
|
||||
'nation_code': 156,
|
||||
"ad_info": {
|
||||
"nation": "中国",
|
||||
"province": "江苏省",
|
||||
"city": "泰州市",
|
||||
"district": "海陵区",
|
||||
"adcode": 321202,
|
||||
"nation_code": 156,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -190,6 +190,6 @@ class wei地图工具:
|
||||
return resData
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
# wei地图工具.腾讯地图计算二点之间的距离(toData终点={"纬度": "30.80377", "经度": "104.151812"}, fromData起点={"纬度": "30.80377", "经度": "104.151812"})
|
||||
print(wei地图工具.ip地址转为地址(x_forwarded_for="119.84.150.100", ))
|
||||
|
||||
@@ -93,6 +93,7 @@ class sixwecom(ViewSet):
|
||||
wecom_token = sixToken.get_wecom_token()
|
||||
uri = f"https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token={wecom_token}&external_userid={ExternalUserID}"
|
||||
data = requests.get(url=uri).json()
|
||||
print("调用了单独添加新用的数据方法调用了单独添加新用的数据方法调用了单独添加新用的数据方法调用了单独添加新用的数据方法", data)
|
||||
# 创建数据库数据表
|
||||
unionid = pydash.get(obj=data, path="external_contact.unionid") # 外部联系人在微信开放平台的唯一身份标识(微信unionid)
|
||||
name = pydash.get(obj=data, path="external_contact.name") # 外部联系人的名称[注1]如果是微信用户,则返回其微信昵称。如果是企业微信联系人,则返回其设置对外展示的别名或实名
|
||||
@@ -100,6 +101,7 @@ class sixwecom(ViewSet):
|
||||
avatar = pydash.get(obj=data, path="external_contact.avatar") # 外部联系人头像。第三方应用和代开发应用均不可获取,
|
||||
gender = pydash.get(obj=data, path="external_contact.gender") # 外部联系人性别 0-未知 1-男性 2-女性。
|
||||
follow_user = pydash.get(obj=data, path="follow_user")
|
||||
print("再打印 下结果", follow_user)
|
||||
for wecom in follow_user:
|
||||
userid = pydash.get(obj=wecom, path="userid") # 添加了此外部联系人的企业成员userid (企微员工的userid)
|
||||
userid = pydash.get(obj=wecom, path="userid") # 添加了此外部联系人的企业成员userid (企微员工的userid)
|
||||
@@ -156,28 +158,6 @@ class sixwecom(ViewSet):
|
||||
# 数据更新完成后: 需要调用添加积分的方法, 对新添加企微的用户,添加积分;
|
||||
(miniUser积分(share分享者unionidID=six上级对象.unionid, click点击者unionidID=self自生对象.unionid, bind绑定的企微unionidID=State)
|
||||
.add添加点击者添加企微员工双向红包积分(share积分类型="新人红包", share分享者二维码state=State))
|
||||
# if is是否首次创建:
|
||||
# # 在这里的场景值:当用户直接扫码添加企微二维码的时候就需要在这里进行处理了
|
||||
# # 怎么判断的逻辑为: 当用户是首次添加的时候,则说明,这个用户以前在数据库中是不存在的;并且可以确定为这个用户一定是新添加的
|
||||
# print("\n🍎 🍏 🍊 🍎首次创建首次创建首次创建首次创建 🍏 🍊 🍎 🍏 \n", 上级对象.unionid)
|
||||
# self自生对象.user_头像 = src
|
||||
# self自生对象.user_昵称 = name
|
||||
# self自生对象.codeQrCode = 上级对象.codeQrCode
|
||||
# self自生对象.codeRemark = 上级对象.codeRemark
|
||||
# self自生对象.codeConfigId = 上级对象.codeConfigId
|
||||
# self自生对象.external_userid = external_userid
|
||||
# self自生对象.user_用户当前的等级 = 上级对象.level + 1
|
||||
# self自生对象.parent = 上级对象
|
||||
# self自生对象.user_绑定企微UNIONID = 上级对象.user_绑定企微UNIONID
|
||||
# self自生对象.user_绑定企微usrID账号 = 上级对象.user_绑定企微usrID账号
|
||||
# self自生对象.save()
|
||||
#
|
||||
# else:
|
||||
# self自生对象.user_头像 = src
|
||||
# self自生对象.user_昵称 = name
|
||||
# self自生对象.external_userid = external_userid
|
||||
# self自生对象.save()
|
||||
|
||||
return None
|
||||
|
||||
def 企微主动删除好友事件(self, UserID, ChangeType, State, ExternalUserID):
|
||||
@@ -197,7 +177,6 @@ class sixwecom(ViewSet):
|
||||
)
|
||||
print("到底哪里报错了呀为什么啊")
|
||||
企微用户关系对象, 企微用户是否为首次 = wecom企微用户.objects.get_or_create(wecom企微ID=UserID, wecom好友的ID=ExternalUserID)
|
||||
print(企微用户关系对象, 企微用户是否为首次, "==========到底哪里报错了呀为什么啊到底哪里报错了呀为什么啊==================")
|
||||
if 企微用户是否为首次:
|
||||
pass
|
||||
else:
|
||||
|
||||
@@ -179,7 +179,7 @@ class sixmini(ViewSet):
|
||||
def 更新物流信息(self, data):
|
||||
WayBillId = jmespath.search(data=data, expression="WayBillId")
|
||||
OrderId = jmespath.search(data=data, expression="OrderId")
|
||||
ems邮政物流工具().更新物流快递数据(order物流公司订单编号=WayBillId, order物流订单号=OrderId)
|
||||
ems邮政物流工具().更新物流快递数据(order物流公司订单编号=WayBillId, )
|
||||
|
||||
def 确认收货(self, data):
|
||||
print("确认订单请求接口进来了", data)
|
||||
|
||||
@@ -6,27 +6,3 @@ 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 order订单
|
||||
from wechat_项目工具包.数据库的工具包.更新用户积分 import miniUser用户角色
|
||||
from wechat_数据库.用户数据库.小程序登陆用户 import weiuser
|
||||
|
||||
|
||||
def 首单自动注册成为推广员(out_trade_no):
|
||||
pass
|
||||
order对象 = order订单.objects.get(order支付商家侧订单号=out_trade_no)
|
||||
|
||||
user用户对象 = weiuser.objects.get(unionid=order对象.order支付者unionid)
|
||||
six绑定的企微员工对象, sixBool = weiuser.objects.get_or_create(unionid=user用户对象.user_绑定企微UNIONID)
|
||||
print(six绑定的企微员工对象.user_区县,user用户对象.user_区县,user用户对象.user_角色权限)
|
||||
# 判断用户成为推广员的标准 成为的条件,当前用户绑定的企微员工账号, 必须是同一个区县的
|
||||
print(order对象.order订单类型)
|
||||
if user用户对象.user_角色权限 == miniUser用户角色().普通会员 and six绑定的企微员工对象.user_区县 == user用户对象.user_区县:
|
||||
# 当前的用户为普通会员 ,这里被调用了说明肯定是下单成功了 , 需要升级为推广员
|
||||
print("支付测试成功了,并且能成为推广员")
|
||||
# user用户对象.user_角色权限 = miniUser用户角色().推广员
|
||||
# user用户对象.save()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
首单自动注册成为推广员(out_trade_no="OAT01KYNGN3T0AKTK1C7WCV5Z047C")
|
||||
|
||||
@@ -124,6 +124,4 @@ if __name__ == "__main__":
|
||||
print(fileImg)
|
||||
print(fileImg.name)
|
||||
# default_storage.save(name=fileImg.name, content=fileImg.open(mode="rb"))
|
||||
srcc = oss上传腾讯云图片.上传图片(key=f"/烟花项目/{fileImg.name}", file=fileImg.open(mode="rb"))
|
||||
print(srcc)
|
||||
# oss上传腾讯云图片.删除图片()
|
||||
|
||||
Reference in New Issue
Block a user