沙箱应用:https://openhome.alipay.com/platform/appDaily.htm?tab=info
沙箱账号:https://openhome.alipay.com/platform/appDaily.htm?tab=account
文档主页: https://openhome.alipay.com/developmentDocument.htm
电脑网站支付产品介绍: https://docs.open.alipay.com/270
电脑网站支付快速接入: https://docs.open.alipay.com/270/105899/
API列表: https://docs.open.alipay.com/270/105900/
SDK文档: https://docs.open.alipay.com/270/106291/
Python支付宝SDK: https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
美多商城私钥加密数据,美多商城公钥解密数据。
支付宝私钥加密数据,支付宝公钥解密数据。
1.Linux中生成公私钥
$ openssl
$ OpenSSL> genrsa -out app_private_key.pem 2048 # 制作私钥RSA2
$ OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
$ OpenSSL> exit
2.配置美多商城公私钥
配置美多商城私钥
a.新建子应用pay,在该子应用下新建文件夹keys用于存储公私钥
将制作的美多商城私钥app_private_key.pem拷贝到keys文件夹中。
b.将payment.keys.app_public_key.pem文件中内容上传到支付宝。
3.配置支付宝公钥
将支付宝公钥内容拷贝到应用key文件夹下:payment.keys.alipay_public_key.pem文件中。
-----BEGIN PUBLIC KEY-----
支付宝公钥内容
-----END PUBLIC KEY-----
订单支付触发页面:《order_success.html》 和 《user_center_order.html》
我们实现订单支付功能时,只需要向支付宝获取登录链接即可,进入到支付宝系统后就是用户向支付宝进行支付的行为。
选项 | 方案 |
---|---|
请求方法 | GET |
请求地址 | /payment/(?P |
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
order_id | int | 是 | 订单编号 |
字段 | 说明 |
---|---|
code | 状态码 |
errmsg | 错误信息 |
alipay_url | 支付宝登录链接 |
A.创建子应用
django-admin startapp pay
B.添加模块
INSTALLED_APPS = [
‘apps.pay’,
]
C.配置路由
urlpatterns = [
path(‘payment//’,PayUrlView.as_view()),
]
urlpatterns = [
path(’’,include(‘apps.pay.urls’)),
]
D.业务逻辑
"""
需求:
当用户点击去支付按钮的时候,要后端生成一个跳转的连接
前端:
axios 请求. 携带 订单id
后端:
请求: 获取订单id
业务逻辑: 生成支付宝链接(读取文档)
读取应用私钥和支付宝公钥
创建支付宝实例,调用支付宝的方法
拼接连接
响应:
路由: GET payment/order_id/
步骤:
1. 获取订单id
2. 验证订单id (根据订单id查询订单信息)
3. 读取应用私钥和支付宝公钥
4. 创建支付宝实例
5. 调用支付宝的支付方法
6. 拼接连接
7. 返回响应
"""
from django.views import View
from apps.orders.models import OrderInfo
from utils.views import LoginRequiredJSONMixin
from django.http import JsonResponse
from meiduo_mall import settings
from alipay import AliPay, AliPayConfig
class PayUrlView(LoginRequiredJSONMixin, View):
def get(self, request, order_id):
user = request.user
# 1. 获取订单id
# 2. 验证订单id (根据订单id查询订单信息)
try:
# 为了业务逻辑的准确性,
# 查询待支付的订单
order = OrderInfo.objects.get(order_id=order_id,
status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'],
user=user)
except OrderInfo.DoesNotExist:
return JsonResponse({
'code': 400, 'errmsg': '没有此订单'})
# 3. 读取应用私钥和支付宝公钥
app_private_key_string = open(settings.APP_PRIVATE_KEY_PATH).read()
alipay_public_key_string = open(settings.ALIPAY_PUBLIC_KEY_PATH).read()
# 4. 创建支付宝实例
alipay = AliPay(
appid=settings.ALIPAY_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=settings.ALIPAY_DEBUG, # 默认False
config=AliPayConfig(timeout=15) # 可选, 请求超时时间
)
# 5. 调用支付宝的支付方法
# 如果你是 Python 3的用户,使用默认的字符串即可
subject = "多多商城测试订单"
# 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
# https://openapi.alipay.com/gateway.do 这个是线上的
# 'https://openapi.alipaydev.com/gateway.do' 这个是沙箱的
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=order_id,
total_amount=str(order.total_amount), # 一定要进行类型转换,因为decimal不是基本数据类型
subject=subject,
return_url=settings.ALIPAY_RETURN_URL, # 支付成功之后,跳转的页面
notify_url="https://example.com/notify" # 可选, 不填则使用默认notify url
)
# 6. 拼接连接
pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
# 7. 返回响应
return JsonResponse({
'code': 0, 'errmsg': 'ok', 'alipay_url': pay_url})
# Create your models here.
from django.db import models
from apps.orders.models import OrderInfo
from utils.models import BaseModel
class Payment(BaseModel):
"""支付信息"""
order = models.ForeignKey(OrderInfo, on_delete=models.CASCADE, verbose_name='订单')
trade_id = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name="支付编号")
class Meta:
db_table = 'tb_payment'
verbose_name = '支付信息'
verbose_name_plural = verbose_name
"""
前端:
当用户支付完成之后,会跳转到 指定商品页面
页面中的请求 查询字符串中有 支付相关信息
前端把这些数据提交给后端就可以了
后端:
请求: 接收数据
业务逻辑: 查询字符串转换为字典,验证数据,验证没有问题获取支付宝交易流水号
改变订单状态
响应:
路由: PUT payment/status/
步骤:
1. 接收数据
2. 查询字符串转换为字典 验证数据
3. 验证没有问题获取支付宝交易流水号
4. 改变订单状态
5. 返回响应
买家账号[email protected]
登录密码111111
支付密码111111
"""
from apps.pay.models import Payment
class PaymentStatusView(View):
def put(self, request):
# 1. 接收数据
data = request.GET
# 2. 查询字符串转换为字典 验证数据
data = data.dict()
# 3. 验证没有问题获取支付宝交易流水号
signature = data.pop("sign")
app_private_key_string = open(settings.APP_PRIVATE_KEY_PATH).read()
alipay_public_key_string = open(settings.ALIPAY_PUBLIC_KEY_PATH).read()
# 创建支付宝实例
alipay = AliPay(
appid=settings.ALIPAY_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=settings.ALIPAY_DEBUG, # 默认False
config=AliPayConfig(timeout=15) # 可选, 请求超时时间
)
success = alipay.verify(data, signature)
if success:
# 获取 trade_no String 必填 64 支付宝交易号
trade_no = data.get('trade_no')
order_id = data.get('out_trade_no')
Payment.objects.create(
trade_id=trade_no,
order_id=order_id
)
# 4. 改变订单状态
OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'])
return JsonResponse({
'code': 0, 'errmsg': 'ok', 'trade_id': trade_no})
else:
return JsonResponse({
'code': 400, 'errmsg': '请到个人中心的订单中查询订单状态'})