1 下单接口前端
理论
# 1 支付宝支付的前端----》后端下单接口
- 点击按钮----》向后端发送请求,生成订单,返回支付链接
- 加入购物车---》购物车表----》显示购物车---》多选,全选----》下单
- 返回支付链接后,在页面中打开支付链接 open(url地址,"_self")
CourseDetail.vue
// 给按钮增加点击事件
handleGoPay(){
// 1 判断是否登录,
let token= this.$cookies.get('token')
if(token){
this.$axios.post(`${this.$settings.BASE_URL}order/pay/`,{
subject:this.course_info.name,
total_amount:this.course_info.price,
pay_type:1,
courses:[this.course_info.id],
},{
headers:{
Authorization:'jwt '+token
}
}).then(res=>{
if(res.data.code==100){
let pay_url=res.data.pay_url
// 打开这个地址,在当前页面中打开
open(pay_url,'_self')
}else {
this.$message('下单失败')
}
})
}else {
this.$message('您没有登录,请先登录')
}
},
2 支付宝get回调和post回调
# 面试:前端下单成功生成支付链接,前端调了支付宝,后端此时挂了,支付宝向后端发送请求成功不了,怎么办?
# 支付宝会有8次异步回调,此外支付宝还有对账功能去比较订单是否支付成功,用户方面如果得不到回应也会打电话给客服。到时候对账然后手动更改即可。
-get :前端回调回某个地址---》必须是前端---》对应一个页面,写购买成功的显示---》具体是否成功还不一样----》页面加载完成,向后端发送ajax请求,查询该订单是否真正的已支付
-post回调:后端接口---》不能写认证,权限类,地址一定要注意,接口触发成功,必须把项目放在公网上或者使用内网穿透
2.1 前端回调页面
<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() {
// location.search是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请求转发给后端,看后端的订单状态是否更改。有可能get回调了,但是post还没有回调
this.$axios({
url: this.$settings.BASE_URL + 'order/success/' + location.search,
method: 'get',
}).then(response => {
if(response.data.code!=100){
alert('暂时未收到您的付款,请稍后刷新再试')
}
}).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>
2.2 前端回调get请求
class SuccessView(ViewSet):
#要不要加认证类
def get(self, request):
# 我们前端的请求
try:
out_trade_no = request.query_params.get('out_trade_no')
Order.objects.get(out_trade_no=out_trade_no, order_status=1)
return APIResponse()
except Exception as e:
return APIResponse(code=101, msg='订单未支付')
2.3 后端支付宝回调接口
# 因为咱们 地址是 127.0.0.1 ,支付宝回调,只能回调公网地址,调不回我们这,我们收不到支付宝的回调--->解决方案:1 使用公网ip部署项目 2 使用内网穿透
https://zhuanlan.zhihu.com/p/370483324
# 内网穿透
-内网机器,在外网中访问不到,现在能访问到的所有网站,其实都有个公网ip,但是公网ip ipv4数量有限制
-没有公网ip,内网穿透【花生壳、ngrok、frp】
-原理:转发---》支付宝向某个域名(随机生成)把请求发送给花生壳【cs架构软件】----》根据请求知道是哪台内网机器(与域名一一映射),把网络请求发送给你。
参考:https://zhuanlan.zhihu.com/p/370483324
class SuccessView(ViewSet):
# 要不要加认证类,不要,支付宝没有我们的token
def get(self, request):
# 我们前端的请求
try:
out_trade_no = request.query_params.get('out_trade_no')
Order.objects.get(out_trade_no=out_trade_no, order_status=1)
return APIResponse()
except Exception as e:
return APIResponse(code=101, msg='订单未支付')
def post(self, request, *args, **kwargs):
try:
result_data = request.data.dict() # 支付宝发送post请求给我们---》数据携带再请求体中---》urlencoded--》request.data不是字典格式,使用dict做成字典格式
out_trade_no = result_data.get('out_trade_no')
signature = result_data.pop('sign')
from libs.alipay_common import alipay
result = alipay.verify(result_data, signature) # 验签通过表示是支付宝给的,不是别人伪造的
# trade_status 确认订单付款成功了
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')
3 上线前准备
# 后端项目,修改好线上配置文件,把代码推送到git仓库
- DEBUG
- BACKEND_URL
- LUFFY_URL
# 前端项目
-修改前端访问的后端地址
export default {
BASE_URL: 'http://8.130.18.221:8000/api/v1/'
}
-把vue项目编译成 html,css,js
npm run build # 在项目目录下生成dist文件夹,内部就是咱们上线要用的
-把dist文件夹压缩,待命
4 阿里云购买
# 购买一台服务
-项目跑在服务器上
-购买公网ip:别人访问我们的ip,就能访问到我们的项目
-购买域名:备案---》访问域名---》转发到你的ip
# 阿里云,华为云,腾讯云
-按量付费---》冲100块---》买4台
-https://ecs.console.aliyun.com/home
# 下载 finalshell ,远程链接linux服务器的
http://www.hostbuf.com/t/988.html
不下这个软件:打开cmd :ssh [email protected] 输入密码
一堆linux命令
4.1 上线架构图
浏览器写ip地址,不写端口号,默认端口是80
# 远程连接
-ssh 22端口 链接 服务器有ssh的服务端
-命令窗口 ssh 用户名@地址 回车 输入密码 就链接上了
- macOS直接用终端
-Win用ssh的客户端
-xshell收费的(个人,学生免费)
-finalshell【本地安装虚拟机用centos系统,也能连进去】
-填名字,填地址,用户名,密码 ---》永久保存
5 安装git
# 方式一:
yum install git -y
# 方式二:(开发会用的软件)
yum -y groupinstall "Development tools"
# 执行下面这条 依赖文件
yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel -y
6 安装mysql
# mysql 5.7
# 前往用户根目录
cd ~
# 下载mysql57
wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
# 安装mysql57
yum -y install mysql57-community-release-el7-10.noarch.rpm
yum install mysql-community-server --nogpgcheck -y
# 启动mysql57并查看启动状态
systemctl start mysqld
systemctl status mysqld
# 查看默认密码并登录
grep "password" /var/log/mysqld.log # U>bjULStm1Q<
mysql -uroot -p
# 修改密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Yma12345?';
# 参考:https://zhuanlan.zhihu.com/p/616550551
7 安装redis
###### 官方下载编译好的reids
# 下载
wget https://packages.redis.io/redis-stack/redis-stack-server-6.2.6-v7.rhel7.x86_64.tar.gz
# 解压
tar -xf redis-stack-server-6.2.6-v7.rhel7.x86_64.tar.gz
# 重命名
mv redis-stack-server-6.2.6-v7/ redis
# 启动
cd redis/bin
./redis-server # 启动redis,使用默认配置启动的
# 在任意路径下敲redis-server都能把服务运行,
-方式一:把bin路径加入到环境变量
-方式二:使用软连接, /usr/bin/ 本身在环境变量 ,在任意路径敲redis-server redis-cli都能找到
ln -s /root/redis/bin/redis-server /usr/bin/redis-server
ln -s /root/redis/bin/redis-cli /usr/bin/redis-cli
# 查看是否创建软连接成功
ls |grep redis
ls -al |grep redis
# 启动redis服务,后台运行
redis-server &
###### 源码安装----》
# 下载redis-6.2.6
wget http://download.redis.io/releases/redis-6.2.6.tar.gz
# 解压安装包
tar -xf redis-6.2.6.tar.gz
# 进入目标文件
cd redis-6.2.6
# 编译环境 gcc 在src路径下把源码编译出 redis-cli reidis-server
make
# 复制环境到指定路径完成安装
cp -r ~/redis-6.2.6 /usr/local/redis
# 配置redis可以后台启动:修改下方内容
vim /usr/local/redis/redis.conf
daemonize yes
# 完成配置修改
>: esc
>: :wq
# 建立软连接
ln -s /usr/local/redis/src/redis-server /usr/bin/redis-server1
ln -s /usr/local/redis/src/redis-cli /usr/bin/redis-cli1
# 后台运行redis
cd /usr/local/redis
redis-server1 ./redis.conf
# 测试redis环境
redis-cli
# 关闭redis服务
pkill -f redis -9
redis-cli shutdown
8 安装python
# 可以使用yum安装,不能指定版本
# 源码安装,下载指定版本的源码,编译安装
# 所有linxu和mac,都自带python2:系统服务,是用python写的
# 阿里云的centos默认装了python3.6.8
# python2.7 python3.6.8 python3.9
# 1 源码安装python,依赖一些第三方zlib* libffi-devel
yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel zlib* libffi-devel -y
# 1 前往用户根目录
cd ~
# 2 下载 或 上传 Python3.8.6 服务器终端
# https://registry.npmmirror.com/binary.html?path=python/
wget https://registry.npmmirror.com/-/binary/python/3.9.10/Python-3.9.10.tgz
#3 解压安装包
tar -xf Python-3.9.10.tgz
#4 进入目标文件
cd Python-3.9.10
#5 配置安装路径:/usr/local/python3
# 把python3.9.10 编译安装到/usr/local/python38路径下
./configure --prefix=/usr/local/python39
#6 编译并安装,如果报错,说明缺依赖
yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel zlib* libffi-devel -y
make && make install
#7 建立软连接:/usr/local/python38路径不在环境变量,终端命令 python3,pip3
ln -s /usr/local/python39/bin/python3 /usr/bin/python3.9
ln -s /usr/local/python39/bin/pip3 /usr/bin/pip3.9
# 机器上有多个python和pip命令,对应关系如下
python 2.x pip
python3 3.6 pip3
python3.9 3.9 pip3.9
#8 删除安装包与文件:
rm -rf Python-3.9.10
rm -rf Python-3.9.10.tar.xz
9安装虚拟环境
1)安装依赖
pip3.9 install virtualenv
# python3.9 -m pip install --upgrade pip
# python3.9 -m pip install --upgrade setuptools
# pip3.9 install pbr
pip3.9 install virtualenvwrapper
2)建立虚拟环境软连接
ln -s /usr/local/python39/bin/virtualenv /usr/bin/virtualenv
3)配置虚拟环境:填入下方内容
# ~/ 表示用户家路径:root用户,就是在/root/.bash_profile
vi ~/.bash_profile
# 按 a
# 光标上下控制,粘贴上下面内容
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3.9
# 在使用virtualenvwrapper时,将使用Python 3.9版本作为创建虚拟环境的基础解释器
source /usr/local/python39/bin/virtualenvwrapper.sh
# 这是一个命令,用于加载virtualenvwrapper.sh脚本文件
# 退出编辑状态
esc
# 保存修改并退出
>: :wq
# 更新配置文件内容
source ~/.bash_profile
# 虚拟环境默认根目录:
/root/.virtualenvs
# 创建虚拟环境
mkvirtualenv -p python3.9 luffy
10 安装uwsgi
# django 项目上线需要使用uwsgi这个web服务器运行django项目,安装这个web服务器
# 使用uwsgi运行django,不再使用测试阶段的wsgiref来运行django了
# uwsgi是符合wsgi协议的web服务器,使用c写的性能高,上线要使用uwsgi
# 安装步骤
1)在真实环境下安装
pip3.9 install uwsgi
#安装到了python39的安装路径的bin路径下了
2)建立软连接
ln -s /usr/local/python39/bin/uwsgi /usr/bin/uwsgi
# 虚拟环境也要安装
pip install uwsgi
11 安装nginx
# 反向代理服务器
- 做请求转发
- 静态资源代理
- 负载均衡
# 可以用yum install装,但是需要配扩展源,不能控制版本。
# 前往用户根目录
cd ~
# 下载nginx1.13.7
wget http://nginx.org/download/nginx-1.13.7.tar.gz
# 解压安装包
tar -xf nginx-1.13.7.tar.gz
# 进入目标文件
cd nginx-1.13.7
# 配置安装路径:/usr/local/nginx
./configure --prefix=/usr/local/nginx
# 编译并安装,2个命令合二为一
make && make install
# 建立软连接:终端命令 nginx
ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
# 删除安装包与文件:
cd ~
rm -rf nginx-1.13.7
rm -rf nginx-1.13.7.tar.xz
# 测试Nginx环境,服务器运行nginx,本地访问服务器ip
nginx # 启动nginx服务,监听80端口----》公网ip 80 端口就能看到页面了
服务器绑定的域名 或 ip:80
# 静态文件放的路径
/usr/local/nginx/html
# 查看进程
ps aux | grep nginx
12 部署前端项目
# dist.zip 文件,在本地,上传到远程服务器
# 在远程服务器上
yum install lrzsz -y # 跟本地机器上传下载的软件
yum install unzip -y #解压zip软件
# 在远程服务器上
rz # 打开你本地的目录,选中dist.zip 上传到远端
如果行不通的话就
# 本地终端上传
scp -r /Users/PRO5/luffy_city/dist.zip [email protected]:~
# 解压
unzip dist.zip
# 移动文件 /home/html 下面有咱们的前端静态文件
mv /root/dist /home/html
# 配置nginx 静态代理
cd /usr/local/nginx/conf # nginx.conf 配置文件
mv nginx.conf nginx.conf.bak
vi nginx.conf
# 按 a 粘贴下面代码
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 80;
server_name 127.0.0.1;
charset utf-8;
location / {
root /home/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}
}
# 按 esc :wq 回车
# 重启nginx
nginx -s reload
13 部署后台项目
# 本地####
# 1 prod.py 配置文件搞好,上午搞了
# 2 修改项目中wsgi.py,asgi.py 用uwsgi运行wsgi.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy_api.settings.prod')
# 3 导出项目依赖
pip3 freeze > requirements.txt
#4 推到远端
### 远程服务器
# 1 拉取项目,安装模块
mkdir /home/project
cd /home/project
git clone https://gitee.com/yeah-xiufeng/luffy_api.git
进入到虚拟环境
workon luffy
cd /home/project/luffy_api
pip install -r requirements.txt # 可能会出错 mysqlclient装不上,先注释,装上能装上的,再单独装mysqlclient
yum install python3-devel -y
yum install mysql-devel --nogpgcheck -y
pip install mysqlclient
# 2 虚拟环境中也要安装uwsgi
pip install uwsgi
# 3 配置数据库
mysql -uroot -p
#创建数据库
create database luffy default charset=utf8;
#设置权限账号密码:账号密码要与项目中配置的一致
grant all privileges on luffy.* to 'luffy'@'%' identified by 'Luffy123?';
grant all privileges on luffy.* to 'luffy'@'localhost' identified by 'Luffy123?';
flush privileges;
#退出mysql
quit;
# 使用本地navicate链接阿里云的luffy库,使用luffy用户
# 4 迁移表
# 把项目中得迁移文件删除,提交,远程
python manage_prod.py makemigrations
python manage_prod.py migrate
# 5 uwsgi 运行django
-写一个uwsgi的配置文件,在项目路径下,新建一个 luffy_api.xml
<uwsgi>
<socket>127.0.0.1:8888</socket>
<chdir>/home/project/luffy_api/</chdir>
<module>luffy_api.wsgi</module>
<processes>4</processes>
<daemonize>uwsgi.log</daemonize>
</uwsgi>
-使用uwsgi启动
uwsgi -x luffy_api.xml
-查看是否正常运行
ps aux |grep uwsgi
# 6 配置nginx转发
cd /usr/local/nginx/conf
vi nginx.conf
# 新增的server
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8888;
uwsgi_param UWSGI_SCRIPT luffy_api.wsgi;
uwsgi_param UWSGI_CHDIR /home/project/luffy_api/;
}
}
# 重启nginx
nginx -s reload
# 7 导入数据
工具--数据同步
# 8 配置域名解析
得备案
13.1 配置后台admin访问
# 1 浏览器访问http://8.130.18.221:8000/admin 发现没有样式
# 因为uwsgi不能给我们代理静态资源---->DEBUG=False
# 收集静态资源,使用nginx代理
# prod.py中加入
STATIC_ROOT = '/home/project/luffy_api/luffy_api/static/'
# 执行命令
# 进入虚拟环境,创建文件夹,收集静态文件
mkdir /home/project/luffy_api/luffy_api/static
python manage_prod.py collectstatic
# 修改nginx配置文件
# 新增的配置静态文件
server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8888;
uwsgi_param UWSGI_SCRIPT luffy_api.wsgi;
uwsgi_param UWSGI_CHDIR /home/project/luffy_api/;
}
location /static {
alias /home/project/luffy_api/luffy_api/static;
}
}
安全组
# 买的阿里云机器80 端口开放的
# 但是,3306,6379 8000端口可能没打开,6379不要打开,反正在内网使用,打开有风险,没有密码,端口还是3306
# 不打开安全组的端口,是访问不进来的
重装系统
# 先关机
# 更换操作系统
# 重启后mysql、redis要重新启动
标签:上线,15,nginx,redis,devel,路飞,usr,luffy,uwsgi
From: https://www.cnblogs.com/10086upup/p/17533824.html