def test_identity_manager_notification_org(self): from django.conf import settings settings.OILAUTH = True # Mock purchase info purchase = MagicMock() purchase.offering.notification_url = '' purchase.offering.applications = [{ 'id': 1, 'name': 'test_app1' }] purchase.organization_owned = True purchase.offering.owner_organization.name = 'test_user' purchase.owner_organization.actor_id = 2 purchase.offering.version = '1.0' purchase.offering.name = 'test_offering' purchase.ref = '11111' self.user.userprofile.access_token = 'aaa' self.user.userprofile.save() purchase.customer = self.user notify_provider.notify_provider(purchase) opener = self._urllib._opener content = json.loads(opener._body) self.assertEquals(len(content['applications']), 1) self.assertEquals(content['applications'][0]['id'], 1) self.assertEquals(content['applications'][0]['name'], 'test_app1') self.assertEquals(content['customer'], 2)
def test_provider_notification(self): settings.OILAUTH = False notify_provider.requests = MagicMock(name="requests") purchase = Purchase.objects.get(pk='61005aba8e05ac2115f022f0') expected_data = { 'offering': { 'name': 'test_offering', 'organization': 'test_organization', 'version': '1.0' }, 'customer': 'test_organization1', 'reference': '61005aba8e05ac2115f022f0', 'resources': [{ "url": "http://antares.ls.fi.upm.es:8000/media/resources/test_user__test_resource__1.0", "version": "1.0", "name": "test_resource", "content_type": "" }] } headers = {'Content-type': 'application/json'} notify_provider.notify_provider(purchase) notify_provider.requests.post.assert_called_with( purchase.offering.notification_url, data=json.dumps(expected_data), headers=headers, cert=(settings.NOTIF_CERT_FILE, settings.NOTIF_CERT_KEY_FILE))
def test_provider_notification(self): settings.OILAUTH = False notify_provider.requests = MagicMock(name="requests") purchase = Purchase.objects.get(pk='61005aba8e05ac2115f022f0') expected_data = { 'offering': { 'name': 'test_offering', 'organization': 'test_organization', 'version': '1.0' }, 'customer': 'test_organization1', 'reference': '61005aba8e05ac2115f022f0', 'resources': [{ "url": "http://antares.ls.fi.upm.es:8000/media/resources/test_user__test_resource__1.0", "version": "1.0", "name": "test_resource", "content_type": "" }] } headers = { 'Content-type': 'application/json' } notify_provider.notify_provider(purchase) notify_provider.requests.post.assert_called_with( purchase.offering.notification_url, data=json.dumps(expected_data), headers=headers, cert=(settings.NOTIF_CERT_FILE, settings.NOTIF_CERT_KEY_FILE) )
def test_provider_notification(self): purchase = Purchase.objects.get(pk='61005aba8e05ac2115f022f0') notify_provider.notify_provider(purchase) opener = self._urllib._opener content = json.loads(opener._body) self.assertEqual(content['offering']['name'], 'test_offering') self.assertEqual(content['offering']['organization'], 'test_organization') self.assertEqual(content['offering']['version'], '1.0') self.assertEqual(content['customer'], 'test_organization1') self.assertEqual(content['reference'], '61005aba8e05ac2115f022f0')
def test_identity_manager_notification_token_refresh(self): from django.conf import settings settings.OILAUTH = True # Mock purchase info purchase = MagicMock() purchase.offering.notification_url = '' purchase.offering.applications = [{ 'id': 1, 'name': 'test_app1' }] purchase.organization_owned = True purchase.offering.owner_organization.name = 'test_user' purchase.owner_organization.actor_id = 2 purchase.offering.version = '1.0' purchase.offering.name = 'test_offering' purchase.ref = '11111' self.user.userprofile.access_token = 'bca' self.user.userprofile.save() # Mock social auth methods UserSocialAuth.refresh_token = MagicMock() user_social_auth = UserSocialAuth.objects.create(user=self.user, provider='fiware') user_social_auth.extra_data = { 'access_token': 'bbb', 'refresh_token': 'ccc' } user_social_auth.save() self.user.social_auth = [user_social_auth] purchase.customer = self.user # Call the tested method notify_provider.notify_provider(purchase) opener = self._urllib._opener content = json.loads(opener._body) UserSocialAuth.refresh_token.assert_any_call() self.assertEquals(len(content['applications']), 1) self.assertEquals(content['applications'][0]['id'], 1) self.assertEquals(content['applications'][0]['name'], 'test_app1') self.assertEquals(content['customer'], 2)
def read(self, request, reference): purchase = None try: token = request.GET.get('token') payer_id = request.GET.get('PayerID', '') db = get_database_connection() # Uses an atomic operation to get and set the _lock value in the purchase # document pre_value = db.wstore_purchase.find_and_modify( query={'_id': ObjectId(reference)}, update={'$set': {'_lock': True}} ) # If the value of _lock before setting it to true was true, means # that the time out function has acquired it previously so the # view ends if '_lock' in pre_value and pre_value['_lock']: raise Exception('') purchase = Purchase.objects.get(ref=reference) # Check that the request user is authorized to end the payment if request.user.userprofile.current_organization != purchase.owner_organization: raise Exception() # If the purchase state value is different from pending means that # the timeout function has completely ended before acquire the resource # so _lock is set to false and the view ends if purchase.state != 'pending': db.wstore_purchase.find_and_modify( query={'_id': ObjectId(reference)}, update={'$set': {'_lock': False}} ) raise Exception('') pending_info = purchase.contract.pending_payment # Get the payment client # Load payment client cln_str = settings.PAYMENT_CLIENT client_class = cln_str.split('.')[-1] client_package = cln_str.partition('.' + client_class)[0] payment_client = getattr(__import__(client_package, globals(), locals(), [client_class], -1), client_class) # build the payment client client = payment_client(purchase) client.end_redirection_payment(token, payer_id) charging_engine = ChargingEngine(purchase) accounting = None if 'accounting' in pending_info: accounting = pending_info['accounting'] charging_engine.end_charging(pending_info['price'], pending_info['concept'], pending_info['related_model'], accounting) except: # Rollback the purchase if existing if purchase is not None: rollback(purchase) context = { 'title': 'Payment Canceled', 'message': 'Your payment has been canceled. An error occurs or the timeout has finished, if you want to acquire the offering purchase it again in WStore.' } return render(request, 'err_msg.html', context) # Check if is the first payment if len(purchase.contract.charges) == 1: if purchase.organization_owned: org = purchase.owner_organization org.offerings_purchased.append(purchase.offering.pk) org.save() else: # Add the offering to the user profile user_profile = UserProfile.objects.get(user=purchase.customer) user_profile.offerings_purchased.append(purchase.offering.pk) user_profile.save() notify_provider(purchase) # _lock is set to false db.wstore_purchase.find_and_modify( query={'_id': reference}, update={'$set': {'_lock': False}} ) # Return the confirmation web page context = { 'title': 'Payment Confirmed', 'message': 'Your payment has been received. To download the resources and the invoice go to the offering details page.' } return render(request, 'err_msg.html', context)
def create_purchase(user, offering, org_owned=False, payment_info=None): if offering.state != 'published': raise PermissionDenied("This offering can't be purchased") if offering.open: raise PermissionDenied('Open offerings cannot be purchased') if accepted_needed(offering) and not payment_info['accepted']: raise PermissionDenied('You must accept the terms and conditions of the offering to acquire it') profile = UserProfile.objects.get(user=user) # Check if the offering is already purchased if (org_owned and offering.pk in profile.current_organization.offerings_purchased) \ or (not org_owned and offering.pk in profile.offerings_purchased): raise PermissionDenied('The offering has been already purchased') organization = profile.current_organization plan = None # Check the selected plan if payment_info and 'plan' in payment_info: plan = payment_info['plan'] # Get the effective tax address if not 'tax_address' in payment_info: if org_owned: tax = organization.tax_address else: tax = profile.tax_address # Check that the customer has a tax address if not 'street' in tax: raise ValueError('The customer does not have a tax address') else: tax = payment_info['tax_address'] # Check tax_address fields if (not 'street' in tax) or (not 'postal' in tax) or (not 'city' in tax) or (not 'country' in tax): raise ValueError('The tax address is not valid') # Check the payment method before purchase creation in order to avoid # an inconsistent state in the database credit_card_info = None if payment_info['payment_method'] == 'credit_card': if 'credit_card' in payment_info: # Check credit card info if (not ('number' in payment_info['credit_card'])) or (not ('type' in payment_info['credit_card']))\ or (not ('expire_year' in payment_info['credit_card'])) or (not ('expire_month' in payment_info['credit_card']))\ or (not ('cvv2' in payment_info['credit_card'])): raise ValueError('Invalid credit card info') credit_card_info = payment_info['credit_card'] else: if org_owned: credit_card_info = organization.payment_info else: credit_card_info = profile.payment_info # Check the credit card info if not 'number' in credit_card_info: raise Exception('The customer does not have payment info') elif payment_info['payment_method'] != 'paypal': raise ValueError('Invalid payment method') # Create the purchase purchase = Purchase.objects.create( customer=user, date=datetime.now(), offering=offering, organization_owned=org_owned, state='pending', tax_address=tax, owner_organization = organization ) # Load ref purchase.ref = purchase.pk purchase.save() if credit_card_info != None: charging_engine = ChargingEngine(purchase, payment_method='credit_card', credit_card=credit_card_info, plan=plan) else: charging_engine = ChargingEngine(purchase, payment_method='paypal', plan=plan) redirect_url = charging_engine.resolve_charging(new_purchase=True) if redirect_url == None: result = purchase # If no redirect URL is provided the purchase has ended so the user profile # info is updated if org_owned: organization.offerings_purchased.append(offering.pk) organization.save() else: profile.offerings_purchased.append(offering.pk) profile.save() notify_provider(purchase) else: result = redirect_url # Update offering indexes index_path = settings.DATADIR index_path = os.path.join(index_path, 'search') index_path = os.path.join(index_path, 'indexes') se = SearchEngine(index_path) se.update_index(offering) return result
def read(self, request, reference): purchase = None try: token = request.GET.get('token') payer_id = request.GET.get('PayerID', '') db = get_database_connection() # Uses an atomic operation to get and set the _lock value in the purchase # document pre_value = db.wstore_purchase.find_and_modify( query={'_id': ObjectId(reference)}, update={'$set': { '_lock': True }}) # If the value of _lock before setting it to true was true, means # that the time out function has acquired it previously so the # view ends if '_lock' in pre_value and pre_value['_lock']: raise Exception('') purchase = Purchase.objects.get(ref=reference) # Check that the request user is authorized to end the payment if request.user.userprofile.current_organization != purchase.owner_organization: raise Exception() # If the purchase state value is different from pending means that # the timeout function has completely ended before acquire the resource # so _lock is set to false and the view ends if purchase.state != 'pending': db.wstore_purchase.find_and_modify( query={'_id': ObjectId(reference)}, update={'$set': { '_lock': False }}) raise Exception('') pending_info = purchase.contract.pending_payment # Get the payment client # Load payment client cln_str = settings.PAYMENT_CLIENT client_class = cln_str.split('.')[-1] client_package = cln_str.partition('.' + client_class)[0] payment_client = getattr( __import__(client_package, globals(), locals(), [client_class], -1), client_class) # build the payment client client = payment_client(purchase) client.end_redirection_payment(token, payer_id) charging_engine = ChargingEngine(purchase) accounting = None if 'accounting' in pending_info: accounting = pending_info['accounting'] charging_engine.end_charging(pending_info['price'], pending_info['concept'], pending_info['related_model'], accounting) except: # Rollback the purchase if existing if purchase is not None: rollback(purchase) context = { 'title': 'Payment Canceled', 'message': 'Your payment has been canceled. An error occurs or the timeout has finished, if you want to acquire the offering purchase it again in WStore.' } return render(request, 'err_msg.html', context) # Check if is the first payment if len(purchase.contract.charges) == 1: if purchase.organization_owned: org = purchase.owner_organization org.offerings_purchased.append(purchase.offering.pk) org.save() else: # Add the offering to the user profile user_profile = UserProfile.objects.get(user=purchase.customer) user_profile.offerings_purchased.append(purchase.offering.pk) user_profile.save() notify_provider(purchase) # _lock is set to false db.wstore_purchase.find_and_modify(query={'_id': reference}, update={'$set': { '_lock': False }}) # Return the confirmation web page context = { 'title': 'Payment Confirmed', 'message': 'Your payment has been received. To download the resources and the invoice go to the offering details page.' } return render(request, 'err_msg.html', context)