Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot redirect to charge confirmation from embedded app #398

Closed
nsweeting opened this issue Mar 29, 2017 · 6 comments
Closed

Cannot redirect to charge confirmation from embedded app #398

nsweeting opened this issue Mar 29, 2017 · 6 comments

Comments

@nsweeting
Copy link

Hi there,

First time using embedded app stuff. So bare with me. When attempting to create a charge and do the redirect to the confirmation url, I end up with a blank page within the embedded app.

My controller code looks like this:

  def create
    charge = current_shop.recurring_application_charges.new
    if charge.save
      fullpage_redirect_to(charge.confirmation_url)
    else
      #handle errors
    end
  end

I then end up with a blank page in the app. The iframe source looks like this (link details modified):

        <!DOCTYPE html>
        <html lang="en">
          <head>
            <meta charset="utf-8" />
            <base target="_top">
            <title>Redirecting…</title>
            <script type="text/javascript">

              // If the current window is the 'parent', change the URL by setting location.href
              if (window.top == window.self) {
                window.top.location.href = "https://shop.myshopify.com/admin/charges/1/confirm_recurring_application_charge?signature=code_is_here";

              // If the current window is the 'child', change the parent's URL with postMessage
              } else {
                normalizedLink = document.createElement('a');
                normalizedLink.href = "https://shop.myshopify.com/admin/charges/1/confirm_recurring_application_charge?signature=code_is_here";

                data = JSON.stringify({
                  message: 'Shopify.API.remoteRedirect',
                  data: { location: normalizedLink.href }
                });
                window.parent.postMessage(data, "https://");
              }

            </script>
          </head>
          <body>
          </body>
        </html>

I also end up with the following error in the console:

Uncaught DOMException: Failed to execute 'postMessage' on 'Window': Invalid target origin 'https://' in a call to 'postMessage'.
    at https://my-app.herokuapp.com/subscriptions:23:31

Any help would be appreciated.

Thanks

@PresleyWong
Copy link

PresleyWong commented Mar 30, 2017

I experience same issue here. I tried use older fullpage_redirect_to definition as below and it works but thats not a solution...

     def fullpage_redirect_to(url)
	    url_json = url.to_json
	    url_json_no_quotes = url_json.gsub(/\A"|"\Z/, '')

	    if ShopifyApp.configuration.embedded_app?
	      render inline: %Q(
	        <!DOCTYPE html>
	        <html lang="en">
	          <head>
	            <meta charset="utf-8" />
	            <base target="_top">
	            <title>Redirecting…</title>
	            <script type="text/javascript">
	              window.top.location.href = #{url_json};
	            </script>
	          </head>
	          <body>
	          </body>
	        </html>
	      )
	    else
	      redirect_to_with_fallback url
	    end
	end

@edavis10
Copy link

I ran into this on Monday.

fullpage_redirect_to is using the sanitized_shop_name method which uses sanitize_shop_param which checks params[:shop] for the shop. If you call it from a page there that params isn't set, then full_page_redirect_to won't be able to create the url for postMessage. You can see that in this line of generated JS code, the https:// should be the full shop url:

                window.parent.postMessage(data, "https://");

In my apps current_shop refers to the currently logged in shop record so I patched sanitized_shop_name to use that in addition to the params.

class ApplicationController < ActionController::Base
  def sanitized_shop_name
    if current_shop.present?
      @sanitized_shop_name ||= ShopifyApp::Utils.sanitize_shop_domain(current_shop.shopify_domain)
    else
      @sanitized_shop_name ||= sanitize_shop_param(params)
    end
    @sanitized_shop_name
  end
end

@kevinhughes27
Copy link
Contributor

cc @Hammadk

@Hammadk
Copy link
Member

Hammadk commented Apr 4, 2017

One option here is to replace window.parent.postMessage(data, "https://#{sanitized_shop_name}"); with window.parent.postMessage(data, "*");

Replacing the target origin with * means that we won't need to worry about the shop at all. We haven't done this so far because this approach is not recommended.

I think it should be ok because we are only redirecting to Shopify specific URLs where the merchant has to be logged in. Thoughts?

@kevinhughes27
Copy link
Contributor

I think I prefer @edavis10's solution.

@Hammadk
Copy link
Member

Hammadk commented Apr 11, 2017

@nsweeting @PresleyWong This issue should be fixed in version 7.2.6. Thanks for the suggestion @edavis10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants