Fetch the repository succeeded.
略...
略...
$ git init
# 全局,以后都可以使用同一个配置
$ git config --global user.name 昵称
$ git config --global user.email 邮箱地址
# 命令的使用方式
$ git remote add 别名 远程地址 # 给远程仓库起别名
$ git remote rename [现在的仓库名] [新的仓库名] # 重命名远程仓库名
$ git remote rm [远程仓库名] # 删除远程仓库名
$ git remote -v # 查看当前所有远程地址别名
# 下面是具体实现
$ git remote add giteeware git@gitee.com:zhouyu2156/geek-digit-mall.git
$ git remote -v # 可以查看一下当前设置好的仓库地址的别名
$ git add .
$ git commit -m "提交信息(比如:本次完成了什么开发工作)"
$ git pull giteeware master # 拉取远程仓库代码
$ git push giteeware master # 再推送之前会自动将拉取的代码与本地提交的代码进行合并,然后推送到远程仓库,如果多个人修改了同一文件的同一个位置,会进行确认是否修改,此时可以小组内讨论是否要解决该冲突,避免项目内的配置被修改后失效
import json
import random
import time
from django.http import HttpResponse
from lxml import etree
from selenium import webdriver
from constant import script
def get_recommend_goods_list(request):
""":description 爬取淘宝首页推荐数据使用"""
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
browser.execute_script(script)
# 获取淘宝推荐链接返回给前端
# 推荐商品基础 xpath: //a[@class="item-link"]
time.sleep(3)
# 获取网页源码
tree = etree.HTML(browser.page_source)
# 获取内容
goods_base_link_list = tree.xpath("//div[@class='tb-recommend-content-item']/a[@class='item-link']/@href")[:30]
# 将商品链接拼接成完整链接
goods_link_list = ['https:' + item for item in goods_base_link_list]
# 商品图片地址列表
goods_base_img_url_list = tree.xpath('//a[@class="item-link"]/div[@class="img-wrapper"]/img/@src')[:30]
goods_img_url_list = ['https:' + item for item in goods_base_img_url_list]
# 商品标题列表
goods_title_list = tree.xpath('//a[@class="item-link"]/div[@class="info-wrapper"]/div[@class="title"]/text()')[:30]
# 商品价格列表
goods_base_price_list = tree.xpath(
'//a[@class="item-link"]/div[@class="price-wrapper"]/span[@class="price-value"]/text()')[:30]
goods_price_list = [float(item) for item in goods_base_price_list]
taobao = []
for i in range(30):
obj = {
'id': i,
'url': goods_link_list[i],
'title': goods_title_list[i],
'img_url': goods_img_url_list[i],
'price': goods_price_list[i]
}
taobao.append(obj)
with open('../taobao.json', 'w', encoding='utf-8') as f:
f.write(json.dumps({'taobao': taobao}, ensure_ascii=False, indent=2))
browser.close()
browser.quit()
return HttpResponse(json.dumps(taobao))
import json
import random
import time
from django.http import HttpResponse
from lxml import etree
from selenium import webdriver
from constant import script
def get_category_goods_list(request):
kw = request.GET.get('kw')
# 获取分类总数
SUM = 30
browser = webdriver.Chrome()
browser.get(f'https://s.taobao.com/search?q={kw}')
# 找到分类标签、点击
# btn = browser.find_element(by=By.XPATH, value='//li[contains(@class,"J_Cat")]/a[contains(text(),"手机")]')
# btn.click()
browser.execute_script(script)
time.sleep(5)
tree = etree.HTML(browser.page_source)
# 商品链接
goods_url_list = tree.xpath(
'//div[contains(@class,"LeftLay--leftContent")]//a[contains(@class,"Card--doubleCardWrapper")]/@href')[:SUM]
# 商品图片链接
goods_img_url_list = tree.xpath('//div[contains(@class,"MainPic--mainPicWrapper")]/img/@src')[:SUM]
# 商品标题列表
goods_base_title_list = tree.xpath(
'//div[contains(@class,"LeftLay--leftContent")]//div[contains(@class,"Title--title")]//span//text()')[:SUM]
goods_title_list = []
# 拼接标题字符串
for item in goods_base_title_list:
tmp = ''
for segment in item:
tmp += segment
goods_title_list.append(tmp)
# 整数价格列表
goods_int_price_list = tree.xpath(
'//div[contains(@class,"Price--priceWrapper")]/span[contains(@class,"Price--priceInt")]//text()')[:SUM]
# 小数部分价格列表
goods_float_price_list = tree.xpath(
'//div[contains(@class,"Price--priceWrapper")]/span[contains(@class,"Price--priceFloat")]//text()')[:SUM]
# 商品购买实情
# goods_sold_count_list = tree.xpath('//div[contains(@class,"LeftLay--leftContent")]//span[contains(@class,"Price--realSales")]/text()')[:SUM]
# 店铺列表
shop_name_list = tree.xpath('//div[contains(@class,"ShopInfo--shopInfo")]//a/text()')[:SUM]
categories = []
for index in range(SUM):
obj = {
'id': index,
'url': goods_url_list[index],
'img_url': goods_img_url_list[index],
'title': goods_title_list[index],
'price': goods_int_price_list[index] + goods_float_price_list[index],
'shop_name': shop_name_list[index],
'sold_count': str(random.randint(0, 500)) + '+人付款'
}
categories.append(obj)
with open(f'{kw}.json', 'w', encoding='utf-8') as fp:
fp.write(json.dumps(categories, ensure_ascii=False, indent=2))
browser.close()
browser.quit()
return HttpResponse(json.dumps(categories))
Django字段属性设置:参考博客
信息 | 字段 | 类型 | 默认值 | 主键 | 外键 |
---|---|---|---|---|---|
用户ID | id | int | 自增 | Yes | |
邮箱 | varchar(16) | not null | unique | ||
密码 | password | varchar(32) | not null | ||
昵称 | nickname | varchar(16) | null | ||
性别 | sex | char(2) | 1 | ||
电话 | phone | char(11) | unique | ||
地址 | address | varchar(64) | |||
余额 | balance | int | |||
登录状态 | status | int | 0未登录,1登陆(默认0) |
信息 | 字段 | 类型 | 默认值 | 主键 | 外键 |
---|---|---|---|---|---|
商品ID | id | int | 自增 | Yes | |
商品标题 | title | varchar(256) | 必填 | ||
商品单价 | price | int | 必填 | ||
商品描述 | desc | text | 必填 | ||
商品库存数量 | total | int | 必填 | ||
商品链接 | url | varchar(256) | 必填 | ||
商品主图 | img_url | varchar(256) | 必填 | ||
商品轮播图1 | url1 | varchar(256) | |||
商品轮播图2 | url2 | varchar(256) | |||
商品轮播图3 | url3 | varchar(256) | |||
商家 | shop_name | varchar(256) | 必填 | ||
真实销售量 | sold_count | varchar(256) | |||
分类 | category | varchar(16) | 必填 | 暂不创建分类表 | |
在售状态 | status | int | 1在售,0下架(默认1) |
信息 | 字段 | 类型 | 默认值 | 主键 | 外键 |
---|---|---|---|---|---|
订单ID | id | int | 自增 | Yes | |
商品编号 | no | varchar(32) | unique | ||
商品ID | goods | int | |||
用户email | user | varchar(16) | |||
商品名称 | goods_name | varchar(32) | |||
用户名 | user_name | varchar(16) | |||
商品图片 | goods_url | varchar(256) | |||
商品单价 | goods_price | int | |||
商品数量 | goods_count | int | |||
邮寄地址 | post_address | varchar(64) | |||
物流信息 | logistics | varchar(256) | |||
收货状态 | status | int | 0未收货,1收货(刚开始创建时默认0) |
mall
功能 | 路径 | 请求方式 | 参数 | 响应 |
---|---|---|---|---|
获取淘宝最新推荐商品数据 | get_recommend_goods_list/ | GET | None | {"categories": [{ "id": 0, "url": "", "img_url": "", "title": "", "price": "", "shop_name": "", "sold_count": "" }]} |
获取本地存储的淘宝推荐商品数据 | get_local_taobao_recommend/ | GET | None | ... |
获取最新分类商品数据 | get_category_goods_list/ | GET | ?kw='手机' | '数码' | ... |
获取本地存储的分类商品数据 | get_local_category_goods_list/ | GET | ?kw='手机' | '数码' | ... |
user
功能 | 路径 | 请求方式 | 参数 | 响应 |
---|---|---|---|---|
获取验证码 | /user/send_verify/ | POST | verify_code | {'status': 200,'msg': '', verify_code: ''} |
用户注册 | /user/register/ | POST | email, password | {'status': 200,'msg': '', email: '', password: ''} |
用户登录 | /user/login/ | POST | email, password | {'status': 200,'msg': '', email: '', password: ''} |
用户退出 | /user/logout/ | GET | {'status': 200,'msg': ''} | |
用户更新个人信息 | /user/update/ | POST | email, password | {'status': 200,'msg': '', 'profile': {...}} |
goods
功能 | 路径 | 请求方式 | 参数 | 响应 |
---|---|---|---|---|
获取商品详情数据 | /goods/get_goods_detail/ | POST | link: 淘宝商品链接 | { 'details': { 'img_url': '', 'title': '', 'price': '' }} |
用户购买商品 | /googds/buy/ | POST | goods_id | {'status': '', } |
下架商品 | /goods/remove/ | DELETE | goods_id | |
修改商品数据 | /goods/update/ | DELETE | goods_id, 新数据 |
order
功能 | 路径 | 请求方式 | 参数 | 响应 |
---|---|---|---|---|
订单获取 | /order/get/ | GET | 订单对象的完整数据 | |
订单生成 | /order/create/ | POST | email, goods_id, goods_name, post_address, count | {'status': 200, 'msg': '下单成功'} |
订单删除 | /order/delete/ | DELETE | email, order_id, | {'status': 200, 'msg': '取消订单成功'} |
修改订单邮寄地址 | /order/post/ | PUT | email, order_id, post_address | {'status': 200, 'msg': '地址修改成功', 'post_address': '新地址'} |
Vue3
+ VueRouter
+ Vite
+ Pinia
+ ElementPlus
+ TypeScript
+ Axios
Django
+ MySQL
+ 爬虫(selenium + xpath)
+ Restful
# 1、创建项目
$ pip install django # 下载django
$ django-admin startproject mall # 创建后端工程开发环境
# 2、创建虚拟环境
$ cd mall
$ pip install virtualenv # 下载虚拟环境创建工具
$ virtualenv venv # 创建虚拟环境
$ cd ./venv/Scripts
$ activate # window上需要先进入该目录才能激活虚拟环境
$ cd ../.. # 返回到后端项目根目录下
# 3、创建应用模块并配置路由、注册应用
$ python manage.py startapp user # 分别对各个模块配置路由和注册应用
$ python manage.py startapp goods
$ python manage.py startapp order
# 设置 PyCharm 解释器为虚拟环境的解释器,后续依赖都使用该虚拟环境
# 记录项目使用的依赖包及版本号
$ pip freeze > requirements.txt # 项目完成,将项目所需依赖包及版本号记录到 requirements.txt 文件中
$ pip install -r requirements.txt # 下载项目依赖记录文件中的所有第三方包
# 注意:如果下载有问题,可以尝试配置下载镜像源 或者 将 requirements.txt 中的版本号去掉,让工具自动选择合适的包下载
$ npm create vue@latest
# ... 配置前端工程开发环境
$ mysqladmin -uroot -p 旧密码 password 新密码 # 修改数据库密码
$ mysql -uroot -p 数据库密码 # 登录 mysql 数据库
$ create database mall character set utf8mb4; # 创建数据库并设置编码格式
写入数据到数据库的脚本如下:
import json
from goods.models import Goods
def main():
offset = 0 # 在生成数据时,将偏移量依次设置为 30、60
# 将下面json文件依次改为 db 目录下的json文件名进行运行
with open("手机.json", 'r', encoding='utf-8') as fp:
recommend_goods_list = json.load(fp=fp)
print(item for item in recommend_goods_list)
for index in range(30):
item = recommend_goods_list[index]
Goods.objects.create(**{
'id': item.get('id') + offset,
'img_url': item.get('img_url'),
'url': item.get('url'),
'title': item.get('title'),
'price': item.get('price'),
'shop_name': item.get('shop_name'),
'sold_count': item.get('sold_count'),
'total': 400,
'category': '手机'
})
print("添加完成\n")
print("数据添加完成...")
在项目根路径下,打开终端输入下面的命令进入
django
的 shell 交互界面,执行以上的脚本:
$ python manage.py shell
$ from db.scripts import main # 导入写好的脚本
$ main() # 执行脚本
$ python manage.py makemigrations # 生成数据库变更迁移文件
$ python manage.py migrate # 执行数据库迁移
$ python manage.py runserver # 在网页上访问,或者下载 Postman 工具来测试自己写的接口,很容易上手的,在b站看个相关的入门视频
访问对应的请求 url 即可自动爬取并返回数据
########################### spider > spider.py
import json
import random
import time
from django.http import HttpResponse
from lxml import etree
from selenium import webdriver
from constant import script
def get_recommend_goods_list(request):
""":description 爬取淘宝首页推荐数据使用"""
browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
browser.execute_script(script)
# 获取淘宝推荐链接返回给前端
# 推荐商品基础 xpath: //a[@class="item-link"]
time.sleep(3)
# 获取网页源码
tree = etree.HTML(browser.page_source)
# 获取内容
goods_base_link_list = tree.xpath("//div[@class='tb-recommend-content-item']/a[@class='item-link']/@href")[:30]
# 将商品链接拼接成完整链接
goods_link_list = ['https:' + item for item in goods_base_link_list]
# 商品图片地址列表
goods_base_img_url_list = tree.xpath('//a[@class="item-link"]/div[@class="img-wrapper"]/img/@src')[:30]
goods_img_url_list = ['https:' + item for item in goods_base_img_url_list]
# 商品标题列表
goods_title_list = tree.xpath('//a[@class="item-link"]/div[@class="info-wrapper"]/div[@class="title"]/text()')[:30]
# 商品价格列表
goods_base_price_list = tree.xpath(
'//a[@class="item-link"]/div[@class="price-wrapper"]/span[@class="price-value"]/text()')[:30]
goods_price_list = [float(item) for item in goods_base_price_list]
taobao = []
for i in range(30):
obj = {
'id': i,
'url': goods_link_list[i],
'title': goods_title_list[i],
'img_url': goods_img_url_list[i],
'price': goods_price_list[i]
}
taobao.append(obj)
with open('../taobao.json', 'w', encoding='utf-8') as f:
f.write(json.dumps({'taobao': taobao}, ensure_ascii=False, indent=2))
browser.close()
browser.quit()
return HttpResponse(json.dumps(taobao))
def get_category_goods_list(request):
kw = request.GET.get('kw')
# 获取分类总数
SUM = 30
browser = webdriver.Chrome()
browser.get(f'https://s.taobao.com/search?q={kw}')
# 找到分类标签、点击
# btn = browser.find_element(by=By.XPATH, value='//li[contains(@class,"J_Cat")]/a[contains(text(),"手机")]')
# btn.click()
browser.execute_script(script)
time.sleep(5)
tree = etree.HTML(browser.page_source)
# 商品链接
goods_url_list = tree.xpath(
'//div[contains(@class,"LeftLay--leftContent")]//a[contains(@class,"Card--doubleCardWrapper")]/@href')[:SUM]
# 商品图片链接
goods_img_url_list = tree.xpath('//div[contains(@class,"MainPic--mainPicWrapper")]/img/@src')[:SUM]
# 商品标题列表
goods_base_title_list = tree.xpath(
'//div[contains(@class,"LeftLay--leftContent")]//div[contains(@class,"Title--title")]//span//text()')[:SUM]
goods_title_list = []
# 拼接标题字符串
for item in goods_base_title_list:
tmp = ''
for segment in item:
tmp += segment
goods_title_list.append(tmp)
# 整数价格列表
goods_int_price_list = tree.xpath(
'//div[contains(@class,"Price--priceWrapper")]/span[contains(@class,"Price--priceInt")]//text()')[:SUM]
# 小数部分价格列表
goods_float_price_list = tree.xpath(
'//div[contains(@class,"Price--priceWrapper")]/span[contains(@class,"Price--priceFloat")]//text()')[:SUM]
# 商品购买实情
# goods_sold_count_list = tree.xpath('//div[contains(@class,"LeftLay--leftContent")]//span[contains(@class,"Price--realSales")]/text()')[:SUM]
# 店铺列表
shop_name_list = tree.xpath('//div[contains(@class,"ShopInfo--shopInfo")]//a/text()')[:SUM]
categories = []
for index in range(SUM):
obj = {
'id': index,
'url': goods_url_list[index],
'img_url': goods_img_url_list[index],
'title': goods_title_list[index],
'price': goods_int_price_list[index] + goods_float_price_list[index],
'shop_name': shop_name_list[index],
'sold_count': str(random.randint(0, 500)) + '+人付款'
}
categories.append(obj)
with open(f'{kw}.json', 'w', encoding='utf-8') as fp:
fp.write(json.dumps(categories, ensure_ascii=False, indent=2))
browser.close()
browser.quit()
return HttpResponse(json.dumps(categories))
流程: 定义模型 -> 配置路由 -> 编写视图 -> 测试完善
# 代码粘贴到这里来
########################### models.py
from django.db import models
# 这里编写你的模型.
class User(models.Model):
# verbose_name 是该字段的注释信息、null表示该字段是否可以为空
id = models.AutoField(auto_created=True, primary_key=True, verbose_name="用户ID")
email = models.CharField(max_length=16, unique=True, null=False, verbose_name="用户邮箱")
password = models.CharField(max_length=32, null=False, verbose_name="用户密码")
nickname = models.CharField(max_length=16, null=True, blank=True, verbose_name="用户昵称")
sex = models.SmallIntegerField(default=1, verbose_name="用户性别")
phone = models.CharField(max_length=11, verbose_name="用户手机号")
address = models.CharField(max_length=50, verbose_name="用户居住地址")
create_date = models.DateTimeField(auto_now=True)
balance = models.IntegerField(default=1000, verbose_name="钱包余额")
status = models.SmallIntegerField(default=0, verbose_name="用户登录状态")
def __str__(self):
return f"<User {self.nickname}>"
class Meta:
db_table = 'user'
注意事项:每次编写完模型后要执行数据库迁移,下面两步都要执行,不要忘记了~~~不然不会生效...
$ python manage.py makemigrations # 生成数据库迁移文件
$ python manage.py migrate # 执行迁移数据库
流程: 定义模型 -> 配置路由 -> 编写视图 -> 测试完善
# 代码粘贴到这里来
########################### models.py 代码
from django.db import models
import uuid
# 这里编写你的模型.
class Goods(models.Model):
"""描述: 填写数据时, 尽量将全部字段填上, 这些字段都很重要, 前端展示需要"""
id = models.UUIDField(max_length=32, default=uuid.uuid4, primary_key=True, auto_created=True, verbose_name="商品ID")
title = models.CharField(max_length=32, verbose_name="商品标题")
price = models.IntegerField(null=False, verbose_name="商品价格")
desc = models.CharField(max_length=256, verbose_name="商品描述")
total = models.IntegerField(null=False, default=100, verbose_name="商品库存数量")
url = models.CharField(max_length=256, null=False, verbose_name="商品主图链接")
url1 = models.CharField(max_length=256, verbose_name="商品轮播图链接1")
url2 = models.CharField(max_length=256, verbose_name="商品轮播图链接2")
url3 = models.CharField(max_length=256, verbose_name="商品轮播图链接3")
business = models.CharField(max_length=256, null=False, verbose_name="商家")
category = models.CharField(max_length=16, null=False)
status = models.SmallIntegerField(default=1)
class Meta:
db_table = 'goods'
注意事项:每次编写完模型后要执行数据库迁移,下面两步都要执行,不要忘记了~~~不然不会生效...
$ python manage.py makemigrations # 生成数据库迁移文件
$ python manage.py migrate # 执行迁移数据库
流程: 定义模型 -> 配置路由 -> 编写视图 -> 测试完善
# 代码粘贴到这里来
########################### models.py 代码
from django.db import models
from user.models import User
from goods.models import Goods
# 在这里编写你的模型.
class Order(models.Model):
id = models.IntegerField(auto_created=True, primary_key=True, verbose_name="订单ID")
goods_id = models.ForeignKey(Goods, max_length=32, on_delete=models.CASCADE, verbose_name="商品ID")
user_email = models.ForeignKey(User, on_delete=models.CASCADE, max_length=16, verbose_name="用户邮箱")
goods_title = models.CharField(max_length=32, verbose_name="商品标题")
user_name = models.CharField(max_length=16, verbose_name="下单用户")
goods_url = models.CharField(max_length=256, verbose_name="商品主图链接")
goods_price = models.IntegerField(null=False, verbose_name="商品单价")
goods_count = models.IntegerField(default=1000, verbose_name="订单数量")
post_address = models.CharField(max_length=50, verbose_name="邮寄地址")
logistics = models.CharField(max_length=256, verbose_name="物流信息")
status = models.IntegerField(default=0, verbose_name="收货状态")
class Meta:
db_table = 'order'
class Membership(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
order = models.ForeignKey(Order, on_delete=models.CASCADE)
注意事项:每次编写完模型后要执行数据库迁移,下面两步都要执行,不要忘记了~~~不然不会生效...
$ python manage.py makemigrations # 生成数据库迁移文件
$ python manage.py migrate # 执行迁移数据库
# 发送邮件的服务配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com' # SMTP地址 例如: smtp.163.com
EMAIL_PORT = 25 # SMTP端口 例如: 25
EMAIL_USE_TLS = True # 与SMTP服务器通信时,是否启动TLS链接(安全链接)。默认是false
DEFAULT_FROM_EMAIL = "1043744584@qq.com" # 默认发信人
EMAIL_HOST_USER = '1043744584@qq.com' # 发件人邮箱
EMAIL_HOST_PASSWORD = 'dpssxjabyofebcef' # 邮箱授权码
EMAIL_FROM = '1043744584@qq.com' # 发件人邮箱
EMAIL_SUBJECT_PREFIX = u'django' # 为邮件Subject-line前缀,默认是'[django]'
@require_http_methods(["POST"]) # 限制只接收 POST 请求
def send_verify_code(request):
# 一、前端数据提交的方式好几种, 所以后端需要捋清楚怎么提取前端发送来的数据
# (1) 若 "Content-Type": "application/json"
# 通过 json.loads(request.body.decode('utf-8')) 前端提交的json数据转化为python的字典对象
# (2) 若 "Content-Type": "x-www-form-urlencoded"
# email = request.POST['email'] 数据存放在POST对象里
# 测试(1):第一种方式获取前端提交 json 格式的数据
# request.body 是字节类型的字符串, 需要解码处理为 'utf-8' 的编码数据
json_data = json.loads(request.body.decode('utf-8'))
print(json_data)
# 测试(2):
print(request.POST)
# 因为我的前端设置的"Content-Type": "application/json" 所以数据在 body 身上, 反之, django会将前端表单提交的数据存放在 request.POST 对象上
# 所以获取前端发送来的邮箱数据如下
whose_email = json.loads(request.body.decode('utf-8')).get('email')
print(whose_email)
# 二、开始生成随机验证码字符
string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
# 生成4随机验证码
verify_code = ''
for i in range(4):
char = string[random.randint(0, 62)]
verify_code += char
print("生成的验证码是: ", verify_code)
# 定义发送内容
subject = '极客数码商城网站注册验证码' # 邮件标题
message = f'你的验证码是: {verify_code}' # 邮件内容
email_to = whose_email # 收件人
send_status = None
try:
send_status = send_mail(
subject=subject,
message=message,
from_email=EMAIL_FROM,
recipient_list=[email_to], # 可以批量定义接收人邮箱
)
print("发送状态: ", send_status) # 1表示成功, 0表示失败
finally:
if send_status:
return JsonResponse({'status': 200, 'msg': '验证码发送成功!'})
else:
return JsonResponse({'status': 400, 'msg': '验证码发送失败!'})
注意事项:使用的时候记得将邮箱改成自己的QQ邮箱,用其他类型的邮箱发送验证码的步骤也是大同小异,可以参考网上资料或者向人工智能GPT提问。
推荐:参考博客
1、配置公钥和私钥
2、下载 SDK
$ pip3 install python-alipay-sdk --upgrade -i https://pypi.douban.com/simple/
3、配置
# 支付宝支付相关配置
ALIPAY_SETTING = {
'ALIPAY_APP_ID': "9021000133647342", # 应用ID(上线之后需要改成,真实应用的appid)
'APLIPAY_APP_NOTIFY_URL': None, # 应用回调地址[支付成功以后,支付宝返回结果到哪一个地址下面] 一般这里不写,用下面的回调网址即可
'ALIPAY_DEBUG': False,
# APIPAY_GATEWAY="https://openapi.alipay.com/gateway.do" # 真实网关
'APIPAY_GATEWAY': "https://openapi.alipaydev.com/gateway.do", # 沙盒环境的网关(上线需要进行修改)
'ALIPAY_RETURN_URL': "http://127.0.0.1:8000/alipay/result/", # 同步回调网址--用于前端,支付成功之后回调
'ALIPAY_NOTIFY_URL': "http://127.0.0.1:8000/alipay/result/", # 异步回调网址---后端使用,post请求,网站未上线,post无法接收到响应内容,付成功之后回调
'APP_PRIVATE_KEY_STRING': os.path.join(BASE_DIR, 'keys/app_private_2048.txt'), # 自己生成的私钥,这个就是路径拼接,配置好了,试试能不能点进去
# 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,********
'ALIPAY_PUBLIC_KEY_STRING': os.path.join(BASE_DIR, 'keys/app_public_2048.txt'), # 一定要注意,是支付宝给你的公钥,不是你自己生成的那个
'SIGN_TYPE': "RSA2", # RSA 或者 RSA2 现在基本上都是用RSA2
}
4、向后端获取付款链接
def wait_pay(request, goods_id, goods_price, goods_title):
""":return 返回付款链接 - 等待支付"""
alipay = alipay_object()
# 生成支付路由: 拼接url --> 返回url
# 电脑网站支付,需要跳转到:https://openapi.alipay.com/gateway.do? + order_string
order_string = alipay.api_alipay_trade_page_pay(
# 这下面的数据,都应该是你数据库的数据,但是我这里做测试,直接写死了
out_trade_no=goods_id, # 商品订单号 唯一的
total_amount=goods_price, # 商品价格
subject='购买' + goods_title + '待付款', # 商品的名称
# 同步回调网址--用于前端,付成功之后回调
return_url=settings.ALIPAY_SETTING.get('ALIPAY_RETURN_URL'),
# 异步回调网址---后端使用,post请求,网站未上线,post无法接收到响应内容,这里需要公网IP,本地测试无法调用使用该方式
notify_url=settings.ALIPAY_SETTING.get('ALIPAY_NOTIFY_URL')
)
# 我这里大概讲一下为什么要有同步/异步,因为同步是前端的,
# 如果前端出现页面崩了,那么校验由后端完成,
# 而且在实际开发中,后端一定要校验,因为前端的校验,可被篡改
url = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do' + '?' + order_string
return JsonResponse({'url': url, 'status': 200})
5、成功后的回调处理
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。