python支付宝支付接口_python调用支付宝支付接口

支付宝支付

# 1、在沙箱环境下实名认证:https://openhome.alipay.com/platform/appDaily.htm?tab=info

# 2、电脑网站支付API:https://docs.open.alipay.com/270/105898/

# 3、完成RSA密钥生成:https://docs.open.alipay.com/291/105971

# 4、在开发中心的沙箱应用下设置应用公钥:填入生成的公钥文件中的内容

# 5、Python支付宝开源框架:https://github.com/fzlee/alipay

# >: pip install python-alipay-sdk --upgrade

# 7、公钥私钥设置

"""

# alipay_public_key.pem

-----BEGIN PUBLIC KEY-----

支付宝公钥

-----END PUBLIC KEY-----

# app_private_key.pem

-----BEGIN RSA PRIVATE KEY-----

用户私钥

-----END RSA PRIVATE KEY-----

"""

# 8、支付宝链接

"""

开发:https://openapi.alipay.com/gateway.do

沙箱:https://openapi.alipaydev.com/gateway.do

"""

aliapy二次封装包

依赖

>: pip install python-alipay-sdk --upgrade

结构

libs

├── iPay # aliapy二次封装包

│ ├── __init__.py # 包文件

│ ├── keys# 密钥文件夹

│ │ ├── alipay_public_key.pem # 支付宝公钥

│ │ └── app_private_key.pem # 应用私钥

└── └── settings.py # 应用配置

setting.py

import os

# 支付宝应用id

APP_ID = 'xxxxx'

# 默认异步回调的地址,通常设置None就行

APP_NOTIFY_URL = None

# 应用私钥文件路径

APP_PRIVATE_KEY_PATH = os.path.join(os.path.dirname(__file__), 'keys', 'app_private_key.pem')

# 支付宝公钥文件路径

ALIPAY_PUBLIC_KEY_PATH = os.path.join(os.path.dirname(__file__), 'keys', 'alipay_public_key.pem')

# 签名方式

SIGN_TYPE = 'RSA2'

# 是否是测试环境

DEBUG = True

_init_.py

from alipay import AliPay

from .settings import *

# 对外提供

from .settings import RETURN_URL, NOTIFY_URL

# 对外提供支付对象

alipay = AliPay(

appid=APP_ID,

app_notify_url=APP_NOTIFY_URL,

app_private_key_path=APP_PRIVATE_KEY_PATH,

alipay_public_key_path=ALIPAY_PUBLIC_KEY_PATH,

sign_type=SIGN_TYPE,

debug=DEBUG

)

alipay_public_key.pem

-----BEGIN PUBLIC KEY-----

支付宝公钥

-----END PUBLIC KEY-----

app_private_key.pem

-----BEGIN RSA PRIVATE KEY-----

应用私钥

-----END RSA PRIVATE KEY-----

补充:dev.py

# 上线后必须换成官网地址

# 同步回调的接口(get),前后台分离时一般设置前台页面url

RETURN_URL = 'http://127.0.0.1:8080/pay/success'

# 异步回调的接口(post),一定设置为后台服务器接口

NOTIFY_URL = 'http://127.0.0.1:8000/order/success/'

支付模块

order/models.py

"""

订单:订单号、流水号、价格、用户

订单详情(自定义关系表):订单、课程

"""

from django.db import models

from utils.model import BaseModel

from user.models import User

from course.models import Course

class Order(BaseModel):

"""订单模型"""

status_choices = (

(0, '未支付'),

(1, '已支付'),

(2, '已取消'),

(3, '超时取消'),

)

pay_choices = (

(1, '支付宝'),

(2, '微信支付'),

)

subject = models.CharField(max_length=150, verbose_name="订单标题")

total_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="订单总价", default=0)

out_trade_no = models.CharField(max_length=64, verbose_name="订单号", unique=True)

trade_no = models.CharField(max_length=64, null=True, verbose_name="流水号")

order_status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="订单状态")

pay_type = models.SmallIntegerField(choices=pay_choices, default=1, verbose_name="支付方式")

pay_time = models.DateTimeField(null=True, verbose_name="支付时间")

user = models.ForeignKey(User, related_name='user_orders', on_delete=models.DO_NOTHING, db_constraint=False,

verbose_name="下单用户")

# 多余字段

orders = models.IntegerField(verbose_name='显示顺序', default=0)

class Meta:

db_table = "luffy_order"

verbose_name = "订单记录"

verbose_name_plural = "订单记录"

def __str__(self):

return "%s - ¥%s" % (self.subject, self.total_amount)

@property

def courses(self):

data_list = []

for item in self.order_courses.all():

data_list.append({

"id": item.id,

"course_name": item.course.name,

"real_price": item.real_price,

})

return data_list

class OrderDetail(BaseModel):

"""订单详情"""

order = models.ForeignKey(Order, related_name='order_courses', on_delete=models.CASCADE, db_constraint=False,

verbose_name="订单")

course = models.ForeignKey(Course, related_name='course_orders', on_delete=models.CASCADE, db_constraint=False,

verbose_name="课程")

price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价")

real_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程实价")

class Meta:

db_table = "luffy_order_detail"

verbose_name = "订单详情"

verbose_name_plural = "订单详情"

def __str__(self):

return "%s订单(%s)" % (self.course.name, self.order.order_number)

支付接口生成支付链接

import time

from rest_framework.views import APIView

from utils.response import APIResponse

from libs.iPay import alipay

from . import authentications, serializers

from rest_framework.permissions import IsAuthenticated

from django.conf import settings

# 获取前台 商品名、价格,产生 订单、支付链接

class PayAPIView(APIView):

authentication_classes = [authentications.JWTAuthentication]

permission_classes = [IsAuthenticated]

def post(self, request, *args, **kwargs):

# 前台提供:商品名、总价、支付方式

request_data = request.data

# 后台产生:订单号、用户

out_trade_no = '%d' % time.time() * 2

request_data['out_trade_no'] = out_trade_no

request_data['user'] = request.user.id

# 反序列化数据,用于订单生成前的校验

order_ser = serializers.OrderModelSerializer(data=request_data)

if order_ser.is_valid():

# 生成订单,订单默认状态为:未支付

order = order_ser.save()

# 支付链接的参数

order_string = alipay.api_alipay_trade_page_pay(

subject=order.subject,

out_trade_no=order.out_trade_no,

total_amount='%.2f' % order.total_amount,

return_url=settings.RETURN_URL,

notify_url=settings.NOTIFY_URL

)

# 形成支付链接:alipay._gateway根据字符环境DEBUG配置信息,决定是沙箱还是真实支付环境

pay_url = '%s?%s' % (alipay._gateway, order_string)

return APIResponse(0, 'ok', pay_url=pay_url)

return APIResponse(1, 'no ok', results=order_ser.errors)

前台回调接口的页面

您已成功购买 1 门课程!

订单号:{{ result.out_trade_no }}

交易号:{{ result.trade_no }}

付款时间:{{ result.timestamp }}

立即学习

import Header from "@/components/Header"

import Footer from "@/components/Footer"

export default {

name: "Success",

data() {

return {

result: {},

};

},

created() {

// 判断登录状态

let token = this.$cookies.get('token');

if (!token) {

this.$message.error('非法请求');

this.$router.go(-1)

}

localStorage.this_nav = '/';

if (!location.search.length) return;

let params = location.search.substring(1);

let items = params.length ? params.split('&') : [];

//逐个将每一项添加到args对象中

for (let i = 0; i < items.length; i++) {

let k_v = items[i].split('=');

//解码操作,因为查询字符串经过编码的

let k = decodeURIComponent(k_v[0]);

let v = decodeURIComponent(k_v[1]);

this.result[k] = v;

// this.result[k_v[0]] = k_v[1];

}

// console.log(this.result);

// 把地址栏上面的支付结果,转发给后端

this.$axios({

url: this.$settings.base_url + '/order/success/' + location.search,

method: 'patch',

headers: {

Authorization: token

}

}).then(response => {

console.log(response.data);

}).catch(() => {

console.log('支付结果同步失败');

})

},

components: {

Header,

Footer,

}

}

.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;

}

支付完成订单校验的接口

from . import models

from utils.logging import logger

from rest_framework.response import Response

class SuccessAPIView(APIView):

# 不能认证,别人支付宝异步回调就进不来了

# authentication_classes = [authentications.JWTAuthentication]

# permission_classes = [IsAuthenticated]

def patch(self, request, *args, **kwargs):

# 默认是QueryDict类型,不能使用pop方法

request_data = request.query_params.dict()

# 必须将 sign、sign_type(内部有安全处理) 从数据中取出,拿sign与剩下的数据进行校验

sign = request_data.pop('sign')

result = alipay.verify(request_data, sign)

if result: # 同步回调:修改订单状态

try:

out_trade_no = request_data.get('out_trade_no')

order = models.Order.objects.get(out_trade_no=out_trade_no)

if order.order_status != 1:

order.order_status = 1

order.save()

except:

pass

return APIResponse(0, '支付成功')

return APIResponse(1, '支付失败')

# 支付宝异步回调

def post(self, request, *args, **kwargs):

# 默认是QueryDict类型,不能使用pop方法

request_data = request.data.dict()

# 必须将 sign、sign_type(内部有安全处理) 从数据中取出,拿sign与剩下的数据进行校验

sign = request_data.pop('sign')

result = alipay.verify(request_data, sign)

# 异步回调:修改订单状态

if result and request_data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ):

out_trade_no = request_data.get('out_trade_no')

logger.critical('%s支付成功' % out_trade_no)

try:

order = models.Order.objects.get(out_trade_no=out_trade_no)

if order.order_status != 1:

order.order_status = 1

order.save()

except:

pass

# 支付宝八次异步通知,订单成功一定要返回 success

return Response('success')

return Response('failed')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值