def test_password_digest_custom(monkeypatch):
    monkeypatch.setattr(os, "urandom", lambda x: b"mocked-random")

    envelope = load_xml("""
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        >
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """)

    created = datetime.datetime(2016, 6, 4, 20, 10)
    token = UsernameToken(
        "michael",
        password_digest="12345",
        use_digest=True,
        nonce="iets",
        created=created,
    )
    envelope, headers = token.apply(envelope, {})
    expected = """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <soap-env:Header>
            <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
              <wsse:UsernameToken>
                <wsse:Username>michael</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">12345</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">aWV0cw==</wsse:Nonce>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-06-04T20:10:00+00:00</wsu:Created>
              </wsse:UsernameToken>
            </wsse:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """  # noqa
    assert_nodes_equal(envelope, expected)
def test_password_prepared():
    envelope = load_xml(
        """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        >
          <soap-env:Header xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <ns0:Security>
              <ns0:UsernameToken/>
            </ns0:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """
    )  # noqa

    token = UsernameToken("michael", "geheim")
    envelope, headers = token.apply(envelope, {})
    expected = """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <soap-env:Header xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <ns0:Security>
              <ns0:UsernameToken>
                <ns0:Username>michael</ns0:Username>
                <ns0:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">geheim</ns0:Password>
              </ns0:UsernameToken>
            </ns0:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """  # noqa
    assert_nodes_equal(envelope, expected)
def test_password_digest_custom(monkeypatch):
    monkeypatch.setattr(os, 'urandom', lambda x: b'mocked-random')

    envelope = load_xml("""
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        >
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """)

    created = datetime.datetime(2016, 6, 4, 20, 10)
    token = UsernameToken(
        'michael', password_digest='12345', use_digest=True,
        nonce='iets', created=created)
    envelope, headers = token.apply(envelope, {})
    expected = """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <soap-env:Header>
            <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
              <wsse:UsernameToken>
                <wsse:Username>michael</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">12345</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">aWV0cw==</wsse:Nonce>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-06-04T20:10:00+00:00</wsu:Created>
              </wsse:UsernameToken>
            </wsse:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """  # noqa
    assert_nodes_equal(envelope, expected)
def test_password_digest(monkeypatch):
    monkeypatch.setattr(os, "urandom", lambda x: b"mocked-random")

    envelope = load_xml(
        """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        >
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """
    )

    token = UsernameToken("michael", "geheim", use_digest=True)
    envelope, headers = token.apply(envelope, {})
    expected = """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <soap-env:Header>
            <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
              <wsse:UsernameToken>
                <wsse:Username>michael</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">hVicspAQSg70JNhe67OHqD9gexc=</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">bW9ja2VkLXJhbmRvbQ==</wsse:Nonce>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-05-08T12:00:00+00:00</wsu:Created>
              </wsse:UsernameToken>
            </wsse:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """  # noqa
    assert_nodes_equal(envelope, expected)
def test_password_prepared():
    envelope = load_xml("""
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        >
          <soap-env:Header xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <ns0:Security>
              <ns0:UsernameToken/>
            </ns0:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """)  # noqa

    token = UsernameToken('michael', 'geheim')
    envelope, headers = token.apply(envelope, {})
    expected = """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <soap-env:Header xmlns:ns0="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <ns0:Security>
              <ns0:UsernameToken>
                <ns0:Username>michael</ns0:Username>
                <ns0:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">geheim</ns0:Password>
              </ns0:UsernameToken>
            </ns0:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """  # noqa
    assert_nodes_equal(envelope, expected)
def test_password_digest(monkeypatch):
    monkeypatch.setattr(os, 'urandom', lambda x: b'mocked-random')

    envelope = load_xml("""
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        >
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """)

    token = UsernameToken('michael', 'geheim', use_digest=True)
    envelope, headers = token.apply(envelope, {})
    expected = """
        <soap-env:Envelope
            xmlns:ns0="http://example.com/stockquote.xsd"
            xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
            xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <soap-env:Header>
            <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
              <wsse:UsernameToken>
                <wsse:Username>michael</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">hVicspAQSg70JNhe67OHqD9gexc=</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">bW9ja2VkLXJhbmRvbQ==</wsse:Nonce>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-05-08T12:00:00+00:00</wsu:Created>
              </wsse:UsernameToken>
            </wsse:Security>
          </soap-env:Header>
          <soap-env:Body>
            <ns0:TradePriceRequest>
              <tickerSymbol>foobar</tickerSymbol>
              <ns0:country/>
            </ns0:TradePriceRequest>
          </soap-env:Body>
        </soap-env:Envelope>
    """  # noqa
    assert_nodes_equal(envelope, expected)
示例#7
0
    def __init__(self, username, password, wsUrl):
        passwordHash = hashlib.sha1(password.encode('utf-8')).hexdigest()

        self._client = zeep.Client(
            wsUrl,
            strict=False,
            wsse=UsernameToken(username, password=passwordHash))
示例#8
0
 def __init__(self, username, password, baseUrl):
     passwordHash = hashlib.sha1(password.encode('utf-8')).hexdigest()
     wsUrl = baseUrl + '/ws/study/v1/studySubjectWsdl.wsdl'
     self._client = zeep.Client(
         wsUrl,
         strict=False,
         wsse=UsernameToken(username, password=passwordHash))
示例#9
0
    def __init__(self, username, password):
        password = hashlib.sha1(password.encode('utf-8')).hexdigest()

        self._client = zeep.Client(
            'https://tds-edc.com/rdpws/ws/study/v1/studyWsdl.wsdl',
            strict=False,
            wsse=UsernameToken(username, password=password))
示例#10
0
 def __init__(self, username, password, baseUrl):
     self._username = username
     passwordHash = hashlib.sha1(password.encode('utf-8')).hexdigest()
     self._passwordHash = hashlib.sha1(password.encode('utf-8')).hexdigest()
     wsUrl = baseUrl + '/ws/event/v1/eventWsdl.wsdl'
     self._thisURL = wsUrl
     self._client = zeep.Client(wsUrl,
                                strict=False,
                                wsse=UsernameToken(username,
                                                   password=passwordHash))
def get_client(wsdl=None, job_board=None):
    wsdl = wsdl or settings.TALENTLINK_API_WSDL

    # Each job_board should define on settings a corresponding API USERNAME
    # Eg. TALENTLINK_API_USERNAME_INTERNAL
    api_username = getattr(
        settings, "TALENTLINK_API_USERNAME_" + job_board.upper()
    )  # Will throw AttributeError if not defined.

    return Client(
        wsdl,
        transport=ZeepAPIKeyTransport(
            cache=ZeepDjangoBackendCache(), api_key=settings.TALENTLINK_API_KEY
        ),
        wsse=UsernameToken(api_username, settings.TALENTLINK_API_PASSWORD),
    )
示例#12
0
    def issue_credit(self, order_number, basket, reference_number, amount,
                     currency):
        """
        Verify the payment processor used for the original order responds as expected to the refund request,
        and the response is saved in the database, with error handling.
        """
        try:
            client = Client(self.soap_api_url,
                            wsse=UsernameToken(self.merchant_id,
                                               self.transaction_key))

            credit_service = {
                'captureRequestID': reference_number,
                'run': 'true',
            }
            purchase_totals = {
                'currency': currency,
                'grandTotalAmount': str(amount),
            }

            response = client.service.runTransaction(
                merchantID=self.merchant_id,
                merchantReferenceCode=order_number,
                orderRequestToken=reference_number,
                ccCreditService=credit_service,
                purchaseTotals=purchase_totals)

            request_id = response.requestID
            ppr = self.record_processor_response(serialize_object(response),
                                                 transaction_id=request_id,
                                                 basket=basket)
        except:
            msg = 'An error occurred while attempting to issue a credit (via CyberSource) for order [{}].'.format(
                order_number)
            logger.exception(msg)
            raise GatewayError(msg)

        if response.decision == 'ACCEPT':
            return request_id
        raise GatewayError(
            'Failed to issue CyberSource credit for order [{order_number}]. '
            'Complete response has been recorded in entry [{response_id}]'.
            format(order_number=order_number, response_id=ppr.id))
示例#13
0
def create_client(wsdl: str, raw_response: bool = True) -> CachingClient:
    """
    Creates Zeep client that caches the WSDL.

    :param str wsdl: Link to the WSDL
    :param bool raw_response: Whether the client should return the raw XML response
    :return CachingClient client: Zeep client
    """
    # We want the raw response as there is an error when Zeep parses the XML
    settings: Settings = Settings(raw_response=raw_response)

    # Client that caches the WSDL
    client: CachingClient = CachingClient(
        wsdl=wsdl,
        # TODO: Store PW encrypted
        wsse=UsernameToken("n00394gz", "g427Ix19LMB"),
        settings=settings,
    )
    logger.debug(f"Client created")

    return client
示例#14
0
def test_integration():
    client_obj = client.Client("tests/wsdl_files/soap.wsdl",
                               wsse=UsernameToken("username", "password"))

    response = """
    <?xml version="1.0"?>
    <soapenv:Envelope
        xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/"
        xmlns:stoc="http://example.com/stockquote.xsd">
       <soapenv:Header/>
       <soapenv:Body>
          <stoc:TradePrice>
             <price>120.123</price>
          </stoc:TradePrice>
       </soapenv:Body>
    </soapenv:Envelope>
    """.strip()

    with requests_mock.mock() as m:
        m.post("http://example.com/stockquote", text=response)
        result = client_obj.service.GetLastTradePrice("foobar")
        assert result == 120.123
示例#15
0
    def request_apple_pay_authorization(self, basket, billing_address,
                                        payment_token):
        """
        Authorizes an Apple Pay payment.

        For details on the process, see the CyberSource Simple Order API documentation at
        https://www.cybersource.com/developers/integration_methods/apple_pay/.

        Args:
            basket (Basket)
            billing_address (BillingAddress)
            payment_token (dict)

        Returns:
            HandledProcessorResponse

        Raises:
            GatewayError
        """
        try:
            client = Client(self.soap_api_url,
                            wsse=UsernameToken(self.merchant_id,
                                               self.transaction_key))
            card_type = APPLE_PAY_CYBERSOURCE_CARD_TYPE_MAP[
                payment_token['paymentMethod']['network'].lower()]
            bill_to = {
                'firstName': billing_address.first_name,
                'lastName': billing_address.last_name,
                'street1': billing_address.line1,
                'street2': billing_address.line2,
                'city': billing_address.line4,
                'state': billing_address.state,
                'postalCode': billing_address.postcode,
                'country': billing_address.country.iso_3166_1_a2,
                'email': basket.owner.email,
            }
            purchase_totals = {
                'currency': basket.currency,
                'grandTotalAmount': str(basket.total_incl_tax),
            }
            encrypted_payment = {
                'descriptor': 'RklEPUNPTU1PTi5BUFBMRS5JTkFQUC5QQVlNRU5U',
                'data':
                base64.b64encode(json.dumps(payment_token['paymentData'])),
                'encoding': 'Base64',
            }
            card = {
                'cardType': card_type,
            }
            auth_service = {
                'run': 'true',
            }
            capture_service = {
                'run': 'true',
            }
            # Enable Export Compliance for SDN validation, amongst other checks.
            # See https://www.cybersource.com/products/fraud_management/export_compliance/
            export_service = {
                'run': 'true',
            }
            item = [{
                'id': index,
                'productCode': line.product.get_product_class().slug,
                'productName': clean_field_value(line.product.title),
                'quantity': line.quantity,
                'productSKU': line.stockrecord.partner_sku,
                'taxAmount': str(line.line_tax),
                'unitPrice': str(line.unit_price_incl_tax),
            } for index, line in enumerate(basket.all_lines())]

            response = client.service.runTransaction(
                merchantID=self.merchant_id,
                merchantReferenceCode=basket.order_number,
                billTo=bill_to,
                purchaseTotals=purchase_totals,
                encryptedPayment=encrypted_payment,
                card=card,
                ccAuthService=auth_service,
                ccCaptureService=capture_service,
                exportService=export_service,
                paymentSolution='001',
                item=item,
            )

        except:
            msg = 'An error occurred while authorizing an Apple Pay (via CyberSource) for basket [{}]'.format(
                basket.id)
            logger.exception(msg)
            raise GatewayError(msg)

        request_id = response.requestID
        ppr = self.record_processor_response(serialize_object(response),
                                             transaction_id=request_id,
                                             basket=basket)

        if response.decision == 'ACCEPT':
            currency = basket.currency
            total = basket.total_incl_tax
            transaction_id = request_id

            return HandledProcessorResponse(
                transaction_id=transaction_id,
                total=total,
                currency=currency,
                card_number='Apple Pay',
                card_type=CYBERSOURCE_CARD_TYPE_MAP.get(card_type))
        else:
            msg = (
                'CyberSource rejected an Apple Pay authorization request for basket [{basket_id}]. '
                'Complete response has been recorded in entry [{response_id}]')
            msg = msg.format(basket_id=basket.id, response_id=ppr.id)
            logger.warning(msg)
        raise GatewayError(msg)
示例#16
0
def test_timestamp_token():
    envelope = load_xml("""
            <soap-env:Envelope
                xmlns:ns0="http://example.com/stockquote.xsd"
                xmlns:soap="https://schemas.xmlsoap.org/wsdl/soap/"
                xmlns:soap-env="https://schemas.xmlsoap.org/soap/envelope/"
                xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/"
                xmlns:wsu="https://schemas.xmlsoap.org/ws/2003/06/utility"
                xmlns:xsd="https://www.w3.org/2001/XMLSchema"
            >
              <soap-env:Header xmlns:ns0="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                <ns0:Security>
                  <ns0:UsernameToken/>
                </ns0:Security>
              </soap-env:Header>
              <soap-env:Body>
                <ns0:TradePriceRequest>
                  <tickerSymbol>foobar</tickerSymbol>
                  <ns0:country/>
                </ns0:TradePriceRequest>
              </soap-env:Body>
            </soap-env:Envelope>
        """)  # noqa

    timestamp_token = WSU.Timestamp()
    timestamp_token.attrib["Id"] = "id-21a27a50-9ebf-49cc-96bf-fcf7131e7858"
    some_date_obj = datetime.datetime(2018, 11, 18, 15, 44, 27, 440252)
    timestamp_elements = [
        WSU.Created(some_date_obj.strftime("%Y-%m-%dT%H:%M:%SZ")),
        WSU.Expires(
            (some_date_obj +
             datetime.timedelta(minutes=10)).strftime("%Y-%m-%dT%H:%M:%SZ")),
    ]
    timestamp_token.extend(timestamp_elements)

    token = UsernameToken("Vishu",
                          "Guntupalli",
                          timestamp_token=timestamp_token)
    envelope, headers = token.apply(envelope, {})
    expected = """
            <soap-env:Envelope
                xmlns:ns0="http://example.com/stockquote.xsd"
                xmlns:soap="https://schemas.xmlsoap.org/wsdl/soap/"
                xmlns:soap-env="https://schemas.xmlsoap.org/soap/envelope/"
                xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/"
                xmlns:wsu="https://schemas.xmlsoap.org/ws/2003/06/utility"
                xmlns:xsd="https://www.w3.org/2001/XMLSchema">
              <soap-env:Header xmlns:ns0="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                <ns0:Security>
                  <ns0:UsernameToken>
                    <ns0:Username>Vishu</ns0:Username>
                    <ns0:Password Type="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Guntupalli</ns0:Password>
                  </ns0:UsernameToken>
                  <wsu:Timestamp xmlns:wsu="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" Id="id-21a27a50-9ebf-49cc-96bf-fcf7131e7858">
                       <wsu:Created>2018-11-18T15:44:27Z</wsu:Created>
                       <wsu:Expires>2018-11-18T15:54:27Z</wsu:Expires>
                  </wsu:Timestamp>
                </ns0:Security>
              </soap-env:Header>
              <soap-env:Body>
                <ns0:TradePriceRequest>
                  <tickerSymbol>foobar</tickerSymbol>
                  <ns0:country/>
                </ns0:TradePriceRequest>
              </soap-env:Body>
            </soap-env:Envelope>
        """  # noqa
    assert_nodes_equal(envelope, expected)