Hello, I am building a Shopify app using the node express template with Javascript. I need to use the billing api to create a one time purchase link for the user. It’s called the confirmation url in Shopify term I guess.
The GraphQL mutation is this
mutation AppPurchaseOneTimeCreate($name: String!, $price: MoneyInput!, $returnUrl: URL!, $test: Boolean) {
appPurchaseOneTimeCreate(name: $name, returnUrl: $returnUrl, price: $price, test: $test) {
userErrors {
field
message
}
appPurchaseOneTime {
createdAt
id
}
confirmationUrl
}
}
And the input looks like this:
variables: {
name: "One Time Purchase",
// returnUrl: `${shopifyAppHost}/api/purchase/callback`,
// returnUrl: `${shopifyAppHost}/api/purchase/callback?shop=${shopDomain}`,
// returnUrl: shopifyAppHost,
// returnUrl: `https://${shopDomain}/admin/apps/${process.env.SHOPIFY_API_KEY}/api/purchase/callback`,
// returnUrl: `https://${shopDomain}/admin/apps/${process.env.SHOPIFY_API_KEY}`,
returnUrl: `${shopifyAppHost}/api/purchase/callback?shop=${shopDomain}`,
test: true,
price: {
amount: amount,
currencyCode: "CAD",
},
},
I have tried different return urls but none of them take the user back. For this version, I got the error:
[shopify-api/ERROR] Missing Authorization header, was the request made with authenticatedFetch? | {isOnline: false}
On the frontend, I use this to redirect the user:
const createBillingMutation = useMutation({
mutationFn: async () => {
const response = await fetch("/api/billing", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ amount }),
});
console.log("********** MakePaymentButton createBillingMutation response:", response);
if (!response.ok) {
const error = await response.json();
throw new Error(error || "Failed to create billing request");
}
return await response.json();
},
onSuccess: (data) => {
// TODO call backend endpoint to add credits to user
alert("Billing success: " + JSON.stringify(data, null, 2));
alert(`Billing transaction id ${data.appPurchaseId}`);
console.log("Billing success:", data);
top.location.href = data.confirmationUrl;
},
onError: (error) => {
console.error("Billing error:", error);
},
});
I was hesitant to use top.location.href to redirect the user because that doesn’t seem to retain any authentication or session info.
However, I was unable to figure how to properly, with authentication, redirect the user to the confirmation url and take the user back to the return url.
Can someone teach me how to implement this? I am not able to find much explanation on the internet.
Thank you!