SyncMadeEasy/force-app/main/default/pages/ShopifyOAuthCallback.page

142 lines
5.9 KiB
Plaintext

<!--
ShopifyOAuthCallback.page
─────────────────────────
Salesforce Site-hosted page that acts as the OAuth redirect_uri for the
Shopify Authorization Code Grant flow.
SETUP (one-time, per org):
1. Deploy this page and ShopifyOAuthCallbackCtrl.cls to your org.
2. Go to Setup → Sites → [your site] → Site Visualforce Pages → Add "ShopifyOAuthCallback".
3. Grant the Site Guest User profile:
• Read + Edit on HIC_ShopifySync__SME_Configuration__c
• Apex class access for ShopifyOAuthCallbackCtrl
4. In your Shopify app settings, add this page's URL as an allowed redirect URI:
https://<your-site-domain>/ShopifyOAuthCallback
After successful authorization the page:
• Saves the access token to the store's configuration record.
• Auto-closes after 3 seconds (if opened as a popup).
• The LWC's polling loop picks up the token and fills the Access Token field.
-->
<apex:page controller="ShopifyOAuthCallbackCtrl" action="{!init}"
showHeader="false" sidebar="false" standardStylesheets="false"
applyHtmlTag="false" docType="html-5.0">
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Shopify OAuth — SyncMadeEasy</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #f4f6f9;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
.card {
background: #fff;
border-radius: 12px;
box-shadow: 0 4px 24px rgba(0,0,0,.10);
padding: 40px 48px;
max-width: 480px;
width: 90%;
text-align: center;
}
.logo {
width: 60px;
height: 60px;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 28px;
margin-bottom: 20px;
}
.logo-success { background: #e8f5e9; }
.logo-error { background: #fdecea; }
h1 { font-size: 22px; font-weight: 600; margin: 0 0 10px; }
h1.success { color: #2e7d32; }
h1.error { color: #c62828; }
p { font-size: 15px; color: #555; margin: 0 0 8px; line-height: 1.5; }
.store-badge {
display: inline-block;
background: #f0f6e4;
border: 1px solid #95BE45;
border-radius: 20px;
padding: 4px 14px;
font-size: 14px;
color: #3b3b3b;
margin: 12px 0 20px;
}
.hint {
font-size: 13px;
color: #888;
margin-top: 16px;
}
.countdown { font-weight: 600; color: #95BE45; }
.sme-loader-gif {
width: 200px;
height: 200px;
object-fit: contain;
margin-bottom: 18px;
}
.processing-text { font-size: 18px; font-weight: 600; color: #3b3b3b; margin: 0 0 8px; }
</style>
</head>
<body>
<div class="card">
<!-- SUCCESS: show the token so the admin copies it into the app manually.
Nothing is saved by this page; no DML runs as the Site Guest User. -->
<apex:outputPanel rendered="{!isSuccess}">
<div class="logo logo-success">&#10003;</div>
<h1 class="success">Access Token Generated!</h1>
<div class="store-badge">{!storeName}.myshopify.com</div>
<p>Copy the token below and paste it into the
<strong>Admin API access token</strong> field in SyncMadeEasy,
then click <strong>Check Credential</strong>.</p>
<div style="display:flex;gap:8px;margin-top:14px;">
<input type="text" id="smeToken" readonly="readonly" value="{!HTMLENCODE(accessToken)}"
style="flex:1;padding:10px 12px;border:1px solid #ccc;border-radius:8px;font-size:14px;font-family:monospace;background:#f8f8f8;" />
<button id="smeCopyBtn" type="button"
style="padding:10px 18px;border:none;border-radius:8px;background:#95BE45;color:#fff;font-size:14px;font-weight:600;cursor:pointer;">
Copy
</button>
</div>
<p class="hint">This token is shown only once. Close this window after copying.</p>
<script>
(function() {
var btn = document.getElementById('smeCopyBtn');
var input = document.getElementById('smeToken');
btn.addEventListener('click', function() {
input.select();
input.setSelectionRange(0, 99999);
if (navigator.clipboard &amp;&amp; navigator.clipboard.writeText) {
navigator.clipboard.writeText(input.value).then(function() {
btn.textContent = 'Copied!';
});
} else if (document.execCommand('copy')) {
btn.textContent = 'Copied!';
}
setTimeout(function() { btn.textContent = 'Copy'; }, 2000);
});
})();
</script>
</apex:outputPanel>
<!-- ERROR -->
<apex:outputPanel rendered="{!!isSuccess}">
<div class="logo logo-error">✗</div>
<h1 class="error">Token Generation Failed</h1>
<p><apex:outputText value="{!statusMsg}" /></p>
<p class="hint">Please close this window and try again.</p>
</apex:outputPanel>
</div>
</body>
</html>
</apex:page>