update
This commit is contained in:
parent
77ce77311a
commit
a003d4c0a0
3
go.sh
Normal file
3
go.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
echo start
|
||||
gunicorn qrcode:app -c gunicorn.conf.py
|
8
gunicorn.conf.py
Normal file
8
gunicorn.conf.py
Normal file
@ -0,0 +1,8 @@
|
||||
# 并行工作线程数
|
||||
workers = 4
|
||||
bind = '0.0.0.0:80'
|
||||
daemon = True
|
||||
timeout = 120
|
||||
accesslog = './logs/acess.log'
|
||||
errorlog = './logs/error.log'
|
||||
autostart = True
|
@ -1,13 +0,0 @@
|
||||
# 并行工作线程数
|
||||
workers = 4
|
||||
# 监听内网端口5000【按需要更改】
|
||||
bind = '127.0.0.1:5001'
|
||||
# 设置守护进程【关闭连接时,程序仍在运行】
|
||||
daemon = True
|
||||
# 设置超时时间120s,默认为30s。按自己的需求进行设置
|
||||
timeout = 120
|
||||
# 设置访问日志和错误信息日志路径
|
||||
accesslog = './logsLi/acess.log'
|
||||
errorlog = './logsLi/error.log'
|
||||
#自动重启
|
||||
autostart = True
|
@ -1,13 +0,0 @@
|
||||
# 并行工作线程数
|
||||
workers = 4
|
||||
# 监听内网端口5000【按需要更改】
|
||||
bind = '127.0.0.1:5000'
|
||||
# 设置守护进程【关闭连接时,程序仍在运行】
|
||||
daemon = True
|
||||
# 设置超时时间120s,默认为30s。按自己的需求进行设置
|
||||
timeout = 120
|
||||
# 设置访问日志和错误信息日志路径
|
||||
accesslog = './logsMe/acess.log'
|
||||
errorlog = './logsMe/error.log'
|
||||
#自动重启
|
||||
autostart = True
|
@ -1,303 +1,84 @@
|
||||
from db import findUser, findCode, delCode, insertOrderCache, cache2Test, findOrder, insertCode
|
||||
from db import findUser, delCode, insertCode
|
||||
from login import getOpenid
|
||||
from pay import checkNotify, createOrderParams
|
||||
from utils import checkData
|
||||
import re
|
||||
import json
|
||||
import time
|
||||
import os
|
||||
|
||||
# 当前文件地址
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
# js文件目录地址
|
||||
datadir = os.path.join(basedir, '../data')
|
||||
|
||||
# 主函数
|
||||
|
||||
# 处理登录操作 debug完成
|
||||
def manageLogin(request, where):
|
||||
if checkContent(request.form['code'],request.form['sign']): # 校验
|
||||
res = getOpenid(request.form['code'], where) # 获取openid
|
||||
def manageLogin(request, is_mine):
|
||||
# 获取openid
|
||||
res = getOpenid(request.form['code'], is_mine)
|
||||
if res['errcode'] == 200: # 获取成功返回用户信息
|
||||
return {'userInfo': findUser(res['errmsg']['openid']), 'openid': res['errmsg']['openid'], 'errcode': 200, 'from': where}
|
||||
return {'userInfo': findUser(res['errmsg']['openid']), 'openid': res['errmsg']['openid'], 'errcode': 200}
|
||||
else: # 获取失败返回失败信息
|
||||
return res
|
||||
else:
|
||||
return False # 参数不全或者没通过校验
|
||||
|
||||
# 用户扫描二维码付款 debug完成
|
||||
def findQR(request):
|
||||
# 这里做不了加密验证,防止攻击
|
||||
# 已知ObjectId只包含数字和字母且长度为24位,使用isalnum
|
||||
codeId = str(request.args.get('id'))
|
||||
if(len(codeId) == 24): # 长度校验
|
||||
if(codeId.isalnum()): # 内容校验
|
||||
return findCode(codeId) # 返回code信息
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
return res
|
||||
|
||||
# 小程序刷新用户信息 debug完成
|
||||
def flash(request):
|
||||
# 正常的加解密校验
|
||||
# 已知openId只包含-、_、数字和字母且长度为28位,使用正则
|
||||
if checkContent(request.form['openId'],request.form['sign']): # 校验
|
||||
# 已知openId只包含-、_、数字和字母且长度为28位,使用正则
|
||||
openId = str(request.form['openId'])
|
||||
if(len(openId) == 28): # 长度校验
|
||||
pattern = re.compile(r'[^\w-]')
|
||||
if(pattern.search(openId)): # 内容校验
|
||||
return False
|
||||
else:
|
||||
return {'userInfo': findUser(openId), 'errcode': 200} # 返回用户信息
|
||||
pattern = re.compile(r'[^\w-]')
|
||||
if(pattern.search(openId)): # 内容校验
|
||||
return False
|
||||
else:
|
||||
# 返回用户信息
|
||||
return {'userInfo': findUser(openId), 'errcode': 200}
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False # 参数不全或者没通过校验
|
||||
return False # 参数不全或者没通过校验
|
||||
|
||||
# 用户删除二维码 debug完成
|
||||
def delQR(request):
|
||||
# 正常加解密校验
|
||||
# 和findQR一样,校验objectId
|
||||
if checkContent(request.form['id'],request.form['sign']): # 校验
|
||||
# 已知openId只包含-、_、数字和字母且长度为28位,使用正则
|
||||
codeId = str(request.form['id'])
|
||||
if(len(codeId) == 24): # 长度校验
|
||||
if(codeId.isalnum()): # 内容校验
|
||||
res = delCode(codeId) # 返回code信息
|
||||
if res:
|
||||
path = '{0}{1}.js'.format('/data/qrcode/data/', codeId)
|
||||
print(path)
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
return res
|
||||
else:
|
||||
return res
|
||||
if(codeId.isalnum()): # 内容校验
|
||||
# 返回code信息
|
||||
res = delCode(codeId)
|
||||
if res:
|
||||
filename = '{0}.js'.format(codeId)
|
||||
path = os.path.join(datadir, filename)
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
return res
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
|
||||
# 用户上传二维码
|
||||
def addQR(request):
|
||||
# 流程同createOrder一样,但是直接插入到正式表中,然后返回id
|
||||
dataCache = json.loads(request.form['data']) # josn化,应该能当dist用
|
||||
checked = checkData(dataCache) # 校验所有用户上传的内容
|
||||
if checked:
|
||||
res = insertCode(checked)
|
||||
if res:
|
||||
res_cache = res
|
||||
res = json.loads(res) # res是str 转成json
|
||||
res = res['$oid'] # 取到里边的id
|
||||
data = findCode(res) # 获取到所有的信息
|
||||
try: # 将信息写入文件
|
||||
f = open('{0}{1}.js'.format('/data/qrcode/data/', res),'w',encoding="utf-8")
|
||||
f.write('{0}{1}'.format('var data = ',data))
|
||||
f.close()
|
||||
except IOError:
|
||||
return False
|
||||
return {'errcode': 200, 'id': res_cache, 'data':data}
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# 微信小程序创建订单 debug完成
|
||||
def createOrder(request):
|
||||
# 先就不加MD5校验了
|
||||
# 校验所有内容,目前策略:微信支付宝取网址后边的东西校验,qq转义
|
||||
# 需要接收的内容 : data : wxcode alcode qqcode username openId node; totalFee
|
||||
# 判断过程:先看是否为空,不是空进行校验,报错返回False
|
||||
dataCache = json.loads(request.form['data']) # josn化,应该能当dist用
|
||||
checked = checkData(dataCache) # 校验所有用户上传的内容
|
||||
if checked:
|
||||
params = createOrderParams(request.form['totalFee']) # 获取到订单信息
|
||||
dataCache = createOrderCache(dataCache, params) # 处理要放进缓存表的数据
|
||||
res = insertOrderCache(dataCache) # 放进缓存表
|
||||
if res:
|
||||
return {'params': params, 'errcode': 200}
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
# 处理订单异步通知 debug完成
|
||||
def manageNotify(request):
|
||||
check = checkNotify(request.form.to_dict()) # 回调验证
|
||||
if check:
|
||||
res = cache2Test(request.form['out_trade_no'],request.form['payjs_order_id']) # 转移到Test
|
||||
if res: # 转移成功返回id
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
# 小程序查询订单状况 debug完成
|
||||
def checkOrder(request):
|
||||
order_id = findOrder(request.form['out_trade_no']) # 查询到的映射id
|
||||
if order_id: # 后端还没收到反馈
|
||||
order_id = json.loads(order_id)['$oid']
|
||||
if order_id: # 查询删除都成功了
|
||||
return {'order_id': order_id, 'errcode': 200}
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
# 工具函数---------------------------------------------------------------------------------
|
||||
|
||||
# 在这里进行解密对照
|
||||
def checkContent(row,rsa):
|
||||
# 回头再写,先默认返回true
|
||||
# 用那个MD5
|
||||
# 应该和MD5放在一个文件里
|
||||
return True
|
||||
|
||||
# 判断str转换完是否为空
|
||||
def isKong(arg):
|
||||
if arg == 'None' or arg == '' or arg == None:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# 上传参数校验
|
||||
def checkData(data):
|
||||
hrefCount = 0
|
||||
usernameCount = 0
|
||||
openIdCount = 0
|
||||
timeoutCount = 0
|
||||
|
||||
# 可能的参数
|
||||
# wxp://f2f0e4PCkhToyNDT-zfA-Nn6zoAgPKvK9HUl
|
||||
# https://qr.alipay.com/fkx03165mn5e2hx4gygpx04
|
||||
# HTTPS://QR.ALIPAY.COM/FKX01227ZSFRLWLKZSHL9C
|
||||
# https://payapp.weixin.qq.com/qr/AQEGbDUlzvPBxYKSJst3hENW?t=GAAG#wechat_pay
|
||||
# https://payapp.weixin.qq.com/qr/AQHoz2ywjCZbBKqDrvUuHDqG?t=GAAG#wechat_pay
|
||||
# 微信验证
|
||||
# 微信为36位长度,只包含-、_、数字和字母,使用正则
|
||||
|
||||
wxp = re.compile(r'[^\w-]')
|
||||
wxcode = str(data['wxcode'])
|
||||
if isKong(wxcode):
|
||||
wxcode = ''
|
||||
else:
|
||||
wxCache1 = re.findall(r"wxp://(.+)",wxcode)
|
||||
wxCache2 = re.findall(r"https://payapp.weixin.qq.com/qr/(.+)\?t",wxcode)
|
||||
if wxCache1:
|
||||
# 第一种
|
||||
if(len(wxCache1[0]) == 36):
|
||||
if not (wxp.search(wxCache1[0])):
|
||||
hrefCount = hrefCount + 1
|
||||
# josn化,应该能当dist用
|
||||
dataCache = json.loads(request.form['data'])
|
||||
# 校验所有用户上传的内容
|
||||
data = checkData(dataCache)
|
||||
if data:
|
||||
id = data['id']
|
||||
res = insertCode(data)
|
||||
if res:
|
||||
# 去除里边的id
|
||||
if data.get('_id'):
|
||||
data.pop('_id')
|
||||
try:
|
||||
filename = '{0}.js'.format(id)
|
||||
path = os.path.join(datadir, filename) # 将信息写入文件
|
||||
f = open(path, 'w', encoding="utf-8")
|
||||
f.write('{0}{1}'.format('var data = ', data))
|
||||
f.close()
|
||||
except IOError:
|
||||
return False
|
||||
return {'errcode': 200, 'id': id}
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
elif wxCache2:
|
||||
# 第二种
|
||||
if(len(wxCache2[0]) == 24):
|
||||
if not (wxp.search(wxCache2[0])):
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
else:
|
||||
# 都不是
|
||||
return False
|
||||
|
||||
# openId验证
|
||||
# openId为28位长度,只包含-、_、数字和字母,使用正则
|
||||
openId = str(data['openId'])
|
||||
if isKong(openId):
|
||||
openId = ''
|
||||
else:
|
||||
if(len(openId) == 28):
|
||||
if not (wxp.search(openId)):
|
||||
openIdCount = 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
# 支付宝验证
|
||||
# 支付宝为23位或22位长度,只有数字和字母,使用isalnum
|
||||
alcode = str(data['alcode'])
|
||||
alCache1 = re.findall(r"https://qr.alipay.com/(.+)",alcode)
|
||||
alCache2 = re.findall(r"HTTPS://QR.ALIPAY.COM/(.+)",alcode)
|
||||
if isKong(alcode):
|
||||
alcode = ''
|
||||
else:
|
||||
if alCache1:
|
||||
# 第一种
|
||||
if len(alCache1[0]) == 23:
|
||||
if alCache1[0].isalnum():
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
elif alCache2:
|
||||
# 第二种
|
||||
if len(alCache2[0]) == 22:
|
||||
if alCache2[0].isalnum():
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
# QQ验证
|
||||
# QQ 一定包含 'qianbao.qq.com',使用正则
|
||||
# *!()_-.% 字母 数字 ,正则写不明白了,woc
|
||||
qqp = re.compile(r'qianbao.qq.com')
|
||||
qqcode = str(data['qqcode'])
|
||||
if isKong(qqcode):
|
||||
qqcode = ''
|
||||
else:
|
||||
if(qqp.search(qqcode)):
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
|
||||
# 用户名验证
|
||||
# 正则替换掉引号,$
|
||||
username = str(data['username'])
|
||||
if(not isKong(username)):
|
||||
username = username.replace('"','')
|
||||
username = username.replace("'",'')
|
||||
username = username.replace('$','')
|
||||
usernameCount = 1
|
||||
else:
|
||||
return False
|
||||
|
||||
# 备注验证
|
||||
# 正则替换掉引号,$
|
||||
node = str(data['node'])
|
||||
if(not isKong(node)):
|
||||
node = node.replace('"','')
|
||||
node = node.replace("'",'')
|
||||
node = node.replace('$','')
|
||||
else:
|
||||
node = ''
|
||||
|
||||
# 过期时间验证
|
||||
timeout = str(data['timeout'])
|
||||
if(not isKong(timeout)):
|
||||
if len(timeout) == 13:
|
||||
timeoutCount = 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
if hrefCount >= 2 and usernameCount and openIdCount and timeoutCount:
|
||||
return {'username': username, 'node': node, 'wxcode': wxcode, 'alcode': alcode, 'qqcode': qqcode, 'openId': openId, 'timeout': timeout, 'create_time':int(time.time())}
|
||||
else:
|
||||
return False
|
||||
|
||||
# 创建订单详情 Cache
|
||||
def createOrderCache(data,params):
|
||||
data['out_trade_no'] = params['out_trade_no']
|
||||
data['create_time'] = int(time.time())
|
||||
return data
|
||||
|
93
lib/db.py
93
lib/db.py
@ -1,25 +1,10 @@
|
||||
from pymongo import MongoClient
|
||||
from bson import ObjectId, json_util
|
||||
|
||||
# 主环境
|
||||
setting = 'test'
|
||||
|
||||
# 获取数据集
|
||||
def col(arg: str = None):
|
||||
conn = MongoClient('mongodb://yingbo:623910ert@localhost:12236/yingbo')
|
||||
param = None
|
||||
if arg:
|
||||
param = arg
|
||||
else:
|
||||
param = setting
|
||||
if param == 'test':
|
||||
return conn.yingbo.test
|
||||
elif param == 'order':
|
||||
return conn.yingbo.order
|
||||
elif param == 'cache':
|
||||
return conn.yingbo.cache
|
||||
elif param == 'code':
|
||||
return conn.yingbo.code
|
||||
conn = MongoClient('mongodb://qrcode:mR6rN4pI0rU6@mongo:27017/qrcode')
|
||||
return conn.qrcode[arg]
|
||||
|
||||
# 查找该用户所有信息
|
||||
def findUser(openid):
|
||||
@ -28,20 +13,6 @@ def findUser(openid):
|
||||
arr.append(i)
|
||||
return json_util.dumps(arr)
|
||||
|
||||
# 查找该二维码所有信息
|
||||
def findCode(id):
|
||||
arr = []
|
||||
try:
|
||||
for i in col('code').find({"_id" : ObjectId(id)}):
|
||||
arr.append(i)
|
||||
except Exception as e:
|
||||
# id不合法
|
||||
return False
|
||||
if(len(arr) == 0):
|
||||
# 查询无结果
|
||||
return False
|
||||
return json_util.dumps(arr)
|
||||
|
||||
# 删除该二维码
|
||||
def delCode(id):
|
||||
try:
|
||||
@ -51,70 +22,12 @@ def delCode(id):
|
||||
return False
|
||||
return {'errcode': 200, 'errmsg': 'ok'}
|
||||
|
||||
# 用户上传进入缓存表
|
||||
def insertOrderCache(data):
|
||||
try:
|
||||
col('cache').insert_one(data)
|
||||
except Exception as e:
|
||||
# 失败
|
||||
return False
|
||||
return True
|
||||
|
||||
# 用户付款回调 从缓存写进正式表
|
||||
def cache2Test(out_trade_no,payjs_order_id):
|
||||
try:
|
||||
# 取出缓存表数据
|
||||
cache = col('cache').find_one({"out_trade_no" : out_trade_no})
|
||||
# 删除缓存表数据
|
||||
col('cache').remove({"out_trade_no" : out_trade_no},1)
|
||||
except Exception as e:
|
||||
# 失败
|
||||
return False
|
||||
# 判断有没有,去重逻辑
|
||||
if cache:
|
||||
# 向原始数据中添加支付识别码
|
||||
cache['payjs_order_id'] = payjs_order_id
|
||||
# 插入到正式表
|
||||
res = col().insert_one(cache)
|
||||
# 返回插入的正式表id
|
||||
inserted_id = res.inserted_id
|
||||
# 放进order表建立 out_trade_no 到 objectId的 映射
|
||||
try:
|
||||
col('order').insert_one({'out_trade_no': out_trade_no, 'inserted_id': inserted_id})
|
||||
except Exception as e:
|
||||
# 失败
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
# 小程序端查询支付结果
|
||||
def findOrder(out_trade_no):
|
||||
arr = []
|
||||
try:
|
||||
for i in col('order').find({"out_trade_no" : out_trade_no}):
|
||||
arr.append(i)
|
||||
except Exception as e:
|
||||
# 失败
|
||||
return False
|
||||
if(len(arr) == 0):
|
||||
# 查询无结果
|
||||
return False
|
||||
else:
|
||||
# 删除order中的记录
|
||||
try:
|
||||
col('order').remove({"out_trade_no" : out_trade_no})
|
||||
except Exception as e:
|
||||
# 失败
|
||||
return False
|
||||
return json_util.dumps(arr[0]['inserted_id'])
|
||||
|
||||
# 用户上传进入主表
|
||||
def insertCode(data):
|
||||
try:
|
||||
res = col('code').insert_one(data)
|
||||
inserted_id = res.inserted_id
|
||||
except Exception as e:
|
||||
# 失败
|
||||
return False
|
||||
return json_util.dumps(inserted_id)
|
||||
return True
|
@ -1,8 +1,8 @@
|
||||
from requests import request
|
||||
import json
|
||||
|
||||
def getOpenid(code, where):
|
||||
if where == 1:
|
||||
def getOpenid(code, is_mine):
|
||||
if is_mine == 1:
|
||||
url = 'https://api.weixin.qq.com/sns/jscode2session?appid=wx0df150c438e4c8f0&secret=e43b9f0356a29c8e5b39e79bb27376f1&js_code='+ code +'&grant_type=authorization_code'
|
||||
else:
|
||||
url = 'https://api.weixin.qq.com/sns/jscode2session?appid=wxc4c92bdf93bfa247&secret=488e9b8f1ea69a0cc0bf0e0ed4d572ae&js_code='+ code +'&grant_type=authorization_code'
|
||||
|
105
lib/pay.py
105
lib/pay.py
@ -1,105 +0,0 @@
|
||||
from payjs import PayJS # 也可根据个人习惯选择使用 Payjs/PAYJS/payjs
|
||||
from payjs import PayJSNotify # 也可根据个人习惯选择使用 PayjsNotify/PAYJSNotify
|
||||
from signature import get_signature
|
||||
import random
|
||||
import time
|
||||
|
||||
MCHID = '1561399401'
|
||||
KEY = 'C0vy3IlwgWn3TxJD'
|
||||
|
||||
# 初始化
|
||||
p = PayJS(MCHID, KEY)
|
||||
|
||||
# 订单查询
|
||||
def checkOrder():
|
||||
res = p.check_status(payjs_order_id=r.payjs_order_id)
|
||||
if res:
|
||||
return res.paid # 是否已支付
|
||||
else:
|
||||
return {'errMsg': s.error_msg, 'err': s} # 错误信息
|
||||
|
||||
# 回调验证
|
||||
def checkNotify(str):
|
||||
return PayJSNotify(KEY, str)
|
||||
|
||||
# 创建微信小程序 Params
|
||||
def createOrderParams(totalFee):
|
||||
body = '收款码合并服务费' # 用户订单标题
|
||||
nonce = random.randint(100000,999999) # 随机数
|
||||
timestamp = int(time.time()) # 当前时间戳
|
||||
outTradeNo = 'QR-WXPay-' + str(timestamp) + '-' + str(nonce) # 商户端订单号
|
||||
notifyUrl = 'https://qr.powerrain.cn/notify' # 异步通知地址
|
||||
attach = 'from wx' # 异步通知附加数据
|
||||
paramsObject = {
|
||||
'mchid': MCHID,
|
||||
'total_fee': totalFee,
|
||||
'out_trade_no': outTradeNo,
|
||||
'body': body,
|
||||
'attach': attach,
|
||||
'notify_url': notifyUrl,
|
||||
'nonce': nonce
|
||||
}
|
||||
|
||||
sign = get_signature(KEY, paramsObject) # MD5签名算法签名
|
||||
|
||||
paramsObject['sign'] = sign
|
||||
|
||||
return paramsObject
|
||||
|
||||
|
||||
# 扫码支付
|
||||
# OUT_TRADE_NO = '2017TEST' # 外部订单号(自己的支付系统的订单号,请保证唯一)
|
||||
# TOTAL_FEE = 1 # 支付金额,单位为分,金额最低 0.01 元最多 10000 元
|
||||
# BODY = '测试支付' # 订单标题
|
||||
# NOTIFY_URL = 'https://pay.singee.site/empty/' # Notify 网址
|
||||
# ATTACH = 'info' # Notify 内容
|
||||
# r = p.QRPay(out_trade_no=OUT_TRADE_NO, total_fee=TOTAL_FEE, body=BODY, notify_url=NOTIFY_URL, attach=ATTACH)
|
||||
# if r:
|
||||
# print(r.code_url) # 二维码地址(weixin:// 开头,请使用此地址构建二维码)
|
||||
# print(r.qrcode) # 二维码地址(https:// 开头,为二维码图片的地址)
|
||||
# print(r.payjs_order_id) # 订单号(PAYJS 的)
|
||||
# else:
|
||||
# print(r.STATUS_CODE) # HTTP 请求状态码
|
||||
# print(r.ERROR_NO) # 错误码
|
||||
# print(r.error_msg) # 错误信息
|
||||
# print(r)
|
||||
|
||||
# 构造收银台支付网址(仅构造链接,请使用浏览器 302 到这个网址,无法预检查调用是否成功)
|
||||
# c = p.get_cashier_url(out_trade_no=OUT_TRADE_NO, total_fee=TOTAL_FEE, body=BODY, callback_url=CALLBACK_URL, notify_url=NOTIFY_URL, attach=ATTACH)
|
||||
# print(c)
|
||||
|
||||
# JSApi 支付
|
||||
# OPENID = '这里填写支付用户的 OpenID' # 支付用户在 PayJS 端的 OpenID,可通过 get_openid 获取
|
||||
# j = p.JSApiPay(out_trade_no=OUT_TRADE_NO, total_fee=TOTAL_FEE, openid=OPENID, body=BODY, notify_url=NOTIFY_URL, attach=ATTACH)
|
||||
# if j:
|
||||
# print(j.jsapi) # 用于发起支付的支付参数
|
||||
# else:
|
||||
# print(j.STATUS_CODE) # HTTP 请求状态码
|
||||
# print(j.ERROR_NO) # 错误码
|
||||
# print(j.error_msg) # 错误信息
|
||||
# print(j)
|
||||
|
||||
# 刷卡支付
|
||||
# AUTH_CODE = '这里填写用户侧 18 位数字' # 用户的支付条码或二维码所对应的数字
|
||||
# m = p.MicroPay(out_trade_no=OUT_TRADE_NO, total_fee=TOTAL_FEE, auth_code=AUTH_CODE, body=BODY)
|
||||
# print(m)
|
||||
|
||||
# 订单关闭
|
||||
# def closeOrder():
|
||||
# res = p.close(r.payjs_order_id)
|
||||
# if res:
|
||||
# return {'errMsg': 'ok', 'errCode': 200}
|
||||
# else:
|
||||
# return {'errMsg': res.return_msg, 'errCode': 500}
|
||||
|
||||
# # 订单退款
|
||||
# def refundOrder():
|
||||
# res = p.refund(r.payjs_order_id)
|
||||
# if res:
|
||||
# return {'errMsg': 'ok', 'errCode': 200}
|
||||
# else:
|
||||
# return {'errMsg': res.return_msg, 'errCode': 500}
|
||||
|
||||
# # 获取用户 OpenId
|
||||
# def getOpenId():
|
||||
# return p.get_openid(callback_url=CALLBACK_URL)
|
@ -1,37 +0,0 @@
|
||||
from hashlib import md5
|
||||
from urllib.parse import urlencode, unquote_plus
|
||||
|
||||
def get_signature(key: str, data: dict):
|
||||
"""
|
||||
签名过程如下:
|
||||
0. 忽略已经存在的 sign
|
||||
1. 将所有参数名按照字典序排列,并以 "参数1=值1&参数2=值2&参数3=值3" 的形式排序
|
||||
2. 将上面的内容加上 "&key=KEY"(KEY 为设置的商户密钥)
|
||||
3. 将组合后的字符串转换为大写 MD5
|
||||
|
||||
:param key: 商户密钥
|
||||
:param data: 要签名的参数字典
|
||||
:return: 签名后的字符串
|
||||
:rtype: str
|
||||
"""
|
||||
d = data.copy()
|
||||
|
||||
# pop 掉 sign 字段
|
||||
try:
|
||||
d.pop('sign')
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# pop 掉无效字段
|
||||
p = sorted([x for x in d.items() if (x[1] or x[1] == 0)], key=lambda x: x[0])
|
||||
|
||||
p.append(('key', key))
|
||||
|
||||
p = unquote_plus(urlencode(p))
|
||||
|
||||
h = md5()
|
||||
h.update(p.encode())
|
||||
|
||||
r = h.hexdigest().upper()
|
||||
|
||||
return r
|
157
lib/utils.py
Normal file
157
lib/utils.py
Normal file
@ -0,0 +1,157 @@
|
||||
import random
|
||||
import datetime
|
||||
import time
|
||||
|
||||
# 生成唯一不重名字符串
|
||||
def randomId():
|
||||
nowTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S") # 生成当前时间
|
||||
randomNum = random.randint(0, 100) # 生成的随机整数n,其中0<=n<=100
|
||||
if randomNum <= 10:
|
||||
randomNum = str(0) + str(randomNum)
|
||||
uniqueNum = str(nowTime) + str(randomNum)
|
||||
return uniqueNum
|
||||
|
||||
# 判断str转换完是否为空
|
||||
def isKong(arg):
|
||||
if arg == 'None' or arg == '' or arg == None:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# 上传参数校验
|
||||
def checkData(data):
|
||||
hrefCount = 0
|
||||
usernameCount = 0
|
||||
openIdCount = 0
|
||||
timeoutCount = 0
|
||||
|
||||
# 可能的参数
|
||||
# wxp://f2f0e4PCkhToyNDT-zfA-Nn6zoAgPKvK9HUl
|
||||
# https://qr.alipay.com/fkx03165mn5e2hx4gygpx04
|
||||
# HTTPS://QR.ALIPAY.COM/FKX01227ZSFRLWLKZSHL9C
|
||||
# https://payapp.weixin.qq.com/qr/AQEGbDUlzvPBxYKSJst3hENW?t=GAAG#wechat_pay
|
||||
# https://payapp.weixin.qq.com/qr/AQHoz2ywjCZbBKqDrvUuHDqG?t=GAAG#wechat_pay
|
||||
# 微信验证
|
||||
# 微信为36位长度,只包含-、_、数字和字母,使用正则
|
||||
|
||||
wxp = re.compile(r'[^\w-]')
|
||||
wxcode = str(data['wxcode'])
|
||||
if isKong(wxcode):
|
||||
wxcode = ''
|
||||
else:
|
||||
wxCache1 = re.findall(r"wxp://(.+)", wxcode)
|
||||
wxCache2 = re.findall(
|
||||
r"https://payapp.weixin.qq.com/qr/(.+)\?t", wxcode)
|
||||
if wxCache1:
|
||||
# 第一种
|
||||
if(len(wxCache1[0]) == 36):
|
||||
if not (wxp.search(wxCache1[0])):
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
elif wxCache2:
|
||||
# 第二种
|
||||
if(len(wxCache2[0]) == 24):
|
||||
if not (wxp.search(wxCache2[0])):
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
# 都不是
|
||||
return False
|
||||
|
||||
# openId验证
|
||||
# openId为28位长度,只包含-、_、数字和字母,使用正则
|
||||
openId = str(data['openId'])
|
||||
if isKong(openId):
|
||||
openId = ''
|
||||
else:
|
||||
if(len(openId) == 28):
|
||||
if not (wxp.search(openId)):
|
||||
openIdCount = 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
# 支付宝验证
|
||||
# 支付宝为23位或22位长度,只有数字和字母,使用isalnum
|
||||
alcode = str(data['alcode'])
|
||||
alCache1 = re.findall(r"https://qr.alipay.com/(.+)", alcode)
|
||||
alCache2 = re.findall(r"HTTPS://QR.ALIPAY.COM/(.+)", alcode)
|
||||
if isKong(alcode):
|
||||
alcode = ''
|
||||
else:
|
||||
if alCache1:
|
||||
# 第一种
|
||||
if len(alCache1[0]) == 23:
|
||||
if alCache1[0].isalnum():
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
elif alCache2:
|
||||
# 第二种
|
||||
if len(alCache2[0]) == 22:
|
||||
if alCache2[0].isalnum():
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
# QQ验证
|
||||
# QQ 一定包含 'qianbao.qq.com',使用正则
|
||||
# *!()_-.% 字母 数字 ,正则写不明白了,woc
|
||||
qqp = re.compile(r'qianbao.qq.com')
|
||||
qqcode = str(data['qqcode'])
|
||||
if isKong(qqcode):
|
||||
qqcode = ''
|
||||
else:
|
||||
if(qqp.search(qqcode)):
|
||||
hrefCount = hrefCount + 1
|
||||
else:
|
||||
return False
|
||||
|
||||
# 用户名验证
|
||||
# 正则替换掉引号,$
|
||||
username = str(data['username'])
|
||||
if(not isKong(username)):
|
||||
username = username.replace('"', '')
|
||||
username = username.replace("'", '')
|
||||
username = username.replace('$', '')
|
||||
usernameCount = 1
|
||||
else:
|
||||
return False
|
||||
|
||||
# 备注验证
|
||||
# 正则替换掉引号,$
|
||||
node = str(data['node'])
|
||||
if(not isKong(node)):
|
||||
node = node.replace('"', '')
|
||||
node = node.replace("'", '')
|
||||
node = node.replace('$', '')
|
||||
else:
|
||||
node = ''
|
||||
|
||||
# 过期时间验证
|
||||
timeout = str(data['timeout'])
|
||||
if(not isKong(timeout)):
|
||||
if len(timeout) == 13:
|
||||
timeoutCount = 1
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
if hrefCount >= 2 and usernameCount and openIdCount and timeoutCount:
|
||||
return {'username': username, 'node': node, 'wxcode': wxcode, 'alcode': alcode, 'qqcode': qqcode, 'openId': openId, 'timeout': timeout, 'create_time': int(time.time()), 'id': randomId()}
|
||||
else:
|
||||
return False
|
@ -32,14 +32,14 @@
|
||||
var id = GetQueryString("id")
|
||||
// 不合法id的处理
|
||||
if(id == null || id.search(/\W+/) != -1 || id.length != 24) {
|
||||
window.location.replace("https://qr.powerrain.cn/qr/410.html");
|
||||
window.location.replace("https://qr.lacus.site/qr/410.html");
|
||||
}
|
||||
var data = document.createElement("script");
|
||||
data.src = `https://qr.powerrain.cn/data/${id}.js`
|
||||
data.src = `https://qr.lacus.site/data/${id}.js`
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
// 加载失败处理,默认失败时间是2秒
|
||||
var timer = setTimeout(function(){
|
||||
window.location.replace("https://qr.powerrain.cn/qr/500.html");
|
||||
window.location.replace("https://qr.lacus.site/qr/500.html");
|
||||
},2000)
|
||||
data.onload = function(){
|
||||
clearTimeout(timer)
|
||||
@ -59,12 +59,12 @@
|
||||
qrcodeApi: "http://qr.topscan.com/api.php?text="
|
||||
}
|
||||
|
||||
var bgs = ['./img/bg1.jpg',
|
||||
'./img/bg2.jpg',
|
||||
'./img/bg3.jpg',
|
||||
'./img/bg4.jpg',
|
||||
'./img/bg5.jpg',
|
||||
'./img/bg6.jpg',]
|
||||
var bgs = ['https://qr.lacus.site/qr/img/bg1.jpg',
|
||||
'https://qr.lacus.site/qr/img/bg2.jpg',
|
||||
'https://qr.lacus.site/qr/img/bg3.jpg',
|
||||
'https://qr.lacus.site/qr/img/bg4.jpg',
|
||||
'https://qr.lacus.site/qr/img/bg5.jpg',
|
||||
'https://qr.lacus.site/qr/img/bg6.jpg',]
|
||||
|
||||
//初始化
|
||||
function init() {
|
||||
@ -81,7 +81,7 @@
|
||||
var timeout = parseInt(data.timeout)
|
||||
timeout = new Date(timeout)
|
||||
var now = new Date()
|
||||
if (timeout - now <= 0) window.location.replace("https://qr.powerrain.cn/qr/410.html");
|
||||
if (timeout - now <= 0) window.location.replace("https://qr.lacus.site/qr/410.html");
|
||||
// 换背景
|
||||
ele('bg').src = bgs[Math.floor(Math.random() * bgs.length)]
|
||||
setting.id = data._id.$oid
|
||||
@ -138,7 +138,7 @@
|
||||
ele("wq_b").setAttribute("class", "wx_b");
|
||||
ele("title").innerHTML = "推荐使用微信支付";
|
||||
ele("user1").innerHTML = setting.username;
|
||||
ele("wq_pay").setAttribute("src", "./img/sprite3.png");
|
||||
ele("wq_pay").setAttribute("src", "https://qr.lacus.site/qr/img/sprite3.png");
|
||||
} else {
|
||||
//木有微信的链接
|
||||
noSupport("微信", 1)
|
||||
@ -150,7 +150,7 @@
|
||||
ele("wq_b").setAttribute("class", "qq_b");
|
||||
ele("title").innerHTML = "推荐使用QQ支付";
|
||||
ele("user1").innerHTML = setting.username;
|
||||
ele("wq_pay").setAttribute("src", "./img/sprite2.png");
|
||||
ele("wq_pay").setAttribute("src", "https://qr.lacus.site/qr/img/sprite2.png");
|
||||
} else {
|
||||
//木有QQ的链接
|
||||
noSupport("QQ", 1);
|
||||
@ -317,7 +317,7 @@
|
||||
.all .imageBox>div {
|
||||
height: 50px;
|
||||
width: 52px;
|
||||
background-image: url('./img/sprite1.png');
|
||||
background-image: url('https://qr.lacus.site/qr/img/sprite1.png');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,11 @@ sys.path.append('./lib')
|
||||
|
||||
import os
|
||||
from flask import Flask, escape, url_for, request, render_template, redirect, abort, send_from_directory
|
||||
from allFunction import manageLogin, findQR, flash, delQR, manageNotify, createOrder, checkOrder, addQR
|
||||
|
||||
from allFunction import manageLogin, flash, delQR, addQR
|
||||
from flask_qrcode import QRcode
|
||||
|
||||
app = Flask(__name__)
|
||||
QRcode(app)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@ -19,15 +21,6 @@ def login():
|
||||
else:
|
||||
abort(400)
|
||||
|
||||
# # 用户扫描二维码
|
||||
# @app.route('/qr',methods=['GET'])
|
||||
# def qr():
|
||||
# res = findQR(request)
|
||||
# if(res):
|
||||
# return render_template('qrcode.html',data = res)
|
||||
# else:
|
||||
# abort(410)
|
||||
|
||||
# 小程序刷新用户信息
|
||||
@app.route('/reflash',methods=['POST'])
|
||||
def reflash():
|
||||
@ -55,36 +48,16 @@ def addQRCode():
|
||||
else:
|
||||
abort(400)
|
||||
|
||||
# 创建新的订单(暂时废弃)
|
||||
# @app.route('/newOrder',methods=['POST'])
|
||||
# def newOrder():
|
||||
# res = createOrder(request)
|
||||
# if(res):
|
||||
# return res
|
||||
# else:
|
||||
# abort(400)
|
||||
|
||||
# 处理订单异步通知(暂时废弃)
|
||||
# @app.route('/notify',methods=['POST'])
|
||||
# def notify():
|
||||
# manageNotify(request)
|
||||
# return 'ok'
|
||||
|
||||
# 小程序查询订单状态(暂时废弃)
|
||||
# @app.route('/checkOrder',methods=['POST'])
|
||||
# def check():
|
||||
# res = checkOrder(request)
|
||||
# print(res)
|
||||
# if res:
|
||||
# return res
|
||||
# else:
|
||||
# abort(500)
|
||||
# 生成二维码
|
||||
@app.route('/generate',methods=['GET'])
|
||||
def generate():
|
||||
text = request.args.get("text")
|
||||
return qrcode(text)
|
||||
|
||||
# 控制小程序是否显示“最佳案例”
|
||||
@app.route('/config', methods=['post'])
|
||||
def config():
|
||||
return {'errcode': 200, 'showBest': 'true'}
|
||||
|
||||
return {'errcode': 200, 'showBest': 'false'}
|
||||
|
||||
# 图标
|
||||
@app.route('/favicon.ico')
|
||||
@ -110,7 +83,4 @@ def page_not_found(e):
|
||||
|
||||
@app.errorhandler(410)
|
||||
def page_not_found(e):
|
||||
return render_template('410.html'), 500
|
||||
|
||||
# 目前的安全模式依赖于限制post访问,非对称加密校验,对所有内容进行规则审查,
|
||||
# 主要还是防止有人恶意访问,等到写密码本的时候尝试模拟ssl加密模式
|
||||
return render_template('410.html'), 500
|
116
qrcodeLi.py
116
qrcodeLi.py
@ -1,116 +0,0 @@
|
||||
import sys
|
||||
sys.path.append('./lib')
|
||||
|
||||
import os
|
||||
from flask import Flask, escape, url_for, request, render_template, redirect, abort, send_from_directory
|
||||
from allFunction import manageLogin, findQR, flash, delQR, manageNotify, createOrder, checkOrder, addQR
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
|
||||
# 用户小程序登录
|
||||
@app.route('/li/login',methods=['POST'])
|
||||
def login():
|
||||
res = manageLogin(request, 2)
|
||||
if(res):
|
||||
return res
|
||||
else:
|
||||
abort(400)
|
||||
|
||||
# # 用户扫描二维码
|
||||
# @app.route('/qr',methods=['GET'])
|
||||
# def qr():
|
||||
# res = findQR(request)
|
||||
# if(res):
|
||||
# return render_template('qrcode.html',data = res)
|
||||
# else:
|
||||
# abort(410)
|
||||
|
||||
# 小程序刷新用户信息
|
||||
@app.route('/li/reflash',methods=['POST'])
|
||||
def reflash():
|
||||
res = flash(request)
|
||||
if(res):
|
||||
return res
|
||||
else:
|
||||
abort(400)
|
||||
|
||||
# 用户删除二维码
|
||||
@app.route('/li/del',methods=['POST'])
|
||||
def delQRCode():
|
||||
res = delQR(request)
|
||||
if(res):
|
||||
return res
|
||||
else:
|
||||
abort(400)
|
||||
|
||||
# 用户添加二维码
|
||||
@app.route('/li/add',methods=['POST'])
|
||||
def addQRCode():
|
||||
res = addQR(request)
|
||||
if(res):
|
||||
return res
|
||||
else:
|
||||
abort(400)
|
||||
|
||||
# 创建新的订单(暂时废弃)
|
||||
# @app.route('/newOrder',methods=['POST'])
|
||||
# def newOrder():
|
||||
# res = createOrder(request)
|
||||
# if(res):
|
||||
# return res
|
||||
# else:
|
||||
# abort(400)
|
||||
|
||||
# 处理订单异步通知(暂时废弃)
|
||||
# @app.route('/notify',methods=['POST'])
|
||||
# def notify():
|
||||
# manageNotify(request)
|
||||
# return 'ok'
|
||||
|
||||
# 小程序查询订单状态(暂时废弃)
|
||||
# @app.route('/checkOrder',methods=['POST'])
|
||||
# def check():
|
||||
# res = checkOrder(request)
|
||||
# print(res)
|
||||
# if res:
|
||||
# return res
|
||||
# else:
|
||||
# abort(500)
|
||||
|
||||
# 控制小程序是否显示“最佳案例”
|
||||
@app.route('/li/config', methods=['post'])
|
||||
def config():
|
||||
return {'errcode': 200, 'showBest': 'true'}
|
||||
|
||||
|
||||
# 图标
|
||||
@app.route('/li/favicon.ico')
|
||||
def favicon():
|
||||
return send_from_directory(os.path.join(app.root_path, 'static'),'favicon.ico', mimetype='image/vnd.microsoft.icon')
|
||||
|
||||
@app.route('/li/<path>')
|
||||
def notDefind():
|
||||
abort(404)
|
||||
|
||||
# 二维码查询失败重定向, 404
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return render_template('404.html'), 404
|
||||
|
||||
@app.errorhandler(400)
|
||||
def page_not_found(e):
|
||||
return render_template('400.html'), 400
|
||||
|
||||
@app.errorhandler(500)
|
||||
def page_not_found(e):
|
||||
return render_template('500.html'), 500
|
||||
|
||||
@app.errorhandler(410)
|
||||
def page_not_found(e):
|
||||
return render_template('410.html'), 500
|
||||
|
||||
# 目前的安全模式依赖于限制post访问,非对称加密校验,对所有内容进行规则审查,
|
||||
# 主要还是防止有人恶意访问,等到写密码本的时候尝试模拟ssl加密模式
|
Loading…
x
Reference in New Issue
Block a user