def validate_amount_max(self, value): try: if value.data: self.amount_max.data = Decimal(str(value.data)) BalanceKit.multiple_hundred(self.amount_max.data) else: self.amount_max.data = 0 except Exception as e: raise StopValidation("无效的 amount_max")
def test_balance_multiple(self): v = Decimal("1.12") v1 = BalanceKit.multiple_unit(v) v2 = BalanceKit.divide_unit(v1) self.assertEqual(v, v2) v = Decimal("1.1211") d = 10000 v1 = BalanceKit.multiple_unit(v, d) v2 = BalanceKit.divide_unit(v1, d) self.assertEqual(v, v2)
def get_day_amount(self, channel: ChannelConfigEnum): value = self.hget(channel.name) if not value: return 0 value = int(value.decode('utf8')) return BalanceKit.divide_hundred(value)
def post(self): """ 用户余额调整 :return: """ form, error = UserBalanceEditForm.request_validate() if error: return error.as_response() uid = form.uid.data # 判断该用户id是否存在 user = User.query.filter_by(**dict(id=uid)).first() if not user: return AdjustUserBalanceError(message="系统找不到该用户").as_response() ad_type = BalanceAdjustTypeEnum.PLUS # 当调整状态为 减少时 需要判断 当前用户余额和商户余额值 amount = BalanceKit.round_4down_5up(Decimal(form.amount.data)) if form.adjust_type.data == BalanceAdjustTypeEnum.MINUS: ad_type = BalanceAdjustTypeEnum.MINUS # 获取用户余额 并判断 user_balance_info = UserBalance.query.filter( UserBalance.id == uid).first() if not user_balance_info: return UserBalanceNoFoundError().as_response() user_balance = user_balance_info.real_balance if Decimal(user_balance) - amount < 0: print("用户没有足够的金额", user_balance, amount) return AdjustUserBalanceError( message="用户没有足够的金额").as_response() # 获取商户余额 并判断 merchant_balance_info = MerchantInfo.query.filter_by(**dict( _merchant=user_balance_info.merchant.value)).first() if not merchant_balance_info: return AdjustUserBalanceError(message="该商户信息不存在").as_response() bl_ava = merchant_balance_info.balance_available if Decimal(bl_ava) - amount < 0: print("商户没有足够的余额", bl_ava, amount) return AdjustUserBalanceError( message="商户没有足够的余额").as_response() # 调整用户及商户余额 flag, error = AdjustTransactionCtl.adjust_create( user=user, source=OrderSourceEnum.MANUALLY, amount=amount, order_type=PayTypeEnum.MANUALLY, bl_type=BalanceTypeEnum.AVAILABLE, ad_type=ad_type, comment=form.comment.data) if not flag: return AdjustUserBalanceError(message="余额调整失败").as_response() return ResponseSuccess().as_response()
def construct_request(self, order, params: dict): pay_params = { PayMethodEnum.ZHIFUBAO_H5: dict(channel=7, render_type=SdkRenderType.QR_CODE), PayMethodEnum.WEIXIN_H5: dict(channel=1, render_type=SdkRenderType.QR_CODE) } payment_method = self.channel_enum.conf['payment_method'] request_fields = ['pay_type', 'mch_id', 'order_id', 'channel_id', 'pay_amount', 'name', 'explain', 'remark', 'result_url', 'notify_url', 'client_ip', 'bank_cardtype', 'bank_code', 'is_qrimg', 'is_sdk', 'ts', 'sign', 'ext'] sorted_params = sorted(request_fields) request_body = {} for field in request_fields: if field == "pay_type": request_body[field] = 2 elif field == "mch_id": request_body[field] = int(self.third_config['mch_id']) elif field == "order_id": request_body[field] = order.sys_tx_id elif field == "channel_id": request_body[field] = pay_params[payment_method]['channel'] elif field == "pay_amount": request_body[field] = str(BalanceKit.round_4down_5up(order.amount)) elif field == "name": request_body[field] = "mch name" elif field == "explain": request_body[field] = "explain text" elif field == "remark": request_body[field] = "remark message" elif field == "result_url": request_body[field] = self.third_config['return_url'] elif field == "notify_url": request_body[field] = self.third_config['callback_url'] elif field == "client_ip": request_body[field] = params['client_ip'] elif field == 'is_qrimg': request_body[field] = 0 elif field == 'is_sdk': request_body[field] = 1 elif field == 'ts': request_body[field] = DateTimeKit.get_cur_timestamp() elif field == 'ext': request_body[field] = "ext message" sign_str = "&".join(["{}={}".format(k, request_body[k]) for k in sorted_params if request_body.get(k, False) or k in ["is_qrimg", "is_sdk"]]) # sign_str += self.third_config['secret_key'] print("sign string: ", sign_str) print("request body: ", request_body) render_type = pay_params[payment_method]['render_type'] return request_body, sign_str, render_type
def test_balance_round(self): i = 1 for x in range(0, 10): d = Decimal(self.format_float(x=x, i=i)) v = BalanceKit.round_4down_5up(d) self.assertEqual(d, v) for y in range(0, 10): d = Decimal(self.format_float(x=x, y=y, i=i)) v = BalanceKit.round_4down_5up(d) self.assertEqual(d, v) for z in range(0, 10): # 原始值 d = Decimal(self.format_float(x=x, y=y, z=z, i=i)) # 期望值 if z >= 5: # z进位,y自增 _x = x _y = y + 1 _i = i if _y >= 10: # y进位,x自增 _y = 0 _x += 1 if _x >= 10: # x进位,i自增 _x = 0 _i += 1 e = Decimal(self.format_float(x=_x, y=_y, i=_i)) else: # 舍掉z e = Decimal(self.format_float(x=x, y=y, i=i)) # 实际值 v = BalanceKit.round_4down_5up(d) self.assertEqual(e, v, (x, y, z))
def calc_cost(cls, amount, fee_type: PaymentFeeTypeEnum, fee_value: Decimal): """ 计算成本: 通道收取的手续费 :param amount: :param fee_type: :param fee_value: :return: """ if fee_type == PaymentFeeTypeEnum.PERCENT_PER_ORDER: return BalanceKit.round_4down_5up(amount * fee_value / Decimal(100.0)) return fee_value
def calc_fee(cls, amount: Decimal, fee_type: PaymentFeeTypeEnum, fee_value: Decimal): """ 计算手续费: 我们收取下游商户的手续费 :param amount: :param fee_type: :param fee_value: :return: """ if fee_type == PaymentFeeTypeEnum.PERCENT_PER_ORDER: return BalanceKit.round_4down_5up( Decimal(amount) * fee_value / Decimal(str(100.0))) return fee_value
def post(self): """ 获取用户余额 """ # uid = g.user.uid # merchant = g.user.merchant # account = g.user.account # is_active = g.user.is_active # state = g.user.state # ac_type = g.user.ac_type # login_pwd = g.user.login_pwd balance = UserBalance.query_balance(uid=g.user.uid, merchant=g.user.merchant).first() return ResponseUserBalance( bs_data=dict(balance=BalanceKit.divide_unit(balance.balance), has_trade_pwd=g.user.has_trade_pwd())).as_response()
def post(self): """ 提现接口: 检查支付密码是否正确,如果密码正确则创建用户提现订单 """ form, error = CreateWithdrawOrderForm().request_validate() if error: return error.as_response() uid = g.user.uid merchant = g.user.merchant if not g.user.has_permission(UserPermissionEnum.WITHDRAW): return UserPermissionDeniedError().as_response() amount = BalanceKit.round_4down_5up(Decimal(form.amount.data)) user_bank_id = form.user_bank.data client_ip = form.client_ip.data trade_password = form.trade_password.data # 判断 支付密码是否正确 if not User.verify_payment_password( merchant=merchant, uid=uid, password=trade_password): cache = UserPaymentPasswordLimitCache(uid=uid) cache.incr_times() times = cache.get_left_times() return PaymentPasswordError(message=PaymentPasswordError.message. format(times)).as_response() order, error = WithdrawTransactionCtl.order_create( user=g.user, amount=amount, client_ip=client_ip, user_bank_id=user_bank_id, ) if error: return error.as_response() return ResponseSuccess().as_response()
def limit_day_max(self): if not self._limit_day_max: return 0 return BalanceKit.divide_hundred(self._limit_day_max)
def limit_per_max(self, value): self._limit_per_max = BalanceKit.multiple_hundred(value)
def limit_per_max(self): return BalanceKit.divide_hundred(self._limit_per_max)
def fee(self, value): self._fee = BalanceKit.multiple_hundred(value)
def cost(self): if not self._cost: return 0 return BalanceKit.divide_hundred(self._cost)
def tx_amount(self): if not self._tx_amount: return 0 return BalanceKit.divide_hundred(self._tx_amount)
def amount_max(self): if self._amount_max: return BalanceKit.divide_hundred(self._amount_max) return 0
def offer(self, value): self._offer = BalanceKit.multiple_hundred(value)
def profit(self): if not self._profit: return 0 return BalanceKit.divide_hundred(self._profit)
def offer(self): if not self._offer: return 0 return BalanceKit.divide_hundred(self._offer)
def fee(self): if not self._fee: return 0 return BalanceKit.divide_hundred(self._fee)
def cost(self, value): self._cost = BalanceKit.multiple_hundred(value)
def limit_day_max(self, value): if value != 0: self._limit_day_max = BalanceKit.multiple_hundred(value) else: self._limit_day_max = 0
def tx_amount(self, value): self._tx_amount = BalanceKit.multiple_hundred(value)
def amount_min(self): if self._amount_min: return BalanceKit.divide_hundred(self._amount_min) return 0
def validate_amount(self, value): try: self.amount.data = Decimal(value.data) BalanceKit.multiple_hundred(self.amount.data) except Exception as e: raise StopValidation("无效的 amount,必须是整数或浮点数字符串,最多保留2位小数")
def amount_max(self, value): if value: self._amount_max = BalanceKit.multiple_hundred(value) else: self._amount_max = 0
def fee(self): return BalanceKit.divide_hundred(self._fee)
def amount(self): return BalanceKit.divide_hundred(self._amount)
def profit(self, value): self._profit = BalanceKit.multiple_hundred(value)