zoukankan      html  css  js  c++  java
  • django实现支付宝支付

    django支付宝支付

    新建支付宝应用

    # 访问"支付宝开发平台"登录,可以访问开发者中心
    https://open.alipay.com/platform/home.htm
    # 可以参考"电脑网站支付" 熟悉电脑支付整体流程
    https://docs.open.alipay.com/270/105899/
    

    创建应用(使用沙箱环境测试)

    按照官方要求生成私钥(可以上支付宝开发平台下载支付宝开发助手)

    把生成的app公钥粘贴到沙箱的app中

    沙箱环境地址: https://openhome.alipay.com/platform/appDaily.htm?tab=info

    查看沙箱账号和密码

    支付宝开发地址

    支付宝开放平台: https://open.alipay.com/platform/home.htm
    支付宝沙箱环境: https://openhome.alipay.com/platform/appDaily.htm?tab=info
    支付宝开发者文档:https://openhome.alipay.com/developmentDocument.htm
    电脑网站支付流程:https://docs.open.alipay.com/270
    生成签名:https://docs.open.alipay.com/291/106103/
    python-alipay-adk : https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
    

    说明

    • 阿里官方没有提供python对接支付的sdk,但是python库中有非官方的sdk包可以使用
    • python-alipay-adk : https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
    • 使用起来非常简单,只要传入几个必要的参数就可以完成
    • 由于支付对安全要求很高,所以要理解对接支付宝安全的流程: 公钥加密、私钥解密 这八个字

    在utils中封装请求支付宝扫码地址url的函数和生成订单id的函数

    私钥和公钥可以放在app_private_key.pem 和 alipay_public_key.pem文件中。使用时引入

    沙箱环境中 app 私钥
    private_key_string= open('app_private_key.pem').read()
    支付宝公钥
    public_key_string = open( 'alipay_public_key.pem').read()

    # -*- coding: utf-8 -*-
    import datetime
    import os
    import random
    from alipay import AliPay
    
    private_key_string = '''-----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEApNZyqxPGS3xs/p6lpgffgnbvELjReMRz3y2WGhynDeY/vwODsafKy7XDvYPvE6iGXegz4vxtJINOBJprPXqamQvPJq20z/R3CZlCsOEy75Pr77ZRGZbMvzVXGkuavnLQoH40FuRbQYMXt8rLR1GnBS+5Bs5tWNfy94f4x4VroEZ80zVDnQEkzy46fmoi6lZ5r6N/7iXFo0fXdFWlvZJ0EDBF0BdSnHz7nSi6gbAix+VRU2mhyxh/C3ziF8GSuffzfolPORAKj/ws/UCLyBEio6OR0LJPPiulEEYR1cOsm784GHqCh+7C8MWoRmF1UWZ7nwVR+87Ezaq+ksxLxlKwYwIDAQABAoIBACc0RdOAgYIEltu8GcP2Lx1MnO+CNXfWqYRkEDYnqGe64mBo0pKXSLlIgsR5M4xmYYbGKkkLJl4vyId5vpXBqjFKSLt3RvDKwOEMjXsKJJYshUne/8zpO8siQZQkdSpknk/9lB/5seaT6jkxR0WwGtw17Hi88e7WdZf/w+CYT++vUNDR3thzhGSzgXvfrWppP4XMDnW75HJY+MgRo591vsbLwuQgEMTRqaroU1i5+ivDRak6KhKsiJ3QKJYUO1a+0AUTZMuoOo1Vhyn1qYiaRASYov73vK0WZDLd5/K8anBxWXKVwxj5IBivXcotrlaEQzvvcdu/HxH6+WT4VKQHq5kCgYEA9VFat/q6hGGoSgP3byl2ZbqohoEB2dGFGwgoXKGt8wO2tLhJCAGeyU4uLRAGTk6eO9qnAVr7ZsGmEQ1yaMOwRmatJLZze9yjQufkKOkInrXvVUebXdvRmeUtJ4l0NqtrmkrNcJw49HNR0pjSOhN6R9BGUd75l/P/hU3yjoFF7n0CgYEArAPz8UDYvq1ZKico2vjrWIrnsDpvDsgx8L+i73LzKrL9B3ZTimW+7wsIcWhQF1s27qMnQFPjKbEuqWOTi92TbV7BYXbAyQND0V+y0Txbfs54rGwB2A+0kVTP+sLA/x0mqnek3P2gAsl4p9A5A37rNGESgM64hLd5NOauH60S8F8CgYAixyzQRf2txNaB37wVY1BoraS0pNdpVN3E7kwijb1GZXFif3nDC8/CBDZhpxLtyRF/tMjWVVqsv6lWY4yjs5Jq+KV1PfRzS91NX+ilsBvLvEk40tUA4mf9pFLZdxAlq/muPwqO+2bLqQmheI7JMvez9J/zfWPvGeVQtbM8ZrFOVQKBgQCY+nr8V5trGGdv4ZuoAi/rcr1SMOWL0+b2ILgbE7PGiaAV/tmU/5+qn7lGgmqYGvrjiB3kS7Z+4aCJ7JDPlqMCZX692wrguhKaJe21v2Pvhlgzn2qUaINBrJe6f3F8cMRuXjE0iCrBz8OKGthZj4pF7v6xpybagQE+VtkMOrPZKQKBgDQh5Q4510y+ta+mFPb3tum4cXKBAUeRTS6+Us/0wvNVGpvnPGKzIcP+rGXlAO0Nl7O/PTBgejcIILjcS9AuyxPSfSWhlt5DjjzeQ8/J4yrgVAwQeNC28jkmnKBe5K3R+++Si++nYq4/nZ1WEyyginFf2nvQrW2G+rkzMOKvtRn/
    -----END RSA PRIVATE KEY-----'''
    
    
    publice_key_string = '''-----BEGIN PUBLIC KEY-----
    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApNZyqxPGS3xs/p6lpyVImg1XELjReMRz3y2WGhynDeY/vwODsafKy7XDvYPvE6iGasegz4vxtJINOBJprPXqamQvPJq20z/R3CZlCsOEy75Pr77ZRGZbMvzVXGkuavnLQoH40FuRbQYMXt8rLR1GnBS+5Bs5tWNfy94f4x4VroEZ80zVDnQEkzy46fmoi6lZ5r6N/7iXFo0fXdFWlvZJ0EDBF0BdSnHz7nSi6gbAix+VRU2mhyxh/C3ziF8GSuffzfolPORAKj/ws/UCLyBEio6OR0LJPPiulEEYR1cOsm784GHqCh+7C8MWoRmF1UWZ7nwVR+87Ezaq+ksxLxlKwYwIDAQAB
    -----END PUBLIC KEY-----'''
    
    # udbble1952@sandbox.com
    ## 获取支付宝url
    def get_alipay_url(order_id, order_amount, subject):
        alipay = AliPay(
              appid="888888888888", # 沙箱appid
              app_notify_url=None, # 默认回调url
              app_private_key_string=private_key_string,
              # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
              alipay_public_key_string=publice_key_string,
              sign_type="RSA2", # RSA 或者 RSA2
              debug=True, # 默认False,我们是沙箱,所以改成True(让访问沙箱环境支付宝地址)
        )
        # 调用支付接口
        # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
        order_string = alipay.api_alipay_trade_page_pay(
              out_trade_no=order_id, # 订单id,应该从前端获取生成链接地址如下
              total_amount=str(order_amount), # 订单总金额
              subject=subject, # 付款标题信息
              return_url='http://127.0.0.1:8888/payment/callback/', # 付款成功回调地址(可以为空)
              notify_url=None # 付款成功后异步通知地址(可以为空)
        )
        pay_url = "https://openapi.alipaydev.com/gateway.do?" + order_string
        return pay_url # 将这个url复制到浏览器,就会打开支付宝支付页面
    
    
    # 获取订单唯一id
    def get_order_id():
        """
        SYL202008241212121200005/24
        生成订单号: 格式: SYL + 年月日时分秒 + 5位随机数
        :return:
        """
        d = datetime.datetime.now()
        base = 'SYL'
        time_str = '%04d%02d%02d%02d%02d%02d' % (d.year, d.month, d.day, d.hour,
        d.minute, d.second)
        # 1.4 syl/setings.py中配置支付相关参数
        # 2.测试
        # 请求地址
        # 携带参数
        # 返回数据
        rand_num = str(random.randint(10000, 99999))
        return base + time_str + rand_num
    
    
    
    

    在model.py中定义表

    from django.db import models
    from utils.MyBaseModel import Base
    # Create your models here.
    
    
    # 商品表
    class Goods(Base):
        GOODS_TYPE = (
            ("1", "vip"),
            ("2", "Course")
        )
        CHANNEL_TYPE = (
            ("1", "普通"),
            ("2", "促销")
        )
        course = models.OneToOneField('course.Course', on_delete=models.PROTECT)
        goods_type = models.CharField("商品种类", choices=GOODS_TYPE, max_length=8)
        product_id = models.CharField("产品id", max_length=8)
        title = models.CharField("商品名称", max_length=24)
        price = models.DecimalField("商品价格", max_digits=8, decimal_places=2)
        channel_type = models.CharField("购买渠道", choices=CHANNEL_TYPE, max_length=8)
        period = models.IntegerField("有效期", default=365)
        is_launched = models.BooleanField("是否上架", default=True)
    
        class Meta:
            db_table = "tb_goods"
    
        def __str__(self):
            return self.title
    
    
    # 订单表
    class Orders(Base):
        PAY_METHOD = (
            ("1", "支付宝"),
        )
        ORDER_STATUS = (
            ("1", "待支付"),
            ("2", "已支付"),
            ("3", "已取消")
        )
        user = models.ForeignKey('user.User', on_delete=models.PROTECT, verbose_name="下单用户")
        goods = models.ForeignKey(Goods, on_delete=models.PROTECT)
        order_id = models.CharField("订单号", max_length=24)
        trade_no = models.CharField("支付订单号", max_length=32, null=True)
        pay_time = models.DateTimeField("支付时间", null=True)
        pay_method = models.CharField("支付方式", choices=PAY_METHOD, default=1, max_length=8)
        status = models.CharField("支付状态", choices=ORDER_STATUS, default=1, max_length=8)
        total_amout = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="商品总金额")
    
        class Meta:
            db_table = "tb_orders"
    
        def __str__(self):
            return self.order_id
    
    
    # 用户购买课程表
    class UserCourse(Base):
        user = models.ForeignKey('user.User', on_delete=models.CASCADE)
        course = models.ForeignKey('course.Course', on_delete=models.CASCADE)
    
        class Meta:
            db_table = "usercourse"
    
        def __str__(self):
            return "用户%s购买的%s" % (self.user, self.course)
    
    

    在views.py中获取支付宝支付的url的接口和回调接口

    from decimal import Decimal
    from django.shortcuts import render
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from .models import Goods, Orders, UserCourse
    from .serializers import GoodsModelSer, OrdersModelSer
    from .util import get_order_id, get_alipay_url
    from course.models import Course
    
    
    # 获取支付宝扫码页面的url
    class Get_Pay_url(APIView):
    
        def post(self,request):
            # 根据前端发送的商品id获取对应的商品信息
            goods_id = request.data.get("goods_id")
            goods_obj = Goods.objects.get(pk=goods_id)
            # 获取用户信息
            user = request.user
    
            # 判断用户的身份对应进行打折
            if user.vip.vip_type == "3":
                goods_price = (goods_obj.price * Decimal('0.60')).quantize(Decimal('0.00'))
            elif user.vip.vip_type == "2":
                goods_price = (goods_obj.price * Decimal('0.80')).quantize(Decimal('0.00'))
            else:
                goods_price = goods_obj.price
    
            # 存入数据库
            order = Orders(
                user= user,
                goods= goods_obj,
                order_id= get_order_id(),  # 调用在util.py中写的函数获取商品订单id
                pay_method= 1,
                status= 1,
                total_amout= goods_price,
            )
            order.save()
    
            subject = "实验楼订单:%s,价格:%s" % (order.order_id, goods_price)
            # 调用util中的获取支付宝路由的函数并把自己生成的订单id
            pay_url = get_alipay_url(order_id=order.order_id, order_amount=order.total_amout, subject=subject)
    
            return Response({"code":200, "msg": "成功", "data": {"pay_url": pay_url}})
    
    
    """
     # 前端回调返回的数据
     { "charset": "utf-8",
      "out_trade_no": "SYL2020101508522512986",     # 我们自己生成的订单id
       "method": "alipay.trade.page.pay.return",
        "total_amount": "100.00",                    # 支付价格
        "sign": "HFfe2xBFw/jY8XaJdzuUnqWg9+wPS/PdH7GGigNRScVhfxF94lm2id1eURP/TdvWs4F2HRukJ0Rf/UNzrz4QG18EKiT68ChGrZvIiZHaONY2ok/ix5r68IkQM/7yCB+YF4NrkHDuw92Iy7mLrdKNkOan3+uLgocNuWDTNWo4hT5gCFTxOPPrrWDSJmanX3RPI6HrLsOWUpTcZjhQafAKK0S6Y+bl+MtgfLPV7+hcMesItb/pvsHDRPD1j63VkGuP2mXwW3eDCns3LCn1YfWqjwmutXGqbLEK0HG9NgOKFBL9N6+lBE2lJqfdSo79vMY9cv7287ZvC1b07cygLXMVDA==",
        "trade_no": "2020101522001458970501542142",  # 支付宝的支付id
        "auth_app_id": "2016103000778269",           
        "version": "1.0", 
        "app_id": "2016103000778269", 
        "sign_type": "RSA2", 
        "seller_id": "2088102181451641", 
        "timestamp": "2020-10-15 16:52:56"           # 支付时间
        }
    """
    # 支付宝回调地址
    class PeyMent(APIView):
    
        def post(self, request):
            # 获取前端发送的数据
            order_id = request.data.get("out_trade_no")  # 自己生成的订单id
            trade_no = request.data.get("trade_no")      # 支付宝返回的支付宝订单id
            pay_time = request.data.get("timestamp")     # 创建时间
    
            # 根据订单id获取到对应的订单信息
            orders = Orders.objects.get(order_id=order_id)
            # 修改订单状态,支付时间,支付宝的订单id
            orders.trade_no = trade_no
            orders.pay_time = pay_time
            orders.status = 2
            orders.save()
    
            # 根据订单获取到对应的商品然后获取到对应的课程
            course_obj = Course.objects.get(pk=orders.goods.course_id)
            # 存到用户购买课程表中
            user = UserCourse(user=request.user, course=course_obj)
            user.save()
    
            return Response({"code":200, "msg": "支付成功"})
    
    

    前端vue

    生成订单, 获取支付链接

    // 生成订单, 获取支付链接
        pay() {
          // goods_id: 课程id
          payurl_post({ goods_id: this.goods.id }).then((resp) => {
            console.log(resp)
            let pay_url = resp.data.pay_url
            // debugger
            window.location = pay_url
          })
        },
    

    回调页面

    <template>
      <div>
        这里是支付回调地址, 把数据发送给后端
        参数是:
        {{query}}
        <p>
          支付结果是: {{msg}}
        </p>
      </div>
    </template>
    <script>
    
    import { payment_post } from './axios_api/api';
    export default {
      data() {
        return {
          query: '',
          msg: '', //支付结果
        }
      },
      mounted() {
        this.query = this.$route.query
        payment_post(this.query).then((resp) => {
          // ({"code": 999, "msg": "非法请求"})
          this.msg = resp.msg
        })
      },
    
    }
    </script>
    
  • 相关阅读:
    MySQL总结二
    MySQL总结一
    Flink 流处理API之Join
    Flink 流处理API之二
    Flink 流处理API之一
    Flink ProcessFunction API
    Flink Window
    Spark性能优化
    BPM软件_K2百家讲坛 | 越秀地产:K2为房企数字化转型带来更多可能_全球领先的工作流引擎
    BPM软件_K2签约龙光地产,为集团实现“千亿目标”保驾护航_全业务流程管理专家
  • 原文地址:https://www.cnblogs.com/hr20-04-19/p/13823407.html
Copyright © 2011-2022 走看看