A place to discuss charging merchants for your apps and services using the billing API.
Hi,
I am trying to create a recurring charge in an embedded app created in Node.js and based on Express. Everything works perfectly until step 3 - these steps - where Shopify is redirecting the merchant to accept or decline the charge. It is simply not allowed because the app is embedded. In the console I get the following error:
Refused to display 'confirmation_url' in a frame because it set 'X-Frame-Options' to 'deny', where I've removed the confirmation_url for readability.
How do I circumvent this? It looks like I'm not the only one who has had this problem, so it is probably a problem that should be addressed in the documentation.
All the best,
Mathias
Hi @mfvas,
You need to do a top level redirect that escapes the iframe when redirecting the merchant to the confirmation url. There's an explanation in our oAuth documentation that also applies here:
Since the application is loaded inside an iframe, it is critical that the initial OAuth redirect to Shopify occurs at the parent level, escaped from the iframe. Shopify returns the
X-Frame-Options=DENY
header and prevents any Shopify admin pages from being loaded inside an iframe. The Embedded App SDK provides a method that can be used to perform a redirect within the parent window.
To learn more visit the Shopify Help Center or the Community Blog.
Hi, you can do a top level page redirect to bypass this-
Eg.
Instead of doing
`window.location.href = response.data.confirmation_url;`
do
`window.top.location.href = response.data.confirmation_url;`
I was stuck on this for awhile too. I wanted to offer multiple plans, but the Shopify app tutorial doesn't provide that example, and neither does the documentation on shopify.dev.
Below is an example using React & the AppBridge component:
NOTE: in the Shopify app tutorial example, the server redirects the client to the appSubscriptionCreate's confirmationURL. Instead you'll need to have your server return the confirmationURL in a string format. That way you can escape the iframe your app is embedded in and resolve the X-Frame-Options issue.
import { Page } from '@shopify/polaris'
import createApp from '@shopify/app-bridge';
import { Redirect } from '@shopify/app-bridge/actions';
import Cookies from "js-cookie";
import axios from 'axios';
export default function Plans() {
const app = createApp({
apiKey: API_KEY,
shopOrigin: Cookies.get('shopOrigin'),
});
const redirect = Redirect.create(app);
function openPlan(planUrl) {
axios.get(planUrl)
.then((res) => {
redirect.dispatch(Redirect.Action.REMOTE, { url: res.data.confirmationUrl, newContext: false })
})
.catch(err => { console.log(err) })
}
return (
<Page>
Pick plan:
<button onClick={() => {
openPlan('/api/plan/basic')
}}>
Basic
</button>
<button onClick={() => {
openPlan('/api/plan/pro')
}}>
Professional
</button>
<button onClick={() => {
openPlan('/api/plan/enterprise')
}}>
Enterprise
</button>
</Page>
)
}
Want to see it in action? Check out our demo store.