{"id":1769,"date":"2023-03-26T22:12:50","date_gmt":"2023-03-26T14:12:50","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1769"},"modified":"2023-04-23T21:20:22","modified_gmt":"2023-04-23T13:20:22","slug":"bigcommerce-app-callback-processing","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/03\/26\/bigcommerce-app-callback-processing\/","title":{"rendered":"BigCommerce App \u56de\u8c03\u5904\u7406"},"content":{"rendered":"<h2>\u5f53\u524d\u914d\u7f6e<\/h2>\n<ul>\n<li>Auth Callback URL: <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/1380ce593ae2.ngrok.io\/auth\">https:\/\/1380ce593ae2.ngrok.io\/auth<\/a><\/li>\n<li>Load Callback URL: <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/1380ce593ae2.ngrok.io\/load\">https:\/\/1380ce593ae2.ngrok.io\/load<\/a><\/li>\n<li>Uninstall Callback URL: <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/1380ce593ae2.ngrok.io\/uninstall\">https:\/\/1380ce593ae2.ngrok.io\/uninstall<\/a><\/li>\n<\/ul>\n<p><!-- more --><\/p>\n<h2>\u5b98\u65b9\u6587\u6863<\/h2>\n<p>Single-Click App Callbacks: <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/developer.bigcommerce.com\/api-docs\/apps\/guide\/callbacks\">https:\/\/developer.bigcommerce.com\/api-docs\/apps\/guide\/callbacks<\/a><br \/>\nVerifying the signed payload: <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/developer.bigcommerce.com\/api-docs\/apps\/guide\/callbacks#verifying-the-signed-payload\">https:\/\/developer.bigcommerce.com\/api-docs\/apps\/guide\/callbacks#verifying-the-signed-payload<\/a><\/p>\n<h2>\u56de\u8c03\u53c2\u6570<\/h2>\n<pre><code>{&quot;signed_payload&quot;:[&quot;eyJ1c2VyIjp7ImlkIjoxODk3NTQwLCJlbWFpbCI6InRlc3RAaW9iZXRhLmNvbSJ9LCJvd25lciI6eyJpZCI6MTg5NzU0MCwiZW1haWwiOiJ0ZXN0QGlvYmV0YS5jb20ifSwiY29udGV4dCI6InN0b3Jlcy9zdzd2MGlkenhxIiwic3RvcmVfaGFzaCI6InN3N3YwaWR6eHEiLCJ0aW1lc3RhbXAiOjE2MTIyNjg2ODMuNDYzODcxN30=.N2M4ZjhmNjgxMTczZTk3MWM1YTgxNWE1NDRhOWYxZjIxMzRjMmYzMjExMWYxZDA3NzIwOWIyZjljMmJmYmZjZQ==&quot;]}<\/code><\/pre>\n<p>Base64\u89e3\u7801\u540e\uff1a<\/p>\n<p>\uff081\uff09data: <\/p>\n<pre><code class=\"language-json\">{&quot;user&quot;:{&quot;id&quot;:1897540,&quot;email&quot;:&quot;test@appblog.cn&quot;},&quot;owner&quot;:{&quot;id&quot;:1897540,&quot;email&quot;:&quot;test@appblog.cn&quot;},&quot;context&quot;:&quot;stores\/sw7v0idzxq&quot;,&quot;store_hash&quot;:&quot;sw7v0idzxq&quot;,&quot;timestamp&quot;:1612269767.6191726}<\/code><\/pre>\n<p>\uff082\uff09sign: <code>39583f9c6020c1f80f450e935d387bfd1917788c7569a7e863686ae13e118a9f<\/code><\/p>\n<pre><code class=\"language-json\">{\n    &quot;user&quot;:{\n        &quot;id&quot;:1897540,\n        &quot;email&quot;:&quot;test@appblog.cn&quot;\n    },\n    &quot;owner&quot;:{\n        &quot;id&quot;:1897540,\n        &quot;email&quot;:&quot;test@appblog.cn&quot;\n    },\n    &quot;context&quot;:&quot;stores\/sw7v0idzxq&quot;,\n    &quot;store_hash&quot;:&quot;sw7v0idzxq&quot;,\n    &quot;timestamp&quot;:1612269767.6191726\n}<\/code><\/pre>\n<h2>\u56de\u8c03\u5904\u7406<\/h2>\n<pre><code class=\"language-java\">private static final String REGISTRATION_ID = SecurityBeansConfig.BIGCOMMERCE_REGISTRATION_ID;\n\n@Resource\nprivate OAuth2AuthorizedClientService clientService;\n\n@Value(&quot;${bigcommerce.client.client_secret}&quot;)\nprivate String clientSecret;\n\n@RequestMapping(path = SecurityConfig.LOAD_PATH, method = RequestMethod.GET)\npublic String load(Model model, @RequestParam(&quot;signed_payload&quot;) String signedPayload) {\n    log.info(&quot;HomeController.load, signed_payload: {}&quot;, signedPayload);\n    if (StringUtils.isNotBlank(signedPayload)) {\n        String[] signedPayloads = signedPayload.split(&quot;\\\\.&quot;);\n        if (signedPayloads.length == 2) {\n            String data = new String(Base64.decodeBase64(signedPayloads[0]));\n            String sign = new String(Base64.decodeBase64(signedPayloads[1]));\n            log.info(&quot;data: {}, sign: {}&quot;, data, sign);\n            try {\n                boolean verified = HmacUtil.verifyHmacSHA256(data, sign, clientSecret);\n                if (verified) {\n                    BigcommerceContext bigcommerceContext = JacksonUtil.toJSONObject(data, BigcommerceContext.class);\n                    if (bigcommerceContext != null) {\n                        SecurityContext context = SecurityContextHolder.getContext();\n                        if (context != null &amp;&amp; context.getAuthentication() != null) {\n                            Authentication principal = context.getAuthentication();\n                            if (principal != null) {\n                                String shopDomain = String.format(&quot;store-%s.mybigcommerce.com&quot;, bigcommerceContext.getStoreHash());\n                                OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(REGISTRATION_ID, shopDomain);\n\n                                if (client != null) {\n                                    \/\/ this store &quot;has not been installed&quot;, or salt and passwords are outdated\n                                    String apiKey = client.getClientRegistration().getClientId();\n                                    OAuth2AuthenticationToken oauth2Authentication = new OAuth2AuthenticationToken(\n                                            new BigcommerceStore(client.getPrincipalName(), client.getAccessToken().getTokenValue(), apiKey),\n                                            null,\n                                            REGISTRATION_ID);\n                                    SecurityContextHolder.getContext().setAuthentication(oauth2Authentication);\n\n                                    model.addAttribute(&quot;shopDomain&quot;, bigcommerceContext.getStoreHash());\n                                    return &quot;success&quot;;\n                                }\n                            }\n                        }\n                    }\n                }\n            } catch (Exception e) {\n                log.error(&quot;&quot;, e);\n            }\n        }\n    }\n    return &quot;authError&quot;;\n}<\/code><\/pre>\n<pre><code class=\"language-java\">public class HmacUtil {\n\n    public static String hmacSHA256(String data, String key) throws Exception {\n        Mac sha256Hmac = Mac.getInstance(&quot;HmacSHA256&quot;);\n        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), &quot;HmacSHA256&quot;);\n        sha256Hmac.init(secretKey);\n        byte[] array = sha256Hmac.doFinal(data.getBytes());\n        StringBuilder sb = new StringBuilder();\n        for (byte item : array) {\n            sb.append(Integer.toHexString((item &amp; 0xFF) | 0x100).substring(1, 3));\n        }\n        return sb.toString();\n    }\n\n    public static boolean verifyHmacSHA256(String text, String sign, String key) throws Exception {\n        String mySign = hmacSHA256(text, key);\n        if (mySign.equalsIgnoreCase(sign)) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u5f53\u524d\u914d\u7f6e Auth Callback URL: https:\/\/1380ce593ae2.ngrok.io\/a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[446],"tags":[],"class_list":["post-1769","post","type-post","status-publish","format-standard","hentry","category-bigcommerce"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1769","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1769"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1769\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1769"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}