142 lines
5.9 KiB
Plaintext
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">✓</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 && 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> |