Ejemplo n.º 1
0
    def test_order(self):
        order = OrderHelper.place_order(type=u'充值', product_id='1234123')
        self.assertTrue(order.id >= 0)
        self.assertEqual(order.extra_data['product_id'], '1234123')

        order = OrderHelper.update_order(order, status=u'关闭')
        self.assertEqual(order.status, u'关闭')

        sub_order = OrderHelper.place_order(type=u'充值', somekey='value')
        sub_order.parent = order

        sub_order.save()

        order = Order.objects.get(pk=order.id)
        self.assertEqual(len(order.children.all()), 1)
Ejemplo n.º 2
0
    def __init__(self, product, user, order_id=None, request=None):
        self.user = user
        self.product = product

        if self.product.status != u"正在招标":
            raise P2PException(u'购买的标不在招标状态')

        self.request = request
        if order_id is None:
            self.order_id = OrderHelper.place_order(user,
                                                    order_type=u'产品申购',
                                                    product_id=product.id,
                                                    status=u'新建').id
        else:
            self.order_id = order_id
        self.margin_keeper = MarginKeeper(user=user, order_id=self.order_id)
        self.product_keeper = ProductKeeper(product, order_id=self.order_id)
        self.equity_keeper = EquityKeeper(user=user,
                                          product=product,
                                          order_id=self.order_id)
        if request:
            self.device = split_ua(request)
            self.device_type = self.device['device_type']
        else:
            self.device = split_ua(request)
            self.device_type = "pc"
Ejemplo n.º 3
0
    def generate_payinfo(cls, clean=False):
        if clean:
            PayInfo.objects.all().delete()

        banks = Bank.objects.all()

        # generate 5 payinfo per user
        for user in get_user_model().objects.all():

            for i in range(0, 6):
                pay = PayInfo()
                pay.user = user
                pay.type = 'D'
                pay.amount = random.randrange(1000, 10000)
                pay.total_amount = pay.amount
                pay.order = OrderHelper.place_order()
                pay.bank = banks[random.randrange(0, len(banks))]

                pay.status = (PayInfo.INITIAL,
                              PayInfo.PROCESSING,
                              PayInfo.SUCCESS,
                              PayInfo.FAIL,
                              PayInfo.EXCEPTION,
                              PayInfo.ACCEPTED)[random.randrange(0, 6)]

                pay.request_ip = '127.0.0.1'
                pay.save()
Ejemplo n.º 4
0
    def __init__(self, *args, **kwargs):
        self.user = kwargs.get('user', None)

        order_id = kwargs.get('order_id', None)
        if order_id is None:
            order_id = OrderHelper.place_order(user=self.user).id

        self.order_id = order_id
Ejemplo n.º 5
0
def reward_user_5(user, introduced_by, reward_type, got_amount, product,
                  only_show):
    reward = Reward.objects.filter(is_used=False, type=reward_type).first()

    text_content = u"【网利宝】您在邀请好友送收益的活动中,获得%s元收益,收益已经发放至您的网利宝账户。请注意查收。回复TD退订4008-588-066【网利宝】" % got_amount
    if only_show is not True:
        send_messages.apply_async(
            kwargs={
                "phones": [user.wanglibaouserprofile.phone],
                "messages": [text_content]
            })
    if only_show is not True:
        earning = Earning()
        earning.amount = got_amount
        earning.type = 'I'
        earning.product = product
        order = OrderHelper.place_order(introduced_by,
                                        Order.ACTIVITY,
                                        u"邀请送收益活动赠送",
                                        earning=model_to_dict(earning))
        earning.order = order
        keeper = MarginKeeper(introduced_by, order.pk)

        # 赠送活动描述
        desc = u'%s,邀请好友首次理财活动中,活赠%s元' % (
            introduced_by.wanglibaouserprofile.name, got_amount)
        earning.margin_record = keeper.deposit(got_amount, description=desc)
        earning.user = introduced_by
        earning.save()

    message_content = u"您在邀请好友送收益的活动中,您的好友%s在活动期间完成首次投资,根据活动规则,您获得%s元收益。<br/>\
                      <a href = 'https://www.wanglibao.com/accounts/home/'>查看账户余额</a><br/>\
                      感谢您对我们的支持与关注。<br/>\
                      网利宝" % (safe_phone_str(
        user.wanglibaouserprofile.phone), got_amount)

    if only_show is not True:
        RewardRecord.objects.create(user=introduced_by,
                                    reward=reward,
                                    description=message_content)
        inside_message.send_one.apply_async(
            kwargs={
                "user_id": introduced_by.id,
                "title": u"邀请送收益活动",
                "content": message_content,
                "mtype": "activity"
            })
    else:
        print message_content
        print introduced_by.wanglibaouserprofile.name
        print safe_phone_str(user.wanglibaouserprofile.phone)
        print text_content
Ejemplo n.º 6
0
    def generate(cls, clean=False):
        User = get_user_model()

        users = User.objects.all()

        for u in users:
            if not hasattr(u, 'margin'):
                margin = Margin(user=u)
                margin.save()

        for u in users:
            order = OrderHelper.place_order()
            keeper = MarginKeeper(order_id=order.id, user=u)
            keeper.deposit(100000000)
Ejemplo n.º 7
0
def AuditEquityCreateContract(request, equity_id):
    equity = P2PEquity.objects.filter(id=equity_id).select_related('product').first()
    product = equity.product
    order = OrderHelper.place_order(order_type=u'生成合同文件', status=u'开始', equity_id=equity_id, product_id=product.id)

    if not equity.latest_contract:
        #create contract file
        EquityKeeperDecorator(product, order.id).generate_contract_one(equity_id=equity_id, savepoint=False)

    equity_new = P2PEquity.objects.filter(id=equity_id).first()
    try:
        f = equity_new.latest_contract
        lines = f.readlines()
        f.close()
        return HttpResponse("\n".join(lines))
    except ValueError, e:
        raise Http404
Ejemplo n.º 8
0
 def settle_hike(cls, product):
     result = redpack_backends.settle_hike(product)
     if not result:
         return
     for x in result:
         order_id = OrderHelper.place_order(x['user'],
                                            order_type=u'加息',
                                            product_id=product.id,
                                            status=u'新建').id
         margin_keeper = MarginKeeper(user=x['user'], order_id=order_id)
         margin_keeper.hike_deposit(x['amount'],
                                    u"加息存入%s元" % x['amount'],
                                    savepoint=False)
         OrderHelper.update_order(Order.objects.get(pk=order_id),
                                  user=x['user'],
                                  status=u'成功',
                                  amount=x['amount'])
Ejemplo n.º 9
0
 def amortize(self,
              principal,
              interest,
              penal_interest,
              coupon_interest,
              description=u'',
              savepoint=True):
     check_amount(principal)
     check_amount(interest)
     check_amount(penal_interest)
     principal = Decimal(principal)
     interest = Decimal(interest)
     penal_interest = Decimal(penal_interest)
     coupon_interest = Decimal(coupon_interest)
     with transaction.atomic(savepoint=savepoint):
         margin = Margin.objects.select_for_update().filter(
             user=self.user).first()
         catalog = u'还款入账'
         margin.margin += principal
         self.__tracer(u'本金入账', principal, margin.margin, u'本金入账')
         margin.margin += interest
         self.__tracer(u'利息入账', interest, margin.margin, u'利息入账')
         if penal_interest > 0:
             margin.margin += penal_interest
             self.__tracer(u'罚息入账', penal_interest, margin.margin, u'罚息入账')
         if coupon_interest > 0:
             margin.margin += coupon_interest
             description = u"加息存入{}元".format(coupon_interest)
             order_id = OrderHelper.place_order(
                 self.user,
                 order_type=Order.INTEREST_COUPON,
                 status=u'新建',
                 amount=coupon_interest).id
             # self.hike_deposit(coupon_interest, u"加息存入{}元".format(coupon_interest), order_id, savepoint=False)
             self.__tracer(u"加息存入", coupon_interest, margin.margin,
                           description, order_id)
             OrderHelper.update_order(Order.objects.get(pk=order_id),
                                      user=self.user,
                                      status=u'成功',
                                      amount=coupon_interest)
         margin.save()
Ejemplo n.º 10
0
def reward_earning(record, reward_user, got_amount, product, flag):
    from wanglibao_p2p.models import Earning
    from order.utils import OrderHelper
    from order.models import Order
    from django.forms import model_to_dict
    from wanglibao_margin.marginkeeper import MarginKeeper

    # 发放收益
    earning = Earning()
    earning.amount = got_amount
    earning.type = 'I'
    earning.product = product
    order = OrderHelper.place_order(reward_user,
                                    Order.ACTIVITY,
                                    u"邀请送收益活动赠送",
                                    earning=model_to_dict(earning))
    earning.order = order
    keeper = MarginKeeper(reward_user, order.pk)

    # 赠送活动描述
    desc = u'%s,邀请好友理财活动中,获赠%s元' % (reward_user.wanglibaouserprofile.name,
                                    got_amount)
    earning.margin_record = keeper.deposit(got_amount,
                                           description=desc,
                                           catalog=u"邀请赠送")
    earning.user = reward_user
    earning.save()

    if flag == 1:
        IntroducedByReward.objects.filter(id=record.id).update(
            checked_status=1, checked_at=timezone.now(), user_send_status=True)
    else:
        IntroducedByReward.objects.filter(id=record.id).update(
            checked_status=1,
            checked_at=timezone.now(),
            introduced_send_status=True)
Ejemplo n.º 11
0
    def preprocess_for_settle(cls, product):
        cls.logger.info('Enter pre process for settle for product: %d: %s',
                        product.id, product.name)

        # Create an order to link all changes
        order = OrderHelper.place_order(order_type=u'满标状态预处理',
                                        status=u'开始',
                                        product_id=product.id)
        if product.status != u'满标已打款':
            raise P2PException(u'产品状态(%s)不是(满标已打款)' % product.status)
        with transaction.atomic():
            # Generate the amotization plan and contract for each equity(user)
            amo_keeper = AmortizationKeeper(product, order_id=order.id)

            amo_keeper.generate_amortization_plan(savepoint=False)

            # for equity in product.equities.all():
            #     EquityKeeper(equity.user, equity.product, order_id=order.id).generate_contract(savepoint=False)
            # EquityKeeperDecorator(product, order.id).generate_contract(savepoint=False)

            product = P2PProduct.objects.get(pk=product.id)
            product.status = u'满标待审核'
            product.make_loans_time = timezone.now()
            product.save()
Ejemplo n.º 12
0
    def pre_pay(self, request):
        """
        返回跳转信息{'message': message,'form': form}供跳转js使用,message包含报错信息
            form包含跳转信息
        :param request:
        :return:
        """
        if not request.user.wanglibaouserprofile.id_is_valid:
            return self.render_to_response({
                'message': u'请先进行实名认证'
            })
        form = dict()
        message = ''
        try:
            amount_str = request.POST.get('amount', '')
            amount = decimal.Decimal(amount_str). \
                quantize(TWO_PLACES, context=decimal.Context(traps=[decimal.Inexact]))
            amount_str = str(amount)
            if amount <= 0:
                # todo handler the raise
                raise decimal.DecimalException()

            gate_id = request.POST.get('gate_id', '')
            bank = Bank.objects.get(gate_id=gate_id)

            # Store this as the default bank
            request.user.wanglibaouserprofile.deposit_default_bank_name = bank.name
            request.user.wanglibaouserprofile.save()

            pay_info = PayInfo()
            pay_info.amount = amount
            pay_info.total_amount = amount
            pay_info.type = PayInfo.DEPOSIT
            pay_info.status = PayInfo.INITIAL
            pay_info.user = request.user
            pay_info.bank = bank
            pay_info.channel = "huifu"
            pay_info.request_ip = get_client_ip(request)

            order = OrderHelper.place_order(request.user, Order.PAY_ORDER, pay_info.status,
                                            pay_info=model_to_dict(pay_info))
            pay_info.order = order
            pay_info.save()

            post = {
                'OrdId': pay_info.pk,
                'GateId': gate_id,
                'OrdAmt': amount_str
            }

            form = self.pay(post)
            pay_info.request = str(form)
            pay_info.status = PayInfo.PROCESSING
            pay_info.save()
            OrderHelper.update_order(order, request.user, pay_info=model_to_dict(pay_info), status=pay_info.status)

            # 处理第三方渠道的用户充值回调
            CoopRegister(request).process_for_recharge(request.user, order.id)
        except decimal.DecimalException:
            message = u'金额格式错误'
        except Bank.DoesNotExist:
            message = u'请选择有效的银行'
        except (socket.error, SignException) as e:
            message = PayResult.RETRY
            pay_info.status = PayInfo.FAIL
            pay_info.error_message = str(e)
            pay_info.save()
            OrderHelper.update_order(order, request.user, pay_info=model_to_dict(pay_info), status=pay_info.status)
            logger.fatal('sign error! order id: ' + str(pay_info.pk) + ' ' + str(e))

        result = {
            'message': message,
            'form': form
        }

        return result
Ejemplo n.º 13
0
    def order_before_pay(self,
                         user,
                         amount,
                         gate_id,
                         request_ip,
                         device_type,
                         card_no=None,
                         phone_for_card=None):
        """
        支付前的订单处理
        card_no和phone_for_card为可选参数,其他为必填参数
        网银支付(页面支付):无card_no和phone_for_card
        快捷支付第一次支付:会带上card_no和phone_for_card,这时的卡号是完整的,用于绑卡
        快捷支付后续支付:只有card_no,无phone_for_card,这时的卡号是10位的短号
        无论长号还是短号,填入pay_info的都是长号
        :param user:
        :param amount:
        :param gate_id:
        :param request_ip:
        :param device_type:
        :param request_para_str: 发往第三方的请求信息
        :return: order.id
        """
        # 处理必填信息
        is_bind_pay = True if card_no else False
        bank, channel = self.get_bank_and_channel(gate_id, is_bind_pay)[:2]

        pay_info = PayInfo()
        pay_info.type = PayInfo.DEPOSIT
        pay_info.user = user
        pay_info.account_name = user.wanglibaouserprofile.name
        pay_info.amount = amount
        pay_info.total_amount = amount
        # pay_info.status = PayInfo.INITIAL
        pay_info.bank = bank
        pay_info.channel = channel
        # pay_info.phone_for_card = phone_for_card
        # todo better 是否记录更全面的客户端信息
        pay_info.request_ip = request_ip
        pay_info.device = device_type

        # 处理可选的银行卡信息
        if card_no:
            pay_info.card_no = self.get_card_no(card_no, user, gate_id,
                                                is_bind_pay)

        if phone_for_card:
            pay_info.phone_for_card = phone_for_card

        # order = OrderHelper.place_order(user, Order.PAY_ORDER, pay_info.status,
        #                                 pay_info = model_to_dict(pay_info))

        # 不同状态(已绑卡,未绑卡)事bank和card_no的处理
        # pay_info.order = order
        # if card:
        #     pay_info.bank = card.bank
        #     pay_info.card_no = card.no
        # else:
        #     pay_info.bank = bank
        #     pay_info.card_no = card_no

        # todo better 时间处理
        pay_info.status = PayInfo.PROCESSING
        pay_info.save()
        # OrderHelper.update_order(order, user, pay_info=model_to_dict(pay_info), status=pay_info.status)

        order = OrderHelper.place_order(user,
                                        Order.PAY_ORDER,
                                        pay_info.status,
                                        pay_info=model_to_dict(pay_info))
        pay_info.order = order
        pay_info.save()

        return order.id
Ejemplo n.º 14
0
    def app_pay(self, request):
        if not request.user.wanglibaouserprofile.id_is_valid:
            return {"ret_code":20071, "message":"请先进行实名认证"}

        amount = request.DATA.get("amount", "").strip()
        deviceid = request.DATA.get("device_id", "").strip()

        if not amount or not deviceid:
            return {"ret_code":20072, 'message':'信息输入不完整'}

        try:
            float(amount)
        except:
            return {"ret_code":20073, 'message':'金额格式错误'}

        amount = util.fmt_two_amount(amount)
        #if amount < 100 or amount % 100 != 0 or len(str(amount)) > 20:
        if amount < 10 or len(str(amount)) > 20:
            #return {"ret_code":20074, 'message':'金额格式错误,大于100元且为100倍数'}
            return {"ret_code":20074, 'message':'充值金额需大于10元'}
        if amount > 20000:
            return {"ret_code":20073, 'message':'单笔充值不超过2万,单月不超过5万。如需充值更多金额可以去网站完成。'}

        terminal = deviceid.split(":")
        deviceid = terminal[-1]
        tmpdic = {"imei":0, "mac":1, "uuid":2, "other":3}
        if terminal[0] in tmpdic:
            terminaltype = tmpdic[terminal[0]]
        else:
            terminaltype = tmpdic['other']


        card_id = request.DATA.get("card_id", "")
        user = request.user
        #amount_sec = int(amount*100)
        amount_sec = long(amount*100)
        useragent = request.META.get("HTTP_USER_AGENT", "noagent").strip()

        try:
            pay_info = PayInfo()
            pay_info.amount = amount
            pay_info.total_amount = amount
            pay_info.type = PayInfo.DEPOSIT
            pay_info.status = PayInfo.INITIAL
            pay_info.user = user
            pay_info.channel = "yeepay"

            if card_id:
                card =  Card.objects.filter(id=card_id, user=user).first()
                if not card:
                    return {"ret_code":20075, 'message':'选择的银行卡不存在'}
                pay_info.bank = card.bank
                pay_info.card_no = card.no

            pay_info.request_ip = util.get_client_ip(request)
            order = OrderHelper.place_order(user, Order.PAY_ORDER, pay_info.status,
                                            pay_info = model_to_dict(pay_info))
            pay_info.order = order
            pay_info.save()

            profile = user.wanglibaouserprofile
            dic = {"merchantaccount":self.MER_ID, "orderid":str(order.id), "transtime":long(time.mktime(pay_info.create_time.timetuple())),
                    "amount":amount_sec, "productcatalog":"18", "productname":"网利宝-APP充值",
                    "identityid":str(user.id), "identitytype":2, "terminaltype":terminaltype,
                    "terminalid":deviceid, "userip":pay_info.request_ip, "userua":useragent,
                    "callbackurl":self.PAY_BACK_RETURN_URL, "fcallbackurl":self.PAY_RETURN_URL,
                    "version":0, "paytypes":"1", "cardno":card_id, "orderexpdate":60}
            data, encryptkey = self._sign(dic)
            logger.error("%s" % dic)

            pay_info.request = str(dic)
            pay_info.status = PayInfo.PROCESSING
            pay_info.account_name = profile.name
            pay_info.save()
            OrderHelper.update_order(order, user, pay_info=model_to_dict(pay_info), status=pay_info.status)

            params = {"data":data, "encryptkey":encryptkey, "merchantaccount":self.MER_ID}
            url = "%s?%s" % (self.PAY_URL, urllib.urlencode(params))
            logger.error(url)
            return {"ret_code":0, "url":url}
        except Exception, e:
            logger.error(traceback.format_exc())
            message = PayResult.RETRY
            pay_info.status = PayInfo.FAIL
            pay_info.error_message = str(e)
            pay_info.save()
            OrderHelper.update_order(order, request.user, pay_info=model_to_dict(pay_info), status=pay_info.status)
            logger.fatal('sign error! order id: ' + str(pay_info.pk) + ' ' + str(e))
            return {"ret_code":"20076", "message":message}
Ejemplo n.º 15
0
    def purchase(self, amount, redpack=0, platform=u''):
        description = u'购买P2P产品 %s %s 份' % (self.product.short_name, amount)
        is_full = False
        product_balance_after = 0
        if self.user.wanglibaouserprofile.frozen:
            raise P2PException(u'用户账户已冻结,请联系客服')
        with transaction.atomic():
            if redpack:
                # 为防止用户同时打开两个浏览器同时使用加息券和红包,须先检测
                coupons = RedPackRecord.objects.filter(user=self.user, product_id=self.product.id) \
                    .filter(redpack__event__rtype='interest_coupon')
                if coupons:
                    raise P2PException(u'已经选择过加息券,不能重复或叠加使用')
                else:
                    this_redpack = RedPackRecord.objects.filter(
                        pk=redpack).first()
                    this_rtype = this_redpack.redpack.event.rtype
                    coupons = RedPackRecord.objects.filter(user=self.user, product_id=self.product.id) \
                        .exclude(redpack__event__rtype='interest_coupon')
                    if coupons and this_rtype == 'interest_coupon':
                        raise P2PException(u'红包和加息券不能同时叠加使用')

                redpack_order_id = OrderHelper.place_order(
                    self.user,
                    order_type=u'优惠券消费',
                    redpack=redpack,
                    product_id=self.product.id,
                    status=u'新建').id
                result = redpack_backends.consume(redpack, amount, self.user,
                                                  self.order_id,
                                                  self.device_type,
                                                  self.product.id)
                if result['ret_code'] != 0:
                    raise Exception, result['message']
                if result['rtype'] != 'interest_coupon':
                    red_record = self.margin_keeper.redpack_deposit(
                        result['deduct'],
                        u"购买P2P抵扣%s元" % result['deduct'],
                        order_id=redpack_order_id,
                        savepoint=False)
                OrderHelper.update_order(
                    Order.objects.get(pk=redpack_order_id),
                    user=self.user,
                    status=u'成功',
                    amount=amount,
                    deduct=result['deduct'],
                    redpack=redpack)

            product_record = self.product_keeper.reserve(amount,
                                                         self.user,
                                                         savepoint=False,
                                                         platform=platform)
            margin_record = self.margin_keeper.freeze(amount,
                                                      description=description,
                                                      savepoint=False)
            equity = self.equity_keeper.reserve(amount,
                                                description=description,
                                                savepoint=False)

            OrderHelper.update_order(Order.objects.get(pk=self.order_id),
                                     user=self.user,
                                     status=u'份额确认',
                                     amount=amount)

            product_balance_after = product_record.product_balance_after
            if product_balance_after <= 0:
                is_full = True

        # fix@chenweibin, add order_id
        # Modify by hb on 2015-11-25 : add "try-except"
        try:
            logger.debug("=20151125= decide_first.apply_async : [%s], [%s], [%s], [%s], [%s], [%s]" % \
                         (self.user.id, amount, self.device['device_type'], self.order_id, self.product.id, is_full) )
            tools.decide_first.apply_async(
                kwargs={
                    "user_id": self.user.id,
                    "amount": amount,
                    "device": self.device,
                    "order_id": self.order_id,
                    "product_id": self.product.id,
                    "is_full": is_full,
                    "product_balance_after": product_balance_after
                })
        except Exception, reason:
            logger.debug(
                "=20151125= decide_first.apply_async Except:{0}".format(
                    reason))
            pass
Ejemplo n.º 16
0
class YeeShortPay:
    """ 易宝快捷支付 """

    FEE = 0

    def __init__(self):
        self.PRIV_KEY = settings.YEE_MER_PRIV_KEY
        self.YEE_PUB_KEY = settings.YEE_PUB_KEY
        self.MER_ID = settings.YEE_MER_ID
        self.BIND_URL = settings.YEE_SHORT_BIND
        self.BIND_CHECK_SMS = settings.YEE_SHORT_BIND_CHECK_SMS
        self.BIND_CARD_QUERY = settings.YEE_SHORT_BIND_CARD_QUERY
        self.BIND_PAY_REQUEST = settings.YEE_SHORT_BIND_PAY_REQUEST
        self.YEE_CALLBACK = settings.YEE_SHORT_CALLBACK
        self.UNBIND_CARD = settings.YEE_URL + '/api/bankcard/unbind'
        self.QUERY_TRX_RESULT = settings.YEE_URL + '/api/query/order' 

    def _sign(self, dic):
        values = self._sort(dic)
        h = SHA.new(values)
        signer = pk.new(self.PRIV_KEY)
        sign_result = signer.sign(h)
        sign_result = base64.b64encode(sign_result)
        dic["sign"] = sign_result

        rand_aes_key = util.randstr()
        data = self.aes_base64_encrypt(json.dumps(dic), rand_aes_key)

        encryptkey = self.rsa_base64_encrypt(rand_aes_key, self.YEE_PUB_KEY)
        return data, encryptkey

    def _sort(self, dic):
        keys = dic.keys()
        keys.sort()
        return "".join([str(dic[k]) for k in keys])

    def aes_base64_encrypt(self,data,key):
        cipher = AES.new(key)
        return base64.b64encode(cipher.encrypt(self._pkcs7padding(data)))

    def aes_base64_decrypt(self,data,key):
        """
        1. base64 decode
        2. aes decode
        3. dpkcs7padding
        """
        cipher = AES.new(key)
        return self._depkcs7padding(cipher.decrypt(base64.b64decode(data)))

    def _pkcs7padding(self, data):
        """
        对齐块
        size 16
        999999999=>9999999997777777
        """
        size = AES.block_size
        count = size - len(data)%size
        if count:
            data+=(chr(count)*count)
        return data

    def _depkcs7padding(self, data):
        """
        反对齐
        """
        newdata = ''
        for c in data:
            if ord(c) > AES.block_size:
                newdata+=c
        return newdata

    def rsa_base64_encrypt(self,data,key):
        """
        1. rsa encrypt
        2. base64 encrypt
        """
        cipher = PKCS1_v1_5.new(key)
        return base64.b64encode(cipher.encrypt(data))

    def rsa_base64_decrypt(self,data,key):
        """
        1. base64 decrypt
        2. rsa decrypt
        示例代码

        key = RSA.importKey(open('privkey.der').read())
        >>>
        >>> dsize = SHA.digest_size
        >>> sentinel = Random.new().read(15+dsize)      # Let's assume that average data length is 15
        >>>
        >>> cipher = PKCS1_v1_5.new(key)
        >>> message = cipher.decrypt(ciphertext, sentinel)
        >>>
        >>> digest = SHA.new(message[:-dsize]).digest()
        >>> if digest==message[-dsize:]:                # Note how we DO NOT look for the sentinel
        >>>     print "Encryption was correct."
        >>> else:
        >>>     print "Encryption was not correct."
        """
        cipher = PKCS1_v1_5.new(key)
        return cipher.decrypt(base64.b64decode(data), Random.new().read(15+SHA.digest_size))

    def _verify(self, dic, sign):
        sign = base64.b64decode(sign)
        values = self._sort(dic)
        verifier = pk.new(self.YEE_PUB_KEY)
        if verifier.verify(SHA.new(values), sign):
            return True
        else:
            return False

    def save_card(self, user, card_no, bank):
        """ 保存卡信息到个人名下 """
        if len(card_no) == 10:
            card = Card.objects.filter(user=user, no__startswith=card_no[:6], no__endswith=card_no[-4:]).first()
        else:
            card = Card.objects.filter(no=card_no, user=user).first()

        if not card:
            card = Card()
            card.user = user
            card.no = card_no
            card.is_default = False

        card.bank = bank
        card.is_bind_yee = True
        card.save()
        return True

    def _format_post(self, post):
        """ 签名格式化请求数据 """
        data, encryptkey = self._sign(post)
        return {"data": data, "encryptkey": encryptkey, "merchantaccount": self.MER_ID}

    def _request_yee(self, url, data):
        # logger.error("request yee_pay: %s" % data)
        post = self._format_post(data)
        res = requests.post(url, post)
        res_dict = self._response_data_change(res=json.loads(res.text))
        logger.error("yee_pay: %s | %s | %s" % (url, data, res_dict))
        return res_dict 

    def _request_yee_get(self, url, data):
        post = self._format_post(data)
        res = requests.get(url, params=post)
        res_dict = self._response_data_change(res=json.loads(res.text))
        logger.error("yee_pay: %s | %s | %s" % (url, data, res_dict))
        return res_dict 

    def _response_data_change(self, res):
        """ 将易宝返回的数据格式化成程序通用数据 """
        if 'error_code' in res:
            # logger.error(res)
            return {'ret_code': res['error_code'], 'message': res['error_msg']}

        if 'data' not in res:
            # logger.error(res)
            return {'ret_code': 20012, 'message': '易宝数据有误'}

        flag, data = self._response_decode(res=res)

        if 'error_code' in data:
            # logger.error(data)
            return {'ret_code': data['error_code'], 'message': data['error_msg'], 'data': data}

        if not flag:
            # logger.error(data)
            return {'ret_code': 20011, 'message': '签名验证失败', 'data': data}

        # logger.error("yee_pay response: %s" % data)
        return {'ret_code': 0, 'message': 'ok', 'data': data}

    def _response_decode(self, res):
        """ 返回数据合法性校验 """
        if 'encryptkey' in res and 'data' in res:
            ybaeskey = self.rsa_base64_decrypt(res['encryptkey'], self.PRIV_KEY)
            data = json.loads(self.aes_base64_decrypt(res['data'], ybaeskey))
            if 'sign' in data:
                sign = data.pop('sign')
                if self._verify(data, sign):
                    return True, data
                else:
                    return False, data
        return False, res

    def _bind_card_request(self, request, phone, card_no, request_id):
        """ 邦卡请求 """
        user = request.user

        post = dict()
        post['merchantaccount'] = self.MER_ID
        post['identityid'] = str(user.wanglibaouserprofile.id_number)
        post['identitytype'] = 5
        post['requestid'] = request_id
        post['cardno'] = card_no
        post['idcardtype'] = '01'
        post['idcardno'] = str(user.wanglibaouserprofile.id_number)
        post['username'] = user.wanglibaouserprofile.name
        post['phone'] = phone
        post['userip'] = util.get_client_ip(request)
        return self._request_yee(url=self.BIND_URL, data=post)

    def _bind_check_sms(self, request_id, validatecode):
        """ 绑卡校验验证码 """
        post = dict()
        post['merchantaccount'] = self.MER_ID
        post['requestid'] = request_id
        post['validatecode'] = validatecode
        return self._request_yee(url=self.BIND_CHECK_SMS, data=post)

    def bind_card_query(self, user):
        """ 查询已经绑定的银行卡 """
        if not user.wanglibaouserprofile.id_is_valid:
            return {"ret_code": 20071, "message": "请先进行实名认证"}

        post = dict()
        post['merchantaccount'] = self.MER_ID
        post['identityid'] = str(user.wanglibaouserprofile.id_number)
        post['identitytype'] = 5
        return self._request_yee_get(url=self.BIND_CARD_QUERY, data=post)

    def delete_bind(self, user, card, bank):
        """ 解绑银行卡 """
        if card.is_bind_yee:
            # 易宝通卡进出,不允许用户解绑,解绑线下进行
            # card.is_bind_yee = False
            # card.yee_bind_id = ''
            # card.save()
            return {'ret_code': 21110, 'message': '易宝支付解绑请联系客服'}
        return {'ret_code': 0, 'message': 'ok'}

    def unbind_card(self, user, mcard):
        """解绑,但有如下限制:解绑后只能绑原卡,或者绑原卡只是预留号码变更的"""
        res = self.bind_card_query(user)
        yee_bindid = identitytype = identityid = ''
        if 'data' in res and 'cardlist' in res['data']:
            identityid = res['data']['identityid']
            identitytype = res['data']['identitytype']
            for card in res['data']['cardlist']:
                if mcard.no.startswith(card['card_top']) \
                        and mcard.no.endswith(card['card_last']):
                    yee_bindid = card['bindid']
                    break
        if yee_bindid:
            post = dict()
            post['merchantaccount'] = self.MER_ID
            post['bindid'] = yee_bindid
            post['identitytype'] = identitytype
            post['identityid'] = identityid
            print '*'*100, self.UNBIND_CARD
            return self._request_yee(url=self.UNBIND_CARD, data=post)

    def _pay_request(self, request, order_id, card, pay_info):
        """ 支付请求 """
        post = dict()
        post['merchantaccount'] = self.MER_ID
        post['orderid'] = str(order_id)
        post['transtime'] = int(time.time())
        post['amount'] = int(pay_info.amount * 100)
        post['productname'] = '网利宝-APP充值'
        post['identityid'] = str(request.user.wanglibaouserprofile.id_number)
        post['identitytype'] = 5
        post['card_top'] = pay_info.card_no[:6]
        post['card_last'] = pay_info.card_no[-4:]
        post['callbackurl'] = self.YEE_CALLBACK
        post['userip'] = util.get_client_ip(request)
        return self._request_yee(url=self.BIND_PAY_REQUEST, data=post)

    def _query_trx_result(self, order_id):
        """
        去第三方查询交易结果
        """
        post = dict()
        post['merchantaccount'] = self.MER_ID
        post['orderid'] = str(order_id)
        return self._request_yee_get(url=self.QUERY_TRX_RESULT, data=post)

    def add_card_unbind(self, user, card_no, bank, request):
        """ 保存卡信息到个人名下,不绑定任何渠道 """
        if len(card_no) == 10:
            card = Card.objects.filter(user=user, no__startswith=card_no[:6], no__endswith=card_no[-4:],
                                       is_bind_yee=True).first()
        else:
            card = Card.objects.filter(no=card_no, user=user).first()

        add_card = False
        if not card:
            card = Card()
            card.user = user
            card.no = card_no
            card.is_default = False

            add_card = True

        card.bank = bank
        card.save()
        # if add_card:
        #     try:
        #         # 处理第三方用户绑卡回调
        #         CoopRegister(request).process_for_binding_card(request.user)
        #     except Exception, e:
        #         logger.error(e)

        return card

    def pre_pay(self, request):
        """ 获取验证码支付还是直接支付
            长卡号获取验证码
            短卡号直接支付
        """
        if not request.user.wanglibaouserprofile.id_is_valid:
            return {"ret_code": 20111, "message": "请先进行实名认证"}

        amount = request.DATA.get("amount", "").strip()
        card_no = request.DATA.get("card_no", "").strip()
        input_phone = request.DATA.get("phone", "").strip()
        gate_id = request.DATA.get("gate_id", "").strip()
        device_type = split_ua(request)['device_type']

        if not amount or not card_no:
            return {"ret_code": 20112, 'message': '信息输入不完整'}
        if len(card_no) > 10 and (not input_phone or not gate_id):
            return {"ret_code": 20113, 'message': '卡号格式不正确'}

        try:
            float(amount)
        except:
            return {"ret_code": 20114, 'message': '金额格式错误'}

        amount = util.fmt_two_amount(amount)
        # if amount < 10 or len(str(amount)) > 20:
        #     return {"ret_code": 20115, 'message': '充值须大于等于10元'}

        if len(str(amount)) > 20:
            return {"ret_code": 20115, 'message': '充值金额太大'}

        if amount < 0.009:
            # 涉及到小数精度,不能用0.01
            return {"ret_code": 20115, 'message': '充值金额太小(至少0.01元)'}

        user = request.user
        profile = user.wanglibaouserprofile
        card, bank = None, None
        if gate_id:
            bank = Bank.objects.filter(gate_id=gate_id).first()
            if not bank or not bank.yee_bind_code.strip():
                return {"ret_code": 201116, "message": "不支持该银行"}

        if len(card_no) == 10:
            card = Card.objects.filter(user=user, no__startswith=card_no[:6], no__endswith=card_no[-4:],
                                       is_bind_yee=True).first()
        else:
            #card = Card.objects.filter(no=card_no, user=user).first()
            card = Card.objects.filter(no=card_no, user=user, bank=bank).first()
            pay_record = PayInfo.objects.filter(card_no=card_no, user=user, bank=bank)
            if pay_record.filter(error_message__icontains='不匹配'):
                return {"ret_code":200118, "message":"银行卡与银行不匹配"}

        if not card:
            card = self.add_card_unbind(user, card_no, bank, request)

        if not card and not bank:
            return {'ret_code': 200117, 'message': '卡号不存在或银行不存在'}

        #if bank and card and bank != card.bank:
            #return {"ret_code": 200118, "message": "银行卡与银行不匹配"}

        # 商户生成的唯一绑卡请求号,最长50位
        request_id = '{phone}{time}'.format(phone=profile.phone, time=timezone.now().strftime("%Y%m%d%H%M%S"))
        if len(card_no) != 10:
            # 未绑定银行卡,需要先绑定银行卡获取验证码,然后在确认支付
            try:
                # 请求绑定银行卡
                res = self._bind_card_request(request, input_phone, card_no, request_id)
                if res['ret_code'] != 0:
                    # 600326已绑定,600302绑卡数超限
                    if res['ret_code'] in ['600326', '600302']:
                        self.sync_bind_card(user)
                        return {'ret_code': '20119', 'message': '银行卡已绑定,请返回使用快捷充值'}
                    else:
                        # logger.error(res)
                        return res
            except Exception, e:
                logger.error(e.message)
                return {"ret_code": "20120", "message": '绑定银行卡失败'}

        try:
            pay_info = PayInfo()
            pay_info.amount = amount
            pay_info.total_amount = amount
            pay_info.type = PayInfo.DEPOSIT
            pay_info.status = PayInfo.INITIAL
            pay_info.user = user
            pay_info.channel = "yeepay_bind"

            pay_info.device = device_type
            pay_info.request_ip = util.get_client_ip(request)
            order = OrderHelper.place_order(user, Order.PAY_ORDER, pay_info.status, pay_info=model_to_dict(pay_info))
            pay_info.order = order

            pay_info.bank = card.bank
            pay_info.card_no = card.no
            pay_info.phone_for_card = input_phone
            pay_info.request = ""
            pay_info.status = PayInfo.PROCESSING
            pay_info.account_name = profile.name
            pay_info.save()
            OrderHelper.update_order(order, user, pay_info=model_to_dict(pay_info), status=pay_info.status)

            if len(card_no) == 10:
                # 直接支付交易,已经绑定了银行卡,直接进行支付操作
                res = self._pay_request(request, order.id, card, pay_info)
                if res['ret_code'] != 0:
                    # logger.error(res)
                    pay_info.error_code = res['ret_code']
                    pay_info.error_message = res['message']
                    if 'data' in res:
                        pay_info.response = res['data']
                    pay_info.save()
                    return res

                margin = Margin.objects.filter(user=user).first()
                return {"ret_code": 22000, "message": u"充值申请已提交,请稍候查询余额。", "amount": amount, "margin": margin.margin}

            else:
                return {"ret_code": 0, "message": "ok", "order_id": order.id, "token": request_id}

        except Exception, e:
            logger.error(traceback.format_exc())
            message = PayResult.RETRY
            pay_info.status = PayInfo.FAIL
            pay_info.error_message = str(e)
            pay_info.save()
            OrderHelper.update_order(order, request.user, pay_info=model_to_dict(pay_info), status=pay_info.status)
            return {"ret_code": "20119", "message": message}
Ejemplo n.º 17
0
    def post(self, request, *args, **kwargs):
        #result, message = verify_captcha(request.POST)
        #if not result:
        #    return self.render_to_response({
        #        'result': message
        #    })

        user = request.user
        if not user.wanglibaouserprofile.id_is_valid:
            return self.render_to_response({'result': u'请先进行实名认证'})
        if user.wanglibaouserprofile.frozen:
            return self.render_to_response(
                {'result': u'账户已冻结!请联系网利宝客服:4008-588-066'})
        phone = user.wanglibaouserprofile.phone
        code = request.POST.get('validate_code', '')
        status, message = validate_validation_code(phone, code)
        if status != 200:
            return self.render_to_response({
                # Modify by hb on 2015-12-02
                #'result': u'短信验证码输入错误'
                'result': message
            })

        result = PayResult.WITHDRAW_SUCCESS

        try:
            card_id = request.POST.get('card_id', '')
            card = Card.objects.get(pk=card_id, user=user)
            card_no = card.no

            # 检测银行卡是否在黑名单中
            black_list = BlackListCard.objects.filter(card_no=card_no).first()
            if black_list and black_list.user != user:
                raise AbnormalCardException

            # 检查白名单
            white_list = WhiteListCard.objects.filter(user=user,
                                                      card_no=card_no).first()
            if not white_list:
                # 增加银行卡号检测功能,检测多张卡
                card_count = Card.objects.filter(no=card_no).count()
                if card_count > 1:
                    raise ManyCardException

                # 检测银行卡在以前的提现记录中是否为同一个用户
                payinfo_record = PayInfo.objects.filter(
                    card_no=card_no).order_by('-create_time').first()
                if payinfo_record:
                    if payinfo_record.user != user:
                        raise AbnormalCardException

            amount_str = request.POST.get('amount', '')
            amount = decimal.Decimal(amount_str). \
                quantize(TWO_PLACES, context=decimal.Context(traps=[decimal.Inexact]))
            margin = user.margin.margin  # 账户余额
            uninvested = user.margin.uninvested  # 充值未投资金额

            # 获取费率配置
            fee_misc = WithdrawFee()
            fee_config = fee_misc.get_withdraw_fee_config()

            # 计算提现费用 手续费 + 资金管理费
            # 提现最大最小金额判断
            if amount > fee_config.get('max_amount') or amount <= 0:
                raise decimal.DecimalException
            if amount < fee_config.get('min_amount'):
                if amount != margin:
                    raise decimal.DecimalException
            # 获取计算后的费率
            fee, management_fee, management_amount = fee_misc.get_withdraw_fee(
                user, amount, margin, uninvested)

            actual_amount = amount - fee - management_fee  # 实际到账金额
            if actual_amount <= 0:
                raise decimal.DecimalException

            # 检测个别银行的单笔提现限额,如民生银行
            bank_limit = util.handle_withdraw_limit(card.bank.withdraw_limit)
            bank_max_amount = bank_limit.get('bank_max_amount', 0)
            if bank_max_amount:
                if amount > bank_max_amount:
                    raise decimal.DecimalException

            pay_info = PayInfo()
            pay_info.amount = actual_amount
            pay_info.fee = fee
            pay_info.management_fee = management_fee
            pay_info.management_amount = management_amount
            pay_info.total_amount = amount
            pay_info.type = PayInfo.WITHDRAW
            pay_info.user = user
            pay_info.card_no = card.no
            pay_info.account_name = user.wanglibaouserprofile.name
            pay_info.bank = card.bank
            pay_info.request_ip = get_client_ip(request)
            pay_info.status = PayInfo.ACCEPTED

            order = OrderHelper.place_order(user,
                                            Order.WITHDRAW_ORDER,
                                            pay_info.status,
                                            pay_info=model_to_dict(pay_info))

            pay_info.order = order
            keeper = MarginKeeper(user, pay_info.order.pk)
            margin_record = keeper.withdraw_pre_freeze(
                amount, uninvested=management_amount)
            pay_info.margin_record = margin_record

            pay_info.save()
            try:
                device = split_ua(request)
            except:
                device = {'device_type': 'pc'}

            name = user.wanglibaouserprofile.name or u'用户'
            withdraw_submit_ok.apply_async(
                kwargs={
                    "user_id": user.id,
                    "user_name": name,
                    "phone": user.wanglibaouserprofile.phone,
                    "amount": amount,
                    "bank_name": card.bank.name,
                    "order_id": order.id,
                    "device": device
                })
        except decimal.DecimalException:
            result = u'提款金额在0~{}之间'.format(fee_config.get('max_amount'))
        except Card.DoesNotExist:
            result = u'请选择有效的银行卡'
        except ManyCardException:
            result = u'银行卡号存在重复,请尝试其他银行卡号码,如非本人操作请联系客服'
        except AbnormalCardException:
            result = u'银行卡号与身份信息存在异常, 如非本人操作请联系客服'
        except MarginLack as e:
            result = u'余额不足'
            pay_info.error_message = str(e)
            pay_info.status = PayInfo.FAIL
            pay_info.save()

        # return self.render_to_response({
        #     'result': result
        # })
        return HttpResponseRedirect(
            reverse('withdraw-complete-result', kwargs={'result': result}))
Ejemplo n.º 18
0
def withdraw(request):
    amount = request.DATA.get("amount", "").strip()
    card_id = request.DATA.get("card_id", "").strip()
    vcode = request.DATA.get("validate_code", "").strip()
    if not amount or not card_id:
        return {"ret_code": 20061, "message": u"信息输入不完整"}

    user = request.user
    if not user.wanglibaouserprofile.id_is_valid:
        return {"ret_code": 20062, "message": u"请先进行实名认证"}

    if user.wanglibaouserprofile.frozen:
        return {"ret_code": 20072, "message": u"用户账户已冻结,请联系客服"}

    try:
        float(amount)
    except:
        return {"ret_code": 20063, 'message': u'金额格式错误'}
    amount = util.fmt_two_amount(amount)
    if len(str(amount)) > 20:
        return {"ret_code": 20064, 'message': u'金额格式错误,大于100元且为100倍数'}

    margin = user.margin.margin
    if amount > margin:
        return {"ret_code": 20065, 'message': u'余额不足'}

    phone = user.wanglibaouserprofile.phone
    status, message = validate_validation_code(phone, vcode)
    if status != 200:
        # Modify by hb on 2015-12-02
        #return {"ret_code": 20066, "message": u"验证码输入错误"}
        return {"ret_code": 20066, "message": message}

    card = Card.objects.filter(pk=card_id).first()
    if not card or card.user != user:
        return {"ret_code": 20067, "message": u"请选择有效的银行卡"}
    # 检测银行卡是否在黑名单中
    black_list = BlackListCard.objects.filter(card_no=card.no).first()
    if black_list and black_list.user != user:
        return {"ret_code": 20072, "message": u'银行卡号异常,请联系客服'}

    # 检查白名单
    white_list = WhiteListCard.objects.filter(user=user,
                                              card_no=card.no).first()
    if not white_list:
        # 增加银行卡号检测功能,检测多张卡
        card_count = Card.objects.filter(no=card.no).count()
        if card_count > 1:
            return {"ret_code": 20073, "message": u'银行卡号有多张重复,请联系客服'}

        # 检测银行卡在以前的提现记录中是否为同一个用户
        payinfo_record = PayInfo.objects.filter(
            card_no=card.no, type='W').order_by('-create_time').first()
        if payinfo_record:
            if payinfo_record.user != user:
                return {"ret_code": 20074, "message": u'银行卡号与身份信息不符,请联系客服'}

    # 计算提现费用 手续费 + 资金管理费
    bank = card.bank
    uninvested = user.margin.uninvested  # 充值未投资金额

    # 获取费率配置
    fee_misc = WithdrawFee()
    fee_config = fee_misc.get_withdraw_fee_config()

    # 检测提现最大最小金额
    if amount > fee_config.get('max_amount') or amount <= 0:
        return {"ret_code": 20068, 'message': u'提现金额超出最大提现限额'}
    if amount < fee_config.get('min_amount'):
        if amount != margin:
            return {
                "ret_code": 20069,
                'message':
                u'账户余额小于{}时需要一次性提完'.format(fee_config.get('min_amount'))
            }

    # 检测银行的单笔最大提现限额,如民生银行
    if bank and bank.withdraw_limit:
        bank_limit = util.handle_withdraw_limit(bank.withdraw_limit)
        bank_max_amount = bank_limit.get('bank_max_amount', 0)

        if bank_max_amount:
            if amount > bank_max_amount:
                return {"ret_code": 20070, 'message': u'提现金额超出银行最大提现限额'}

    # 获取计算后的费率
    fee, management_fee, management_amount = fee_misc.get_withdraw_fee(
        user, amount, margin, uninvested)

    # 实际提现金额
    actual_amount = amount - fee - management_fee
    if actual_amount <= 0:
        return {"ret_code": 20071, "message": u'实际到账金额为0,无法提现'}

    pay_info = PayInfo()
    pay_info.amount = actual_amount
    pay_info.fee = fee
    pay_info.management_fee = management_fee
    pay_info.management_amount = management_amount
    pay_info.total_amount = amount
    pay_info.type = PayInfo.WITHDRAW
    pay_info.user = user
    pay_info.card_no = card.no
    pay_info.account_name = user.wanglibaouserprofile.name
    pay_info.bank = card.bank
    pay_info.request_ip = util.get_client_ip(request)
    pay_info.status = PayInfo.ACCEPTED
    pay_info.channel = "app"

    try:
        order = OrderHelper.place_order(user,
                                        Order.WITHDRAW_ORDER,
                                        pay_info.status,
                                        pay_info=model_to_dict(pay_info))
        pay_info.order = order
        keeper = MarginKeeper(user, pay_info.order.pk)
        margin_record = keeper.withdraw_pre_freeze(
            amount, uninvested=management_amount)
        pay_info.margin_record = margin_record

        pay_info.save()
        return {
            "ret_code": 0,
            'message': u'提现成功',
            "amount": amount,
            "phone": phone,
            "bank_name": bank.name,
            "order_id": order.id
        }
    except Exception, e:
        pay_info.error_message = str(e)
        pay_info.status = PayInfo.FAIL
        pay_info.save()
        return {"ret_code": 20065, 'message': u'余额不足'}
Ejemplo n.º 19
0
    def post(self, request):
        user = request.user
        now = timezone.now()
        start_dt = local_to_utc(datetime(2016, 6, 7), 'min')
        user_joined = user.date_joined  # 用户注册时间
        device = split_ua(request)
        device_type = decide_device(device['device_type'])
        purchase_code = 'experience_purchase'

        experience_product = ExperienceProduct.objects.filter(
            isvalid=True).first()
        if not experience_product:
            return Response({'ret_code': 30001, 'message': u'体验标有误,请重试'})

        total_amount = 0
        total_amount_tmp = 0

        # 查询用户符合条件的理财金记录
        with transaction.atomic(savepoint=True):
            # 锁表,主要用来锁定体验金投资时的动作
            purchase_lock_record = ExperiencePurchaseLockRecord.objects.select_for_update().\
                filter(user=user, purchase_code=purchase_code).first()

            if not purchase_lock_record:
                # 没有记录时创建一条
                try:
                    purchase_lock_record = ExperiencePurchaseLockRecord.objects.create(
                        user=user,
                        purchase_code=purchase_code,
                        purchase_times=0)
                except Exception:
                    logger.exception(
                        "Error: experience purchase err, user: %s, phone: %s" %
                        (user.id, user.wanglibaouserprofile.phone))
                    return Response({
                        'ret_code': 30003,
                        'message': u'体验金投资失败,请重试'
                    })

            experience_record = ExperienceEventRecord.objects.filter(user=user, apply=False) \
                .filter(event__invalid=False, event__available_at__lt=now, event__unavailable_at__gt=now)\
                .select_related('event')

            records_ids = ''
            if experience_record:
                catalog = u'购买体验标'

                for i in experience_record:
                    total_amount_tmp += i.event.amount

                buy_p2p = P2PRecord.objects.filter(user_id=user.id).exists()
                buy_count = MarginRecord.objects.filter(
                    user_id=user.id, catalog=catalog).count()
                if not buy_p2p:
                    if user_joined > start_dt:
                        # 如果查询到已经购买过至少 1 次体验标,则不再检测账户余额
                        if buy_count == 0:
                            if total_amount_tmp >= 28888 and user.margin.margin < 1:
                                return Response({
                                    'ret_code': 30009,
                                    'message': u'账户余额不足,请先充值'
                                })

                for record in experience_record:
                    event = record.event
                    total_amount += event.amount
                    records_ids += str(record.id) + ','

                    record.apply = True
                    record.apply_amount = event.amount
                    record.apply_at = timezone.now()
                    record.apply_platform = device_type
                    record.save()

                terms = get_amortization_plan(u'日计息一次性还本付息').generate(
                    total_amount,
                    experience_product.expected_earning_rate / 100.0,
                    timezone.now(), experience_product.period)

                for index, term in enumerate(terms['terms']):
                    amortization = ExperienceAmortization()
                    amortization.product = experience_product
                    amortization.user = user
                    amortization.principal = term[1]  # 本金
                    amortization.interest = term[2]  # 利息
                    amortization.term = index + 1  # 期数
                    amortization.description = u'第%d期' % (index + 1)
                    amortization.term_date = term[6] - timedelta(days=1)

                    amortization.save()

                # 从账户中扣除 1 元 (没有购买过体验标的情况)
                if not buy_p2p:
                    if user_joined > start_dt:
                        if total_amount >= 28888 and buy_count == 0:
                            amount = 1.00
                            order_id = OrderHelper.place_order(
                                user, order_type=catalog, status=u'新建').id
                            margin_keeper = MarginKeeper(user=user,
                                                         order_id=order_id)
                            margin_keeper.reduce_margin_common(
                                amount, catalog=catalog, description=catalog)

                # 更新当前的一组流水id
                purchase_lock_record.purchase_times += 1
                purchase_lock_record.description = records_ids
                purchase_lock_record.save()

                term_date = amortization.term_date
                interest = amortization.interest

                return Response({
                    'ret_code': 0,
                    'data': {
                        'amount': total_amount,
                        'term_date': term_date.strftime("%Y-%m-%d"),
                        'interest': interest
                    }
                })

            else:
                return Response({
                    'ret_code': 30002,
                    'message': u'没有体验金记录,无法购买体验标'
                })
Ejemplo n.º 20
0
def send_reward(start, end, amount_min, percent):
    from wanglibao_sms.tasks import send_messages
    from wanglibao_p2p.models import Earning
    from order.utils import OrderHelper
    from order.models import Order
    from django.forms import model_to_dict
    from wanglibao_margin.marginkeeper import MarginKeeper
    from wanglibao.templatetags.formatters import safe_phone_str
    from marketing.models import RewardRecord
    from decimal import Decimal

    start = datetime.strptime(start, '%Y-%m-%d')
    end = datetime.strptime(end, '%Y-%m-%d')

    # 审核通过,给用户发放奖励
    reward_type = u'邀请送收益'
    records = IntroducedByReward.objects.filter(
        checked_status=0,
        activity_start_at=local_to_utc(start, source_time='min'),
        activity_end_at=local_to_utc(end, source_time='max'),
        activity_amount_min=Decimal(amount_min),
        percent_reward=Decimal(percent),
    )

    if not records.exists():
        return

    for record in records:
        # with transaction.atomic():
        user, introduced_by, reward_type, got_amount, product = record.user, record.introduced_by_person, reward_type, record.introduced_reward, record.product

        reward = Reward.objects.filter(is_used=False, type=reward_type).first()

        # 发送短信
        # text_content = u"【网利宝】您在邀请好友送收益的活动中,获得%s元收益,收益已经发放至您的网利宝账户。请注意查收。" % got_amount
        # send_messages.apply_async(kwargs={
        #     "phones": [introduced_by.wanglibaouserprofile.phone],
        #     "messages": [text_content]
        # })

        # 发放收益
        earning = Earning()
        earning.amount = got_amount
        earning.type = 'I'
        earning.product = product
        order = OrderHelper.place_order(introduced_by,
                                        Order.ACTIVITY,
                                        u"邀请送收益活动赠送",
                                        earning=model_to_dict(earning))
        earning.order = order
        keeper = MarginKeeper(introduced_by, order.pk)

        # 赠送活动描述
        desc = u'%s,邀请好友首次理财活动中,活赠%s元' % (
            introduced_by.wanglibaouserprofile.name, got_amount)
        earning.margin_record = keeper.deposit(got_amount,
                                               description=desc,
                                               catalog=u"邀请首次赠送")
        earning.user = introduced_by
        earning.save()

        # 发放站内信
        message_content = u"您在邀请好友送收益的活动中,您的好友%s在活动期间完成首次投资,根据活动规则,您获得%s元收益。<br/>\
                  <a href='/accounts/home/' target='_blank'>查看账户余额</a><br/>\
                  感谢您对我们的支持与关注。<br/>\
                  网利宝" % (safe_phone_str(
            user.wanglibaouserprofile.phone), got_amount)
        RewardRecord.objects.create(user=introduced_by,
                                    reward=reward,
                                    description=message_content)
        inside_message.send_one.apply_async(
            kwargs={
                "user_id": introduced_by.id,
                "title": u"邀请送收益活动",
                "content": message_content,
                "mtype": "activity"
            })

        IntroducedByReward.objects.filter(id=record.id).update(
            checked_status=1)
Ejemplo n.º 21
0
    def pre_pay(self, request, bank=None):
        """ 汇付天下直接进行邦卡支付,不能够获取验证码 """
        if not request.user.wanglibaouserprofile.id_is_valid:
            return {"ret_code": 20111, "message": "请先进行实名认证"}

        amount = request.DATA.get("amount", "").strip()
        card_no = request.DATA.get("card_no", "").strip()
        input_phone = request.DATA.get("phone", "").strip()
        gate_id = request.DATA.get("gate_id", "").strip()

        if not amount or not card_no or not gate_id:
            return {"ret_code": 20112, 'message': '信息输入不完整'}
        if len(card_no) > 10 and not input_phone:
            return {"ret_code": 20112, 'message': '信息输入不完整'}
        if card_no and len(card_no) == 10:
            return {'ret_code': 20013, 'message': '卡号格式不正确'}

        try:
            float(amount)
        except:
            return {"ret_code": 20114, 'message': '金额格式错误'}

        amount = fmt_two_amount(amount)

        user = request.user
        profile = user.wanglibaouserprofile

        bank = Bank.objects.filter(gate_id=gate_id).first()
        if not bank or not bank.huifu_bind_code.strip():
            return {"ret_code": 201151, "message": "不支持该银行"}

        if len(card_no) == 10:
            card = Card.objects.filter(user=user, no__startswith=card_no[:6], no__endswith=card_no[-4:]).first()
            card_no = card.no
        else:
            card = Card.objects.filter(no=card_no, user=user).first()

        if not card:
            card = self.bind_card_wlbk(user, card_no, bank, request)

        if not card:
            return {"ret_code": -1, "message": '银行卡不存在'}

        if bank and card and bank != card.bank:
            return {"ret_code": 201153, "message": "银行卡与银行不匹配"}
        if card and not card.is_bind_huifu:
            res = self.open_bind_card(user, bank, card)
            if res['ret_code'] != 0:
                return res

            card.is_bind_huifu = True
            card.save()

        try:
            pay_info = PayInfo()
            pay_info.amount = amount
            pay_info.total_amount = amount
            pay_info.type = PayInfo.DEPOSIT
            pay_info.status = PayInfo.INITIAL
            pay_info.user = user
            pay_info.channel = "huifu_bind"

            pay_info.request_ip = get_client_ip(request)
            order = OrderHelper.place_order(user, Order.PAY_ORDER, pay_info.status, pay_info=model_to_dict(pay_info))
            pay_info.order = order

            if card:
                pay_info.bank = card.bank
                pay_info.card_no = card.no
            else:
                pay_info.bank = bank
                pay_info.card_no = card_no

            pay_info.status = PayInfo.PROCESSING
            pay_info.account_name = profile.name
            pay_info.save()
            OrderHelper.update_order(order, user, pay_info=model_to_dict(pay_info), status=pay_info.status)

            # 充值
            req, res = self._card_pay_huifu(user=user, amount=pay_info.amount, card_no=card_no)

            pay_info.error_code = res['RespCode']
            pay_info.error_message = res['ErrMsg']
            pay_info.request = req
            pay_info.response = res
            pay_info.response_ip = get_client_ip(request)

            if res['RespCode'] != u'000000':
                pay_info.save()
                return {"ret_code": -3, "message": res['ErrMsg']}
            else:
                pay_info.fee = self.FEE
                keeper = MarginKeeper(pay_info.user, pay_info.order.pk)
                margin_record = keeper.deposit(amount)
                pay_info.margin_record = margin_record
                pay_info.status = PayInfo.SUCCESS
                pay_info.save()
                rs = {"ret_code": 0, "message": "success", "amount": amount, "margin": margin_record.margin_current}

            if rs['ret_code'] == 0:
                device = split_ua(request)
                try:
                    # fix@chenweibi, add order_id
                    tools.deposit_ok.apply_async(kwargs={"user_id": pay_info.user.id, "amount": pay_info.amount,
                                                         "device": device, "order_id": order.id})
                except:
                    pass

                # 充值成功后,更新本次银行使用的时间
                Card.objects.filter(user=pay_info.user, no=pay_info.card_no).update(last_update=timezone.now())

            OrderHelper.update_order(pay_info.order, pay_info.user, pay_info=model_to_dict(pay_info), status=pay_info.status)
            return rs
        except Exception, e:
            message = PayResult.RETRY
            pay_info.status = PayInfo.FAIL
            pay_info.error_message = str(e)
            pay_info.save()
            OrderHelper.update_order(order, request.user, pay_info=model_to_dict(pay_info), status=pay_info.status)
            return {"ret_code": "20119", "message": message}
Ejemplo n.º 22
0
def buy_month_product(token=None,
                      red_packet_id=None,
                      amount_source=None,
                      user=None,
                      device=None,
                      period=0):
    """
    对这个购买的月利宝记录进行扣款冻结操作.
    :param token: month_product's unique token.
    ###  :param product: pass a month_product object error!
    amount_source: 购买的总金额
    ###### 以下  如果是 amount 是 优惠后的金额
    :return:
    """
    # 标志购买成功才去走活动检查.
    flag = False
    with transaction.atomic(savepoint=True):
        product = MonthProduct.objects.select_for_update().filter(
            token=token).first()

        if not product:
            return

        ret = dict()

        if product.trade_status != 'NEW':
            ret.update(status=1, token=product.token, msg='already saved!')
        else:
            # 未被取消的订单才可以扣款
            if not product.cancel_status:
                # 状态成功, 对买家扣款, 加入冻结资金
                try:
                    buyer_keeper = PhpMarginKeeper(product.user,
                                                   product.product_id)

                    user = User.objects.filter(pk=user).first()

                    # update by lili 2016-06-14
                    # 如果使用红包的话,需要先将红包的钱判断正确后存入用户账户,然后再去检测购买金额和余额
                    # 如果使用红包的话, 增加红包使用记录
                    if red_packet_id and int(red_packet_id) > 0:
                        logger.info(
                            'buy_month_product token = {} used with red_pack_id = {}'
                            .format(token, red_packet_id))
                        redpack = RedPackRecord.objects.filter(
                            pk=red_packet_id).first()
                        redpack_order_id = OrderHelper.place_order(
                            user,
                            order_type=u'优惠券消费',
                            redpack=redpack.id,
                            product_id=product.product_id,
                            status=u'新建').id
                        result = php_redpack_consume(red_packet_id,
                                                     amount_source, user,
                                                     product.id,
                                                     device['device_type'],
                                                     product.product_id)
                        if result['ret_code'] != 0:
                            raise Exception, result['message']
                        if result['rtype'] != 'interest_coupon':
                            red_record = buyer_keeper.redpack_deposit(
                                result['deduct'],
                                u"购买月利宝抵扣%s元" % result['deduct'],
                                order_id=redpack_order_id,
                                savepoint=False)

                    buyer_keeper.php_freeze(amount_source,
                                            description=u'月利宝购买冻结')
                    product.trade_status = 'PAID'
                    product.save()
                    ret.update(status=1, token=token, msg='success')
                    flag = True

                except Exception, e:
                    logger.exception("buy_month_product failed:")
                    logger.debug(
                        'buy_month_product failed with exception: {}, red_pack_id = {}'
                        .format(str(e), red_packet_id))
                    product.trade_status = 'FAILED'
                    product.save()
                    ret.update(status=0,
                               token=product.token,
                               msg='pay failed!' + str(e))
Ejemplo n.º 23
0
def build_earning(product_id):

    p2p = P2PProduct.objects.select_related('activity__rule').get(
        pk=product_id)

    num = Earning.objects.filter(product=p2p).count()
    if num > 0:
        return

    #按用户汇总某个标的收益
    earning = P2PRecord.objects.values('user').annotate(
        sum_amount=Sum('amount')).filter(product=p2p, catalog=u'申购')

    phone_list = []
    earning_list = []
    rule = p2p.activity.rule

    unit = period_unit(p2p.pay_method)

    #把收益数据插入earning表内
    for obj in earning:
        # bind = Binding.objects.filter(user_id=obj.get('user')).first()
        # if bind and bind.isvip:

        earning = Earning()
        amount = rule.get_earning(obj.get('sum_amount'), p2p.period,
                                  p2p.pay_method)
        earning.amount = amount
        earning.type = 'D'
        earning.product = p2p
        user = User.objects.get(pk=obj.get('user'))
        order = OrderHelper.place_order(user,
                                        Order.ACTIVITY,
                                        u"活动赠送",
                                        earning=model_to_dict(earning))
        earning.order = order

        keeper = MarginKeeper(user, order.pk)

        #赠送活动描述
        desc = u'%s,%s赠送%s%s' % (p2p.name, p2p.activity.name,
                                 p2p.activity.rule.rule_amount * 100, '%')
        earning.margin_record = keeper.deposit(amount,
                                               description=desc,
                                               catalog=u"活动赠送")
        earning.user = user

        #earning.save()

        earning_list.append(earning)
        phone_list.append(user.wanglibaouserprofile.phone)

        earning_time = timezone.localtime(
            timezone.now()).strftime("%Y-%m-%d %H:%M:%S")
        title, content = messages.msg_bid_earning(p2p.name, p2p.activity.name,
                                                  p2p.period, earning_time,
                                                  rule.percent_text, amount,
                                                  unit)
        inside_message.send_one.apply_async(
            kwargs={
                "user_id": obj.get('user'),
                "title": title,
                "content": content,
                "mtype": "activity"
            })

    #发送活动赠送短信
    # send_messages.apply_async(kwargs={
    #                 "phones": phone_list,
    #                 "messages": [messages.earning_message(rule.percent_text)]
    #             })

    Earning.objects.bulk_create(earning_list)
Ejemplo n.º 24
0
    def prepayment(self, penal_interest, repayment_type, payment_date, savepoint=True):
        """
                #1. 拿到当期未还款计划
                #1.11 如果是按期提前还款
                #1.12 利息 = 当期利息
                #1.21 如果是按日提前还款
                #1.22 利息 = 年利率/360*计息天数*本金
                #2. 拿到此标的年华收益
                #3. 计算日收益
                #4. 计算当期未计息天数
        """
        pname = ''
        amortization_records_tmp = list()
        phone_list = list()
        message_list = list()
        with transaction.atomic(savepoint=savepoint):
            amortization = ProductAmortization.objects.select_for_update().get(id=self.amortization.id)
            if amortization.settled:
                raise PrepaymentException()
            # 1.生成产品提前还款记录
            # amortization = self.amortization
            product_record = self.get_product_repayment(penal_interest, repayment_type, payment_date)
            order_id = OrderHelper.place_order(None, order_type=self.catalog, product_id=self.product.id, status=u'新建').id
            product_record.order_id = order_id

            amortization_records = list()
            # 用户还款计划
            user_amortizations = amortization.subs.all().select_related('user__wanglibaouserprofile')

            product = amortization.product
            import re
            matches = re.search(u'日计息', product.pay_method)
            if matches and matches.group():
                pname = u"%s,期限%s天" % (product.name, product.period)
            else:
                pname = u"%s,期限%s个月" % (product.name, product.period)

            for user_amortization in user_amortizations:
                logger.error("提前还款用户: [%s], [%s]" % (user_amortization.user.id, user_amortization.user.wanglibaouserprofile.phone))
                # 计算最终计算提前还款的本金, 利息, 罚息, 加息
                user_record = self.get_user_repayment(user_amortization, penal_interest, repayment_type, payment_date)
                logger.error("新的本金: [%s], 利息:[%s], 加息:[%s], repayment_type:[%s], payment_date:[%s]" % (
                    user_record.principal, user_record.interest, user_record.coupon_interest, repayment_type, payment_date))

                user_margin_keeper = MarginKeeper(user_record.user)
                # 提前还款需要将加息金额还给用户(重新计算后的该用户所用加息券的加息金额)
                user_margin_keeper.amortize(user_record.principal, user_record.interest, user_record.penal_interest,
                                            user_record.coupon_interest, savepoint=False, description=self.description)

                order_id = OrderHelper.place_order(user_record.user, order_type=self.catalog, product_id=self.product.id, status=u'新建').id

                user_record.order_id = order_id
                user_record.amortization = amortization

                amortization_records.append(user_record)
                amortization_records_tmp.append(user_record)  # 发消息临时list变量(不包含product_record)
                logger.error("order_id: %s" % order_id)

            amortization_records.append(product_record)

            AmortizationRecord.objects.bulk_create(amortization_records)

            ProductAmortization.objects.filter(product=self.product, settled=False)\
                .update(settled=True, settlement_time=timezone.now())
            UserAmortization.objects.filter(product_amortization__product=self.product, settled=False)\
                .update(settled=True, settlement_time=timezone.now())
            ProductKeeper(self.product).finish(None)

        # 将提前还款的消息发送放到事务外边
        for user_record in amortization_records_tmp:
            try:
                # 提前还款短信
                # 提前还款金额 = 本金 + 利息 + 罚息 + 加息
                amo_amount = user_record.principal + user_record.interest + \
                    user_record.penal_interest + user_record.coupon_interest
                user = user_record.user
                user_profile = user.wanglibaouserprofile
                phone_list.append(user_profile.phone)
                message_list.append(messages.product_prepayment(user_profile.name,
                                                                amortization.product,
                                                                amo_amount))

                # 标的每一期还款完成后,检测该用户还款的本金是否有符合活动的规则,有的话触发活动规则
                try:
                    if user_record.principal > 0:
                        # activity_backends.check_activity(user, 'repaid', 'pc', user_record.principal, product.id)
                        check_activity_task.apply_async(kwargs={
                            "user_id": user.id,
                            "trigger_node": 'repaid',
                            "device_type": 'pc',
                            "amount": user_record.principal,
                            "product_id": product.id
                        }, queue='celery02')
                except Exception:
                    logger.exception("==提前还款==活动检测==")
                    logger.debug("提前还款, user: {}, principal: {}, product_id: {}".format(
                        user, user_record.principal, product.id
                    ))
                try:
                    # 提前还款站内信
                    title, content = messages.msg_bid_prepayment(pname, timezone.now(), amo_amount)
                    inside_message.send_one.apply_async(kwargs={
                        "user_id": user.id,
                        "title": title,
                        "content": content,
                        "mtype": "amortize"
                    })
                except Exception, e:
                    logger.exception("==提前还款==站内信==")
                    logger.debug(("user:%s====提前还款==站内信==" % user.id) + traceback.format_exc())
                try:
                    weixin_user = WeixinUser.objects.filter(user=user).first()

                    if weixin_user and weixin_user.subscribe:
                        now = datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')
                        sentTemplate.apply_async(kwargs={
                            "kwargs": json.dumps({
                                "openid": weixin_user.openid,
                                "template_id": PRODUCT_AMORTIZATION_TEMPLATE_ID,
                                "keyword1": product.name,
                                "keyword2": "%s 元" % str(amo_amount),
                                "keyword3": now,
                            })
                        }, queue='celery02')
                except Exception, e:
                    logger.exception("==提前还款==微信模板==")
                    logger.debug(("user:%s====提前还款==微信模板==" % user.id) + traceback.format_exc())