支付宝sdk——python-alipay-sdk

文章目录

  • 一、支付宝支付介绍
  • 二、支付宝支付使用
  • 三、支付宝支付二次封装


一、支付宝支付介绍

线上支付有:

  1. 支付宝支付
  2. 微信支付
  3. 云闪付

支付流程:
1.用户把钱打到第三方平台(支付宝,微信)的商家账户中
2.商家提现提出来(第三方平台收手续费)

注意:必须是商户(企业),有营业执照才能申请支付宝,微信的支付接入


二、支付宝支付使用

第一步:找到支付宝沙箱
支付宝sdk——python-alipay-sdk_第1张图片
第二步:画框处后续需要用到
支付宝sdk——python-alipay-sdk_第2张图片
第三步:创建公钥私钥
安装支付宝开放平台开发助手:点击进入支付宝文档下载
支付宝sdk——python-alipay-sdk_第3张图片
生成公钥私钥
支付宝sdk——python-alipay-sdk_第4张图片
第四步:将生成的公钥配置到支付宝沙箱中

支付宝sdk——python-alipay-sdk_第5张图片
示例:
直接使用python-alipay-sdk调用支付宝
首先安装

pip install python-alipay-sdk
from alipay import AliPay

app_private_key_string = open("./pri").read() #在pri文件下加入私钥
alipay_public_key_string = open("./pub").read() #在pub文件下加入支付宝公钥
alipay = AliPay(
    appid="xxxxxxxxxxxx", # 此处填写支付宝公开平台的appid
    app_notify_url=None,  # 默认回调 url
    app_private_key_string=app_private_key_string,
    # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
    alipay_public_key_string=alipay_public_key_string,
    sign_type="RSA2",  # RSA 或者 RSA2
    debug=True,  # 默认 False
)
# 电脑网站支付,需要跳转到:https://openapi.alipay.com/gateway.do? + order_string
res=alipay.api_alipay_trade_page_pay(
    out_trade_no='asdsad623232332', # 订单号,自设
    total_amount=float(999),  # 只有生成支付宝链接时,不能用Decimal
    subject='充气球', # 订单内容,自设
    return_url='http://127.0.0.1:8000', # 回调地址
    notify_url='http://127.0.0.1:8000', 
)

gataway = 'https://openapi.alipaydev.com/gateway.do?' # 支付宝网关地址
print(gataway+res) # 此处是生成的支付链接

三、支付宝支付二次封装

创建一个包

ipay  #包名
    -pem  #存放公钥私钥
        alipay_public_key.pem
        app_private_key.pem
    __init__.py 
    pay.py   #生成一个对象
    settings.py #配置文件

公钥私钥必须按照格式来存放
pem文件下的app_private_key.pem存放私钥

-----BEGIN RSA PRIVATE KEY-----
此处为私钥内容
-----END RSA PRIVATE KEY-----

pem文件下的alipay_public_key.pem存放支付宝公钥

-----BEGIN PUBLIC KEY-----
此处为公钥内容
-----END PUBLIC KEY-----

init.py

from .pay import alipay
from .settings import GATEWAY

pay.py

from alipay import AliPay

from . import settings

alipay = AliPay(
    appid=settings.APP_ID,
    app_notify_url=None,  # 默认回调 url
    app_private_key_string=settings.APP_PRIVATE_KEY_STRING,
    # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
    alipay_public_key_string=settings.ALIPAY_PUBLIC_KEY_STRING,
    sign_type=settings.SIGN,  # RSA 或者 RSA2
    debug=settings.DEBUG,  # 默认 False
)

settings.py

import os

# 应用私钥
APP_PRIVATE_KEY_STRING = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pem', 'app_private_key.pem')).read()

# 支付宝公钥
ALIPAY_PUBLIC_KEY_STRING = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pem', 'alipay_public_key.pem')).read()

# 应用ID
APP_ID = 'xxxxxxxx'

# 加密方式
SIGN = 'RSA2'

# 是否是支付宝测试环境(沙箱环境),如果采用真是支付宝环境,配置False
DEBUG = True

# 支付网关
GATEWAY = 'https://openapi.alipaydev.com/gateway.do?' if DEBUG else 'https://openapi.alipay.com/gateway.do?'

调用二次封装支付的sdk:

dev.py(开发配置文件相当于setting.py)

# 上线后必须换成公网地址
# 后台基URL
HOST_URL = 'http://127.0.0.1:8000'
# 前台基URL
LUFFY_URL = 'http://127.0.0.1:8080'
# 支付宝同步异步回调接口配置
# 后台异步回调接口--->post回调,调后台
NOTIFY_URL = HOST_URL + "/api/v1/order/success/"  #后台的用来修改订单状态
# 前台同步回调接口,没有 / 结尾  ----》 get回调调前台
RETURN_URL = LUFFY_URL + "/pay/success"   # 前端需要有个页面显示
    def _get_pay_url(self, out_trade_no, total_amount, subject):
        # 生成pay_url,放入到context中
        res = alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=float(total_amount),  # 只有生成支付宝链接时,不能用Decimal
            subject=subject, #订单内容
            return_url=settings.RETURN_URL, #支付宝回调post请求地址,就是用户支付后支付宝调用该结果告知订单已完成
            notify_url=settings.NOTIFY_URL, # 前端页面get请求地址,就是订单完成后,返回给用户的页面
        )
        pay_url = GATEWAY + res #网管拼接api_alipay_trade_page_pay的返回值才是支付链接
        self.context['pay_url'] = pay_url

前端回调页面是自设的
例如:

<template>
  <div class="pay-success">
    <!--如果是单独的页面,就没必要展示导航栏(带有登录的用户)-->
    <Header/>
    <div class="main">
      <div class="title">
        <div class="success-tips">
          <p class="tips">您已成功购买 1 门课程!</p>
        </div>
      </div>
      <div class="order-info">
        <p class="info"><b>订单号:</b><span>{{ result.out_trade_no }}</span></p>
        <p class="info"><b>交易号:</b><span>{{ result.trade_no }}</span></p>
        <p class="info"><b>付款时间:</b><span><span>{{ result.timestamp }}</span></span></p>
      </div>
      <div class="study">
        <span>立即学习</span>
      </div>
    </div>
  </div>
</template>

<script>
import Header from "@/components/Header"

export default {
  name: "Success",
  data() {
    return {
      result: {},
    };
  },
  created() {
    // url后拼接的参数:?及后面的所有参数 => ?a=1&b=2
    // console.log(location.search);

    // 解析支付宝回调的url参数
    console.log(location.search)
    let params = location.search.substring(1);  // 去除? => a=1&b=2
    let items = params.length ? params.split('&') : [];  // ['a=1', 'b=2']
    //逐个将每一项添加到args对象中
    for (let i = 0; i < items.length; i++) {  // 第一次循环a=1,第二次b=2
      let k_v = items[i].split('=');  // ['a', '1']
      //解码操作,因为查询字符串经过编码的
      if (k_v.length >= 2) {
        // url编码反解
        let k = decodeURIComponent(k_v[0]);
        this.result[k] = decodeURIComponent(k_v[1]);
        // 没有url编码反解
        // this.result[k_v[0]] = k_v[1];
      }

    }
    // 解析后的结果
    console.log(this.result);


    // 把地址栏上面的支付结果,再get请求转发给后端
    this.$axios({
      url: this.$settings.base_url + '/order/success/' + location.search,
      method: 'get',
    }).then(response => {
      console.log(response.data);
      if (response.data.code != 100) {
        alert(response.data.msg)
      }
    }).catch(() => {
      console.log('支付结果同步失败');
    })
  },
  components: {
    Header,
  }
}
</script>

<style scoped>
.main {
  padding: 60px 0;
  margin: 0 auto;
  width: 1200px;
  background: #fff;
}

.main .title {
  display: flex;
  -ms-flex-align: center;
  align-items: center;
  padding: 25px 40px;
  border-bottom: 1px solid #f2f2f2;
}

.main .title .success-tips {
  box-sizing: border-box;
}

.title img {
  vertical-align: middle;
  width: 60px;
  height: 60px;
  margin-right: 40px;
}

.title .success-tips {
  box-sizing: border-box;
}

.title .tips {
  font-size: 26px;
  color: #000;
}


.info span {
  color: #ec6730;
}

.order-info {
  padding: 25px 48px;
  padding-bottom: 15px;
  border-bottom: 1px solid #f2f2f2;
}

.order-info p {
  display: -ms-flexbox;
  display: flex;
  margin-bottom: 10px;
  font-size: 16px;
}

.order-info p b {
  font-weight: 400;
  color: #9d9d9d;
  white-space: nowrap;
}

.study {
  padding: 25px 40px;
}

.study span {
  display: block;
  width: 140px;
  height: 42px;
  text-align: center;
  line-height: 42px;
  cursor: pointer;
  background: #ffc210;
  border-radius: 6px;
  font-size: 16px;
  color: #fff;
}
</style>

支付宝回调函数post和前端的反馈结果get

class PaySuccessView(ViewSet):
    authentication_classes = []
    permission_classes = []

    # 给前端做二次校验用
    def list(self, resquest):
        out_trade_no = resquest.query_params.get('out_trade_no')
        order = Order.objects.filter(out_trade_no=out_trade_no, order_status=1).first()
        if order:
            return Luffy_Response(200, '支付成功')
        else:
            return Luffy_Response(code=101, msg='暂时还没收到你的付款')

    # 给支付宝用的--->必须把项目部署在公网上才能回调成功
    def create(self, request):
        try:
            # post提交的数据(支付宝回调格式:urlencoded,QueryDic)
            #
            # from django.http.request import QueryDict
            #
            # print(type(request.data))
            # 把QueryDic对象转成真正的dict对象,就可以修改,pop
            result_data = request.data.dict()
            #我们的订单号
            out_trade_no = result_data.get('out_trade_no')
            #支付宝的签名
            signature = result_data.pop('sign')
            from libs.ipay import alipay
            result = alipay.verify(result_data, signature)
            if result and result_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
                # 完成订单修改:订单状态、流水号、支付时间
                Order.objects.filter(out_trade_no=out_trade_no).update(order_status=1)
                # 完成日志记录
                logger.warning('%s订单支付成功' % out_trade_no)
                # 支付宝要的格式就这个格式
                return Response('success')
            else:
                logger.error('%s订单支付失败' % out_trade_no)
        except:
            pass
        return Response('failed')

你可能感兴趣的:(支付方法,支付宝)