python微信智能AI机器人实现多种支付方式


Posted in Python onApril 12, 2022

多支付

原理

1.利用鸭子类型。规定前台传过来支付方式。pay_methon
2.再支付方式里面实现pay(名字统一)方法
3.回调函数,在支付方式里面写notify(名字统一)统一方法,返回的data统一格式。
		eg: data={"statu":'success',"order_id":notity_data['order_id'],"print":"0000"}

        
   这样的的牛逼之处:我们在修改、添加支付方式的时候,只需要按照鸭子类型,命名一样的函数名,写好自己的支付方式即可。不需要改其他的代码

多支付接口代码

urls.py:

path("order/create",order.Creat.as_view()),

path("order/notify/<paymethod>",order.Notify.as_view())
# 这里所有的支付都是走的小程序微信支付:

import importlib

class Creat(APIView):
    ...伪代码
    
    pay_methon = "Wxpay"  # 如果是PC端,可以前台传过来支付方式
    try:
        #pay_file是对象
        pay_file = importlib.import_module(f"app01.Pay.{pay_methon}")  # 调用对应的支付方式
        pay_class = getattr(pay_file, pay_methon)  # 反射机制
        order_data['open_id'] = openid # 传的参数
        order_data['ip'] = host_ip  # 传的参数
        data = pay_class().pay(order_data)  # 调用支付
    except:
        return  Response({"code":201,"msg":"未知支付方式"})



# 异步回调的
class Notify(APIView):
    def post(self,request,paymethod):
        pay_file = importlib.import_module(f"app01.Pay.{paymethod}")
        pay_class = getattr(pay_file,paymethod)
        data = pay_class().notify(request.data)  # 调用异步回调

        # 判断data数据中属性,然后修改订单
        if data["statu"] == "success":
            models.Order.objects.filter(order_id =data['order_id']).update(pay_status =1)
            return Response(data["print"])

支付方式代码

python微信智能AI机器人实现多种支付方式

Alipay支付

# Alipay支付
class Alipay:
    def pay(self,order_data):
        #统一下单方法
        pass


    def notify(self,notity_data):
        if notity_data['success'] :
            #notity_data['order_id']表示商城订单号
            data={"statu":'success',"order_id":notity_data['order_id'],"print":"0000"}
            return   data

YLpay支付方式

# YLpay支付方式

class YLpay:
    def pay(self,order_data):
        pass


    def notify(self,request_data):
        #验签
        #数据处理
        pass

Wxpay支付方式

import time
from app01.wx import settings


class Wxpay:
    def pay(self,order_data):
        self.order_id = order_data["order_id"]
        self.open_id = order_data['open_id']
        self.ip = order_data['ip']
        data_body = self.get_body_data()
        import requests
        url = "https://api.mch.weixin.qq.com/pay/unifiedorder"
        response = requests.post(url, data_body.encode("utf-8"), headers={'content-type': "application/xml"})
        res_dict = self.xml_to_dic(response.content)
        timeStamp = str(int(time.time()))
        paySign = self.get_pay_sign(res_dict, timeStamp)

        data_dic = {
            'timeStamp': timeStamp,
            'nonceStr': res_dict['nonce_str'],
            'package': f"prepay_id={res_dict['prepay_id']}",
            'signType': 'MD5',
            "paySign": paySign,
        }

        return data_dic

    def get_pay_sign(self, res_dict, timeStamp):
        data_dic = {
            'appId': res_dict['appid'],
            'timeStamp': timeStamp,
            'nonceStr': res_dict['nonce_str'],
            'package': f"prepay_id={res_dict['prepay_id']}",
            "signType": "MD5"
        }
        sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
        sign_str = f"{sign_str}&key={settings.pay_apikey}"
        import hashlib
        md5 = hashlib.md5()
        md5.update(sign_str.encode("utf-8"))
        sign = md5.hexdigest()
        return sign.upper()

    def xml_to_dic(self, xml_data):
        import xml.etree.ElementTree as ET
        '''
        xml to dict
        :param xml_data:
        :return:
        '''
        xml_dict = {}
        root = ET.fromstring(xml_data)
        for child in root:
            xml_dict[child.tag] = child.text
        return xml_dict

    def get_random(self):
        import random
        data = "123456789zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP"
        nonce_str = "".join(random.sample(data, 30))
        return nonce_str



    def get_sign(self):
        data_dic = {
            "nonce_str": self.nonce_str,
            "out_trade_no": self.out_trade_no,
            "spbill_create_ip": self.spbill_create_ip,
            "notify_url": self.notify_url,
            "openid": self.open_id,
            "body": self.body,
            "trade_type": "JSAPI",
            "appid": self.appid,
            "total_fee": "1",
            "mch_id": self.mch_id
        }

        sign_str = "&".join([f"{k}={data_dic[k]}" for k in sorted(data_dic)])
        sign_str = f"{sign_str}&key={settings.pay_apikey}"
        import hashlib
        md5 = hashlib.md5()
        md5.update(sign_str.encode("utf-8"))
        sign = md5.hexdigest()
        return sign.upper()

    def get_body_data(self):
        self.appid = settings.AppId
        # openid=self.open_id
        self.mch_id = str(settings.pay_mchid)
        self.nonce_str = self.get_random()
        self.out_trade_no = self.order_id
        self.spbill_create_ip = self.ip
        self.notify_url = "https://www.test.com"
        self.body = "老男孩学费"
        self.sign = self.get_sign()
        body_data = f"""
           <xml>
               <appid>{self.appid}</appid>
               <mch_id>{self.mch_id}</mch_id>
               <nonce_str>{self.nonce_str}</nonce_str>
               <sign>{self.sign}</sign>
               <body>{self.body}</body>
               <out_trade_no>{self.out_trade_no}</out_trade_no>
               <total_fee>1</total_fee>
               <spbill_create_ip>{ self.spbill_create_ip}</spbill_create_ip>
               <notify_url>{self.notify_url}</notify_url>
               <openid>{self.open_id}</openid>
               <trade_type>JSAPI</trade_type> 
           </xml>"""
        return body_data

Creat下订单

from  rest_framework.views import  APIView
from rest_framework.response import  Response
from app01.wx import wx_login
import hashlib ,time
from app01 import models
from django.core.cache import cache
from django.db import transaction
from app01.func import function_tool
import importlib

class Creat(APIView):
    @transaction.atomic
    def post(self,request):
        #小程序提交给我们的数据
        '''
        {'token': '0bb2aa1102ca9c8306133b2539c3508b',
        'remark': '',
        'province': '广东省',
        'city': '广州市',
        'county': '海珠区',
        'address':
        '新港中路397号',
        'phone': '020-81167888',
        'name': '张三',
        'buy_list': {'2': 1}}
        '''
        param = request.data
        if param.get("token") and param.get("buy_list"):
            user_cache = cache.get(param["token"])
            if user_cache:
                # 获取ip
                if request.META.get("HTTP_X_FORWARDED_FOR"):
                    host_ip = request.META["HTTP_X_FROWARDED_FOR"]
                else:
                    host_ip = request.META["REMOTE_ADDR"]
                openid = user_cache.split("&")[0]  #data['openid']+"&"+data["session_key"]
                user_data = models.Wxuser.objects.filter(openid=openid).first()
                order_data = {
                    "consignee_mobile": param['phone'],
                    'consignee_name': param['name'],
                    'wxuser_id': user_data.id,
                    "memo": param['remark'],
                    "consignee_area": f"{param['province']},{param['city']},{param['county']}",
                    "consignee_address": param['address'],
                    "order_id": function_tool.get_order_id(),
                    "order_total": 0
                }
                # 1 上面的order_data 出来上面的数据,有些是需要通过购买上面列表做累加才能获得到
                # 2 order_item 是通过buy_list里面的商品列表,一个键值对就是一条记入'buy_list': {'2': 1,“1”:2}
                # 3 再每一次增加一个order_item的时候,我们都需要校验库存。如果有一个商品的库存不足,我们就应该不然用户下单
                # 4 由于第三步中进行多次增加,如果再后面的的商品库存有问题,我们不让他下单,但是前面的数据已经插入。
                # 所有我们要用数据库的事务管理数据的统一。就算order_item没有问题,order_data,插入的时候,也可能出错,所以也要用事务
                # 5 由于并发问题,所有的用户都会对数据的库存进行加减,所以我们这里再校验库存的时候要用锁。
                buy_list = param.get("buy_list")
                # 获取到buy_list是没有商品信息只有有id,我们先把buy_list中的所有商品查出来
                goods_key = list(buy_list.keys())
                all_product = models.Product.objects.filter(product_id__in = goods_key)
                #用for循环添加order_item

                sid = transaction.savepoint()
                for product in all_product:
                    # 将product.product_id 转字符串,为了通过product.product_id在buy_list获取商品的购买数量
                    product.product_id = str(product.product_id)
                    # 获取订单总金额
                    order_data['order_total'] += product.price* buy_list[product.product_id]

                    for i in range(3):
                        #先查库存,重新查库的
                        stock = product.stock.quantity

                        #当前的库存的库存数量,减去购买数量,是否大于0
                        new_stock = stock-buy_list[product.product_id]
                        if new_stock < 0 :
                            #库存不足,回滚
                            transaction.savepoint_rollback(sid)
                            return Response({"code":201,"msg": f"{product.name}库存不足"})
                        #乐观锁
                        res = models.Stock.objects.filter(quantity= stock,stock_id =product.stock.stock_id).update(quantity = new_stock)
                        if not res:
                            if i == 2:
                                transaction.savepoint_rollback(sid)
                                return  Response({"code":201,"msg": "创建订单失败"})
                            else:
                                continue
                        else:
                            break
                    #获取购买数量
                    new_buy_cout = product.buy_count + buy_list[product.product_id]
                    models.Product.objects.filter(product_id=product.product_id).update(buy_count =new_buy_cout)
                    #组织order_item的数据
                    order_item_data = {
                         'order_id': order_data['order_id'],
                         'product_id': product.product_id,
                         "name": product.name,
                         "image": product.image,
                         "price": product.price,
                          "nums": buy_list[product.product_id],
                          "brief": product.brief
                     }
                    models.Order_items.objects.create(**order_item_data)

                models.Order.objects.create(**order_data)
                transaction.savepoint_commit(sid)

                #所有的支付都是走的小程序微信支付:
                pay_methon = "Wxpay"
                try:
                    #pay_file是对象
                    pay_file = importlib.import_module(f"app01.Pay.{pay_methon}")
                    pay_class = getattr(pay_file, pay_methon)
                    order_data['open_id'] = openid
                    order_data['ip'] = host_ip
                    data = pay_class().pay(order_data)
                except:
                    return  Response({"code":201,"msg":"未知支付方式"})

                # 1对接小程序支付
                # 2 我们要用celery去定时检查,该订单在指定时间内用没有支付,没有支付,取消订单,回滚库存
                function_tool.pay_status(order_data['order_id'])
                return  Response({"code":200,"msg":"ok","data":data})

            else:
                return Response({"code": 201, "msg": "无效的token"})

        else:
            return Response({"code":202,"msg":"缺少参数"})


class Notify(APIView):
    def post(self,request,paymethod):
        pay_file = importlib.import_module(f"app01.Pay.{paymethod}")
        pay_class = getattr(pay_file,paymethod)
        data = pay_class().notify(request.data)

        # 判断data数据中属性,然后修改订单
        if data["statu"] == "success":
            models.Order.objects.filter(order_id =data['order_id']).update(pay_status =1)
            return Response(data["print"])

以上就是python实现微信小程序的多种支付方式的详细内容!

Python 相关文章推荐
python正则表达式re模块详解
Jun 25 Python
九步学会Python装饰器
May 09 Python
在Python的Django框架中包装视图函数
Jul 20 Python
Python3实现的简单工资管理系统示例
Mar 12 Python
Python爬取数据保存为Json格式的代码示例
Apr 09 Python
如何利用Python开发一个简单的猜数字游戏
Sep 22 Python
Pytest mark使用实例及原理解析
Feb 22 Python
python GUI库图形界面开发之PyQt5窗口控件QWidget详细使用方法
Feb 26 Python
python退出循环的方法
Jun 18 Python
Python下载网易云歌单歌曲的示例代码
Aug 12 Python
python time()的实例用法
Nov 03 Python
pycharm安装深度学习pytorch的d2l包失败问题解决
Mar 25 Python
Python中request的基本使用解决乱码问题
Apr 12 #Python
python模拟浏览器 使用selenium进入好友QQ空间并留言
Python安装使用Scrapy框架
Python使用华为API为图像设置多个锚点标签
python实现手机推送 代码也就10行左右
Apr 12 #Python
Python内置包对JSON文件数据进行编码和解码
详细介绍python操作RabbitMq
You might like
用Apache反向代理设置对外的WWW和文件服务器
2006/10/09 PHP
用DBSQL类加快开发MySQL数据库程序的速度
2006/10/09 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
2020/02/29 PHP
Javascript中的数学函数集合
2007/05/08 Javascript
解析js中获得父窗口链接getParent方法以及各种打开窗口的方法
2013/06/19 Javascript
node.js中的fs.fchownSync方法使用说明
2014/12/16 Javascript
基于JavaScript实现一定时间后去执行一个函数
2015/12/14 Javascript
json的使用小结
2016/06/08 Javascript
jQuery animate easing使用方法图文详解
2016/06/17 Javascript
AngularJS中isolate scope的用法分析
2016/11/22 Javascript
JavaScript中Array对象用法实例总结
2016/11/29 Javascript
nodejs模块nodemailer基本使用-邮件发送示例(支持附件)
2017/03/28 NodeJs
Vuejs 单文件组件实例详解
2018/02/09 Javascript
vue 中动态绑定class 和 style的方法代码详解
2018/06/01 Javascript
JS获取浏览器地址栏的多个参数值的任意值实例代码
2018/07/24 Javascript
详解小程序缓存插件(mrc)
2018/08/17 Javascript
angular6根据environments配置文件更改开发所需要的环境的方法
2019/03/06 Javascript
JavaScript面向对象核心知识与概念归纳整理
2020/05/09 Javascript
如何利用 JS 脚本实现网页全自动秒杀抢购功能
2020/10/12 Javascript
Python THREADING模块中的JOIN()方法深入理解
2015/02/18 Python
python实现井字棋游戏
2020/03/30 Python
Python生成数字图片代码分享
2017/10/31 Python
Python使用Matplotlib实现Logos设计代码
2017/12/25 Python
matplotlib作图添加表格实例代码
2018/01/23 Python
python 读取文本文件的行数据,文件.splitlines()的方法
2018/07/12 Python
Python 实现3种回归模型(Linear Regression,Lasso,Ridge)的示例
2020/10/15 Python
python实现简单的井字棋游戏(gui界面)
2021/01/22 Python
在css3中background-clip属性与background-origin属性的用法介绍
2012/11/13 HTML / CSS
茵宝(Umbro)英国官方商店:英国足球服装生产商
2016/12/29 全球购物
Yves Rocher伊夫·黎雪美国官网:法国始创植物美肌1959
2019/01/09 全球购物
Onzie官网:美国时尚瑜伽品牌
2019/08/21 全球购物
库存图片、照片、矢量图、视频和音乐:Shutterstock
2021/02/12 全球购物
担保书范文
2015/01/20 职场文书
医疗纠纷调解协议书
2015/08/06 职场文书
Java详细解析==和equals的区别
2022/04/07 Java/Android
速龙x4-860k处理器相当于i几
2022/04/20 数码科技