34-支付宝支付
支付宝支付
一、快速连接通道
1. 支付宝
<1>. 支付宝API:六大接口
https://docs.open.alipay.com/270/105900/
<2>. 支付宝工作流程
https://docs.open.alipay.com/270/105898/
<3>. 支付宝8次异步通知机制(支付宝对我们的服务器发送POST请求,索要success
7个字符)
https://docs.open.alipay.com/270/105902/
2. 沙箱环境
<1>. 在沙箱环境下实名认证
https://openhome.alipay.com/platform/appDaily.htm?tab=info
<2>. 电脑网站支付API
https://docs.open.alipay.com/270/105900/
<3>. 完成RSA秘钥生成
https://docs.open.alipay.com/291/105971
<4>. 在开发中心的沙箱应用下设置应用公钥
填入生成的公钥文件中的内容
<5>. Python支付宝开源框架
https://github.com/fzlee/alipay
pip install python-alipay-sdk --upgrade
<6>. 公钥私钥设置
"""
# alipay_public_key.pem
-----BEGIN PUBLIC KEY-----
支付宝公钥
-----END PUBLIC KEY-----
# app_private_key.pem
-----BEGIN RSA PRIVATE KEY-----
用户私钥
-----END RSA PRIVATE KEY-----
"""
<7>. 支付宝回调连接
开发:https://openapi.alipay.com/gateway.do
沙箱:https://openapi.alipaydev.com/gateway.do
二、支付流程图
三、支付宝介入入门
1. 流程
'''
# 支付宝开放平台
1. 服务范围(自研开发服务) -> 实名认证
2. 控制台 -> 我的应用 -> 创建应用 -> 网页&移动应用 -> 支付接入 -> 应用名称 -> 应用图标 ->
1) 移动应用 -> 应用平台 -> Bundle ID ...
2) 网页应用 (不成功. 需要使用营业执照) -> 网址url -> 简介
注意: 先选择功能再审核
能力列表:添加能力 -> 支付能力 -> 电脑网站支付
开发设置:
加签管理 -> 公钥 -
支付宝网关
应用网关
授权回调地址
3. 文档 -> 网页 & 移动应用 接口文档能力列表
1) 开放能力:
支付能力 -> 电脑网站支付
2) 产品介绍:
注意: 会跳到支付宝的页面, 支付宝会有一个get页面回调, post数据返回后端回调
费率: 0.6%
3) 快速接入:
SDK快速接入: python没有, 只能使用API开发
支付流程: 下单 -> 商户系统 -> 支付宝 -> 回调(get显示订单结果, post修改订单状态)
4) 支付API:
公共请求参数
请求参数
订单号 out_trade_no
总金额 total_amount
订单标题 subjet
公共响应参数
支付宝交易号 trade_no
我们的订单号 out_trade_no
5) GitHub开源SDK
pip install python-alipay-sdk
# 支付宝沙箱环境
1. 沙箱环境地址: https://openhome.alipay.com/platform/appDaily.htm
2. 沙箱应用:
APPID
支付宝网关: 地址中带dev表示沙箱环境, 不带表示正式环境
加密方式: 使用支付宝提供的密钥生成(支付宝开放平台组助手).
之前是xx.jar包, 现在变成xx.exe软件. 需要生成公钥和私钥
将自己的公钥配置在支付宝中, 支付宝会生成一个支付宝的公钥.
3. 项目中使用:
注释 .read这里是操作文件的
app_private_key_string 配置自己的私钥
alipay_public_key_string 配置支付宝的公钥
注意: 不能有空格
AliPay类中的参数配置:
APPID配置 沙箱环境的APPID
sign_type 配置自己的 RSA2
debug=False测试环境, True正式环境
alipay.api_alipay_trade_page_pay中的参数配置:
out_trade_no 配置自己的商品订单号
total_amount 总金额
subject 订单标题
return_url 回调地址 (注意: 需要使用公网地址)
notify_url 回调地址
支付宝网关 + order_string => 生成连接地址
提示: 生成连接地址打开会出现钓鱼网站异常
4. 解决提示钓鱼问题: 浏览器里面有多个窗口
沙箱环境存在的问题, 如果出现问题, 开无痕窗口即可, 付完之后会回调到之前配置的return_url中配置的网页
支付宝沙箱环境充值:
控制台 -> 沙箱账号 -> 账户余额
# 支付宝公私密钥生成, sdk使用
支付宝开放平台组助手使用: 生成公私钥
支付宝开放平台下载:https://ideservice.alipay.com/ide/getPluginUrl.htm?clientType=assistant&platform=win&channelType=WEB
密钥长度: RSA2
密钥格式: PKCS1
生成即可
GitHub开源SDK:
支付宝开源框架地址: https://github.com/fzlee/alipay
pip install python-alipay-sdk
# 拓展:
xx.apk 如果apk使用QQ 或者 微信传送, 它会改名, 再后面加个.1 -> xx.apk.1. 目的就是防止恶意软件.
如果你需要安装, 只需要将后缀名修改过来即可
'''
2. 测试目录结构
3. t_alipay.py
from alipay import AliPay
app_private_key_string = """-----BEGIN rsa2 PRIVATE KEY-----
MIIEowIBAAKCAQEAr6my/KRUtoPcQzuBt8TZtxLvLtwI8Rf/ETubH6dfi143yuiHd0SnfTctD+ZTmGyRHxuqNwwTNV4CN0d58wuI2F3hky4Tm8ocp8n0tzjlYxDvoh1b4d4ksxXCM0yhSzywdIK+K+Y9VP74uU4mlT47oBFUs6TBK9AAlMfZfoPTUAUjSDF3usUE0IvkbKyv4Yd/cD0Stnqrl5qzplBjrA7H0HSRbw5nrk8Pj8aWnZYAayq3aGCJZxc+UfLKo8rfhV3GY6Tu29cTvTX2K69TZLQYPHkH1+8nLtwQywuWioXHOWwac6fE3270XR41xaUHo9avS48Gr4HNdkTAUtvq6YmfAwIDAQABAoIBAC8AuWPglMpBfi5/PbZuddMGvflL5xib0yRJTripkGc6TrN8hMLlG+vlV6lpd/TRGAO641DXakxdWzpvZbIi4/sBI9q9+YE2E3TSFSjxkG9xmK1ILc3CIw/IQq53UrFPC+ghE8GrWb3ke6kZwDku7cVm3cMz0nxmq8EjuI6ht2kxhUKzdsE9Z1DMOHWiEZSM6dvNMW/axToM2UawwPsermbTa++IJujvzjKH0UJORBqVnC6Ar2tPbEOJ9wbybVihnpHTyaCCWq2XDx/nEkOWeW8oeRp41uXrJf7iaHbYFYA2GlvQT2vMkFU5qKPzKYJDdBZdvlN0dEpEUstx4WYcSAECgYEA1QP1Vr54PFuh7KWxkV7WJz1iZyNcyPHWG4XjzTifK4uTPyciabDhUO1aPmnd7I2GvaRwyCWAZQSn7bIV9rumebEWzMWbcttm2e/iL7lzE1Aj8Ank8pXXaIXQHE+4yUfdE3jsHcTq99EzIY+K7Js4LckvR9sCWiM9J6Za1TuO9WkCgYEA0xwqePmrfYE965quZpbNZZ5uGO6AJZ0YZlK69RwVT5NV1fmdLsqk/4jgJKrZnnspt16cKjDJ5DyeGH4uikL1F6AReDbCPSVJjWqo50Al98K6WDqf6HhJnz+A+dxtgzHbQKUWlWiWuqbeB6ITXnVG0mrBi6jHR247fkh3FkOAh4sCgYEAriN2RVugX3dpgFRUPUsSNzHvZ/F4wK0zI3zpJbPMK4UG8vHDKDP5fncK90sEqYVpSU9NA9HkjLCpt5+GZRYymfkzcmN5GQRTqIZ6mhk5AejZ+DmepeNIWLtR1tS9XGPUuveR04kFA9SaIbj8yiwq5enSlulBIM/fq3qcYSolN7UECgYA3MiMMtEKZMuRsqGm22vDjA9RHYnxQ2U0a28CT+3666ovDwVrOdB9FzJTGIYF6hTs3/V2ZTl5K9WpkfwFOFwmb3rcSlkac1BXyCpQUulny+I/eJ53Nmz2sjF79dRuQ9MUdlsxbzheyv5RHrKGhzcnxlAX8rOlFjNWzQ+EXChkd1wKBgG/B0o8VeajSxcOqlAJZbbcnKzX3V/Fea6TPxUpzG7HCBL0y7xMSt+KtBBQzD+0GRIkwZqhsHw1tCzvTTI74z3DiSMy95atflE9PIyRriKaMiUfSALw6UA5okEis56IGmY5mSZ60O3z+mONjRXXBCeRIjJAd0UByVBjcUoNxABe3
-----END rsa2 PRIVATE KEY-----"""
alipay_public_key_string = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCqAQEAgvXw19HTUH0t1thzkoq8KBhDBwFCoDqRJyBYnpN/KOTxTuSoUR0+pLK3vJbeQ0w5GJ/tiHpLh38hc88LNSR5nk26IBXX8WuNmxxC56d/A4/AaqiO3xgs9jKZjvYs0xuaFkwLswMuD8vm3xh6/YCD97EPkDqMY6aqbBdjHv8wOZ2Y/X6uFkANValvx2x+Lf8vSO+I2Iyq0sDmdCFS8LdnKgN5L8GoR1WkorgY6sTs2eV86acb95iAZC+7fVpVWzpX6yxBOL7hDIFDNDXCXhhWnsR3HfILNOMw84/jXdUKnXQIYYGCkSOQlK2hSB8/DtJaOoBTMrvpa29SCeIGvxFJRQIDAQAB
-----END PUBLIC KEY-----"""
alipay = AliPay(
appid="2021000117620642",
app_notify_url=None, # 默认回调url
app_private_key_string=app_private_key_string,
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
alipay_public_key_string=alipay_public_key_string,
sign_type="RSA2", # rsa2 或者 RSA2
debug=False # 默认False
)
# 如果你是 Python 3的用户,使用默认的字符串即可
subject = "测试订单"
# 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
alipay_url = 'https://openapi.alipaydev.com/gateway.do?'
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no="20161112", # 订单号, 必须唯一
total_amount=10, # 总金额
subject=subject, # 订单标题
return_url="http://139.196.184.91/", # 同步回调(支付成功)
notify_url="http://139.196.184.91/" # 异步回调(订单状态) 可选, 不填则使用默认notify url
)
print(alipay_url + order_string)
4. 注意事项
from alipay import AliPay
app_private_key_string = """-----BEGIN rsa2 PRIVATE KEY-----
MIIEowIBAAKCAQEAr6my/KRUtoPcQzuBt8TZtxLvLtwI8Rf/ETubH6dfi143yuiHd0SnfTctD+ZTmGyRHxuqNwwTNV4CN0d58wuI2F3hky4Tm8ocp8n0tzjlYxDvoh1b4d4ksxXCM0yhSzywdIK+K+Y9VP74uU4mlT47oBFUs6TBK9AAlMfZfoPTUAUjSDF3usUE0IvkbKyv4Yd/cD0Stnqrl5qzplBjrA7H0HSRbw5nrk8Pj8aWnZYAayq3aGCJZxc+UfLKo8rfhV3GY6Tu29cTvTX2K69TZLQYPHkH1+8nLtwQywuWioXHOWwac6fE3270XR41xaUHo9avS48Gr4HNdkTAUtvq6YmfAwIDAQABAoIBAC8AuWPglMpBfi5/PbZuddMGvflL5xib0yRJTripkGc6TrN8hMLlG+vlV6lpd/TRGAO641DXakxdWzpvZbIi4/sBI9q9+YE2E3TSFSjxkG9xmK1ILc3CIw/IQq53UrFPC+ghE8GrWb3ke6kZwDku7cVm3cMz0nxmq8EjuI6ht2kxhUKzdsE9Z1DMOHWiEZSM6dvNMW/axToM2UawwPsermbTa++IJujvzjKH0UJORBqVnC6Ar2tPbEOJ9wbybVihnpHTyaCCWq2XDx/nEkOWeW8oeRp41uXrJf7iaHbYFYA2GlvQT2vMkFU5qKPzKYJDdBZdvlN0dEpEUstx4WYcSAECgYEA1QP1Vr54PFuh7KWxkV7WJz1iZyNcyPHWG4XjzTifK4uTPyciabDhUO1aPmnd7I2GvaRwyCWAZQSn7bIV9rumebEWzMWbcttm2e/iL7lzE1Aj8Ank8pXXaIXQHE+4yUfdE3jsHcTq99EzIY+K7Js4LckvR9sCWiM9J6Za1TuO9WkCgYEA0xwqePmrfYE965quZpbNZZ5uGO6AJZ0YZlK69RwVT5NV1fmdLsqk/4jgJKrZnnspt16cKjDJ5DyeGH4uikL1F6AReDbCPSVJjWqo50Al98K6WDqf6HhJnz+A+dxtgzHbQKUWlWiWuqbeB6ITXnVG0mrBi6jHR247fkh3FkOAh4sCgYEAriN2RVugX3dpgFRUPUsSNzHvZ/F4wK0zI3zpJbPMK4UG8vHDKDP5fncK90sEqYVpSU9NA9HkjLCpt5+GZRYymfkzcmN5GQRTqIZ6mhk5AejZ+DmeeNIWLtR1tS9XGPUuveR04kFA9SaIbj8yiwq5enSlulBIM/fq3qcYSolN7UECgYA3MiMMtEKZMuRsqGm22vDjA9RHYnxQ2U0a28CT+3666ovDwVrOdB9FzJTGIYF6hTs3/V2ZTl5K9WpkfwFOFwmb3rcSlkac1BXyCpQUulny+I/eJ53Nmz2sjF79dRuQ9MUdlsxbzheyv5RHrKGhzcnxlAX8rOlFjNWzQ+EXChkd1wKBgG/B0o8VeajSxcOqlAJZbbcnKzX3V/Fea6TPxUpzG7HCBL0y7xMSt+KtBBQzD+0GRIkwZqhsHw1tCzvTTI74z3DiSMy95atflE9PIyRriKaMiUfSALw6UA5okEis56IGmY5mSZ60O3z+mONjRXXBCeRIjJAd0UByVBjcUoNxABe3
-----END rsa2 PRIVATE KEY-----"""
alipay_public_key_string = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgvXw19HTUH0t1thzkoq8KBhDBwFCoDqRJyBYnpN/KOTxTuSoUR0+pLK3vJbeQ0w5GJ/tiHpLh38hc88LNSR5nk26IBXX8WuNmxxC56d/A4/AaqiO3xgs9jKZjvYs0xuaFkwLswMuD8vm3xh6/YCD97EPkDqMY6aqbBdjHv8wOZ2Y/X6uFkANValvx2x+Lf8vSO+I2Iyq0sDmdCFS8LdnKgN5L8GoR1WkorgY6sTs2eV86acb95iAZC+7fVpVWzpX6yxBOL7hDIFDNDXCXhhWnsR3HfILNOMw84/jXdUKnXQIYYGCkSOQlK2hSB8/DtJaOoBTMrvpa29SCeIGvxFJRQIDAQAB
-----END PUBLIC KEY-----"""
alipay = AliPay(
appid="2021000117620642",
app_notify_url=None, # 默认回调url
app_private_key_string=app_private_key_string,
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
alipay_public_key_string=alipay_public_key_string,
sign_type="RSA2", # rsa2 或者 RSA2
debug=False # 默认False
)
# 如果你是 Python 3的用户,使用默认的字符串即可
subject = "测试订单"
# 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string
alipay_url = 'https://openapi.alipaydev.com/gateway.do?'
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no="20161112", # 订单号, 必须唯一
total_amount=10, # 总金额
subject=subject, # 订单标题
return_url="http://139.196.184.91/", # 同步回调(支付成功)
notify_url="http://139.196.184.91/" # 异步回调(订单状态) 可选, 不填则使用默认notify url
)
print(alipay_url + order_string)
四、支付宝二次封装
1. GitHub开源框架参考
https://github.com/fzlee/alipay
2. 调用支付宝支付SDK
pip install python-alipay-sdk --upgrade
# 课程出现的错误解决: 抛ssl相关错误,代表缺失该包
pip install pyopenssl
3. 流程
'''
1. libs中新建文件, 文件中新建__init__.py, 新建.py文件
2. 将之前写死的 app...string 等, 修改成从文件中读取 open().read()
3. 新建文件夹存放支付宝公钥和自己的私钥用于被第二步读取
公钥私钥存放的文件格式是:
-----xxx-----
公钥 或者 私钥
-----xxx-----
4. 新建settings.py文件存放一些常量
5. debug 配置成和 setting.py中的debug一直性
6. 使用三元运算配置支付宝的支付网关
7. 使用__init__.py优化导入的层级
注意: 网站支付alipay.api_alipay_trade_page_pay放到外面书写和订单一起.
'''
4. 目录结构
libs
├── al_alipay # aliapy二次封装包
│ ├── __init__.py # 包文件
│ ├── pem # 公钥私钥文件夹
│ │ ├── alipay_public_key.pem # 支付宝公钥文件
│ │ ├── app_private_key.pem # 应用私钥文件
│ ├── pay.py # 支付文件
└── └── settings.py # 应用配置
5. pem/alipay_public_key.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt99Bp0XLP1Zu2WdRu74CMB/tVx1/2thIo8t3oAo8eD8smku1e76PfeOw4iqYMHU32Vq1Fg7BLa9oPMw7Ro+kNjX4jTDz4wC3LA6dUI5OeGxYd9+tkpsBwyg+buVNhhogppQn5rcCzkRFTx0DwlnRUjcs420fS8J2MaCZf+4HJx6PdvQ2+Jo9SDqbnCqrkWy68/Gwpy2O/PUHXFrCs0hY/Pvu8HaK1xUre4yNJx+yyGTAKYEHTz4zq9BKJOlBUB+ZoFD0aanTFKyi4dYXeJaNGDICab21aRKL2S043KzPvBWqPAWE5KRGata5GhBuzQjh6TaXdP/hpJu/tXTD7LO5HwIDAQAB
-----END PUBLIC KEY-----
6. pem/app_private_key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAj91mUtyrPlFFkfoLB+66lYcwexzXzEt6SlJuxsj3lW6+8pqla4YKqiUf98DeuBpX+USFm+baYFPqP5FWKyAUmGSDU8T4xD9BwLc+gm7rjeEjE5LzdyMInoEjW0QKXnn6S5y4gGPwI2WjOhg9vfr2R0GTDMTqn4i7zDB/u+wTksX5eDTSpb5VhtFFqYPklLUB+p0eCVE+iuFmJQLw2YvQ2T23mVFvYfpOVUvLZxIaMheERks73TfGRcZpJX3r5rUyn8wLiMPQkhoxS4kBPTZOHr6ymzP2qqjXZ8yNENewczocIu1MYm/HVPm25qJoiwILFmi5Wkt8+85UjXz2uHGiQQIDAQABAoIBAFrdWpCBgcMVb9x4UllLRhvFTDCmEgKdtXqVwBPbwMxoK0BtvodAHSJD2oIQFluvf9sXlU/XqhvnRG+r6wHH/FoYOf5BzWGeFniTBG87gZmWFiJ50T5xKTN7mwo82lO7tQPm0318IaMpwcOipfSFOuHcn/UTtqDWqs6X30WhIOe1IR6y08M9D1bZpnzG/t2If5Hoj2otjuIgdTac6qVJgg/MH4TTnSEss3nAnohnduTGujF7zigimDPPkBOykddk/jXhr3dSba6P/SSBCnqV4J5mZ6fm2mW9FX12VohMIPwcyxke7DnRS8aaeJ0w2jCNtr2s/L33RPxt1q36QcayMEUCgYEA1qlRVQGoPw+975cGuuLtf/GIQe/nKaL4ewKOjmz+CU9q7nXTQZP6Wv1PLe48mhtEvJ67mzdMYFvB1GMUvm9XeWtfJIWChTigDl4kgApbwHStPO4Ka5uxYb3uArREfiuSRhzqg12CzeXz67JH+8hYj2XqMolJQE3BqCentgH++E8CgYEAq5HaWm53esYoiPZ7YkfMI7xtsZNQPFp1kr5ZfGeEwpa6wz65E0lNuwLpGdN2o4gfLCpqTjnemzEvjwflsgcUQ9V2ENuZlGu+CHQ/QtESmnPRClJmWs7/AncmeUzuE+GJWcmP8Ny3WzA8Hj3GlEJRw85OSLRftjDkddm+3bDmiG8CgYEA0CSvq2iG9lbSSg48RVyjBAt0ntL7Z6ERpV0uU6YVkXuDaSOwq4bMHAxBCX1XH+rO9MJJkVDGayytvr4wMBOQUzissaIPlBP7BtN8OvdQTkYUcN80FXGLRwY+UjrvqxOeqwOA1c4HdpTBtspRCDAUxz8AHu6Fq6d53w5MjaxTyfsCgYAioIZMWB0/Jz1JH04ZsNnvoHkXLN81vyAZpNdUt2PhDiDVhRQ/Yz0P8G9xae944+E+vbTE4wMdmVi66mIegzVA15VDo76kaPZqqGOYLbAugg9/oM/NphdrvPaD5tXqJ0vcVkT53OIYwmxvwhIRHC16cmn0XIswrz981ZyjC7ALewKBgDGwoNN4+0lQzQpNF7L3AFs7qk8KdTpNqaaFmzlWpRhWKdP7l0EkxFeP/8n+9Z4t3u3giU6UYWRjR6VGFsJ53Ytr63+XmqUPYfeAyadSPVNNBnDkJ9yrvPfElI4Fu+aroxhcjkTuCgYepD6c4jXq+xsoJz/jMbjv6cnd1T7QDYvL
-----END RSA PRIVATE KEY-----
7. __init__.py
from .alipay_task import alipay, alipay_gateway
8. pay.py
from alipay import AliPay
from . import settings
alipay = AliPay(
appid=settings.APPID,
app_notify_url=None,
app_private_key_string=settings.APP_PRIVATE_KEY_SIRING,
alipay_public_key_string=settings.ALIPAY_PUBLIC_KEY_SIRING,
sign_type=settings.SIGN_TYPE,
debug=settings.DEBUG,
)
gateway = settings.GATEWAY
9. settings.py
import os
APPID = '2021000117613064'
# 默认回调
APP_NOTIFY_URL = None
# 自己私钥
APP_PRIVATE_KEY_SIRING = open(os.path.join(os.path.dirname(__file__), 'pem', 'app_private_kay.pem')).read()
# 阿里公钥
ALIPAY_PUBLIC_KEY_SIRING = open(os.path.join(os.path.dirname(__file__), 'pem', 'alipay_public_key.pem')).read()
# 标签加密类型
SIGN_TYPE = 'RSA2'
# True表示测试沙箱环境
DEBUG = True
# 阿里网关
GATEWAY = 'https://openapi.alipaydev.com/gateway.do?' if DEBUG else 'https://openapi.alipay.com/gateway.do?'
10. 配置文件中配置支付宝替换接口:settings.py|开发人员
# 后台基URL
BASE_URL = 'http://139.196.184.91:8000' # 注意: 这里的8000上线以后指定的nginx的8000端口, 由nginx的8000端口发送到nginx配置内部的uwsgi的端口中
# 前台基URL
LUFFY_URL = 'http://139.196.184.91' # 注意: 这里没有写端口默认就是80端口.
# 支付宝同步异步回调接口配置
# 后台: 支付宝异步回调的接口
NOTIFY_URL = BASE_URL + "/order/success/"
# 前台: 支付宝同步回调接口,没有 / 结尾
RETURN_URL = LUFFY_URL + "/pay/success"
五、后台-支付接口
1. 订单模块表
<1>. 流程
'''
1. 新建订单app, 注册, 子路由urls, 总路由分发,
2. 表分析
订单表:
订单标题, 总价格, 订单id(自己的), 流水号(支付宝), 订单状态, 支付方式, 支付时间, 订单用户(注意: 导入用户表路径尽量小), 创建时间, 更新时间
订单详情表:
订单一对多外键, 课程一对多外键(级联删除改为Set_NULL, null=True), 原价格, 实价
str的健壮性校验
订单和订单详情表关系分析: 一对多 订单详情是多的一方 一个订单可以有多个订单详情, 一个订单详情不可以同时属于多个订单.
订单表和课程表关系分析: 多对多 一个订单可以包含多个课程, 一个课程可以属于多个订单
重点: 但是我们这里不着不过对订单表与课程表建立多对多的关系,而是通过订单详情表与课程表建立关系.
订单详情表和课程表关系分析: 一对多 订单详情是多的一方 订单详情多的一方 一个订单详情不可以属于多个课程, 而一个课程可以属于多个订单详情
订单表和用户表关系分析: 一对多 订单是多的一方 一个用户可以下多个订单, 一个订单不能属于多个用户
on_delete -> DO_NOTHING
db_constraint=False
提示: 不继承BaseModel表. is_show, orders没有必要存在
3. 数据迁移
'''
<2>. order/models.py
"""
class Order(models.Model):
# 主键、总金额、订单名、订单号、订单状态、创建时间、支付时间、流水号、支付方式、支付人(外键) - 优惠劵(外键,可为空)
pass
class OrderDetail(models.Model):
# 订单号(外键)、商品(外键)、实价、成交价 - 商品数量
pass
"""
from django.db import models
from user.models import User
from course.models import Course
import utils
class Order(models.Model):
"""订单模型"""
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="支付时间")
created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
# 订单表和用户表关系分析: 一对多 订单是多的一方 一个用户可以下多个订单, 一个订单不能属于多个用户
user = models.ForeignKey(User, related_name='order_user', on_delete=models.DO_NOTHING, db_constraint=False,
verbose_name="下单用户")
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(models.Model):
"""订单详情"""
price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价")
real_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程实价")
# 订单和订单详情表关系分析: 一对多 订单详情是多的一方 一个订单可以有多个订单详情, 一个订单详情不可以同时属于多个订单.
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.SET_NULL, null=True,
db_constraint=False,
verbose_name="课程")
class Meta:
db_table = "luffy_order_detail"
verbose_name = "订单详情"
verbose_name_plural = "订单详情"
def __str__(self):
"""str的健壮性校验"""
try:
return "%s的订单:%s" % (self.course.name, self.order.out_trade_no)
except Exception as e:
utils.log.error(str(e))
return super().__str__()
2. 订单模块接口之支付接口
<1>. 流程
'''
1. 支付接口: 生成订单, 生成支付连接, 返回支付连接
1) 新建路由pay, payView
2) 新建视图payView
# 思路
order表和orderdetail表插入数据, 重写create方法.
生成订单号 uuid
登录后才能支付 jwt认证
当前登录用户就是下单用户, 存到order表中
订单价格校验. 如: 下了三个课程, 总价格100, 前端提交的价格是99
# 实现
继承 C, G
新建序列化类 OrderModelSeriailzer
注意: 这是一个反序列化的表
# 传输的数据格式
{course: [1, 2, 3], total_amount: 100, subject: 商品名, pay_type: 1}
# 控制字段
fields=['total_amount', 'subject', 'pay_type', 'course_list']
# 可以再局部钩子中把course=[1, 2, 3]生成course=[obj1, obj2, obj3] 或者使用 PrimayKeyRElatedField
course=serialisers.CharField()
# 校验
1. 校验订单总价格: 获取总价格, 获取课程对象列表从总价格列表中获取每个价格叠加与总价格对比 (注意: 需要返回总价格)
2. 生成订单号: str(uuid).replace('-', '')
3. 获取支付用户: 视图中重写create方法借助self.context传将request对象传给序列化类
4. 生成支付连接: 导入alipay, alipay_gateway. 拷贝, 将post, get2个回调的地址存放到配置文件中(配置到django的配置文件中), 拼接地址返回即可!
5. 入库(订单, 订单详情): 将user对象存入attrs中, 把订单号存入attrs中, 将pay_url存入self.context中
6. create方法. 先pop出课程列表对象, 存order表. for循环存入课程详情
视图中: Response返回给前端的, 前端只需要一个连接, 那么序列化校验的第五步, 在self.context中将它存入, 将它返回给前端
3) 配置jwt认证
对PayView类进行限制. 使用内置限制(认证 + 权限)
内置认证类: JSONWebTokenAUthentication
内置权限类: isAuthenticated
4) 序列化中让所有的fields中的字段必填. 有默认值的字段, 就不是必填的. required=True
5) 出现错误: 支付宝支付的时候pay_total_amount是一个decimal类型, 需要转换成float类型. (提示: decimal累加可以)
提示: 支付方式目前只写了支付宝的支付方式因此pay_type=1, 3个课程一起买一共138
2. 支付宝异步回调的post接口: 验签, 修改订单状态
3. 当支付宝get回调前端, vue组件一创建, 立马向后端你发一个get请求.(比较绕)
'''
<2>. order/views.py
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import CreateModelMixin
from rest_framework import status
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
import utils
from . import models
from . import serializer
class PayView(CreateModelMixin, GenericViewSet):
# 对PayView类进行限制. 使用内置限制(认证 + 权限)
authentication_classes = [JSONWebTokenAuthentication]
permission_classes = [IsAuthenticated]
queryset = models.Order.objects.all()
serializer_class = serializer.OrderModelSeriailzer
def create(self, request, *args, **kwargs):
# 视图中重写create方法借助self.context传将request对象传给序列化类
serializer = self.get_serializer(data=request.data, context={'request': request})
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
# 视图中: Response返回给前端的, 前端只需要一个连接, 那么序列化校验的第五步, 在self.context中将它存入, 将它返回给前端
return utils.APIResponse(serializer.context['pay_link'], status=status.HTTP_201_CREATED, headers=headers)
<3>. order/serializer.py
import uuid
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from django.conf import settings
from . import models
from libs.alipay_sdk import alipay, alipay_gateway
class OrderModelSeriailzer(serializers.ModelSerializer):
# 可以再局部钩子中把course_list=[1, 2, 3]生成course_list=[obj1, obj2, obj3] 或者使用 PrimayKeyRElatedField
course_list = serializers.PrimaryKeyRelatedField(write_only=True, many=True, queryset=models.Course.objects.all())
class Meta:
model = models.Order
fields = ['subject', 'total_amount', 'pay_type', 'course_list']
extra_kwargs = {
# 序列化中让所有的fields中的字段必填. 有默认值的字段, 就不是必填的. required=True
'total_amount': {'required': True},
'pay_type': {'required': True},
}
@staticmethod
def _verify_amount(attrs):
total_amount = attrs.get('total_amount')
course_list = attrs.get('course_list')
course_amount = 0
for course in course_list:
course_amount += course.price
if course_amount == total_amount:
return total_amount
raise ValidationError("订单总价错误!")
@staticmethod
def _order_number():
return str(uuid.uuid1()).replace('-', '')
def _pay_user(self):
return self.context['request'].user
def _pay_link(self, out_trade_no, total_amount, subject):
# print('total_amount:', total_amount, type(total_amount)) # total_amount: 138.00 <class 'decimal.Decimal'>
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=out_trade_no, # 订单号, 必须唯一
# 支付宝支付的时候pay_total_amount是一个decimal类型, 需要转换成float类型. (提示: decimal累加可以)
# 如果不转换成float那么格式就会抛出异常: Object of type 'Decimal' is not JSON serializable
# total_amount=total_amount, # 总金额
total_amount=float(total_amount), # 总金额
subject=subject, # 订单标题
return_url=settings.RETURN_URL, # 同步回调(支付成功)
notify_url=settings.NOTIFY_URL # 异步回调(订单状态) 可选, 不填则使用默认notify url
)
return alipay_gateway + order_string
def _before_create(self, attrs, out_trade_no, user, pay_link):
attrs['out_trade_no'] = out_trade_no
attrs['user'] = user
self.context['pay_link'] = pay_link
def validate(self, attrs):
"""
1. 校验订单总价格: 获取总价格, 获取课程对象列表从总价格列表中获取每个价格叠加与总价格对比 (注意: 需要返回总价格)
2. 生成订单号: str(uuid).replace('-', '')
3. 获取支付用户: 视图中重写create方法借助self.context传将request对象传给序列化类
4. 生成支付连接: 导入alipay, alipay_gateway. 拷贝, 将post, get2个回调的地址存放到配置文件中(配置到django的配置文件中), 拼接地址返回即可!
5. 入库(订单, 订单详情): 将user对象存入attrs中, 将pay_link存入self.context中
"""
# 1. 校验订单总价格
total_amount = self._verify_amount(attrs)
# 2. 生成订单号
order_number = self._order_number()
# 3. 获取支付用户
user = self._pay_user()
# 4. 生成支付连接
pay_link = self._pay_link(out_trade_no=order_number, total_amount=total_amount, subject=attrs.get('subject'))
# 5. 入库(订单, 订单详情)
self._before_create(attrs=attrs, out_trade_no=order_number, user=user, pay_link=pay_link)
return attrs
def create(self, validated_data):
course_list = validated_data.pop('course_list')
order = models.Order.objects.create(**validated_data)
for course in course_list:
models.OrderDetail.objects.create(course=course, price=course.price, real_price=course.price, order=order)
return order
<4>. settings/dev.py
# 后台基URL
BASE_URL = 'http://139.196.184.91'
# 前台基URL
LUFFY_URL = 'http://139.196.184.91'
# 支付宝同步异步回调接口配置
# 后台异步回调接口
NOTIFY_URL = BASE_URL + "/order/success/"
# 前台同步回调接口,没有 / 结尾
RETURN_URL = LUFFY_URL + "/pay/success"
<5>. luffyapi/urls.py
path('order/',include('order.urls')),
<6>. order/urls.py子路由
from django.urls import path, re_path, include
from . import views
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('pay', views.PayView, 'pay')
urlpatterns = [
path('', include(router.urls)),
]
六、前台-支付生成页面
1. 前端跳转到支付宝支付
<1>. 流程
'''
提示: 一共三个地方都有立即购买操作
1. FreeCourse.vue
1) 定义buy_now()点击触发事件的方法
从this.$cookies中获取token
判断如果没有token那么触发this.$message
发送ajax的post请求, this.$settings.base_url + /order/pay/, headers需要携带认证 Authorization, data需要携带对着数据. 使用另一种用法{}
获取到pay_link, 前端发送get请求
window.open(pay_link, '_self')
2) 付款成功以后需要跳转到/order/success页面, 前端需要success组件. 后端需要success接口
'''
<2>. FreeCoourse.vue
# template
<span class="buy-now" @click="buy_now(course)">立即购买</span>
# script
methods: {
buy_now(course) {
// 获取token, 校验用户是否登录
let token = this.$cookies.get('token');
if (!token) {
this.$message({
message: "请先登录!",
type: 'warning',
});
return false;
}
// 发送axios
this.$axios({
method: 'post',
url: `${this.$settings.base_url}/order/pay/`,
data: {
"subject": course.name,
// "total_amount": 11,
"total_amount": course.price,
"pay_type": 1,
"course_list": [
course.id,
]
},
headers: {
Authorization: `jwt ${this.$cookies.get('token')}`
},
}).then(response => {
console.log(response.data);
if (response.data.code) {
open(response.data.data, '_self');
} else {
this.$message({
message: '订单处理失败!',
type: 'warning',
})
}
}).catch(error => {
this.$message({
message: "未知错误!",
type: 'warning',
})
})
},
...
}
2. 支付成功前端页面
<1>. 流程
'''
1. 新建PaySuccess.vue组件
2. 配置路由 path: '/pay/success'
注意: 回调以后会在你的url地址中, 携带者很多东西
3. 拷贝PaySuccess页面
提示: 页面只有支付宝回调回来才有数据, 直接查看是没有的
4. create里面有一种特殊用法
5. 同步回调参数
trade_no 支付宝的流水号
auth_app_id 商家流水号
app_id 我们的id号
页面需要的参数: 订单号, 交易号, 付款时间
'''
<2>. routere/index.js
import PaySuccess from '../views/PaySuccess.vue'
const routes = [
...
{
path: '/pay/success',
name: 'PaySuccess',
component: PaySuccess
},
];
<3>. 支付宝返回参数
charset=utf-8&
out_trade_no=7f7c7d12d57d45b693e1b49a6b01e1dd& # 自己的订单号
method=alipay.trade.page.pay.return&
total_amount=39.00&
sign=FUmceqiNMWvxcD%2BUPCHiOTaEwlJ%2FXIXL5UwZWOSI1TwRjPIZVzjRLB4j2G5CQpn472JO8X%2BwMx04dHqjLxqLcY3TRu0XurQ%2FwKTNpyfDrtNuNv0rfGPuVHw52y3blbS7%2FKFVsWryw4%2BBuF2fCrJ4qWH8Zg14Rct7qoMbu73N74WkQtDyzXefiKDbkMMRMfLbelE9TFyeIeygeMId8%2B58mcJMUOh6aQqwpr9bzuBbfJ17fkqU%2F0ys9zGr%2FlDtLL7aAh6BPViqZN%2F9T7byCoferD1BhcSzJNR6V6VuhOdTq8iEaH2XgJT9aIiyHgg3GT1taBBvZX2gK41FSmkguk%2BfsA%3D%3D&
trade_no=2020030722001464020500585462& # 支付宝的流水号
auth_app_id=2016093000631831&
version=1.0&
app_id=2016093000631831&
sign_type=RSA2&
seller_id=2088102177958114&
timestamp=2020-03-07%2014%3A47%3A48 # 付款时间
`
// 同步回调没与订单状态
<4>. views/PaySuccess.vue
<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参数
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);
}).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>
七、后台-支付成功的备选接口
1. 流程
'''
优化: 后端序列化中判断用户支付金额是否是0, 是0那么就直接修改订单状态, 也不用发送pay_link了
# 前端: created分析
1. localtion.search就可以获取支付好?号后面的参数获取到(包括问号), 使用.substring(1), 取出左边的?号
2. 使用三元表达式, 对params进行split. 以及后面将这种参数进行处理
3. decodeURICompontent,
4. 把地址栏上面的支付结果, 再get请求发给后端
this.$settings.base_url + '/order/success/' + localtion.search
# 后端
1. 路由: success/ SuccessView
2. 视图: 继承APIView 因为不和序列化类有关系, 和数据库有点关系
# get:
获取前端传递过来的 out_trade_no, 去数据库中查取, 判断订单 order_status 的订单状态是否成功.
最后返回响应中通过code=0或者code=1返回给前端即可
# post: 支付宝回调
回调地址: https://github.com/fzlee/alipay/blob/master/README.zh-hans.md#alipay.fund.trans.toaccount.transfer
回调参数: https://opendocs.alipay.com/open/270/105902/
注意: 必须data内容返回 success
request.data可能有2种情况. 如果是json格式是字典, 如果是QuseryDict需要注意
失败了之后需要记录日志
成功了之后需要记录日志, 并且修改订单状态, 使用 out_trade_no 作为过来标志, order_status 修改为1, 交易支付时间pay_time=gmt_payment
'''
2. 同步理论参数
charset=utf-8&
out_trade_no=7f7c7d12d57d45b693e1b49a6b01e1dd&
method=alipay.trade.page.pay.return&
total_amount=39.00&
sign=FUmceqiNMWvxcD%2BUPCHiOTaEwlJ%2FXIXL5UwZWOSI1TwRjPIZVzjRLB4j2G5CQpn472JO8X%2BwMx04dHqjLxqLcY3TRu0XurQ%2FwKTNpyfDrtNuNv0rfGPuVHw52y3blbS7%2FKFVsWryw4%2BBuF2fCrJ4qWH8Zg14Rct7qoMbu73N74WkQtDyzXefiKDbkMMRMfLbelE9TFyeIeygeMId8%2B58mcJMUOh6aQqwpr9bzuBbfJ17fkqU%2F0ys9zGr%2FlDtLL7aAh6BPViqZN%2F9T7byCoferD1BhcSzJNR6V6VuhOdTq8iEaH2XgJT9aIiyHgg3GT1taBBvZX2gK41FSmkguk%2BfsA%3D%3D&
trade_no=2020030722001464020500585462&
auth_app_id=2016093000631831&
version=1.0&
app_id=2016093000631831&
sign_type=RSA2&
seller_id=2088102177958114&
timestamp=2020-03-07%2014%3A47%3A48
`
// 同步回调没与订单状态
3. order/urls.py
path('success/',views.successView.as_view()),
4. order/views.py
from rest_framework.views import APIView
from libs.alipay_sdk import alipay
class SuccessView(APIView):
def get(self, request, *args, **kwargs):
"""
获取前端传递过来的 out_trade_no, 去数据库中查取, 判断订单 order_status 的订单状态是否成功.
最后返回响应中通过code=0或者code=1返回给前端即可
"""
out_trade_no = request.query_params.get('out_trade_no')
order = models.Order.objects.filter(out_trade_no=out_trade_no).first()
# order.order_status值为1表示订单成功
if order.order_status == 1:
return utils.APIResponse()
return utils.APIResponse(code=0, msg='失败')
def post(self, request, *args, **kwargs):
"""
回调地址: https://github.com/fzlee/alipay/blob/master/README.zh-hans.md#alipay.fund.trans.toaccount.transfer
回调参数: https://opendocs.alipay.com/open/270/105902/
注意: 必须data内容返回 success
request.data可能有2种情况. 如果是json格式是字典, 如果是QuseryDict需要注意
失败了之后需要记录日志
成功了之后需要记录日志, 并且修改订单状态, 使用 out_trade_no 作为过来标志, order_status修改为1, 交易支付时间pay_time=gmt_payment
"""
# request.data类型判断
data = request.data.dict()
utils.log(f'data: {data}')
signature = data.pop("sign")
out_trade_no = data.get('out_trade_no')
gmt_payment = data.get('gmt_payment')
# 校验
success = alipay.verify(data, signature)
if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED"):
# 修改订单状态
models.Order.objects.filter(out_trade_no=out_trade_no).update(order_status=1, pay_time=gmt_payment)
utils.log.info(f'{out_trade_no}订单支付成功!')
# !!!注意!!!: 服务器异步通知页面特性
'''
当商户收到服务器异步通知并打印出 success 时,服务器异步通知参数 notify_id 才会失效。
也就是说在支付宝发送同一条异步通知时(包含商户并未成功打印出 success 导致支付宝重发数次通知),服务器异步通知参数 notify_id 是不变的。
'''
return utils.APIResponse(data='success')
utils.log.error(f'{out_trade_no}订单支付失败!')
return utils.APIResponse(code=0, msg='失败')
八、上线前准备
1. 后端
# pro.py
'''
DEBUG = False
ALLOWED_HOSTS = ["*"] # 服务器的公网IP
# 后台基URL
BASE_URL = 'http://139.196.184.91:8000' # 注意: 这里的8000上线以后指定的nginx的8000端口, 由nginx的8000端口发送到nginx配置内部的uwsgi的端口中
# 前台基URL
LUFFY_URL = 'http://139.196.184.91' # 注意: 这里没有写端口默认就是80端口.
# 支付宝同步异步回调接口配置
# 后台: 支付宝异步回调的接口
NOTIFY_URL = BASE_URL + "/order/success/"
# 前台: 支付宝同步回调接口,没有 / 结尾
RETURN_URL = LUFFY_URL + "/pay/success"
# 注意: 检查mysql配置, 如果mysql配置的HOST是127.0.0.1, 那么需要检查远端服务器上的mysql本地密码是否正确.
'''
# wsgi.py
'''
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffyapi.settings.pro')
'''
# manage.py
'''
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffyapi.settings.dev')
'''
# 拷贝manage.py改名manage_pro.py(在项目根路径)
'''
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffyapi.settings.pro')
'''
2. 前端
# 配置src/assets/js/settings.py文件
export default {
// 注意: 这里的8000的端口是nginx的监听端口
base_url: 'http://139.196.184.91:8000'
}
# 将vue代码打包成html, css, js
cmpn run build