需求说明:html
1
2
3
4
5
6
7
8
9
10
|
额度
15000
或自定义
实现购物商城,买东西加入 购物车,调用信用卡接口结帐
能够提现,手续费
5
%
支持多帐户登陆
支持帐户间转帐
记录每个月平常消费流水
提供还款接口
ATM记录操做日志
提供管理接口,包括添加帐户、用户额度,冻结帐户等。。。
用户认证用装饰器
|
程序说明:python
主菜单,进入主菜单显示以下:git
【1】购物商城 【2】用户中心 【3】信用卡中心 【4】后台管理 【5】登陆系统 【6】退出json
购物商城:app
显示各类商品和价格,选择对应的序号进行购买函数
用户中心:post
【1】修改密码 【2】额度查询 【3】消费记录 【4】返回编码
信用卡中心:加密
【1】额度查询 【2】提现 【3】转帐 【4】还款 【5】返回url
后台管理,主要是admin用户进行管理:
【1】建立用户 【2】冻结信用卡 【3】解冻用户
【4】额度调整 【5】退出后台管理
登陆系统:
未登陆的用户须要进行登陆
代码结构
#!/usr/bin/env python #-*- coding:utf-8 -*- # @Time : 2017/10/19 22:18 # @Author : lichuan # @File : creditcard.py from config import template import time from datetime import datetime from module import common import pickle from log import my_log_settings import logging from module.users import Users import os,sys #加在日志配置模块 my_log_settings.load_my_logging_cfg() #访问日志logger,path=log/access.log acess_logger=logging.getLogger(__name__) #消费日志logger,path=log/shop.log shop_logger=logging.getLogger('shop') #用户认证函数 # @wraps def auth(func): ''' 用户是否已经登陆的认证装饰器 :param func: :return: ''' def warpper(*args,**kwargs): import pickle # userinfo=pickle.loads(open('.json','rb').read())\ userinfos = load_user() if len(userinfos)!=0: func(*args,**kwargs) else: login() userinfos = load_user() if len(userinfos)!=0: func(*args,**kwargs) return warpper @auth def shop_center(): ''' 购物商城界面选择 :return: ''' shop={'apple手机':7000,'魅族手机':2000,'小米手机':2500,'华为手机':4000,'小米笔记本':4000} shop_list=['apple手机','魅族手机','小米手机','华为手机','小米笔记本'] salary=15000 userinfo=load_user() # print(userinfo) buy_list={} salary=int(userinfo['salary']) shop_flag=True while shop_flag: print(template.shopping_index_menu) choice=input('请选择:').strip() if not choice.isdigit() or int(choice) not in range(1,7): print('输入错误,请重试!') continue if int(choice) == 6: Users[userinfo['name']]=userinfo dump_user(userinfo) print('退出购物商城,再见!') break else: key=shop_list[int(choice)-1] money=shop[key] if money > salary: print('剩余额度不够,请选择别的商品!') continue else: salary=salary-money username=userinfo['name'] shop_logger.info('[%s]购买%s,花费%d元!' % (username,key,money)) print('%s,价值%d元,已购买!' % (key,money)) print('剩余额度:%d元' % salary) #更新信息到Users配置文件 userinfo['salary']=salary if key in buy_list: buy_list[key]+=1 else: buy_list[key] = 1 userinfo['buy_list']=buy_list Users[userinfo['name']] = userinfo common.update_users(Users) #从文件加载登陆用户的信息 def load_user(): ''' 从文件加载登陆用户的信息 :return: userinfo信息 ''' try: with open('.pkl', 'rb') as read_f: userinfo = {} userinfo = pickle.loads(read_f.read()) # print(userinfo) except (FileNotFoundError,EOFError): pass return userinfo #将登陆用户信息从新写入.pkl def dump_user(users): ''' 将users信息从新写入.pkl文件进行保存。 :param users:users信息是个字典 :return: ''' with open('.pkl', 'w'): pass with open('.pkl', 'wb') as read_f: p = pickle.dumps(users) read_f.write(p) #用户登陆函数 def login(): ''' 用户登陆函数,对用户名密码进行校验,用户密码采用加密模块hashlib进行加盐加密 :return: ''' err_count=0 login_flag=True while login_flag: username=input('please input your username: ').strip() password=input('please input your password: ').strip() if username in Users: if Users[username]['password'] == common.encrypt(password) and Users[username]['islocked'] == 0: userinfo=Users[username] err_count = 0 with open('.pkl','wb') as write_f: p=pickle.dumps(userinfo) write_f.write(p) acess_logger.info(str(username)+' login success!') print(str(username)+' login success!') login_flag=False elif Users[username]['islocked'] != 0: print('user is locked ! cannot login!') err_count = 0 login_flag=False break else: print('name or password is wrong!!!') acess_logger.info(str(username)+' login Falied ,password is wrong') err_count+=1 #错误登陆3次以上,锁定用户 if err_count >= 3: Users[username]['islocked']=1 acess_logger.info(str(username)+' user locked!') print(str(username)+' user locked!') common.update_users(Users) break else: print('name or password is wrong!') # err_count+=1 @auth def user_center(today,weekday): ''' 用户登陆后进入的用户我的中心界面 :param name:用户名称 :param today: :param weekday:星期几 :return: ''' center_flag=True userinfo=load_user() name=userinfo['name'] while center_flag: print(template.index_user_center.format(name,today,weekday)) choice=input('please input your choice:').strip() if not choice.isdigit() or int(choice) not in range(1,5): print('input wrong,please try again!') continue if int(choice) == 4: print('用户中心和您再见!') center_flag=False break elif int(choice) == 1: common.modify_passwd(userinfo) elif int(choice) == 2: query_salary() elif int(choice) == 3: buylist=common.buy_list(userinfo['name']) for b in buylist: print(b,end='') #额度查询函数,显示信用卡基本信息 def query_salary(): status_all=['正常','被锁定'] userinfo=load_user() salary=userinfo['salary'] total_salary=userinfo['total_salary'] cardno=userinfo['bindcard'] name=userinfo['name'] status=status_all[0] if userinfo['islocked'] ==0 else status_all[1] print(template.card_info.format(cardno,name,total_salary,salary,status)) # print(template.card_info.format(str(cardno),name,str(total_salary),str(salary),status)) #转帐函数 def forward_cash(): userinfo = load_user() salary = userinfo['salary'] u_card_no = userinfo['bindcard'] card_list=[] print('您如今剩余的可用额度为:%d' %salary) card_no=input('请输入对方的卡号:').strip() money=input('请输入转帐的金额:').strip() if not money.isdigit(): print('金额输入有误!') return for k in Users: if Users[k]['bindcard'] != u_card_no: card_list.append(Users[k]['bindcard']) if card_no not in card_list: print('卡号有误') return if int(money) > salary: print('转帐金额超出你的信用额度!') return #减去本身的额度 salary=salary-int(money) userinfo['salary']=salary dump_user(userinfo) Users[userinfo['name']]['salary']=salary #增长别人的额度 for k in Users: if card_no == Users[k]['bindcard']: Users[k]['salary']+=int(money) common.update_users(Users) print('[%s]转帐%d元给%s,手续费%d元' % (userinfo['name'],int(money),card_no)) shop_logger.info('[%s]转帐%d元给%s' % (userinfo['name'],int(money),card_no)) #提现函数 def draw_cash(): cash=input('请输入提现金额:').strip() if not cash.isdigit() or int(cash) < 0: print('金额输入错误!') return userinfo=load_user() salary=userinfo['salary'] if int(cash) > salary: print('你的额度是%s,额度不够!' % salary) return else: salary = salary - int(cash)*1.05 userinfo['salary']=salary dump_user(userinfo) Users[userinfo['name']]['salary'] = salary common.update_users(Users) query_salary() shop_logger.info('[%s]取现%d元,手续费%d元!' % (userinfo['name'],int(cash),int(cash)*0.05)) print('[%s]取现%d元,手续费%d元!' % (userinfo['name'],int(cash),int(cash)*0.05)) #信用卡还款 def repay_salary(): repay_money=input('请输入还款金额:').strip() if not repay_money.isdigit(): print('金额有误!') return else: repay_money=int(repay_money) userinfo = load_user() userinfo['salary'] = userinfo['salary']+repay_money dump_user(userinfo) Users[userinfo['name']]=userinfo common.update_users(Users) query_salary() shop_logger.info('[%s]还款%d元' % (userinfo['name'], repay_money)) print('[%s]还款%d元' % (userinfo['name'], repay_money)) #信用卡中心程序 @auth def card_center(): ''' 信用卡中心程序 :return: ''' func={ '1': query_salary, '2': draw_cash, '3': forward_cash, '4': repay_salary, } card_flag=True while card_flag: #初始化打印信息 userinfo=load_user() user_name=userinfo['name'] card_no=userinfo['bindcard'] print(template.index_card_center.format(user_name,card_no)) choice=input('请选择:').strip() if not choice.isdigit() or int(choice) not in range(1,6): print('输入错误,请重试!') continue if int(choice) == 5: print('信用卡中心和您再见!') break else: func[choice]() #后台管理程序 @auth def manager(): func={ '1':common.create_card, '2':common.lock_card, '3':common.unlock_card, '4':common.modify_salary, } userinfo=load_user() if userinfo['name'] != 'admin': print('只有admin用户能够进入后台管理!') return manager_flag=True while manager_flag: print(template.index_admin.format(userinfo['name'])) choice=input('请选择:').strip() if not choice.isdigit() or int(choice) not in range(1,6): print('输入错误!') continue if int(choice) == 5: print('后台管理和您再见!') manager_flag=False break else: func[choice]() if __name__ == '__main__': Flag=True # Flag=False while Flag: userinfo = load_user() # print(userinfo) # print(userinfo['name']) username = '' # username = userinfo['name'] if len(userinfo) != 0 else '' today=time.strftime('%Y-%m-%d',time.localtime()) weekday=common.numTo_characters(datetime.now().weekday()) print(template.index_default_menu.format(username,today,weekday)) choice = input("请选择:").strip() if not choice.isdigit(): print("输入错误,请从新输入") continue if int(choice) not in range(1,7): print("输入错误,,请从新输入") continue if int(choice) == 1: shop_center() elif int(choice) == 2: user_center(today,weekday) elif int(choice) == 3: card_center() elif int(choice) == 4: manager() elif int(choice) == 5: login() elif int(choice) == 6: with open('.pkl','w',encoding='utf-8'): pass print("再见!") Flag=False creditcard.py
#!/usr/bin/env python #-*- coding:utf-8 -*- # @Time : 2017/10/20 15:28 # @Author : lichuan # @File : template.py """ 该模块用来定义系统的菜单模板,用的网上别人的模板。 """ # 主程序中的主菜单 index_default_menu = ''' ------------------------------------------------------------------------- ATM 模拟程序 {0} 今天 {1} 星期{2} ------------------------------------------------------------------------- 【1】购物商城 【2】用户中心 【3】信用卡中心 【4】后台管理 【5】登陆系统 【6】退出 ''' #购物商城界面 shopping_index_menu = ''' ================================================================================== = = = 信用卡购物商城 = = = ================================================================================== 【1】apple手机 7000元 【2】魅族手机 2000元 【3】小米手机 2500元 【4】华为手机 4000元 【5】小米笔记本 4000元 【6】退出 ''' index_card_center = ''' ------------------------------------------------------------------------------ 信用卡管理中心 用户:{0} 卡号:{1} ------------------------------------------------------------------------------ 【1】额度查询 【2】提现 【3】转帐 【4】还款 【5】返回 ''' # 显示信用卡基本信息模板 card_info = ''' ----------------------------------------------------------------------------------- 信用卡基本信息 卡号:{0} 全部人:{1} 信用额度:{2} 剩余额度:{3} 状态:{4} ----------------------------------------------------------------------------------- ''' index_user_center = ''' ------------------------------------------------------------------------- 用户中心 当前用户:{0} 今天 {1} 星期{2} ------------------------------------------------------------------------- 【1】修改密码 【2】额度查询 【3】消费记录 【4】返回 ''' # 后台管理模板 index_admin = ''' ------------------------------------------------------------------------------ 后台管理 用户:{0} ------------------------------------------------------------------------------ 【1】建立用户 【2】冻结信用卡 【3】解冻用户 【4】额度调整 【5】退出后台管理 ''' #'----------------------------------------------------------------------------------------------------------------------------------------------------------------------' template.py
#!/usr/bin/env python #-*- coding:utf-8 -*- # @Time : 2017/10/20 15:46 # @Author : lichuan # @File : common.py import hashlib from module.users import Users import os import re from log import my_log_settings import logging my_log_settings.load_my_logging_cfg() acess_logger=logging.getLogger(__name__) def numTo_characters(num): ''' 传入数字,转换成星期几中的几 :param num: :return:汉字 ''' if num in range(0,7): week=('一','二','三','四','五','六','日') return week[num] def encrypt(str): ''' 对传入字符串进行加盐加密 :param str: 须要进行加密的字符串 :return: 返回加密过的字符串 ''' encrpt=hashlib.md5() encrpt.update(bytes('admin1234nnnnnn',encoding='utf-8')) encrpt.update(bytes(str,encoding='utf-8')) return encrpt.hexdigest() def update_users(Users): ''' 更新Users信息的函数 :param Users: 用户信息,是个字典 :return: ''' import os user_path=os.path.dirname(os.path.abspath(__file__))+'\\users.py' with open(user_path,'w',encoding='utf-8') as write_f: Users_new='Users='+str(Users) write_f.write(Users_new) #修改密码 def modify_passwd(userinfo): ''' 用于更新Users用户密码信息 :param userinfo: 传入用户信息 :param new_passwd: 新的密码信息 :return: ''' old_passwd=input('请输入如今密码:') new_passwd=input('请输入新密码:') pattern_new_passwd=input('请再次输入新密码:') old_passwd=encrypt(old_passwd) if new_passwd != pattern_new_passwd: print('两次输入密码不一致!') return if old_passwd != userinfo['password']: print('密码错误!') return encrypt_passwd=encrypt(new_passwd) userinfo['password']=encrypt_passwd Users[userinfo['name']]=userinfo update_users(Users) acess_logger.info('%s修改了用户密码!' % userinfo['name']) print('修改密码成功!') #用户的购物消费信息 def buy_list(username): buy=[] shop_path=os.path.normpath(os.path.join( os.path.abspath(__file__), os.pardir, os.pardir, 'log', 'shop.log' )) with open(shop_path,'r',encoding='utf-8') as read_f: lines=read_f.readlines() r='.*\[%s\].*' %username patern = re.compile(r) for line in lines: if patern.match(line): buy.append(line) return buy #建立信用卡用户 def create_card(): flag=True while True: username=input('请输入name:').strip() if len(username) <= 0: print('输入错误!') flag = False break if username in Users: print('用户已存在!') continue mobile=input('请输入手机号:').strip() if len(mobile) <= 0: print('输入错误!') flag = False break for i in Users: if Users[i]['mobile'] == mobile: print('手机号已经存在!') flag=False break card_no = input('请输入卡号:').strip() if len(card_no) <= 0 or not card_no.isdigit(): print('输入错误!') flag = False break for i in Users: if Users[i]['bindcard'] == card_no: print('卡号已经存在!') flag = False break passwd = input('请输入密码:').strip() encrypt_passwd=encrypt(passwd) userinfo={ 'isdel': 0, 'name': username, 'password': encrypt_passwd, 'islocked': 0, 'salary': 15000, 'total_salary': 15000, 'bindcard': card_no, 'mobile': mobile, 'buy_list': {} } Users[username]=userinfo update_users(Users) acess_logger.info('新建立用户%s' % username) print('新建立用户%s已成功' % username) flag=False #冻结信用卡 def lock_card(): name=input('请输入要冻结的用户名:').strip() if name == 'admin': print('不能冻结admin帐号!') return if name in Users: Users[name]['islocked'] = 1 update_users(Users) acess_logger.info('%s用户被冻结' %name) print('%s用户被成功冻结' %name) else: print('用户不存在!') #解冻信用卡 def unlock_card(): name = input('请输入要解冻的用户名:').strip() if name in Users: Users[name]['islocked'] = 0 update_users(Users) acess_logger.info('%s用户被解冻' % name) print('%s用户被成功解冻' % name) else: print('用户不存在!') #调整额度 def modify_salary(): name = input('请输入要调整额度的用户名:').strip() total_salary=input('请输入新额度:').strip() if not total_salary.isdigit(): print('额度错误!') return if name in Users: Users[name]['salary'] = int(total_salary) - (Users[name]['total_salary']-Users[name]['salary']) Users[name]['total_salary'] = int(total_salary) update_users(Users) acess_logger.info('%s用户额度调整为%s' % (name,total_salary)) print('%s用户额度调整为%s' % (name,total_salary)) else: print('用户不存在!') if __name__ == '__main__': # modify_passwd({},'bbb') # print('it is common') r=buy_list('alex') for i in r: print(i,end='') common.py
Users={'alex': {'isdel': 0, 'name': 'alex', 'password': 'bc5b9cb3e4ab483335edab3347f3c102', 'islocked': 0, 'salary': 52187.4, 'total_salary': 15000, 'bindcard': '1001012345', 'mobile': '13511111111', 'buy_list': {'apple手机': 1, '魅族手机': 1, '小米手机': 1, '华为手机': 1, '小米笔记本': 2}}, 'egon': {'isdel': 0, 'name': 'egon', 'password': 'bc5b9cb3e4ab483335edab3347f3c102', 'islocked': 0, 'salary': 16950, 'total_salary': 15000, 'bindcard': '1001012346', 'mobile': '13511111112', 'buy_list': {}}, 'admin': {'isdel': 0, 'name': 'admin', 'password': 'bc5b9cb3e4ab483335edab3347f3c102', 'islocked': 0, 'salary': 15000, 'total_salary': 15000, 'role': 'admin', 'bindcard': '1001010002', 'mobile': '15257157418'}, 'lit': {'isdel': 0, 'name': 'lit', 'password': 'bc5b9cb3e4ab483335edab3347f3c102', 'islocked': 0, 'salary': 50000, 'total_salary': 50000, 'bindcard': '1001012347', 'mobile': '13520381333', 'buy_list': {}}} users.py
""" logging配置 """ import os import logging.config # 定义三种日志输出格式 开始 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' shop_format= '[%(asctime)s]%(message)s' # 定义日志输出格式 结束 logfile_dir = os.path.dirname(os.path.abspath(__file__)) # log文件的目录 logfile_name = 'access.log' # log文件名 # 若是不存在定义的日志目录就建立一个 if not os.path.isdir(logfile_dir): os.mkdir(logfile_dir) # log文件的全路径 logfile_path = os.path.join(logfile_dir, logfile_name) shop_path = os.path.join(logfile_dir, 'shop.log') # log配置字典 LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, 'id_simple': { 'format': id_simple_format }, 'shop_format': { 'format': shop_format }, }, 'filters': {}, 'handlers': { #打印到终端的日志 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, #打印到文件的日志,收集info及以上的日志 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': logfile_path, # 日志文件 'maxBytes': 1024*1024*5, # 日志大小 5M 'backupCount': 5, 'encoding': 'utf-8', # 日志文件的编码,不再用担忧中文log乱码了 }, 'boss': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': 'boss.log', # 日志文件 'maxBytes': 1024 * 1024 * 5, # 日志大小 5M 'backupCount': 5, 'encoding': 'utf-8', # 日志文件的编码,不再用担忧中文log乱码了 }, 'shop': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'shop_format', 'filename': shop_path, # 日志文件 'encoding': 'utf-8', # 日志文件的编码,不再用担忧中文log乱码了 }, }, 'loggers': { #logger1=logging.getLogger(__name__)拿到的logger配置 '': { 'handlers': ['default',], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)传递 }, #logger1=logging.getLogger('collect')拿到的logger配置 'collect': { 'handlers': ['boss',], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)传递 }, 'shop': { 'handlers': ['shop'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 'level': 'INFO', 'propagate': True, # 向上(更高level的logger)传递 }, }, } def load_my_logging_cfg(): logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置 # logger = logging.getLogger(__name__) # 生成一个log实例 # logger = logging.getLogger('shopping') # 生成一个log实例 # logger.info('It works2!') # 记录该文件的运行状态 if __name__ == '__main__': load_my_logging_cfg() my_log_settings.py