def payment_process(self): """Simulate the CyberSource payment process. Mirrors the way a user would behave when interacting with the payment flow. Contacts the ecommerce service directly to emulate the merchant notification sent by CyberSource. """ self.auto_auth() self.api_client = LocustEdxRestApiClient( settings.data['ecommerce']['url']['api'], session=self.client, signing_key=settings.secrets['jwt']['secret_key'], issuer=settings.secrets['jwt']['issuer'], username=self._username, email=self._email, ) # Emulate rendering of payment buttons self.api_client.payment.processors().get() # Emulate basket creation and payment order_id = self.cybersource_notification() # Emulate rendering of the receipt page self.api_client.orders(order_id).get(name='/api/v2/orders/:id/')
def payment_process(self): """Simulate the CyberSource payment process. Mirrors the way a user would behave when interacting with the payment flow. Contacts the ecommerce service directly to emulate the merchant notification sent by CyberSource. """ self.auto_auth() self.api_client = LocustEdxRestApiClient( ECOMMERCE_API_URL, session=self.client, signing_key=ECOMMERCE_JWT_SECRET_KEY, issuer=ECOMMERCE_JWT_ISSUER, username=self._username, email=self._email, ) # Emulate rendering of payment buttons self.api_client.payment.processors().get() # Emulate basket creation and payment order_id = self.cybersource_notification() # Emulate rendering of the receipt page self.api_client.orders(order_id).get(name='/api/v2/orders/:id/')
def payment_process(self): """Simulate the CyberSource payment process. Mirrors the way a user would behave when interacting with the payment flow. Contacts the ecommerce service directly to emulate the merchant notification sent by CyberSource. """ self.auto_auth() self.api_client = LocustEdxRestApiClient( settings.data['ecommerce']['url']['api'], session=self.client, signing_key=settings.data['jwt']['secret_key'], issuer=settings.data['jwt']['issuer'], username=self._username, email=self._email, ) # Emulate rendering of payment buttons self.api_client.payment.processors().get() # Emulate basket creation and payment order_id = self.cybersource_notification() # Emulate rendering of the receipt page self.api_client.orders(order_id).get(name='/api/v2/orders/:id/')
def get_credential_client(self): """ New property added for using LocustEdxRestApiClient. Default locust client will remain same for using auto_auth(). """ return LocustEdxRestApiClient( CREDENTIAL_API_URL, session=HttpSession(base_url=self.locust.host), jwt=self._get_token())
def __init__(self): super(CourseDiscoveryLocust, self).__init__() access_token_endpoint = '{}/oauth2/access_token'.format( settings.secrets['oauth']['provider_url'].strip('/')) access_token, __ = LocustEdxRestApiClient.get_oauth_access_token( access_token_endpoint, settings.secrets['oauth']['client_id'], settings.secrets['oauth']['client_secret'], ) api_url = self.host.strip('/') self.client = LocustEdxRestApiClient( api_url, session=HttpSession(base_url=self.host), oauth_access_token=access_token)
def get_credential_client(self): """ New property added for using LocustEdxRestApiClient. Default locust client will remain same for using auto_auth(). """ return LocustEdxRestApiClient( settings.data['credentials']['url']['api'], session=HttpSession(base_url=self.locust.host), jwt=self.get_access_token() )
def __init__(self): super(ProgramsUser, self).__init__() if not self.host: raise LocustError( 'You must specify a base host, either in the host attribute in the Locust class, ' 'or on the command line using the --host option.') self.client = LocustEdxRestApiClient( PROGRAMS_API_URL, session=HttpSession(base_url=self.host), jwt=self._get_token())
def get_access_token(): """ Returns the OAuth 2.0 access token for the Credentials Service. Returns: str: JWT """ access_token_url = settings.secrets['oauth']['access_token_url'] client_id = settings.secrets['oauth']['client_id'] client_secret = settings.secrets['oauth']['client_secret'] access_token, __ = LocustEdxRestApiClient.get_oauth_access_token(access_token_url, client_id, client_secret, token_type='jwt') return access_token
def get_ecom_worker_client(): """ Gets the ecommerce worker client Using the oauth credentials in the settings file, this method returns up the ecommerce work clients which enables a task to call the api on behalf of the ecommerce worker. Returns: LocustEdxRestApiClient: The ecommerce worker client """ access_token_endpoint = '{}/oauth2/access_token'.format( settings.secrets['oauth']['provider_url'].strip('/')) access_token, __ = LocustEdxRestApiClient.get_oauth_access_token( access_token_endpoint, settings.secrets['oauth']['client_id'], settings.secrets['oauth']['client_secret'], ) return LocustEdxRestApiClient(ECOMMERCE_HOST, session=HttpSession(base_url=ECOMMERCE_HOST), oauth_access_token=access_token)
def __init__(self): super(CourseDiscoveryLocust, self).__init__() access_token_endpoint = '{}/oauth2/access_token'.format( settings.data['oauth']['provider_url'].strip('/') ) access_token, __ = LocustEdxRestApiClient.get_oauth_access_token( access_token_endpoint, settings.data['oauth']['client_id'], settings.data['oauth']['client_secret'], ) api_url = '{}/api/v1/'.format(self.host.strip('/')) self.client = LocustEdxRestApiClient( api_url, session=HttpSession(base_url=self.host), oauth_access_token=access_token )
class CybersourcePaymentTasks(AutoAuthTasks): def __init__(self, *args, **kwargs): super(CybersourcePaymentTasks, self).__init__(*args, **kwargs) self.ecommerce_service_url = settings.data['ecommerce']['url']['service'] self.cybersource_secret_key = settings.secrets['ecommerce']['cybersource_secret_key'] @task def payment_process(self): """Simulate the CyberSource payment process. Mirrors the way a user would behave when interacting with the payment flow. Contacts the ecommerce service directly to emulate the merchant notification sent by CyberSource. """ self.auto_auth() self.api_client = LocustEdxRestApiClient( settings.data['ecommerce']['url']['api'], session=self.client, signing_key=settings.secrets['jwt']['secret_key'], issuer=settings.secrets['jwt']['issuer'], username=self._username, email=self._email, ) # Emulate rendering of payment buttons self.api_client.payment.processors().get() # Emulate basket creation and payment order_id = self.cybersource_notification() # Emulate rendering of the receipt page self.api_client.orders(order_id).get(name='/api/v2/orders/:id/') def cybersource_notification(self): """Contact Otto's CyberSource notification endpoint.""" basket_id, amount = self._get_basket_details() data = self._get_cybersource_notification_data(basket_id, amount) # This endpoint isn't part of the versioned API. It's also not protected # by JWT auth, so there's no need to use the API client here. url = '{}/payment/cybersource/notify/'.format(self.ecommerce_service_url) self.client.post( url, data=data, headers={'Content-Type': 'application/x-www-form-urlencoded'} ) order_id = data['req_reference_number'] return order_id def _get_basket_details(self): """Creates a basket and returns its ID and amount. Contacts Otto directly to create the user's basket. """ basket = self.api_client.baskets.post({ 'products': [{'sku': settings.data['ecommerce']['paid_sku']}], 'checkout': True, 'payment_processor_name': 'cybersource' }) return basket['id'], basket['payment_data']['payment_form_data']['amount'] def _get_cybersource_notification_data(self, basket_id, amount): """Returns a dict simulating a CyberSource payment response.""" order_id = basket_id + settings.data['ecommerce']['order']['offset'] order_number = u'{prefix}-{order_id}'.format( prefix=settings.data['ecommerce']['order']['prefix'], order_id=order_id ) notification = { 'decision': 'ACCEPT', 'req_reference_number': order_number, 'transaction_id': '123456', 'auth_amount': amount, 'req_amount': amount, 'req_tax_amount': '0.00', 'req_currency': 'USD', 'req_card_number': 'xxxxxxxxxxxx1111', 'req_card_type': '001', 'req_bill_to_forename': 'Ed', 'req_bill_to_surname': 'Xavier', 'req_bill_to_address_line1': '141 Portland Ave.', 'req_bill_to_address_line2': '9th Floor', 'req_bill_to_address_city': 'Cambridge', 'req_bill_to_address_postal_code': '02141', 'req_bill_to_address_state': 'MA', 'req_bill_to_address_country': 'US' } notification['signed_field_names'] = ','.join(notification.keys()) notification['signature'] = self._generate_cybersource_signature( self.cybersource_secret_key, notification ) return notification def _generate_cybersource_signature(self, secret_key, data): """Generate a signature for the given data dict.""" keys = data[u'signed_field_names'].split(u',') message = u','.join([u'{key}={value}'.format(key=key, value=data[key]) for key in keys]) return sign(message, secret_key)
class CybersourcePaymentTasks(AutoAuthTasks): def __init__(self, *args, **kwargs): super(CybersourcePaymentTasks, self).__init__(*args, **kwargs) self.ecommerce_service_url = ECOMMERCE_SERVICE_URL self.cybersource_secret_key = CYBERSOURCE_SECRET_KEY @task def payment_process(self): """Simulate the CyberSource payment process. Mirrors the way a user would behave when interacting with the payment flow. Contacts the ecommerce service directly to emulate the merchant notification sent by CyberSource. """ self.auto_auth() self.api_client = LocustEdxRestApiClient( ECOMMERCE_API_URL, session=self.client, signing_key=ECOMMERCE_JWT_SECRET_KEY, issuer=ECOMMERCE_JWT_ISSUER, username=self._username, email=self._email, ) # Emulate rendering of payment buttons self.api_client.payment.processors().get() # Emulate basket creation and payment order_id = self.cybersource_notification() # Emulate rendering of the receipt page self.api_client.orders(order_id).get(name='/api/v2/orders/:id/') def cybersource_notification(self): """Contact Otto's CyberSource notification endpoint.""" basket_id, amount = self._get_basket_details() data = self._get_cybersource_notification_data(basket_id, amount) # This endpoint isn't part of the versioned API. It's also not protected # by JWT auth, so there's no need to use the API client here. url = '{}/payment/cybersource/notify/'.format(self.ecommerce_service_url) self.client.post( url, data=data, headers={'Content-Type': 'application/x-www-form-urlencoded'} ) order_id = data['req_reference_number'] return order_id def _get_basket_details(self): """Creates a basket and returns its ID and amount. Contacts Otto directly to create the user's basket. """ basket = self.api_client.baskets.post({ 'products': [{'sku': PAID_SKU}], 'checkout': True, 'payment_processor_name': 'cybersource' }) return basket['id'], basket['payment_data']['payment_form_data']['amount'] def _get_cybersource_notification_data(self, basket_id, amount): """Returns a dict simulating a CyberSource payment response.""" order_id = basket_id + ECOMMERCE_ORDER_OFFSET order_number = u'{prefix}-{order_id}'.format( prefix=ECOMMERCE_ORDER_PREFIX, order_id=order_id ) notification = { 'decision': 'ACCEPT', 'req_reference_number': order_number, 'transaction_id': '123456', 'auth_amount': amount, 'req_amount': amount, 'req_tax_amount': '0.00', 'req_currency': 'USD', 'req_card_number': 'xxxxxxxxxxxx1111', 'req_card_type': '001', 'req_bill_to_forename': 'Ed', 'req_bill_to_surname': 'Xavier', 'req_bill_to_address_line1': '141 Portland Ave.', 'req_bill_to_address_line2': '9th Floor', 'req_bill_to_address_city': 'Cambridge', 'req_bill_to_address_postal_code': '02141', 'req_bill_to_address_state': 'MA', 'req_bill_to_address_country': 'US' } notification['signed_field_names'] = ','.join(notification.keys()) notification['signature'] = self._generate_cybersource_signature( self.cybersource_secret_key, notification ) return notification def _generate_cybersource_signature(self, secret_key, data): """Generate a signature for the given data dict.""" keys = data[u'signed_field_names'].split(u',') message = u','.join([u'{key}={value}'.format(key=key, value=data[key]) for key in keys]) return sign(message, secret_key)