diff --git a/ecommerce/extensions/api/serializers.py b/ecommerce/extensions/api/serializers.py index e00a211ddac..68a1189bd0a 100644 --- a/ecommerce/extensions/api/serializers.py +++ b/ecommerce/extensions/api/serializers.py @@ -861,11 +861,12 @@ def _update_app_store_product(self, mobile_seat, price): partner_short_code = self.context['request'].site.siteconfiguration.partner.short_code configuration = settings.PAYMENT_PROCESSOR_CONFIG[partner_short_code.lower()][IOSIAP.NAME.lower()] headers = get_auth_headers(configuration) - try: - ios_product_id = mobile_seat.attr.app_store_id - apply_price_of_inapp_purchase(price, ios_product_id, headers) - except AttributeError: + ios_product_id = getattr(mobile_seat.attr, 'app_store_id', None) + if not ios_product_id: logger.error("app_store_id not associated with [%s]", mobile_seat.course) + return + + apply_price_of_inapp_purchase(price, ios_product_id, headers) def get_partner(self): """Validate partner""" diff --git a/ecommerce/extensions/iap/api/v1/utils.py b/ecommerce/extensions/iap/api/v1/utils.py index 93f536cc1a5..6a62ac5a877 100644 --- a/ecommerce/extensions/iap/api/v1/utils.py +++ b/ecommerce/extensions/iap/api/v1/utils.py @@ -36,9 +36,7 @@ def create_ios_product(course, ios_product, configuration): """ headers = get_auth_headers(configuration) try: - in_app_purchase_id = create_inapp_purchase(course, ios_product.partner_sku, configuration['apple_id'], headers) - ios_product.product.attr.app_store_id = in_app_purchase_id - ios_product.product.save() + in_app_purchase_id = get_or_create_inapp_purchase(ios_product, course, configuration, headers) localize_inapp_purchase(in_app_purchase_id, headers) apply_price_of_inapp_purchase(course['price'], in_app_purchase_id, headers) upload_screenshot_of_inapp_purchase(in_app_purchase_id, headers) @@ -51,6 +49,22 @@ def create_ios_product(course, ios_product, configuration): return error_msg +def get_or_create_inapp_purchase(ios_stock_record, course, configuration, headers): + """ + Returns inapp_purchase_id from product attr + If not present there create a product on ios store and return its inapp_purchase_id + """ + + in_app_purchase_id = getattr(ios_stock_record.product.attr, 'app_store_id', '') + if not in_app_purchase_id: + in_app_purchase_id = create_inapp_purchase(course, ios_stock_record.partner_sku, + configuration['apple_id'], headers) + ios_stock_record.product.attr.app_store_id = in_app_purchase_id + ios_stock_record.product.save() + + return in_app_purchase_id + + def request_connect_store(url, headers, data=None, method="post"): """ Request the given endpoint with multiple tries and backoff time """ # Adding backoff and retries because of following two reasons diff --git a/ecommerce/extensions/iap/api/v1/views.py b/ecommerce/extensions/iap/api/v1/views.py index bcf4f9a1ebe..7bcae9d690c 100644 --- a/ecommerce/extensions/iap/api/v1/views.py +++ b/ecommerce/extensions/iap/api/v1/views.py @@ -404,7 +404,7 @@ def post(self, request): product_class__name=SEAT_PRODUCT_CLASS_NAME, children__expires__gt=now(), course=course_run, - ) + ).distinct() if not parent_product.exists(): failed_course_runs.append(course_run_key) diff --git a/ecommerce/extensions/iap/utils.py b/ecommerce/extensions/iap/utils.py index ecd02d9c3d4..802886f4d6e 100644 --- a/ecommerce/extensions/iap/utils.py +++ b/ecommerce/extensions/iap/utils.py @@ -57,7 +57,9 @@ def create_mobile_seat(sku_prefix, existing_web_seat): if 'ios' in sku_prefix: # We need this attribute defined for ios products # Actual values will be assigned when we create product on appstore - new_mobile_seat.attr.app_store_id = '' + app_store_id = getattr(new_mobile_seat.attr, 'app_store_id', None) + if not app_store_id: + new_mobile_seat.attr.app_store_id = '' new_mobile_seat.attr.save()