# -*- encoding: utf-8 -*- # ----------------------------------------------------------------------------- # @File Name : order_service.py # @Time : 2020/11/18 下午3:35 # @Author : X. Peng # @Email : acepengxiong@163.com # @Software : PyCharm # ----------------------------------------------------------------------------- import time from app.api.engine import tamp_pay_session, tamp_user_session from app.config.errors import Errors from app.controller.errorhandler import CustomFlaskErr from app.model.account_balance import AccountBalance from app.model.account_topup_order import AccountTopupOrder from app.model.curriculum_order import OrderFlow from app.model.tamp_user_models import CurriculumPrice, CurriculumColumn, CurriculumRes from xml.etree import cElementTree as etree from app.utils.alipay.alipayWap import prePay from app.utils.apple_pay import apple_pay from app.utils.wxpay.wx_app_pay import WXPay class TopUpOrderService: """""" def __init__(self): pass def get_order(self, user_id): res = tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.user_id == user_id).all() return [r.to_dict() for r in res] def create_order(self, args): args['order_no'] = time.strftime('%Y%m%d', time.localtime(time.time())) + str(int(time.time() * 100000)) args['id'] = AccountTopupOrder.__tablename__ + str(int(time.time() * 100000)) args['amount'] = args['amount'] * 100 args['order_status'] = 0 subject = '探普币充值' out_trade_no = args['order_no'] notify_path = '/tamp_order/micro_shop/topUpOrderNotify' pay_params = None if args['pay_method'] == 2: # 微信支付 wx_pay = WXPay(out_trade_no, subject, args['amount'], args['remote_addr'], notify_path=notify_path) params = wx_pay.getReturnParams() pay_params = params elif args['pay_method'] == 3: # 支付宝支付 total_amount = args['amount'] / 100 res = prePay(subject, out_trade_no, total_amount, notify_path=notify_path) pay_params = res elif args['pay_method'] == 4: # 苹果支付 receipt_data = args.get('receipt_data', '') if not apple_pay(receipt_data): raise CustomFlaskErr(Errors.APPLE_VOCHER_INVALID) args['order_status'] = 1 if not tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == args['user_id']).all(): tamp_pay_session.add(AccountBalance(id=AccountBalance.__tablename__+str(int(time.time()*100000)), user_id=args['user_id'], apple_balance=args['amount'])) else: tamp_pay_session.query(AccountBalance).filter( AccountBalance.user_id == args['user_id']).update({ 'apple_balance': AccountBalance.apple_balance + args['amount'] }) args.pop('remote_addr', '') args.pop('receipt_data', '') order_info = AccountTopupOrder(**args) tamp_pay_session.add(order_info) tamp_pay_session.commit() tamp_pay_session.close() return pay_params class CurriculumOrderService: """""" def __init__(self): pass def get_order(self, user_id): """.""" curriculum_column = tamp_user_session.query(CurriculumColumn).all() curriculum_res = tamp_user_session.query(CurriculumRes).all() res = tamp_user_session.query(OrderFlow).filter(OrderFlow.createby == user_id).all() curriculum_column = {r.id: r.to_dict() for r in curriculum_column} curriculum_res = {r.id: r.to_dict() for r in curriculum_res} orders = [r.to_dict() for r in res] for order in orders: prod_type = order.get('ab_si_type', '') prod_id = order.get('ab_proid', '') if prod_type == '1': order['prod_info'] = curriculum_column.get(prod_id, None) elif prod_type in ['3', '4', '5']: order['prod_info'] = curriculum_res.get(prod_id, None) return orders def create_order(self, args): """。""" args['ab_ordernum'] = time.strftime('%Y%m%d', time.localtime(time.time())) + str(int(time.time() * 100000)) amount = tamp_user_session.query(CurriculumPrice.price).filter(CurriculumPrice.rel_id == args['ab_proid']).first()[0] args['id'] = OrderFlow.__tablename__ + str(int(time.time()*100000)) args['ab_payment'] = amount * 100 args['ab_status'] = 'WAIT' subject = args.get('prod_name', '') out_trade_no = args['ab_ordernum'] notify_path = '/tamp_order/micro_shop/topUpOrderNotify' pay_params = None if args['ab_pay_mode'] == 4: # 探普币支付 if args['env'] == 'ios': res = tamp_pay_session.query(AccountBalance.apple_balance).filter(AccountBalance.user_id == args['user_id']).first() if not res: raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH) elif res[0] < args['ab_payment']: raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH) else: tamp_pay_session.query(AccountBalance.apple_balance).filter(AccountBalance.user_id == args['user_id']).update({ 'apple_balance': AccountBalance.apple_balance - args['ab_payment'] }) args['ab_status'] = 'SUCCESS' elif args['env'] == 'android': res = tamp_pay_session.query(AccountBalance.android_balance).filter( AccountBalance.user_id == args['user_id']).first() if not res: raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH) elif res[0] < args['ab_payment']: raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH) else: tamp_pay_session.query(AccountBalance.android_balance).filter( AccountBalance.user_id == args['user_id']).update({ 'android_balance': AccountBalance.android_balance - args['ab_payment'] }) args['ab_status'] = 'SUCCESS' elif args['ab_pay_mode'] == 5: # 微信支付 wx_pay = WXPay(out_trade_no, subject, args['ab_payment'], args['remote_addr'], notify_path=notify_path) params = wx_pay.getReturnParams() pay_params = params elif args['ab_pay_mode'] == 6: # 支付宝支付 total_amount = args['ab_payment'] / 100 res = prePay(subject, out_trade_no, total_amount, notify_path=notify_path) pay_params = res args['createby'] = args.pop('user_id', '') args.pop('prod_name', '') args.pop('env', '') args.pop('remote_addr', '') order_info = OrderFlow(**args) tamp_user_session.add(order_info) tamp_user_session.commit() tamp_pay_session.commit() return pay_params def topUpSuccessAction(order_no): """.""" topup_order = tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.order_no == order_no).first() # 幂等校验 if topup_order.order_status == 1: return False tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.order_no == order_no).update({ 'order_status': 1 }) # 账户充值 account_topup_order = tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.order_no == order_no).first().to_dict() # 安卓支付宝,微信支付 if not tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == account_topup_order.user_id).all(): tamp_pay_session.add(AccountBalance(id=AccountBalance.__tablename__ + str(int(time.time()*10000)), user_id=account_topup_order.user_id, android_balance=account_topup_order.amount)) else: tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == account_topup_order.user_id).update({ 'apple_balance': AccountBalance.android_balance + account_topup_order.amount }) tamp_pay_session.commit() def consumeSucessAction(order_no): """.""" curriculum_order = tamp_pay_session.query(OrderFlow.ab_ordernum == order_no).all() # 幂等校验 if curriculum_order.ab_status == 'SUCCESS': return False tamp_pay_session.query(OrderFlow).filter(OrderFlow.ab_ordernum == order_no).update({ 'ab_status': 'SUCCESS' }) tamp_pay_session.commit() def getAccountBalance(user_id): """查询探普币余额""" account_balance = tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == user_id).first() if not account_balance: return {'user_id': user_id, 'android_balance': 0, 'apple_balance': 0} else: return account_balance.to_dict() def xml2dict(content): """将从微信服务器接收到的xml转为dict.""" raw = {} root = etree.fromstring(content) for child in root: raw[child.tag] = child.text return raw def dict2xml(dict_): """将dict转为要发送到微信服务器的xml格式.""" s = "" for k, v in dict_.items(): s += "<{0}>{1}</{0}>".format(k, v) s = "<xml>{0}</xml>".format(s) return s.encode("utf-8") def alipayWxPayCheck(res_info): """支付宝,微信支付异步通知""" success = False body = None header = {'Content-Type': 'application/text'} res = {} if 'trade_status' in res_info: # 支付宝支付 res_info = res_info.split('&') for ss in res_info: key, value = ss.split('=') res[key] = value if res['trade_status'] == 'TRADE_SUCCESS': success = True body = 'success'.encode() else: # 微信支付 res = xml2dict(res_info) if res['result_code'] == 'SUCCESS' and res['return_code'] == 'SUCCESS': success = True header = {'Content-Type': 'application/xml'} body = '<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>' return {'success': success, 'header': header, 'body': body, 'order_no': res['out_trade_no']}