示例#1
0
def pay_test():
    session.forget(response)
    import db_common
    import ed_common
    scid = request.vars.get('pattern_id')
    curr, xcurr, ecurr= db_common.get_currs_by_abbrev(db,'RUB')
    dealer_deal = db((db.dealer_deals.scid==scid)
            & (db.dealer_deals.dealer_id==dealer.id)).select().first()
    deal = db.deals[dealer_deal.deal_id]
    print deal.name
    dealer, dealer_acc, d_ = ed_common.select_ed_acc(db, deal, ecurr)
    print dealer_acc.acc, dealer_acc.balance
    vol = float(request.vars.get('sum') or request.vars.get('redsum') or 13)

    acc = '---???---'
    res = ed_common.pay_test(db, deal, dealer, dealer_acc, dealer_deal, acc, vol, True, request.vars)
    print res
    return BEAUTIFY(res)
示例#2
0
def pay_test_to_deal():
    if not request.args(0): return '/deal_id - 46 (skype) / summ?acc=_'
    session.forget(response)
    import db_common
    import ed_common
    
    deal = db.deals[request.args(0)]
    dealer = db.dealers[1]
    curr, xcurr, ecurr= db_common.get_currs_by_abbrev(db,'RUB')
    dealer_deal = db((db.dealer_deals.deal_id==deal.id)
            & (db.dealer_deals.dealer_id==dealer.id)).select().first()
    #deal = db.deals[dealer_deal.deal_id]
    print deal.name
    dealer, dealer_acc, d_ = ed_common.select_ed_acc(db, deal, ecurr)
    print dealer_acc.acc, dealer_acc.balance
    
    vol = float(request.args(1) or 100)
    
    acc = request.vars.get('acc')
    res = ed_common.pay_test(db, deal, dealer, dealer_acc, dealer_deal, acc, vol, True, None)
    print res
    return BEAUTIFY(res)
示例#3
0
def get():

    #common.page_stats(db, response['view'])
    #print request.vars
    args = request.args
    if len(args) < 2: return mess('args<2 err...')
    curr_id = args(0)
    if len(curr_id) > 5 or not curr_id.isdigit(): return mess('curr_id dig...')
    # теперь можно задать открытие кнопки
    scr = "$('#cvr%s').css('display','none');$('#tag%s').show('slow');" % (
        curr_id, curr_id)
    response.js = scr

    deal_id = args(1)

    if not deal_id or len(deal_id) > 10 or not deal_id.isdigit():
        return mess('deal_id vars..')

    curr_in = db.currs[curr_id]
    if not curr_in: return mess(T('curr...'))
    xcurr_in = db(db.xcurrs.curr_id == curr_id).select().first()
    if not xcurr_in: return mess(T('xcurr...'))

    #print request.vars
    try:
        # если русский язык то выдаст ошибку в if v.find(c) >-1:
        for k, v in request.vars.items():
            #print k, v
            for c in u'\\/<>\'"':
                if v.find(c) > -1:
                    return mess('error in pars <script>')
    except:
        pass

    client = db(db.clients.deal_id == deal_id).select().first()
    if client:
        redirect(URL('to_shop', 'index', args=[client.id], vars={}))

    volume_out = test_vol(request.vars.vol)
    if not volume_out: return mess('volume_out error...')

    deal = db.deals[deal_id]
    vol = (deal.MIN_pay or 100) * 2
    dealer, dealer_acc, dealer_deal = ed_common.select_ed_acc(
        db, deal, ecurr_out, vol, True)
    if not dealer:
        return mess('ERROR: not found dealer for "%s"' % deal.name)
    dealer_acc = ed_common.sel_acc_max_for_balance(db,
                                                   dealer,
                                                   ecurr_out,
                                                   vol,
                                                   unlim=True)

    MIN = db_common.gMIN(deal, dealer)
    #MAX = deal.MAX_ or 777

    if MIN > volume_out:
        return mess('ОШИБКА: Слишком маленькая сумма платежа, меньше чем: %s' %
                    MIN)

    ################################################
    # соберем аккаунт для оплаты из введенных данных
    ################################################
    if dealer_deal.grab_form:
        deal_pars = {}
        #print request.post_vars
        # удалим наши параметры
        for key in ['xcurr', 'volume', 'deal_id']:
            deal_pars[key] = request.post_vars.pop(key)
        # парамтеры что ввел пользователь обрежем чтобы скрипты не писали
        for (k, v) in request.post_vars.iteritems():
            if len(v) > 20:
                request.post_vars[k] = v[:20]
        acc = request.post_vars  #.list.sort()
        if len(acc) > 10:
            m = 'ОШИБКА: параметров слишком много: %s, свяжитесь с администратором' % acc
            print m
            return mess(m)
        acc = json.dumps(acc)
        #print 'ACC:', acc
    else:
        # проверку параметров
        # и собрем из параметров счет клиента
        acc_pars = []
        if dealer_deal.p2p:
            if deal.template_ == '--':
                pay_pars_deal = []
                pay_pars_dealer = []
                acc_pars.append('main')
            else:
                pay_pars_deal = ed_common.PAY_PARS_P2P
                pay_pars_dealer = ed_YD.PAY_PARS_P2P
        else:
            pay_pars_deal = deal.template_ and json.loads(
                deal.template_) or ed_common.PAY_PARS
            pay_pars_dealer = dealer_deal.template_ and json.loads(
                dealer_deal.template_) or ed_YD.PAY_PARS
        #print request.vars
        for par in pay_pars_deal:
            ## par - параметры от ДЕЛА
            if 'calc' in par:
                continue
            p_n_name = par.get('n')
            if not p_n_name: continue

            val = request.vars[p_n_name] or ''
            p = pay_pars_dealer[p_n_name]
            #print p, val

            if 'f' in par:
                # фильтр регулярный
                #regular = re.compile(p['f'])
                #val = regular.sub("","%s" % val)
                val = re.sub(p['f'], "", "%s" % val)
            if 'ln' in p:
                # проверка длинны
                ln = (p['ln'] + 0)
                if len(val) != ln:
                    l = p['l']
                    db.deal_errs.insert(deal_id=deal.id,
                                        err='len!=%s - %s = %s' % (ln, l, val))
                    l = l.encode('utf8')
                    return mess('ОШИБКА: Проверьте введенные данные!')
            acc_pars.append(val)

        #все прошло

        # теперь проверку на правильность лицевого счета и прочего для дилера электронных платежей
        #dealer_acc
        #print pars
        if len(acc_pars) > 10:
            m = 'ОШИБКА: параметров слишком много: %s, свяжитесь с администратором' % acc_pars
            print m
            return mess(m)
        acc = ' '.join(
            acc_pars).rstrip()  # и удалим пробелы справа от калькуляторов
        #print 'ACCOUNT:',acc

    if not acc or len(acc) < 3:
        return mess('ОШИБКА: Аккаунт слишком короткий: %s' % acc)

    # запомним что это дело кто-то захотел оплатить
    dealer_deal.update_record(wanted=dealer_deal.wanted + 1)

    pattern_id = dealer_deal.scid
    res = ed_common.pay_test(
        db,
        deal,
        dealer,
        dealer_acc,
        dealer_deal,
        acc,
        #(deal.MIN_pay or dealer.pay_out_MIN or 10)*2,
        volume_out,
        False)

    err_mess = '%s' % res
    if res['status'] != 'success':
        ed_common.dealer_deal_errs_add(db, dealer_deal, acc, err_mess)

        response.title = T("ОШИБКА")
        #print res
        mm = 'error_description' in res and res['error_description'] or res[
            'error'] or 'dealer error'
        mm = T('Платежная система %s отвергла платеж, потому что: %s') % (
            dealer.name, mm)
        return mess(mm)

    dealer_info = json.loads(dealer.info)
    if deal.url and len(deal.url) > 0:
        shops_url = deal.url
    else:
        shops_url = dealer_info['shops_url'] + "%s" % dealer_deal.scid
    deal_img = make_img(deal, dealer_info, shops_url)

    # get new or old adress for payment
    x_acc_label = db_client.make_x_acc(deal, acc, curr_out.abbrev)
    #print x_acc_label
    # найдем ранее созданный адресс для этого телефона, этой крипты и этого фиата
    # сначала найтем аккаунт у дела
    deal_acc_id = db_client.get_deal_acc_id(db, deal, acc, curr_out)
    #print 'deal_acc_id',deal_acc_id
    #return
    # теперь найдем кошелек для данной крипты
    #print x_acc_label
    deal_acc_addr = db_client.get_deal_acc_addr_for_xcurr(
        db, deal_acc_id, curr_in, xcurr_in, x_acc_label)
    if not deal_acc_addr:
        return mess(T(' связь с кошельком ') + curr_in.name + T(' прервана.'))

    addr = deal_acc_addr.addr

    deal_name = deal.name
    # если есть скрытый партнерский код то его забьем пользователю
    deal_acc = db.deal_accs[deal_acc_id]
    import gifts_lib
    adds_mess = XML(gifts_lib.adds_mess(deal_acc, PARTNER_MIN, T))

    deal_url = A(deal.name, _href=shops_url, _target="_blank")
    e_bal, MAX = get_e_bal(deal, dealer, dealer_acc)

    if MAX and volume_out > MAX: volume_out = MAX
    # используем быстрый поиск курса по формуле со степенью на количество входа
    # только надо найти кол-во входа от выхода
    pr_b, pr_s, pr_avg = rates_lib.get_average_rate_bsa(
        db, curr_in.id, curr_out.id, None)
    if pr_avg:
        vol_in = volume_out / pr_b
        amo_out, _, best_rate = rates_lib.get_rate(db, curr_in, curr_out,
                                                   vol_in)
    else:
        best_rate = None
    if not best_rate:
        return mess('[' + curr_in.name + '] -> [' + curr_out.name + ']' +
                    T(' - лучшая цена не доступна.'))

    is_order = True
    # сначала открутим обратную таксу
    volume_in, mess_in = db_client.calc_fees_back(db,
                                                  deal,
                                                  dealer_deal,
                                                  curr_in,
                                                  curr_out,
                                                  volume_out,
                                                  best_rate,
                                                  is_order,
                                                  note=0)
    ## теперь таксы для человека получим и должна та же цифра выйти
    vol_out_new, tax_rep = db_client.calc_fees(db,
                                               deal,
                                               dealer_deal,
                                               curr_in,
                                               curr_out,
                                               volume_in,
                                               best_rate,
                                               is_order,
                                               note=1)
    vol_out_new = common.rnd_8(vol_out_new)
    if volume_out != vol_out_new:
        print 'to_phone error_in_fees: volume_out != vol_out_new', volume_out, vol_out_new

    # теперь для заказ на курс уберем комиссию диллера - просто пересчитаем вход с наченкой диллера
    fee_curr = db.currs[deal.fee_curr_id]
    fee_rate = Decimal(
        rates_lib.get_avr_rate_or_null(db, fee_curr.id, curr_out.id))
    vol_out_dd_neg, _ = db_client.dealer_deal_tax_neg(db, T, fee_rate,
                                                      dealer_deal, '',
                                                      Decimal(volume_out), '')
    #print vol_out_dd_neg

    # причем тут учитываем уже накрутку диллера за дело - в заказе курс будет с учетом накрутки автоматом
    volume_in = common.rnd_8(volume_in)
    rate_out = volume_out / volume_in

    # new make order
    order_rate_id = db.orders.insert(
        ref_=deal_acc_addr.id,
        volume_in=volume_in,
        volume_out=vol_out_dd_neg,
    )
    # теперь стек добавим, который будем удалять потом
    db.orders_stack.insert(ref_=order_rate_id)

    addr_return = deal_acc_addr.addr_return
    if addr_return:
        addr_ret = DIV(
            DIV(T('Адрес для возвратов'),
                ': ',
                B(addr_return[:5] + '...' + addr_return[-5:]),
                _class='col-sm-12'),
            _class='row success',
        )
    else:
        addr_ret = LOAD(
            'aj',
            'addr_ret',
            #args=[deal_acc_addr.addr_return or 0, deal_acc_addr.id, ],
            # лучше передавать через переменные - чтобы там по кругу они гонялись
            # в request
            args=[deal_acc_addr.id],
            ajax=
            False,  # тут без асинхронной подгрузки модуля - вместе со страницей сразу грузим модуль
        )

    _uri, uri_url = common.uri_make(
        curr_in.name2, addr, {
            'amount': volume_in,
            'label': db_client.make_x_acc_label(deal, acc, curr_out.abbrev)
        })

    qr = DIV(DIV(DIV(P(T('Показать QR-код'), _class='btn_mc2'),
                     _class='btn_mc1'),
                 _onclick='''
            jQuery(this).html('%s');
            ajax("%s", [], 'tag_qr');
        ''' % (IMG(_src=URL('static', 'images/loading.gif'),
                   _width=64), URL('plugins', 'qr', vars={'mess': uri_url})),
                 _id='tag_qr',
                 _class='btn_mc col-sm-6'),
             _class='row')

    curr_in_abbrev = curr_in.abbrev
    lim_bal, may_pay = db_client.is_limited_ball(curr_in)
    if lim_bal:
        if may_pay > 0:
            lim_bal_mess = P(
                'Внимание! Для криптовалюты %s существует предел запаса и поэтому наша служба может принять только %s [%s], Просьба не превышать это ограничение'
                % (curr_in.name, may_pay, curr_in_abbrev),
                '.',
                _style='color:black;')
        else:
            lim_bal_mess = P(
                'ВНИМАНИЕ! Наша служба НЕ может сейчас принимать %s, так как уже достугнут предел запаса её у нас. Просьба попробовать позже, после того как запасы [%s] снизятся благодаря покупке её другими пользователями'
                % (curr_in.name, curr_in_abbrev),
                '. ',
                'Иначе Ваш платеж будет ожидать момента когда запасы снизятся ниже %s'
                % lim_bal,
                '.',
                _style='color:brown;')
    else:
        lim_bal_mess = ''

    return dict(deal_name=deal_name,
                adds_mess=adds_mess,
                MIN=MIN,
                MAX=MAX,
                acc=acc,
                order_rate_id=order_rate_id,
                rate_out=rate_out,
                curr_in_name=curr_in_abbrev,
                curr_out_name=curr_out.abbrev,
                e_bal=e_bal,
                deal_url=deal_url,
                volume_in=volume_in,
                volume_out=volume_out,
                tax_rep=tax_rep,
                deal_img=deal_img,
                uri_url=uri_url,
                addr=addr,
                addr_ret=addr_ret,
                qr=qr,
                curr_id=curr_id,
                lim_bal_mess=lim_bal_mess)
示例#4
0
def pay():
    # TODO тут на входе дело ловить а не валюту выхода

    #common.page_stats(db, response['view'])
    #print response['view'], ss, db_common.ip()

    response.title = T("Проверьте данные")
    ph = request.vars.get('phone')
    if not ph or len(ph) == 0:
        redirect(URL('to_wallet', 'index', args=['err01']))
        return

    try:
        volume_out = float(request.vars['volume'])
        dealer_id = request.vars['dealer']
        dealer = db.dealers[dealer_id]
    except:
        time.sleep(333)
        raise HTTP('bee-bee-bee')

    dealer_acc = ed_common.sel_acc_max(db, dealer, ecurr_out, volume_out)
    if not dealer_acc:
        return dict(uri=T(
            'Не найден акк-дилер для обмена, возможно превышены лимиты, просьба подождать до следующего дня или месяца'
        ),
                    addr=None)
    dealer_deal = db((db.dealer_deals.dealer_id == dealer.id)
                     & (db.dealer_deals.deal_id == deal.id)).select().first()
    if not dealer_deal:
        response.title = T("ОШИБКА")
        return dict(uri=T('Не найден дилер для дела:'), addr=None)

    # теперь проверку на правильность кошелька для дилера электронных платежей
    #dealer_acc
    # pay_test(deal, dealer, dealer_acc, dealer_deal, acc, volume_out)
    res = ed_common.pay_test(db, deal, dealer, dealer_acc, dealer_deal, ph,
                             deal.MIN_pay or dealer.pay_out_MIN or 20, False)
    if res['status'] != 'success':
        response.title = T("ОШИБКА")
        mess = 'error_description' in res and res['error_description'] or res[
            'error'] or 'dealer error'
        mess = T('Платежная система %s отвергла платеж, потому что: %s') % (
            dealer.name, mess)
        return dict(uri=mess, addr=None)

    session.visitor_wallet = ph

    # найдем по имени крипту
    curr_in, xcurr_in, e = db_common.get_currs_by_abbrev(
        db, request.vars['curr_in'])
    if not xcurr_in:
        response.title = T("ОШИБКА")
        return dict(uri=T('Криптовалюта ') + request.vars['curr_in'] +
                    T(' не найдена в базе данных.'),
                    addr=None)
    # get new or old adress for payment
    x_acc_label = db_client.make_x_acc(deal, ph, curr_out.abbrev)
    # найдем ранее созданный адресс для этого телефона, этой крипты и этого фиата
    # сначала найтем аккаунт у дела
    deal_acc_id = db_client.get_deal_acc_id(db, deal, ph, curr_out)
    # теперь найдем кошелек для данной крипты
    deal_acc_addr = db_client.get_deal_acc_addr_for_xcurr(
        db, deal_acc_id, curr_in, xcurr_in, x_acc_label)
    if not deal_acc_addr:
        response.title = T("ОШИБКА")
        return dict(uri=T(' связь с кошельком ') + curr_in.name +
                    T(' прервана.'),
                    addr=None)

    #request.vars['deal_acc_addr']=deal_acc_addr
    addr = deal_acc_addr.addr
    request.vars['addr'] = addr

    MIN = deal.MIN_pay or dealer.pay_out_MIN or 3
    if MIN > volume_out:
        u = URL('to_wallet', 'index',
                args=['err02'])  #, vars={'l':deal.MIN_pay})
        redirect(u)
        return

    request.vars['e_bal'], MAX = get_e_bal(deal, dealer, dealer_acc)
    if volume_out > MAX: volume_out = MAX

    ###best_rate, pairs, taxs, ed_fee = db_client.get_best_price_by_volume_out(db, curr_in.id, curr_out.id, volume_out, dealer.id)
    # используем быстрый поиск курса по формуле со степенью на количество входа
    # только надо найти кол-во входа от выхода
    best_rate = pairs = taxs = ed_fee = None

    pr_b, pr_s, pr_avg = rates_lib.get_average_rate_bsa(
        db, curr_in.id, curr_out.id, None)
    #print pr_b, pr_s, pr_avg
    if pr_avg:
        vol_in = volume_out / pr_b
        #print vol_in, curr_in.abbrev, '-->', volume_out, curr_out.abbrev
        amo_out, _, best_rate = rates_lib.get_rate(db, curr_in, curr_out,
                                                   vol_in)
        #best_rate = best_rate and 1/best_rate
        #print best_rate, 1/best_rate

    #print best_rate, pair
    if not best_rate:
        response.title = T("ОШИБКА")
        return dict(uri='[' + curr_in.name + '] -> [' + curr_out.name + ']' +
                    T(' - лучшая цена не доступна.'),
                    addr=None)
    # найдем цену без процентов - чтобы было не так страшно
    #best_rate_clear = best_rate / (1 - ed_fee)
    #for t in taxs:
    #    best_rate_clear = best_rate_clear / (1 - t['tax'])

    volume_in, rate_out, tax_info = db_client.get_fees_for_out(
        db, deal, dealer_deal, curr_in, curr_out, volume_out, best_rate, pairs,
        taxs, ed_fee)

    #print tax_info
    request.vars['dealer_name'] = dealer.name
    request.vars['curr_out_name'] = curr_out.abbrev
    request.vars['curr_in_name'] = curr_in.abbrev
    request.vars['best_rate'] = rate_out
    request.vars['best_rate_rev'] = round(1.0 / best_rate, 8)
    request.vars['volume_in'] = volume_in
    request.vars['volume'] = volume_out

    # make tax and fee report for this RATE
    tax_rep = ''
    for ss in tax_info:
        tax_rep = tax_rep + ss
    request.vars['rate_report'] = tax_rep

    #deal = db(db.deals.name==deal_name).select().first()
    # new make order
    #print deal_acc_addr
    id = db.orders.insert(
        ref_=deal_acc_addr.id,
        volume_in=volume_in,
        volume_out=volume_out,
    )
    # теперь стек добавим, который будем удалять потом
    db.orders_stack.insert(ref_=id)
    request.vars['order'] = id

    uri, qr = common.uri_make(
        curr_in.name2, addr, {
            'amount': volume_in,
            'label': db_client.make_x_acc_label(deal, ph, curr_out.abbrev)
        })

    return dict(uri=uri, addr=addr, qr=qr)
示例#5
0
def get():

    # CHECK ARGS AND VARS
    args = request.args
    if len(args) != 1: return mess('err...')
    curr_id = args(0)
    if not curr_id.isdigit(): return mess('dig...')
    # теперь можно задать открытие кнопки
    scr = "$('#cvr%s').css('display','none');$('#tag%s').show('slow');" % (
        curr_id, curr_id)
    response.js = scr

    vol = request.vars['vol']
    if not vol or len(vol) > 20:
        return mess(T('ОШИБКА') + ': ' + T('Задайте количество'))
    try:
        vol = float(vol)
        curr_id = int(curr_id)
    except:
        return mess('digs...')

    if vol < MIN:
        try:
            session.vol = MIN
        except:
            print 'to_phone session error .vol:', type(MIN), MIN

        return mess(
            T('ОШИБКА: Слишком маленькая сумма платежа %s < %s') % (vol, MIN))

    kod = request.vars.kod or '7'
    ph = request.vars.phone
    #print request.vars
    if not ph:
        return mess(T('ОШИБКА: Задайте номер телефона'))
    ph = valid_phone(kod + ph)
    if not ph:
        return mess(
            T('ОШИБКА: Проверьте номер телефона, он должен содержать 10 цифр с досупными разделитялями: пробел, скобки, тире.'
              ))

    curr_in = db.currs[curr_id]
    if not curr_in: return mess(T('curr...'))
    xcurr_in = db(db.xcurrs.curr_id == curr_id).select().first()
    if not xcurr_in: return mess(T('xcurr...'))

    # ALL CHECKED GOOD - store vars
    try:
        ph_sess = ph
        if len(ph) == 10:
            # для наших добавим 7-ку
            ph_sess = '7' + ph_sess
        session.toPhone = ph_sess
        session.vol = vol
    except:
        print 'to_phone session error .toPhone:', type(ph), ph
        print 'to_phone session error .vol:', type(vol), vol

    ##print 'ph, session.phone:', ph, session.toPhone

    # теперь проверку на правильность телефона для дилера электронных платежей
    # dealer и dealer_acc - выбирается в начале файла
    # pay_test(deal, dealer, dealer_acc, dealer_deal, acc, volume_out)
    res = dealer_acc and ed_common.pay_test(db, deal, dealer, dealer_acc,
                                            dealer_deal, ph, vol, False)
    ##print 'PAY:',res
    if True:
        pass
    elif not res:
        return mess(
            'dealer error - Возможно достигнуто ограничение переводов на сотовые телефоны и электронные кошельки, просьба воспользоваться прямой оплатой нужных Вам услуг, например из меню "Всё"'
        )
    elif res['status'] != 'success':
        mm = 'error_description' in res and res['error_description'] or res[
            'error'] or 'dealer error'
        return mess(
            T('Платежная система %s отвергла платеж, потому что: %s (... %s)')
            % (dealer.name, mm, dealer_acc.acc[-4:]))

    gift_cod = request.vars.gift_cod
    curr_out_abbrev = curr_out.abbrev
    x_acc_label = db_client.make_x_acc(deal, ph, curr_out_abbrev)
    # найдем ранее созданный адресс для этого телефона, этой крипты и этого фиата
    # сначала найтем аккаунт у дела
    deal_acc_id = db_client.get_deal_acc_id(db, deal, ph, curr_out)
    # теперь найдем кошелек для данной крипты
    deal_acc_addr = db_client.get_deal_acc_addr_for_xcurr(
        db, deal_acc_id, curr_in, xcurr_in, x_acc_label)
    #deal_acc_addr = '123qwewfddgdfgfg'
    if not deal_acc_addr:
        return mess(
            T('Связь с кошельком ') + curr_in.name + T(' прервана.') + ' ' +
            T('Пожалуйста попробуйте позже'), 'warning')

    #request.vars['deal_acc_addr']=deal_acc_addr
    addr = deal_acc_addr.addr

    curr_in_abbrev = curr_in.abbrev

    h = CAT()
    addr_return = deal_acc_addr.addr_return
    if addr_return:
        addr_ret = DIV(
            DIV(T('Адрес для возвратов'),
                ': ',
                B(addr_return[:5] + '...' + addr_return[-5:]),
                _class='col-sm-12'),
            _class='row success',
        )
    else:
        addr_ret = LOAD(
            'aj',
            'addr_ret',
            #args=[deal_acc_addr.addr_return or 0, deal_acc_addr.id, ],
            # лучше передавать через переменные - чтобы там по кругу они гонялись
            # в request
            args=[deal_acc_addr.id],
            ajax=
            False,  # тут без асинхронной подгрузки модуля - вместе со страницей сразу грузим модуль
        )

    okIN = session.okPh
    h += sect(
        DIV(addr_ret,
            okIN and DIV(SPAN(A('Правила оплаты',
                                _onclick='$(".okIN").show("fast");',
                                _class='button warn right'),
                              _class='pull-right-'),
                         _class='col-sm-12') or '',
            DIV(okIN and ' ' or H3('ПРАВИЛА ОПЛАТЫ', _class='center'),
                P(T('При оплате необходимо соблюдать следующие правила:')),
                UL(
                    T('У оплат дела [%s] существуют ограничения по суммам, поэтому если Вы хотите оплатить бОльшую сумму, то Вам нужно делать платежи небольшими суммами в эквиваленте до %s рублей на тот же адрес кошелька, который Вы получили от нашей службы для этой услуги'
                      ) % (deal.name, MAX),
                    T('Желательно задать обратный адрес для возврата монет на случай если наша служба по каким-либо причинам не сможет совершить оплату по делу [%s]'
                      ) % deal.name,
                    T('Если Вы не задали обратный адрес для возврата монет, то необходимо платить биткоины и другую криптовалюту только со своего кошелька, задав адреса входов, которыми Вы действительно обладаете, а не с кошельков бирж, пулов или разных онлайн-кошельков. Так как монеты, в случае если платеж будет отвергнут нашим партнёром, могут автоматически вернуться только на адрес отправителя.'
                      ),
                    T('Если Вы оплатите другую сумму, то курс обмена может немножко измениться'
                      ),
                    T('Если Вы платите регулярно, то можете платить на тот же адрес кошелька криптовалюты, что получили ранее. Хотя желательно заходить на нашу службу для получения новостей хотябы раз в пол года или подписаться на важные новости и сообщения оставив свой емайл.'
                      ),
                ),
                H4(A('Понятно',
                     _onclick='$(".okIN").hide("fast");ajax("%s")' %
                     URL('aj', 'ok_to', args=['Ph']),
                     _class='button warn'),
                   _class='center'),
                _class='col-sm-12 okIN',
                _style='display:%s;' % (okIN and 'none' or 'block')),
            _style='color:chocolate',
            _class='row'), 'bg-warning pb-10')

    # если есть скрытый партнерский код то его забьем пользователю
    deal_acc = db.deal_accs[deal_acc_id]
    #print gift_cod, deal_acc
    if gift_cod:
        if not deal_acc.gift and not deal_acc.partner:
            #print 'added', gift_cod
            deal_acc.update_record(gift=gift_cod)
            h += P('Подарочный код', ': ', gift_cod)

    import gifts_lib
    adds_mess = XML(gifts_lib.adds_mess(deal_acc, PARTNER_MIN, T))
    if adds_mess:
        h += sect(XML(adds_mess), 'gift-bgc pb-10 pb-10')

    volume_out = vol
    hh = CAT(H2(T('3. Оплатите по данным реквизитам'), _class='center'))

    ###if volume_out > MAX: volume_out = MAX
    # используем быстрый поиск курса по формуле со степенью на количество входа
    # только надо найти кол-во входа от выхода
    pr_b, pr_s, pr_avg = rates_lib.get_average_rate_bsa(
        db, curr_in.id, curr_out.id, None)
    if pr_avg:
        vol_in = volume_out / pr_b
        amo_out, _, best_rate = rates_lib.get_rate(db, curr_in, curr_out,
                                                   vol_in)
    else:
        best_rate = None

    if best_rate:
        is_order = True
        # сначала открутим обратную таксу
        volume_in, _mess_in = db_client.calc_fees_back(db,
                                                       deal,
                                                       dealer_deal,
                                                       curr_in,
                                                       curr_out,
                                                       volume_out,
                                                       best_rate,
                                                       is_order,
                                                       note=0)
        ## теперь таксы для человека получим и должна та же цифра выйти
        vol_out_new, tax_rep = db_client.calc_fees(db,
                                                   deal,
                                                   dealer_deal,
                                                   curr_in,
                                                   curr_out,
                                                   volume_in,
                                                   best_rate,
                                                   is_order,
                                                   note=1)
        vol_out_new = common.rnd_8(vol_out_new)
        if volume_out != vol_out_new:
            print 'to_phone error_in_fees: volume_out != vol_out_new', volume_out, vol_out_new

        volume_in = common.rnd_8(volume_in)
        rate_out = volume_out / volume_in

        # new make order
        order_id = db.orders.insert(
            ref_=deal_acc_addr.id,
            volume_in=volume_in,
            volume_out=volume_out,
        )
        # теперь стек добавим, который будем удалять потом
        db.orders_stack.insert(ref_=order_id)

        hh += DIV(
            T('Создан заказ №'),
            ' ',
            order_id,
            ' ',
            T('на заморозку курса'),
            ' ',
            rate_out,
            #T('обратный курс'), ' ', round(1.0/rate_out,8),
            H5(
                T('*Данный курс будет заморожен для Вас на 20 минут для объёма криптовалюты не больше указанного. Проверить можно по номеру заказа в списке платежей.'
                  )),
            _class='row')
    else:
        volume_in = rate_out = None
        tax_rep = ''
        hh += mess(
            '[' + curr_in.name + '] -> [' + curr_out.name + ']' +
            T(' - лучшая цена не доступна.') +
            T('Но Вы можете оплатить вперед'), 'warning')

    _, url_uri = common.uri_make(
        curr_in.name2, addr, {
            'amount': volume_in,
            'label': db_client.make_x_acc_label(deal, ph, curr_out_abbrev)
        })

    lim_bal, may_pay = db_client.is_limited_ball(curr_in)
    if lim_bal:
        if may_pay > 0:
            lim_bal_mess = P(
                'Внимание! Для криптовалюты %s существует предел запаса и поэтому наша служба может принять только %s [%s], Просьба не превышать это ограничение'
                % (curr_in.name, may_pay, curr_in_abbrev),
                '.',
                _style='color:black;')
        else:
            lim_bal_mess = P(
                'ВНИМАНИЕ! Наша служба НЕ может сейчас принимать %s, так как уже достугнут предел запаса её у нас. Просьба попробовать позже, после того как запасы [%s] снизятся благодаря покупке её другими пользователями'
                % (curr_in.name, curr_in_abbrev),
                '. ',
                'Иначе Ваш платеж будет ожидать момента когда запасы снизятся ниже %s'
                % lim_bal,
                '.',
                _style='color:brown;')
    else:
        lim_bal_mess = ''

    hh += DIV(
        P(
            T('Оплата телефона'),
            ': ',  #kod, ' ',
            ph,
            ' ',
            T('на сумму'),
            ' ',
            volume_out,
            ' ',
            curr_out_abbrev,
            ' ',
            T('из доступных в службе'),
            ' ',
            free_bal),
        volume_out > free_bal and P(
            H3(T('Сейчас средств на балансе меньше чем Вам надо'),
               _style='color:crimson;'),
            SPAN(T('Поэтому Ваш заказ будет исполнен позже'),
                 BR(),
                 T('когда на балансе службы появится достаточно средств'),
                 _style='color:black;'),
            BR(),
        ) or '',
        lim_bal_mess,
        DIV(CENTER(
            A(SPAN(
                T('Оплатить'), ' ', volume_in or '', ' ',
                IMG(_src=URL('static',
                             'images/currs/' + curr_in_abbrev + '.png'),
                    _width=50)),
              _class='block button blue-bgc',
              _style='font-size:x-large; max-width:500px; margin:0px 7px;',
              _href=url_uri), ),
            _class='row'),
        BR(),
        DIV(
            A(
                T('Показать QR-код'),
                _class='btn btn-info',
                #_onclick="jQuery(this).parent().html('%s')" % IMG(_src=URL('static','images/loading.gif'), _width=64),
                _onclick=
                "jQuery(this).parent().html('<i class=\"fa fa-spin fa-refresh\" />')",
                callback=URL('plugins', 'qr', vars={'mess': url_uri}),
                target='tag0',
                #delete='div#tag0'
            ),
            _id='tag0'),
        T('или'),
        BR(),
        T('Оплатите вручную'),
        ': ',
        FORM(  ## ВНИМАНИЕ !!! тут имена полей надр друние указывать или
            # FORM в основной делать тоже иначе они складываются
            INPUT(_name='v', value=volume_in, _class="pay_val", _readonly=''),
            curr_in_abbrev,
            BR(),
            T("Для этого скопируйте сумму и адрес (двойной клик по полю для выделения) и вставьте их в платеж на вашем кошельке"
              ),
            ': ',
            INPUT(_name='addr', _value=addr, _class='wallet', _readonly=''),
            BR(),
            T('Резервы службы'),
            ' ',
            B(free_bal),
            ' ',
            T('рублей'),
            BR(),
            ##LOAD('where', 'for_addr', vars={'addr': addr}, ajax=True, times=100, timeout=20000,
            ##    content=IMG(_src=URL('static','images/loading.gif'), _width=48)),
            INPUT(
                _type='submit',
                _class='button blue-bgc',
                _value=T('Подробный просмотр платежей'),
                _size=6,
            ),
            _action=URL('where', 'index'),
            _method='post',
        ))

    h += sect(hh, 'bg-info pb-10')

    h += sect(
        DIV(DIV(
            H3(T('Почему получился такой курс?')),
            tax_rep,
            BR(),
            T('При этом Вы получаете следующие преимущества при оплате биткоинами услуг и дел у нас'
              ),
            UL([
                T('не нужно нигде регистрироваться'),
                T('не нужно делать подтверждения по СМС или по емайл'),
                T('не нужно копить много денег - платежи возможны от %s [%s]')
                % (MIN, curr_out_abbrev),
                T('не нужно ждать сутки вывода')
            ]),
            T(' Время - деньги!'),
            _class='col-sm-12'),
            _class='row'))

    h += SCRIPT('''
        $('html, body').animate( { scrollTop: $('#cvr%s').offset().top - $('#aside1').height() }, 500 );
      ''' % (curr_id))
    return h