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)
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)
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))
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))
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)
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)
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)