コード例 #1
0
def create_ticket(old_id=None,
                  event_id=None,
                  order_id=None,
                  eventdate_id=None,
                  ticket_type=None,
                  name=None,
                  price=None,
                  status=None,
                  ticket_number=None):
    data = {
        'old_id': old_id,
        'event_id': event_id,
        'order_id': order_id,
        'ticket_type': ticket_type,
        'eventdate_id': eventdate_id,
        'name': name,
        'price': price,
        'status': status,
        'ticket_number': ticket_number,
    }

    ticket = Ticket(**data)

    dao_create_record(ticket)

    return ticket
コード例 #2
0
def create_order(old_id=1,
                 created_at=None,
                 member_id=None,
                 old_member_id=1,
                 email_address='*****@*****.**',
                 buyer_name='Test buyer',
                 txn_id='1122334455',
                 txn_type='cart',
                 payment_status='completed',
                 payment_total='10.0',
                 params='some_test_params&test_param2',
                 address_street='1 Test Steeet',
                 address_city='Test City',
                 address_postal_code='T11 2TS',
                 address_state='London',
                 address_country='UK',
                 address_country_code='GB',
                 delivery_zone='UK',
                 delivery_status='completed',
                 delivery_balance=0.0,
                 books=[],
                 tickets=[],
                 errors=[],
                 linked_txn_id=None):
    data = {
        'old_id': old_id,
        'created_at': created_at,
        'member_id': member_id,
        'old_member_id': old_member_id,
        'email_address': email_address,
        'buyer_name': buyer_name,
        'txn_id': txn_id,
        'txn_type': txn_type,
        'payment_status': payment_status,
        'payment_total': payment_total,
        'params': params,
        'address_street': address_street,
        'address_city': address_city,
        'address_postal_code': address_postal_code,
        'address_state': address_state,
        'address_country': address_country,
        'address_country_code': address_country_code,
        'delivery_zone': delivery_zone,
        'delivery_status': delivery_status,
        'delivery_balance': delivery_balance,
        'books': books,
        'tickets': tickets,
        'errors': errors
    }
    if linked_txn_id:
        data.update(linked_txn_id=linked_txn_id)

    order = Order(**data)
    dao_create_record(order)

    if books:
        for book in books:
            dao_update_book_to_order_quantity(book.id, order.id, 1)

    return order
コード例 #3
0
def import_magazine():
    data = request.get_json(force=True)

    validate(data, post_import_magazine_schema)

    magazine = Magazine(old_id=data['old_id'],
                        title=data['title'],
                        old_filename=data['old_filename'],
                        filename=data['filename'])

    dao_create_record(magazine)

    return jsonify(magazine.serialize()), 201
コード例 #4
0
def create_magazine():
    data = request.get_json(force=True)

    validate(data, post_create_magazine_schema)

    new_filename = get_magazine_filename(data['filename'])

    if new_filename:
        magazine = Magazine(title=data['title'], filename=new_filename)

        dao_create_record(magazine)

        upload_tasks.upload_magazine.apply_async(
            (str(magazine.id), data['pdf_data']))

        return jsonify(magazine.serialize()), 201

    raise InvalidRequest(
        'Invalid filename for magazine: {}'.format(data['filename']), 400)
コード例 #5
0
def create_magazine(
    old_id=None,
    title='title',
    old_filename=None,
    filename='new filename',
    tags='',
):
    data = {
        'old_id': old_id,
        'title': title,
        'old_filename': old_filename,
        'filename': filename,
        'tags': tags
    }

    magazine = Magazine(**data)

    dao_create_record(magazine)

    return magazine
コード例 #6
0
ファイル: rest.py プロジェクト: NewAcropolis/api
def paypal_ipn(params=None, allow_emails=True, replace_order=False):
    message = ''
    bypass_verify = False
    if not params:
        params = request.form.to_dict(flat=False)
    else:
        bypass_verify = True
    current_app.logger.info('IPN params: %r', params)

    def get_data(params):
        data = {}
        for key in params.keys():
            if isinstance(params[key], list):
                data[key] = params[key][0]
            else:
                data[key] = params[key]
        return data

    if bypass_verify or (current_app.config['TEST_VERIFY']
                         and current_app.config['ENVIRONMENT'] != 'live'):
        v_response = 'VERIFIED'
        current_app.logger.info('Test paypal verify')
    else:
        VERIFY_URL = current_app.config['PAYPAL_VERIFY_URL']

        params['cmd'] = '_notify-validate'
        headers = {
            'content-type': 'application/x-www-form-urlencoded',
            'user-agent': 'Python-IPN-Verification-Script'
        }
        current_app.logger.info("params: %r", params)  # debug

        r = requests.post(VERIFY_URL,
                          params=params,
                          headers=headers,
                          verify=True)
        r.raise_for_status()
        v_response = r.text
        if v_response == 'VERIFIED':
            current_app.logger.info('VERIFIED: %s', params['txn_id'])

    # Check return message and take action as needed
    if v_response == 'VERIFIED':
        status = product_message = delivery_message = error_message = ''
        diff = 0.0
        data = get_data(params)

        order_data, tickets, events, products, delivery_zones, errors = parse_ipn(
            data, replace_order)
        if 'payment already made' in (','.join(errors)):
            current_app.logger.info("Transaction payment already made %r",
                                    data['txn_id'])
            return "Duplicate transaction %s" % {data['txn_id']}

        order_data['params'] = json.dumps(params)
        if 'is_donation' in order_data.keys(
        ) and order_data['is_donation'] == "Donation":
            order_data['is_donation'] = True
            order_data['linked_txn_id'] = None

        order = Order(**order_data)
        dao_create_record(order)

        if order_data['payment_status'] != 'Completed':
            err_msg = f"Payment not Completed: {order_data['payment_status']}"
            errors = [err_msg]
        else:
            message = f"<p>Thank you for your order ({order.id})</p>"

            if order_data['txn_type'] == 'web_accept' and order_data[
                    'linked_txn_id']:
                linked_order = dao_get_order_with_txn_id(
                    order_data['linked_txn_id'])

                diff = linked_order.delivery_balance - Decimal(
                    order_data['payment_total'])
                if diff == 0:
                    status = statuses.DELIVERY_EXTRA_PAID
                elif diff > 0:
                    status = statuses.DELIVERY_EXTRA
                    current_app.logger.warning(
                        'Delivery balance not paid in full')
                elif diff < 0:
                    status = statuses.DELIVERY_REFUND
                    current_app.logger.warning('Delivery balance overpaid')

                dao_update_record(Order,
                                  linked_order.id,
                                  delivery_status=status,
                                  payment_total=linked_order.payment_total +
                                  Decimal(order_data['payment_total']),
                                  delivery_balance=abs(diff))

                order_data['delivery_status'] = status
                order_data['delivery_zone'] = linked_order.delivery_zone
                order_data['delivery_balance'] = abs(diff)

                _payment_total = _get_nice_cost(order.payment_total)
                _diff = _get_nice_cost(diff)
                if status == statuses.DELIVERY_EXTRA_PAID:
                    message += f"<div>Outstanding payment for order ({order_data['linked_txn_id']}) of &pound;" \
                        f"{_payment_total} for delivery to {order_data['delivery_zone']} has been paid.</div>"
                elif status == statuses.DELIVERY_EXTRA:
                    message += f"<div>Outstanding payment for order ({order_data['linked_txn_id']}) of &pound;" \
                        f"{_payment_total} for delivery to {order_data['delivery_zone']} has been " \
                        f"partially paid.</div><div>Not enough delivery paid, &pound;{_diff} due.</div>"
                elif status == statuses.DELIVERY_REFUND:
                    message += f"<p>You have overpaid for delivery on order ({order_data['linked_txn_id']}) " \
                        f"by &pound;{_diff}, please send a message to website admin if there is " \
                        "no refund within 5 working days.</p>"
            else:
                if products:
                    for product in products:
                        if product['type'] == BOOK:
                            book_to_order = BookToOrder(
                                book_id=product['book_id'],
                                order_id=order.id,
                                quantity=product['quantity'])
                            dao_create_book_to_order(book_to_order)

                            product_message += (
                                f'<tr><td>{product["title"]}</td><td> x {product["quantity"]}</td>'
                                f'<td> = {_get_nice_cost(product["price"] * product["quantity"])}</td></tr>'
                            )
                    product_message = f'<table>{product_message}</table>'
                    address_delivery_zone = None

                    if 'address_country_code' not in order_data:
                        delivery_message = "No address supplied. "
                        status = "missing_address"
                    else:
                        address_delivery_zone = get_delivery_zone(
                            order_data['address_country_code'])
                        admin_message = ""

                        total_cost = 0
                        for dz in delivery_zones:
                            _d = [
                                _dz for _dz in DELIVERY_ZONES
                                if _dz['name'] == dz
                            ]
                            if _d:
                                d = _d[0]
                                total_cost += d['price']
                                _price = _get_nice_cost(d['price'])
                                admin_message += f"<tr><td>{d['name']}</td><td>{_price}</td></tr>"
                            else:
                                errors.append(f'Delivery zone: {dz} not found')
                                admin_message += f"<tr><td>{dz}</td><td>Not found</td></tr>"
                        _total_cost = _get_nice_cost(total_cost)
                        _price = _get_nice_cost(address_delivery_zone['price'])
                        diff = total_cost - address_delivery_zone['price']

                        if diff != 0:
                            admin_message = f"<p>Order delivery zones: <table>{admin_message}" \
                                f"</table>Total: &pound;{_total_cost}</p>"

                            admin_message += "<p>Expected delivery zone: " \
                                f"{address_delivery_zone['name']} - &pound;{_price}</p>"

                            order_data['delivery_balance'] = _get_nice_cost(
                                diff)
                            if diff > 0:
                                status = "refund"
                                delivery_message = f"Refund of &pound;{order_data['delivery_balance']} " \
                                    "due as wrong delivery fee paid"
                            elif diff < 0:
                                _diff = _get_nice_cost(diff)

                                status = "extra"
                                delivery_message = "{}, &pound;{} due. ".format(
                                    "No delivery fee paid" if total_cost == 0
                                    else "Not enough delivery paid",
                                    order_data['delivery_balance'])

                            admin_message = f"Transaction ID: {order.txn_id}<br>Order ID: {order.id}" \
                                f"<br>{delivery_message}.{admin_message}"

                            for user in dao_get_admin_users():
                                send_smtp_email(user.email,
                                                f'New Acropolis {status}',
                                                admin_message)
                        else:
                            status = statuses.DELIVERY_PAID

                    dao_update_record(
                        Order,
                        order.id,
                        delivery_status=status,
                        delivery_zone=address_delivery_zone['name']
                        if address_delivery_zone else None,
                        delivery_balance=str(abs(diff)))

                    if delivery_message:
                        order_data['delivery_status'] = status
                        if status == 'refund':
                            delivery_message = f"<p>{delivery_message}, please send a message " \
                                "to website admin if there is no refund within 5 working days.</p>"
                        else:
                            order_data['delivery_zone'] = address_delivery_zone['name']\
                                if address_delivery_zone else None
                    else:
                        product_message = (
                            f'{product_message}<br><div>Delivery to: {order_data["address_street"]},'
                            f'{order_data["address_city"]}, '
                            f'{order_data["address_postal_code"]}, {order_data["address_country"]}</div>'
                        )

                if tickets:
                    for i, _ticket in enumerate(tickets):
                        _ticket['order_id'] = order.id
                        ticket = Ticket(**_ticket)
                        dao_create_record(ticket)
                        tickets[i]['ticket_id'] = ticket.id
                        tickets[i]['title'] = ticket.event.title

                    storage = Storage(current_app.config['STORAGE'])
                    for ticket in tickets:
                        link_to_post = '{}{}'.format(
                            current_app.config['API_BASE_URL'],
                            url_for('.use_ticket',
                                    ticket_id=ticket['ticket_id']))
                        img = pyqrcode.create(link_to_post)
                        buffer = io.BytesIO()
                        img.png(buffer, scale=2)

                        img_b64 = base64.b64encode(buffer.getvalue())
                        target_image_filename = '{}/{}'.format(
                            'qr_codes', str(ticket['ticket_id']))
                        storage.upload_blob_from_base64string(
                            'qr.code', target_image_filename, img_b64)

                        message += '<div><span><img src="{}/{}"></span>'.format(
                            current_app.config['IMAGES_URL'],
                            target_image_filename)

                        event_date = dao_get_event_date_by_id(
                            ticket['eventdate_id'])
                        minutes = ':%M' if event_date.event_datetime.minute > 0 else ''
                        message += "<div>{} on {}</div></div>".format(
                            ticket['title'],
                            event_date.event_datetime.strftime(
                                '%-d %b at %-I{}%p'.format(minutes)))

                        if event_date.event.remote_access:
                            message += f"<br><div>Meeting id: {event_date.event.remote_access}"
                            if event_date.event.remote_pw:
                                message += f", Password: {event_date.event.remote_pw}"
                            message += "</div>"
                            message += f"<div><a href='https://zoom.us/j/{event_date.event.remote_access}'>"\
                                "Join zoom event</a></div>"

        if errors:
            error_message = ''
            for error in errors:
                error_message += f"<div>{error}</div>"
                order.errors.append(OrderError(error=error))
            error_message = f"<p>Errors in order: {error_message}</p>"

        if status in [
                statuses.DELIVERY_EXTRA, statuses.DELIVERY_MISSING_ADDRESS,
                statuses.DELIVERY_NOT_PAID
        ]:
            _delivery_zone_balance = ''

            if 'delivery_balance' in order_data:
                _delivery_balance = _get_nice_cost(
                    order_data['delivery_balance'])
                _delivery_zone_balance = f"/{order_data['delivery_zone']}/{_delivery_balance}"\
                    if order_data['delivery_zone'] else ''

            delivery_message = (
                f"<p>{delivery_message}Please "
                f"<a href='{current_app.config['FRONTEND_URL']}/order/{order_data['delivery_status']}/"
                f"{order_data['txn_id']}{_delivery_zone_balance}'>complete</a> "
                "your order.</p>")

        if allow_emails:
            send_email(
                order.email_address, 'New Acropolis Order',
                message + product_message + delivery_message + error_message)
    else:
        if v_response == 'INVALID':
            current_app.logger.info('INVALID %r', params['txn_id'])
        else:
            current_app.logger.info('UNKNOWN response %r', params['txn_id'])

        data = get_data(params)
        data[
            'txn_id'] = f"XX-{v_response}_{int(datetime.utcnow().timestamp())}-{data['txn_id']}"

        order_data, tickets, events, products, delivery_zones, errors = parse_ipn(
            data)

        order_data['params'] = json.dumps(params)

        order = Order(**order_data)
        order.errors.append(OrderError(error=f"{v_response} verification"))
        dao_create_record(order)

    return 'Paypal IPN'
コード例 #7
0
ファイル: rest.py プロジェクト: kentsanggds/api
def paypal_ipn():
    VERIFY_URL = current_app.config['PAYPAL_VERIFY_URL']

    params = request.form.to_dict(flat=False)
    current_app.logger.info('IPN params: %r', params)

    params['cmd'] = '_notify-validate'
    headers = {
        'content-type': 'application/x-www-form-urlencoded',
        'user-agent': 'Python-IPN-Verification-Script'
    }
    r = requests.post(VERIFY_URL, params=params, headers=headers, verify=True)
    r.raise_for_status()

    # Check return message and take action as needed
    if r.text == 'VERIFIED':
        current_app.logger.info('VERIFIED: %s', params['txn_id'])

        data = {}
        for key in params.keys():
            if isinstance(params[key], list):
                data[key] = params[key][0]
            else:
                data[key] = params[key]

        order_data, tickets, events = parse_ipn(data)

        if not order_data:
            return 'Paypal IPN no order created'
        order_data['params'] = json.dumps(params)

        order = Order(**order_data)

        dao_create_record(order)
        for i, _ticket in enumerate(tickets):
            _ticket['order_id'] = order.id
            ticket = Ticket(**_ticket)
            dao_create_record(ticket)
            tickets[i]['ticket_id'] = ticket.id

        storage = Storage(current_app.config['STORAGE'])
        message = "<p>Thank you for your order:<p>"
        for i, event in enumerate(events):
            link_to_post = '{}{}'.format(
                current_app.config['API_BASE_URL'],
                url_for('.use_ticket', ticket_id=tickets[i]['ticket_id']))
            img = pyqrcode.create(link_to_post)
            buffer = io.BytesIO()
            img.png(buffer, scale=2)

            img_b64 = base64.b64encode(buffer.getvalue())
            target_image_filename = '{}{}'.format('qr_codes',
                                                  str(tickets[i]['ticket_id']))
            storage.upload_blob_from_base64string('qr.code',
                                                  target_image_filename,
                                                  img_b64)

            message += '<div><span><img src="{}/{}"></span>'.format(
                current_app.config['IMAGES_URL'], target_image_filename)

            event_date = dao_get_event_date_by_id(tickets[i]['eventdate_id'])
            minutes = ':%M' if event_date.event_datetime.minute > 0 else ''
            message += "<span>{} on {}</span></div>".format(
                event.title,
                event_date.event_datetime.strftime(
                    '%-d %b at %-I{}%p'.format(minutes)))

        send_email(order.email_address, 'New Acropolis Event Tickets', message)

    elif r.text == 'INVALID':
        current_app.logger.info('INVALID %r', params['txn_id'])
    else:
        current_app.logger.info('UNKNOWN response %r', params['txn_id'])

    return 'Paypal IPN'