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 sixGuoDjango import ResData, BaseResponse from wechat_数据库.支付订单数据库.商品订单数据 import order订单 from wechat_数据库.雪花算法.雪花算法工具 import generator from wechat_项目工具包.微信支付工具包.微信支付类 import paymentCategory, wechatPay class 微信支付ViewSets( ViewSet ): @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": out_trade_no, # 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。 "appid": paymentCategory.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( ) return Response( data=httpResData, status=status.HTTP_200_OK ) @action( detail=False, methods=[ "post" ], url_path="navite" ) def 二维码支付( self, request: WSGIRequest | Request ) -> Response: """ 生成收款的二维码链接,可以让用户来扫码支付 :param request: :return: """ out_trade_no = f"{generator.generate_id( )}" native_body = { "mchid": paymentCategory.mchid, # 服务商户号 "out_trade_no": out_trade_no, # 商户系统内部订单号 "appid": paymentCategory.appid, # 服务商应用ID "description": "测试", # 商品的描述信息 "notify_url": "https://server.xiao.band/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 ) import segno qr = segno.make_qr( content="------", ) 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 ): """ 扫用户付款码的测试接口 :param request: """ nonce_str = secrets.token_hex( 10 ) # 随机字符串 order_random = f"{generator.generate_id( )}" auth_code = request.data.get( "auth_code", False ) # 前端扫码读取的付款码的数据信息 # auth_code = "123497182327333282" # TODO 扫码支付付款码,设备读取用户微信中的条码或者二维码信息(这个值需要小程序端,扫码,将数据传递进来) # fu_kuan_data 是微信官方要求组装的数据类型 fu_kuan_data = { "appid": paymentCategory.appid, # 小程序的appid "mch_id": paymentCategory.mchid, # 微信支付分配的商户号 "nonce_str": nonce_str, # 随机字符串 "out_trade_no": order_random, # 商户订单号 "body": "test", "auth_code": auth_code, "total_fee": 1, # 订单总金额,单位为分,只能为整数,详见支付金额(必填) } wechat_data = wechatPay( payment=paymentCategory ).getpay_code扫用户付款码( body_data=fu_kuan_data ) print( wechat_data ) # return_code 通信返回码:'SUCCESS' 表示与微信服务器通信成功,'FAIL' 表示通信失败(如网络或参数错误) return_code = jmespath.search( data=wechat_data, expression="xml.return_code" ) # return_msg 通信返回信息:当 return_code 为 'FAIL' 时,此字段包含错误描述;成功时通常为 'OK' return_msg = jmespath.search( data=wechat_data, expression="xml.return_msg" ) # result_code 业务结果码:'SUCCESS' 表示支付成功,'FAIL' 表示支付失败(需结合 err_code 分析,但此处未提取) result_code = jmespath.search( data=wechat_data, expression="xml.result_code" ) # mch_id 商户号(MCH ID):微信支付分配给商户的唯一标识 mch_id = jmespath.search( data=wechat_data, expression="xml.mch_id" ) # appid 公众号或小程序的 AppID:发起支付的应用身份标识 appid = jmespath.search( data=wechat_data, expression="xml.appid" ) # nonce_str 随机字符串:用于防止重放攻击,由商户生成并随请求发送,微信原样返回 nonce_str = jmespath.search( data=wechat_data, expression="xml.nonce_str" ) # openid 用户在当前 AppID 下的唯一标识(OpenID):可用于关联用户账户 openid = jmespath.search( data=wechat_data, expression="xml.openid" ) # total_fee 订单总金额(单位:分):例如 '1' 表示 0.01 元 total_fee = jmespath.search( data=wechat_data, expression="xml.total_fee" ) # cash_fee_type 现金支付币种:目前微信支付仅支持 'CNY'(人民币) cash_fee_type = jmespath.search( data=wechat_data, expression="xml.cash_fee_type" ) # transaction_id 微信支付系统生成的唯一交易单号:用于对账、退款、查询等操作 transaction_id = jmespath.search( data=wechat_data, expression="xml.transaction_id" ) # 商户系统内部订单号:由商户在调用支付接口时传入,用于关联自身业务订单 out_trade_no = jmespath.search( data=wechat_data, expression="xml.out_trade_no" ) # 附加数据:商户在支付请求中可自定义传入,微信原样返回(常用于传递门店ID、商品类型等) attach = jmespath.search( data=wechat_data, expression="xml.attach" ) # time_end 支付完成时间:格式为 yyyyMMddHHmmss,例如 '20260304233708' 表示 2026年03月04日 23:37:08 time_end = jmespath.search( data=wechat_data, expression="xml.time_end" ) 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, ) 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 ): """注释""" 二维码支付回调数据 = wechatPay( payment=paymentCategory ).callBack回调解密( headers=request.headers, response_body=request.body, ) print( "二维码支付回调数据=>::", 二维码支付回调数据 ) return Response( data={ "msg": "success" } ) 微信支付ViewSetsRouter = DefaultRouter( ) 微信支付ViewSetsRouter.register( prefix="", viewset=微信支付ViewSets, basename="" )