def test_create_with_invalid_parameters_encrypted(self):
        error_msg = 'Invalid encrypted input'

        responses.add(
            responses.POST,
            '%s/services/2/shoppers' % client.default().endpoint_url,
            status=400,
            content_type='application/xml',
            body='''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<messages xmlns="http://ws.plimus.com">
<message>
    <code>19002</code>
    <description>%s</description>
</message>
</messages>''' % error_msg)

        shopper = Shopper()

        with self.assertRaises(exceptions.APIError) as cm:
            shopper.create(
                contact_info=ContactInfo(email=''),
                credit_card=self.encrypted_credit_card
            )
        self.assertEqual(cm.exception.status_code, 400)
        self.assertEqual(cm.exception.description, error_msg)
    def test_create_with_invalid_parameters(self):
        error_msg = (
            'Seller 397608 encountered a problem creating a new shopper due '
            'to incorrect input.')
        responses.add(
            responses.POST,
            '%s/services/2/shoppers' % client.default().endpoint_url,
            status=400,
            content_type='application/xml',
            body='''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<messages xmlns="http://ws.plimus.com">
<message>
    <description>%s</description>
</message>
<message>
    <code>10001</code>
    <description>'Email Address' is not a valid email address.</description>
    <invalid-property>
        <name>shopperInfo.shopperContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
<message>
    <code>10001</code>
    <description>Field 'Email Address' is required.</description>
    <invalid-property>
        <name>shopperInfo.shopperContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
<message>
    <code>10001</code>
    <description>Field 'Email Address' is required.</description>
    <invalid-property>
        <name>shopperInfo.invoiceContactsInfo.invoiceContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
<message>
    <code>10001</code>
    <description>'Email Address' is not a valid email address.</description>
    <invalid-property>
        <name>shopperInfo.invoiceContactsInfo.invoiceContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
</messages>''' % error_msg)

        shopper = Shopper()

        with self.assertRaises(exceptions.APIError) as cm:
            shopper.create(
                contact_info=ContactInfo(email=''),
                credit_card=self.credit_card
            )

        self.assertEqual(cm.exception.status_code, 400)
        self.assertEqual(cm.exception.description, 'None')
        self.assertGreater(len(cm.exception.messages), 1)
        self.assertEqual(cm.exception.messages[0]['description'], error_msg)
示例#3
0
    def test_create_with_invalid_parameters(self):
        error_msg = (
            'Seller 397608 encountered a problem creating a new shopper due '
            'to incorrect input.')
        responses.add(
            responses.POST,
            '%s/services/2/shoppers' % client.default().endpoint_url,
            status=400,
            content_type='application/xml',
            body='''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<messages xmlns="http://ws.plimus.com">
<message>
    <description>%s</description>
</message>
<message>
    <code>10001</code>
    <description>'Email Address' is not a valid email address.</description>
    <invalid-property>
        <name>shopperInfo.shopperContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
<message>
    <code>10001</code>
    <description>Field 'Email Address' is required.</description>
    <invalid-property>
        <name>shopperInfo.shopperContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
<message>
    <code>10001</code>
    <description>Field 'Email Address' is required.</description>
    <invalid-property>
        <name>shopperInfo.invoiceContactsInfo.invoiceContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
<message>
    <code>10001</code>
    <description>'Email Address' is not a valid email address.</description>
    <invalid-property>
        <name>shopperInfo.invoiceContactsInfo.invoiceContactInfo.email</name>
        <message-value/>
    </invalid-property>
</message>
</messages>''' % error_msg)

        shopper = ShopperResource()

        with self.assertRaises(exceptions.APIError) as cm:
            shopper.create(contact_info=ContactInfo(email=''),
                           credit_card=self.credit_card)

        self.assertEqual(cm.exception.status_code, 400)
        self.assertEqual(cm.exception.description, 'None')
        self.assertGreater(len(cm.exception.messages), 1)
        self.assertEqual(cm.exception.messages[0]['description'], error_msg)
示例#4
0
    def test_update_fails_with_invalid_shopper_id(self):
        shopper_id = '1'
        error_msg = 'User: %s is not authorized to update shopper: %s.' % (
            client.default().username, shopper_id)

        responses.add(responses.PUT,
                      '%s/services/2/shoppers/%s' %
                      (client.default().endpoint_url, shopper_id),
                      status=403,
                      content_type='application/xml',
                      body=error_msg)

        shopper = ShopperResource()

        with self.assertRaises(exceptions.APIError) as cm:
            shopper.update(shopper_id, contact_info=self.contact_info)
        self.assertEqual(cm.exception.status_code, 403)
        self.assertEqual(cm.exception.description, error_msg)
    def test_update_fails_with_invalid_shopper_id(self):
        shopper_id = '1'
        error_msg = 'User: %s is not authorized to update shopper: %s.' % (
            client.default().username, shopper_id)

        responses.add(
            responses.PUT,
            '%s/services/2/shoppers/%s' % (
                client.default().endpoint_url, shopper_id),
            status=403,
            content_type='application/xml',
            body=error_msg)

        shopper = Shopper()

        with self.assertRaises(exceptions.APIError) as cm:
            shopper.update(shopper_id, contact_info=self.contact_info)
        self.assertEqual(cm.exception.status_code, 403)
        self.assertEqual(cm.exception.description, error_msg)
    def test_find_by_bogus_shopper_id_and_seller_shopper_id_raises_exception(self):
        bogus_shopper_id = 'bogus_shopper_id'
        bogus_seller_shopper_id = 'bogus_seller_shopper_id'

        responses.add(
            responses.GET,
            '%s/services/2/shoppers/%s' % (
                client.default().endpoint_url, bogus_shopper_id),
            status=403,
            content_type='application/xml',
            body='User: %s is not authorized to view shopper: %s.' % (
                client.default().username, bogus_shopper_id)
        )
        responses.add(
            responses.GET,
            '%s/services/2/shoppers/%s,%s' % (
                client.default().endpoint_url,
                bogus_seller_shopper_id,
                client.default().seller_id),
            status=403,
            content_type='application/xml',
            body='User: %s is not authorized to view seller shopper: %s.' % (
                client.default().username, bogus_seller_shopper_id)
        )

        with self.assertRaises(exceptions.APIError) as cm:
            Shopper().find_by_shopper_id(bogus_shopper_id)
            self.assertTrue(False, 'APIError not raised')
        self.assertEqual(cm.exception.status_code, 403)
        self.assertRegexpMatches(
            cm.exception.description,
            'User: %s is not authorized to view shopper: %s.' % (
                client.default().username, bogus_shopper_id))

        with self.assertRaises(exceptions.APIError) as cm:
            Shopper().find_by_seller_shopper_id(bogus_seller_shopper_id)
            self.assertTrue(False, 'APIError not raised')
        self.assertEqual(cm.exception.status_code, 403)
        self.assertRegexpMatches(
            cm.exception.description,
            'User: %s is not authorized to view seller shopper: %s.' % (
                client.default().username, bogus_seller_shopper_id))
示例#7
0
    def test_find_by_bogus_shopper_id_and_seller_shopper_id_raises_exception(
            self):
        bogus_shopper_id = 'bogus_shopper_id'
        bogus_seller_shopper_id = 'bogus_seller_shopper_id'

        responses.add(responses.GET,
                      '%s/services/2/shoppers/%s' %
                      (client.default().endpoint_url, bogus_shopper_id),
                      status=403,
                      content_type='application/xml',
                      body='User: %s is not authorized to view shopper: %s.' %
                      (client.default().username, bogus_shopper_id))
        responses.add(
            responses.GET,
            '%s/services/2/shoppers/%s,%s' %
            (client.default().endpoint_url, bogus_seller_shopper_id,
             client.default().seller_id),
            status=403,
            content_type='application/xml',
            body='User: %s is not authorized to view seller shopper: %s.' %
            (client.default().username, bogus_seller_shopper_id))

        with self.assertRaises(exceptions.APIError) as cm:
            ShopperResource().find_by_shopper_id(bogus_shopper_id)
            self.assertTrue(False, 'APIError not raised')
        self.assertEqual(cm.exception.status_code, 403)
        self.assertRegexpMatches(
            cm.exception.description,
            'User: %s is not authorized to view shopper: %s.' %
            (client.default().username, bogus_shopper_id))

        with self.assertRaises(exceptions.APIError) as cm:
            ShopperResource().find_by_seller_shopper_id(
                bogus_seller_shopper_id)
            self.assertTrue(False, 'APIError not raised')
        self.assertEqual(cm.exception.status_code, 403)
        self.assertRegexpMatches(
            cm.exception.description,
            'User: %s is not authorized to view seller shopper: %s.' %
            (client.default().username, bogus_seller_shopper_id))
示例#8
0
    def test_create_with_invalid_parameters_encrypted(self):
        error_msg = 'Invalid encrypted input'

        responses.add(
            responses.POST,
            '%s/services/2/shoppers' % client.default().endpoint_url,
            status=400,
            content_type='application/xml',
            body='''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<messages xmlns="http://ws.plimus.com">
<message>
    <code>19002</code>
    <description>%s</description>
</message>
</messages>''' % error_msg)

        shopper = ShopperResource()

        with self.assertRaises(exceptions.APIError) as cm:
            shopper.create(contact_info=ContactInfo(email=''),
                           credit_card=self.encrypted_credit_card)
        self.assertEqual(cm.exception.status_code, 400)
        self.assertEqual(cm.exception.description, error_msg)
示例#9
0
def _add_callbacks():
    _client = client.default()

    def assert_request_authorised(func):
        """
        Wrapper that ensures that the request has the correct API credentials.
        """
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            assert request.headers['authorization'] == (
                'Basic %s' % b64encode('%s:%s' %
                                       (_client.username, _client.password)))
            return func(request, *args, **kwargs)

        return wrapper

    def parse_xml_in_request_body(func):
        """
        Wrapper that parses the XML body and authorises the request.
        """
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            assert request.headers['content-type'] == 'application/xml'

            body = xmltodict.parse(request.body)
            return func(request, body, *args, **kwargs)

        return wrapper

    def and_assert_shopper_is_authorised(func):
        """
        Wrapper that asserts that a shopper is authorised to perform an action.
        """
        @wraps(func)
        def wrapper(request, body, *args, **kwargs):
            # Check client configuration
            shopper_info = body['shopper']['shopper-info']
            assert shopper_info['store-id'] == _client.default_store_id
            assert shopper_info['shopper-currency'] == _client.default_currency
            assert shopper_info['locale'] == _client.locale
            return func(request, body, *args, **kwargs)

        return wrapper

    @assert_request_authorised
    @parse_xml_in_request_body
    @and_assert_shopper_is_authorised
    def create_shopper_callback(request, body):
        shopper_info = body['shopper']['shopper-info']

        new_shopper_id = max(shoppers.keys() or [0]) + 1

        shopper_info['shopper-id'] = new_shopper_id
        shopper_info['username'] = '******' % new_shopper_id
        shopper_info['password'] = '******' % new_shopper_id
        shopper_info['shipping-contact-info'] = None
        shopper_info['invoice-contacts-info'] = {
            'invoice-contact-info':
            dict(default=True, **shopper_info['shopper-contact-info']),
        }

        try:
            credit_card_info = shopper_info['payment-info'][
                'credit-cards-info']['credit-card-info']
            credit_card = credit_card_info['credit-card']

            card_number = None

            # Attempt to extract credit card number
            if 'card-number' in credit_card:
                card_number = credit_card['card-number']
            elif ('encrypted-card-number' in credit_card
                  and credit_card['encrypted-card-number'].startswith(
                      'encrypted_')):
                card_number = credit_card['encrypted-card-number'][10:]

            # Check if invalid card numbers were used
            card_signature = _generate_card_signature({
                'card_number':
                card_number,
                'expiration_month':
                credit_card['expiration-month'],
                'expiration_year':
                credit_card['expiration-year'],
            })
            if card_signature in credit_card_number_to_error_responses:
                return (400, {
                    'content-type': 'application/xml'
                }, credit_card_number_to_error_responses[card_signature])

            credit_card['card-last-four-digits'] = card_number[-4:]

            # Remove unexpected fields
            keys_to_keep = {'card-type', 'card-last-four-digits'}
            for key_to_discard in (set(credit_card.keys()) - keys_to_keep):
                del credit_card[key_to_discard]

            credit_card_info = [credit_card_info]

        except (KeyError, TypeError):
            credit_card_info = []

        shopper_info['payment-info'] = {
            'credit-cards-info': {
                'credit-card-info': credit_card_info,
            }
        }

        shoppers[new_shopper_id] = body

        headers = {
            'location':
            '%s/services/2/shoppers/%d' %
            (_client.endpoint_url, new_shopper_id),
        }
        return (201, headers, '')

    @assert_request_authorised
    def get_shopper_callback(request):
        try:
            raw_shopper_id = request.path_url.split('/')[-1]
            shopper_id = int(raw_shopper_id)
            shopper = shoppers[shopper_id]
        except (KeyError, ValueError):
            return (404, {},
                    'User: %s is not authorized to view shopper: %s.' %
                    (_client.username, raw_shopper_id))
        else:
            return (200, {}, xmltodict.unparse(shopper))

    @assert_request_authorised
    def put_shopper_callback(request):
        try:
            raw_shopper_id = request.path_url.split('/')[-1]
            shopper_id = int(raw_shopper_id)
            shopper = shoppers[shopper_id]
        except (KeyError, ValueError):
            return (404, {},
                    'User: %s is not authorized to view shopper: %s.' %
                    (_client.username, raw_shopper_id))
        else:
            body = xmltodict.parse(request.body)
            payment_info = body['shopper']['shopper-info']['payment-info']
            credit_card = payment_info['credit-cards-info'][
                'credit-card-info']['credit-card']

            card_number = None

            # Attempt to extract credit card number
            if 'card-number' in credit_card:
                card_number = credit_card['card-number']
            elif ('encrypted-card-number' in credit_card
                  and credit_card['encrypted-card-number'].startswith(
                      'encrypted_')):
                card_number = credit_card['encrypted-card-number'][10:]

            # Check if invalid card numbers were used
            card_signature = _generate_card_signature({
                'card_number':
                card_number,
                'expiration_month':
                credit_card['expiration-month'],
                'expiration_year':
                credit_card['expiration-year'],
            })
            if card_signature in credit_card_number_to_error_responses:
                return (400, {
                    'content-type': 'application/xml'
                }, credit_card_number_to_error_responses[card_signature])

            credit_card['card-last-four-digits'] = card_number[-4:]

            # Remove unexpected fields
            keys_to_keep = {'card-type', 'card-last-four-digits'}
            for key_to_discard in (set(credit_card.keys()) - keys_to_keep):
                del credit_card[key_to_discard]

            # Update shopper
            credit_card_info = shopper['shopper']['shopper-info'][
                'payment-info']['credit-cards-info']['credit-card-info']
            credit_card_info.append(
                payment_info['credit-cards-info']['credit-card-info'])

            return (204, {}, '')

    @assert_request_authorised
    @parse_xml_in_request_body
    def post_order_callback(request, body):
        new_order_id = max(orders.keys() or [0]) + 1
        order_date = datetime.now().strftime('%d-%b-%y')

        order = body['order']

        order['order-id'] = new_order_id

        # Ordering shopper section
        ordering_shopper = order['ordering-shopper']

        # Validate shopper id
        try:
            raw_shopper_id = ordering_shopper['shopper-id']
            shopper_id = int(raw_shopper_id)
            shopper_body = shoppers[shopper_id]
        except (KeyError, ValueError):
            return (403, {},
                    'User: %s is not authorized to place an order for '
                    'shopper: %s.' % (_client.username, raw_shopper_id))

        try:
            credit_card = ordering_shopper['credit-card']
        except KeyError:
            return (400, {
                'content-type': 'application/xml'
            }, mock_responses['order_failed__no_payment_method'])

        # Validate credit card selection
        card_found = False
        for credit_card_info in shopper_body['shopper']['shopper-info'][
                'payment-info']['credit-cards-info']['credit-card-info']:
            print dict(credit_card_info['credit-card']), dict(credit_card)
            if dict(credit_card_info['credit-card']) == dict(credit_card):
                card_found = True
                break

        if not card_found:
            return (400, {
                'content-type': 'application/xml'
            }, mock_responses['order_failed__wrong_payment_details'])

        cart = order['cart']
        sku = cart['cart-item']['sku']
        assert sku['sku-id'] == helper.TEST_PRODUCT_SKU_ID
        sku_charge_price = sku['sku-charge-price']
        cart['charged-currency'] = sku_charge_price['currency']
        cart['cart-item']['item-sub-total'] = sku_charge_price['amount']
        cart['tax'] = '0.00'
        cart['tax-rate'] = '0'
        cart['total-cart-cost'] = sku_charge_price['amount']

        order['post-sale-info'] = {
            'invoices': {
                'invoice': {
                    'invoice-id': 'invoice_%d' % new_order_id,
                    'url': 'https://sandbox.bluesnap.com/jsp/show_invoice.jsp',
                    'financial-transactions': {
                        'financial-transaction': {
                            'status': 'Pending',
                            'date-due': order_date,
                            'date-created': order_date,
                            'amount': sku_charge_price['amount'],
                            'currency': sku_charge_price['currency'],
                            'soft-descriptor':
                            'BLS*%s' % order['soft-descriptor'],
                            'payment-method': 'Credit Card',
                            'target-balance': 'PLIMUS_ACCOUNT',
                            'credit-card':
                            order['ordering-shopper']['credit-card'],
                            'paypal-transaction-data': None,
                            'skus': {
                                'sku': {
                                    'sku-id': sku['sku-id'],
                                },
                            },
                        }
                    }
                }
            }
        }

        orders[new_order_id] = body

        return (200, {
            'content-type': 'application/xml'
        }, xmltodict.unparse(body))

    responses.add_callback(responses.POST,
                           '%s/services/2/shoppers' % _client.endpoint_url,
                           callback=create_shopper_callback)
    responses.add_callback(responses.GET,
                           re.compile(r'%s/services/2/shoppers/\d+' %
                                      _client.endpoint_url),
                           callback=get_shopper_callback)
    responses.add_callback(responses.PUT,
                           re.compile(r'%s/services/2/shoppers/\d+' %
                                      _client.endpoint_url),
                           callback=put_shopper_callback)
    responses.add_callback(responses.POST,
                           '%s/services/2/orders' % _client.endpoint_url,
                           callback=post_order_callback)
示例#10
0
def _add_callbacks():
    _client = client.default()

    def assert_request_authorised(func):
        """
        Wrapper that ensures that the request has the correct API credentials.
        """
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            assert request.headers['authorization'] == (
                'Basic %s' % b64encode('%s:%s' % (
                    _client.username, _client.password)))
            return func(request, *args, **kwargs)
        return wrapper

    def parse_xml_in_request_body(func):
        """
        Wrapper that parses the XML body and authorises the request.
        """
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            assert request.headers['content-type'] == 'application/xml'

            body = xmltodict.parse(request.body)
            return func(request, body, *args, **kwargs)
        return wrapper

    def and_assert_shopper_is_authorised(func):
        """
        Wrapper that asserts that a shopper is authorised to perform an action.
        """
        @wraps(func)
        def wrapper(request, body, *args, **kwargs):
            # Check client configuration
            shopper_info = body['shopper']['shopper-info']
            assert shopper_info['store-id'] == _client.default_store_id
            assert shopper_info['shopper-currency'] == _client.default_currency
            assert shopper_info['locale'] == _client.locale
            return func(request, body, *args, **kwargs)
        return wrapper

    @assert_request_authorised
    @parse_xml_in_request_body
    @and_assert_shopper_is_authorised
    def create_shopper_callback(request, body):
        shopper_info = body['shopper']['shopper-info']

        new_shopper_id = max(shoppers.keys() or [0]) + 1

        shopper_info['shopper-id'] = new_shopper_id
        shopper_info['username'] = '******' % new_shopper_id
        shopper_info['password'] = '******' % new_shopper_id
        shopper_info['shipping-contact-info'] = None
        shopper_info['invoice-contacts-info'] = {
            'invoice-contact-info': dict(
                default=True,
                **shopper_info['shopper-contact-info']
            ),
        }

        try:
            credit_card_info = shopper_info['payment-info'][
                'credit-cards-info']['credit-card-info']
            credit_card = credit_card_info['credit-card']

            card_number = None

            # Attempt to extract credit card number
            if 'card-number' in credit_card:
                card_number = credit_card['card-number']
            elif ('encrypted-card-number' in credit_card
                    and credit_card['encrypted-card-number'].startswith(
                        'encrypted_')):
                card_number = credit_card['encrypted-card-number'][10:]

            # Check if invalid card numbers were used
            card_signature = _generate_card_signature({
                'card_number': card_number,
                'expiration_month': credit_card['expiration-month'],
                'expiration_year': credit_card['expiration-year'],
            })
            if card_signature in credit_card_number_to_error_responses:
                return (400,
                        {'content-type': 'application/xml'},
                        credit_card_number_to_error_responses[card_signature])

            credit_card['card-last-four-digits'] = card_number[-4:]

            # Remove unexpected fields
            keys_to_keep = {'card-type', 'card-last-four-digits'}
            for key_to_discard in (set(credit_card.keys()) - keys_to_keep):
                del credit_card[key_to_discard]

            credit_card_info = [credit_card_info]

        except (KeyError, TypeError):
            credit_card_info = []

        shopper_info['payment-info'] = {
            'credit-cards-info': {
                'credit-card-info': credit_card_info,
            }
        }

        shoppers[new_shopper_id] = body

        headers = {
            'location': '%s/services/2/shoppers/%d' % (
                _client.endpoint_url, new_shopper_id),
        }
        return (201, headers, '')

    @assert_request_authorised
    def get_shopper_callback(request):
        try:
            raw_shopper_id = request.path_url.split('/')[-1]
            shopper_id = int(raw_shopper_id)
            shopper = shoppers[shopper_id]
        except (KeyError, ValueError):
            return (404, {},
                    'User: %s is not authorized to view shopper: %s.' % (
                        _client.username, raw_shopper_id))
        else:
            return (200, {}, xmltodict.unparse(shopper))

    @assert_request_authorised
    def put_shopper_callback(request):
        try:
            raw_shopper_id = request.path_url.split('/')[-1]
            shopper_id = int(raw_shopper_id)
            shopper = shoppers[shopper_id]
        except (KeyError, ValueError):
            return (404, {},
                    'User: %s is not authorized to view shopper: %s.' % (
                        _client.username, raw_shopper_id))
        else:
            body = xmltodict.parse(request.body)
            payment_info = body['shopper']['shopper-info']['payment-info']
            credit_card = payment_info['credit-cards-info'][
                'credit-card-info']['credit-card']

            card_number = None

            # Attempt to extract credit card number
            if 'card-number' in credit_card:
                card_number = credit_card['card-number']
            elif ('encrypted-card-number' in credit_card
                    and credit_card['encrypted-card-number'].startswith(
                        'encrypted_')):
                card_number = credit_card['encrypted-card-number'][10:]

            # Check if invalid card numbers were used
            card_signature = _generate_card_signature({
                'card_number': card_number,
                'expiration_month': credit_card['expiration-month'],
                'expiration_year': credit_card['expiration-year'],
            })
            if card_signature in credit_card_number_to_error_responses:
                return (400,
                        {'content-type': 'application/xml'},
                        credit_card_number_to_error_responses[card_signature])

            credit_card['card-last-four-digits'] = card_number[-4:]

            # Remove unexpected fields
            keys_to_keep = {'card-type', 'card-last-four-digits'}
            for key_to_discard in (set(credit_card.keys()) - keys_to_keep):
                del credit_card[key_to_discard]

            # Update shopper
            credit_card_info = shopper['shopper']['shopper-info'][
                'payment-info']['credit-cards-info']['credit-card-info']
            credit_card_info.append(
                payment_info['credit-cards-info']['credit-card-info'])

            return (204, {}, '')

    @assert_request_authorised
    @parse_xml_in_request_body
    def post_order_callback(request, body):
        new_order_id = max(orders.keys() or [0]) + 1
        order_date = datetime.now().strftime('%d-%b-%y')

        order = body['order']

        order['order-id'] = new_order_id

        # Ordering shopper section
        ordering_shopper = order['ordering-shopper']

        # Validate shopper id
        try:
            raw_shopper_id = ordering_shopper['shopper-id']
            shopper_id = int(raw_shopper_id)
            shopper_body = shoppers[shopper_id]
        except (KeyError, ValueError):
            return (403, {},
                    'User: %s is not authorized to place an order for '
                    'shopper: %s.' % (_client.username, raw_shopper_id))

        try:
            credit_card = ordering_shopper['credit-card']
        except KeyError:
            return (400, {'content-type': 'application/xml'},
                    mock_responses['order_failed__no_payment_method'])

        # Validate credit card selection
        card_found = False
        for credit_card_info in shopper_body['shopper']['shopper-info'][
                'payment-info']['credit-cards-info']['credit-card-info']:
            print dict(credit_card_info['credit-card']), dict(credit_card)
            if dict(credit_card_info['credit-card']) == dict(credit_card):
                card_found = True
                break

        if not card_found:
            return (400, {'content-type': 'application/xml'},
                    mock_responses['order_failed__wrong_payment_details'])

        cart = order['cart']
        sku = cart['cart-item']['sku']
        assert sku['sku-id'] == helper.TEST_PRODUCT_SKU_ID
        sku_charge_price = sku['sku-charge-price']
        cart['charged-currency'] = sku_charge_price['currency']
        cart['cart-item']['item-sub-total'] = sku_charge_price['amount']
        cart['tax'] = '0.00'
        cart['tax-rate'] = '0'
        cart['total-cart-cost'] = sku_charge_price['amount']

        order['post-sale-info'] = {
            'invoices': {
                'invoice': {
                    'invoice-id': 'invoice_%d' % new_order_id,
                    'url': 'https://sandbox.bluesnap.com/jsp/show_invoice.jsp',
                    'financial-transactions': {
                        'financial-transaction': {
                            'status': 'Pending',
                            'date-due': order_date,
                            'date-created': order_date,
                            'amount': sku_charge_price['amount'],
                            'currency': sku_charge_price['currency'],
                            'soft-descriptor': 'BLS*%s' % order[
                                'soft-descriptor'],
                            'payment-method': 'Credit Card',
                            'target-balance': 'PLIMUS_ACCOUNT',
                            'credit-card': order['ordering-shopper'][
                                'credit-card'],
                            'paypal-transaction-data': None,
                            'skus': {
                                'sku': {
                                    'sku-id': sku['sku-id'],
                                },
                            },
                        }
                    }
                }
            }
        }

        orders[new_order_id] = body

        return (200, {'content-type': 'application/xml'},
                xmltodict.unparse(body))

    responses.add_callback(
        responses.POST,
        '%s/services/2/shoppers' % _client.endpoint_url,
        callback=create_shopper_callback)
    responses.add_callback(
        responses.GET,
        re.compile(r'%s/services/2/shoppers/\d+' % _client.endpoint_url),
        callback=get_shopper_callback)
    responses.add_callback(
        responses.PUT,
        re.compile(r'%s/services/2/shoppers/\d+' % _client.endpoint_url),
        callback=put_shopper_callback)
    responses.add_callback(
        responses.POST,
        '%s/services/2/orders' % _client.endpoint_url,
        callback=post_order_callback)