def run_task(one): """ # 对每个用户去进行监控 :param one: :return: """ days_dic = reckon_remaind(one.user_uuid) if days_dic and 'last_days' in days_dic: days = days_dic['last_days'] # 用户没有主机时候不用监控 if days <= 0: log.info( '[monitor][run_task] the user:%s no host.Need not monitor', one.user_uuid) return check_alert = AlertRecord.objects.filter(user_id=one.user_uuid) minor_alarm_days = get_config_value('minor_alarm_days') critical_alarm_days = get_config_value('critical_alarm_days') emergency_alarm_days = get_config_value('emergency_alarm_days') if days > minor_alarm_days: log.info('[monitor] run_task.the account is enough') return if days <= minor_alarm_days and days > critical_alarm_days: check_alert_time(one.user_uuid, check_alert, 1, days) elif days <= critical_alarm_days and days > emergency_alarm_days: check_alert_time(one.user_uuid, check_alert, 2, days) elif days <= emergency_alarm_days: check_alert_time(one.user_uuid, check_alert, 3, days) log.info( '[monitor][run_task] the user:%s\'s account can support %s days.', one.user_uuid, days)
def __init__(self): # 客户端ID self.MODE = get_config_value('paypal_mode') # 客户端密钥 self.CLIENT_ID = get_config_value('paypal_client_id') # 客户端密匙 self.CLIENT_SECRET = get_config_value('paypal_client_secret')
def __init__(self): # 安全检验码,以数字和字母组成的32位字符 self.ALIPAY_KEY = get_config_value('alipay_key') # 合作身份者ID,以2088开头的16位纯数字 self.ALIPAY_PARTNER = get_config_value('alipay_partner') # 告警通知邮箱 self.ALIPAY_SELLER_EMAIL = get_config_value('alipay_seller_email')
def get_alert_strategy(): sms_notify = int(get_config_value('sms_notify')) email_notify = int(get_config_value('email_notify')) if sms_notify == 0 and email_notify == 0: notify_strategy = 0 elif sms_notify == 0 and email_notify == 1: notify_strategy = 1 elif sms_notify == 1 and email_notify == 0: notify_strategy = 2 else: notify_strategy = 3 return notify_strategy
def list(self, request): ''' # 使用user_uuid查询账户详情, user_uuid不存在时使用该uuid以及默认配置创建新账户 ''' pk = request.GET.get('user_uuid') if not is_valid_user_uuid(pk): return Response({ 'detail': 'user_uuid非法', 'error_code': '2400' }, status=status.HTTP_400_BAD_REQUEST) try: queryset = PaymentAccount.objects.get(user_uuid=pk) except PaymentAccount.DoesNotExist: # 查询不到该用户时使用默认配置创建新账号 queryset = PaymentAccount(user_uuid=pk, credit=get_config_value('credit', 0)) queryset.save() log.info( '[account] create payment account %s use default settings.', pk) except ValueError: log.error('[account] get account info error, user_uuid: %s', pk) return Response({ 'detail': '参数错误', 'error_code': '1400' }, status=status.HTTP_400_BAD_REQUEST) serializer = PaymentAccountRetrieveSerializer( queryset, context={'request': request}) return Response(serializer.data)
def paypal_return_url(self, request): """ paypal 余额支付回调接口 """ payment_no = request.query_params.get('paymentId') log.info('[payment] received paypal payment_no: %s', payment_no) payer_id = request.query_params.get('PayerID') try: payment = Payment.objects.get(payment_no=payment_no) except Payment.DoesNotExist: log.error('[payment] no such payment %s', ) return Response({ 'error': u'未发现订单', 'error_code': '3404' }, status=status.HTTP_404_NOT_FOUND) paypal_payment = execute_payment(payment_no, payer_id) if paypal_payment is None and payment.paid_status == 'waiting': # 交易失败 payment.paid_status = 'failed' payment.save() return Response({'error': u'charge fail'}) for transaction in paypal_payment.transactions: for related_resource in transaction.related_resources: sale_id = related_resource.sale.id payment.sale_id = sale_id sale_state = related_resource.sale.state # 充值 payment_charge_success(payment, request.query_params) # return Response({'success': u'charge success'}) return HttpResponseRedirect( get_config_value('redirect_url') + '/wallet')
def alert_message(user_uuid, level_days, notify_strategy=None): """ # 调用通知接口 """ data = {} data['user_name'] = get_user_name(user_uuid) data['level'] = 'INFO' data['module'] = 'BL' data['msg_title'] = 'account alert' data['msg_content'] = '您的账户余额已不足,预估可使用[%s]天' % (level_days) data['msg_url'] = '' if notify_strategy is None: data['is_phone'] = 'True' if get_config_value( 'sms_notify') else 'False' data['is_email'] = 'True' if get_config_value( 'email_notify') else 'False' elif notify_strategy == 0: data['is_phone'] = 'False' data['is_email'] = 'False' elif notify_strategy == 1: data['is_phone'] = 'False' data['is_email'] = 'True' elif notify_strategy == 2: data['is_phone'] = 'True' data['is_email'] = 'False' else: data['is_phone'] = 'True' data['is_email'] = 'True' alert_url = ENV_INIT['ALERT_URL'] try: alert_return = requests.post(alert_url, data=data, timeout=10) except requests.exceptions.RequestException: log.error('[monitor.alert_message] connect {} error'.format(alert_url)) return log.debug("[monitor.alert_message] call the message api [%s]" % (alert_url)) if alert_return.status_code == 200: log.info("[monitor.alert_message] send message[%s]success" % (str(data))) else: log.error("[monitor.alert_message] send message[%s]fail" % (str(data)))
def alipay_return_url(self, request): """ 支付宝同步回调接口 """ # if notify_verify(request.data) is False: # print '签名验证失败' # return HttpResponse('fail') # print request.query_params # return HttpResponse('success') # 完成的url return HttpResponseRedirect( get_config_value('redirect_url') + '/wallet')
def get_account_by_user_uuid(**kwargs): """ # 使用user_uuid查询账户详情, user_uuid不存在时使用该uuid以及默认配置创建新账户 """ if not is_valid_user_uuid(kwargs.get('user_uuid')): return False try: queryset = PaymentAccount.objects.get( user_uuid=kwargs.get('user_uuid')) except PaymentAccount.DoesNotExist: # 查询不到该用户时使用默认配置创建新账号 queryset = PaymentAccount(user_uuid=kwargs['user_uuid'], credit=get_config_value('credit', 0)) queryset.save() log.info('[account] create payment account %s use default settings.', kwargs.get('user_uuid')) return queryset
def check_account(self, request): """ 检查账户余额 :param request: :return: """ try: payment_accountid = request.data['payment_accountid'] price_uuid = request.data['price_uuid'] num = request.data['num'] except KeyError: return Response({'detail': 'the key is not enough or error'}, status=status.HTTP_400_BAD_REQUEST) # print 'type(price_uuid):',type(price_uuid) price = gain_price_byuuid(price_uuid=price_uuid) if price: dict1 = {} # 估算余额可以支持使用的时长 try: days_dic = reckon_remaind(payment_accountid, num, price.price) if days_dic['last_days'] < int( get_config_value('min_remaining_days')): dict1['is_allow'] = False else: dict1['is_allow'] = True dict1['last_days'] = days_dic['last_days'] dict1['active_money'] = days_dic['active_money'] return Response(dict1, status=status.HTTP_200_OK) except Exception as e: log.error('[monitor] {}'.format(e.__str__())) return Response({'detail': 'server error'}, status.HTTP_500_INTERNAL_SERVER_ERROR) else: return Response({'detail': 'the price strategy is not existed'}, status.HTTP_400_BAD_REQUEST)
def reckon_remaind(user_uuid, num=0, minute_price=0): """ # user_uuid,minute_price # 通过user_uuid估算剩余使用天数(天), """ log.info( '[monitor] reckon_remaind user_uuid:[%s],num=[%s],minute_price[%s]' % (user_uuid, num, minute_price)) # 默认值 data_dic = {'last_days': 0, 'active_money': 0, 'host_num': 1} try: num = int(num) minute_price = float(minute_price) host_url = create_url('1a' + user_uuid) except Exception: log.error('[monitor] reckon_remaind parameter is in invalid') return data_dic # 查看用户账户余额 account = get_account_by_user_uuid(user_uuid=user_uuid) if not account: return data_dic strategy = get_config_value('strategy') if strategy == 'NO_BALANCE_LEFT': credit = 0 else: credit = get_config_value('credit', 0) # 如果余额加信用额度小于0,就直接返回 if account.balance + credit <= 0: log.info( '[monitor] reckon_remaind user:%s,account.balance:%s,credit:%s balance \ less than 0' % (user_uuid, account.balance, credit)) data_dic['active_money'] = account.balance + credit return data_dic try: hosts_all = requests.get(host_url, timeout=10).json() log.debug('[monitor] get data from [%s]return[%s]' % (host_url, str(hosts_all))) except Exception: log.error( '[monitor] util.run_task:connect beancounter timeout or refused') return data_dic host_userid = '' if isinstance(hosts_all, dict) and 'id' in hosts_all: host_userid = hosts_all['id'] if not host_userid: return data_dic # 没有主机的情况 if 'hosts' not in hosts_all or len(hosts_all['hosts']) == 0: data_dic['host_num'] = 0 if num and minute_price: data_dic['last_days'] = round( float(account.balance + credit) / (minute_price * num * 60 * 24), 2) else: data_dic['last_days'] = 0 data_dic['active_money'] = account.balance log.debug( '[monitor] [reckon_remaind] the user:%s no host. last_days=%s', user_uuid, data_dic['last_days']) return data_dic no_pay_fee = 0 price_minute = 0 for host in hosts_all['hosts']: hostObj = Host(user_uuid, host_userid, host) if hostObj.is_invalid(): log.error('[monitor] The host is invalid') continue price_minute += hostObj.price no_pay_fee += hostObj.get_nopay_fee() # 如果主机删除,生成账单并扣费 if hostObj.is_deleted(): hostObj.create_bill() log.info( '[monitor][reckon_remaind] the user:%s\'s host:%s is deleted', user_uuid, hostObj.host_uuid) # 实际可用余额 active_money = account.balance - no_pay_fee # 实际可用余额小于0,直接返回 if active_money <= 0: data_dic['active_money'] = active_money log.info('[monitor] [reckon_remaind] the user:%s active_money=%s', user_uuid, active_money) return data_dic if num and minute_price: # 如果是check_account接口来调用,那么每分钟价格需要加上需要开启主机的数量和每种规格的价格 price_minute = price_minute + minute_price * num if price_minute > 0: last_days = round( float(active_money + credit) / (price_minute * 60 * 24), 2) else: last_days = 0 data_dic['last_days'] = last_days data_dic['active_money'] = active_money return data_dic
def change_balance(user_uuid, modify_source_type, modify_balance, modify_source_uuid, payment_account_uuid=None): """ # 账户变更接口, 变更用户额度以及可用性. { "payment_account_uuid":"68c4add4-9f14-11e6-80d3-6451066036bd", "modify_balance":-100, "modify_source_type": "bill", "modify_source_uuid":"68c4add4-9f14-11e6-80d3-6451066036bd" } """ try: if user_uuid: paymentAccount = PaymentAccount.objects.get(user_uuid=user_uuid) elif payment_account_uuid: paymentAccount = PaymentAccount.objects.get( payment_account_uuid=payment_account_uuid) else: log.error('[account] no param payment_account_uuid or user_uuid') return False except PaymentAccount.DoesNotExist: log.error('[account] %s not found', payment_account_uuid or user_uuid) return False if modify_balance < 0 and modify_source_type not in ('bill', 'admin', 'refund'): log.error('[account] modify_source_type not match modify_balance') return False elif modify_balance > 0 and modify_source_type not in ('payment', 'admin'): log.error('[account] modify_source_type not match modify_balance') return False # 基于策略以及额度判断 balance = paymentAccount.balance + modify_balance if get_config_value('strategy', 'NO_BALANCE_LEFT') == 'NO_BALANCE_LEFT': is_valid = False if balance < 0 else True if get_config_value('strategy', 'NO_BALANCE_LEFT') == 'NO_CREDIT_LEFT': is_valid = False if (balance + paymentAccount.credit) < 0 else True try: accountRecord = AccountRecord(payment_account_uuid=paymentAccount, modify_balance=modify_balance, modify_source_type=modify_source_type, modify_source_uuid=modify_source_uuid) # 用户额度变更 paymentAccount.balance = balance paymentAccount.is_valid = is_valid paymentAccount.save() # 变更记录生成 accountRecord.save() log.info('[account] change balance from modify_source_uuid %s success', modify_source_uuid) if modify_balance > 0: reset_monitor(user_id=paymentAccount.user_uuid) log.info('[account] notify monitor reset alarm times') return True except TransactionManagementError: log.error('[account] change balance from modify_source_uuid %s error', modify_source_uuid) return False