{"id":925,"date":"2023-04-25T15:25:29","date_gmt":"2023-04-25T07:25:29","guid":{"rendered":"https:\/\/open-doc.jkos.com\/?docs=%e9%96%8b%e6%94%be%e5%b9%b3%e5%8f%b0\/oauth-%e9%a9%97%e7%b0%bd%e5%b7%a5%e5%85%b7"},"modified":"2025-05-19T11:41:20","modified_gmt":"2025-05-19T03:41:20","slug":"oauth-%e9%a9%97%e7%b0%bd%e5%b7%a5%e5%85%b7","status":"publish","type":"docs","link":"https:\/\/open-doc.jkos.com\/?docs=inapp-%e7%ac%ac%e4%b8%89%e6%96%b9%e6%9c%8d%e5%8b%99\/oauth\/oauth-%e9%a9%97%e7%b0%bd%e5%b7%a5%e5%85%b7","title":{"rendered":"OAuth \u9a57\u7c3d\u5de5\u5177"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">JKOS Sign<\/h2>\n\n\n\n<script type=\"text\/javascript\" src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/crypto-js\/3.1.2\/rollups\/hmac-sha256.js\"><\/script>\n<script>\nconst getSign = () => {\nconst secretKey = document.getElementById('secret').value;\n        const params = document.getElementById('msg').value;\n\n        const ignoreKeyMap = [\n          'client_id',\n          'method',\n          'sign',\n          'sign_method',\n          'timestamp',\n          'access_token',\n        ];\n        const arr = params.split('&');\n        const initObj = {};\n        const obj = {};\n\n        const objKeySort = (obj) => {\n          const result = {};\n          const newKey = Object.keys(obj).sort();\n\n          newKey.forEach((key) => {\n            result[key] = obj[key];\n          });\n          return result;\n        };\n        arr.forEach((item) => {\n          const filterArr = item.split('=');\n\n          initObj[filterArr[0]] = filterArr[1];\n\n          if (!ignoreKeyMap.includes(filterArr[0])) {\n            obj[filterArr[0]] = filterArr[1];\n          }\n        });\nconst bodyMap = objKeySort(obj);\n        const jsonBody = JSON.stringify({\n          client_id: initObj['client_id'],\n          ...bodyMap,\n          timestamp: initObj['timestamp'],\n        });\n        const date = Math.trunc(new Date().getTime() \/ 1000 \/ 86400);\n        const finalSignString =\n          secretKey.toString() + jsonBody.toString() + date.toString();\n        const sign256 = CryptoJS.SHA256(finalSignString.toLowerCase())\n          .toString(CryptoJS.enc.Hex)\n          .toUpperCase();\n\n        document.getElementById('jsonBody').value = jsonBody;\n        document.getElementById('finalSignString').value = finalSignString;\n        document.getElementById('output').value = sign256;\n}\n<\/script>\n<div class=\"w-75\">\n    <div class=\"mb-3\">\n        <div class=\"mb-1\">\u8acb\u6c42\u53c3\u6578\uff1a<\/div>\n        <textarea id=\"msg\" class=\"form-control\" rows=\"5\" cols=\"5\" placeholder=\"grant_type=authorization_code&amp;code=test_code&amp;client_id=000000000&amp;method=jkopay.system.oauth.token&amp;sign=test_signD&amp;timestamp=1649929400000&amp;sign_method=JKOS_SIGN\"><\/textarea>\n    <\/div>\n    <div class=\"mb-3\">\n        <div class=\"mb-1\">Secret Key\uff1a<\/div>\n        <input id=\"secret\" type=\"text\" class=\"form-control\" placeholder=\"secret\">\n    <\/div>\n    <button type=\"button\" class=\"btn btn-info mb-5 p-2\" onclick=\"getSign()\">\u8a08\u7b97\u7c3d\u540d<\/button>\n    <div class=\"mb-3\">\n        <div class=\"mb-1\">1. \u6392\u5e8f\u696d\u52d9\u53c3\u6578\u4ee5\u5f8c\uff0c\u5728\u6700\u524d\u7aef\u52a0\u4e0a client_id\u3001(\u82e5\u5b58\u5728 access_token)\uff0c\u4e26\u5728\u6700\u5f8c\u52a0\u4e0a timestamp \u53c3\u6578\uff0c\u7d44\u6210 json body<\/div>\n        <textarea id=\"jsonBody\" type=\"text\" class=\"form-control\" rows=\"3\" cols=\"5\"><\/textarea>\n    <\/div>\n    <div class=\"mb-3\">\n        <div class=\"mb-1\">2. \u5c07 secret\u3001json body \u8207\u8a08\u7b97\u904e\u5f8c\u7684 timestamp \u505a\u7d44\u5408<\/div>\n        <textarea id=\"finalSignString\" type=\"text\" class=\"form-control\" rows=\"3\" cols=\"5\"><\/textarea>\n    <\/div>\n    <div class=\"mb-3\">\n        <div class=\"mb-1\">3. \u7c3d\u540d\u7d50\u679c<\/div>\n        <textarea id=\"output\" type=\"text\" class=\"form-control\" rows=\"3\" cols=\"5\"><\/textarea>\n    <\/div>\n<\/div>\n\n\n\n<hr class=\"wp-block-separator is-style-wide\"\/>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">\u5728\u672c\u7bc4\u4f8b\u4e2d\u5f15\u5165\u4ee5\u4e0b\u76f8\u95dc\u4f9d\u8cf4\uff0c\u5efa\u8b70\u76f4\u63a5\u9032\u884c\u76f8\u4f9d\u5957\u4ef6\u5f15\u5165<\/mark><\/strong><\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">\u4f7f\u7528\u65b9\u6cd5\uff1a<\/h3>\n\n\n<div class=\"wp-block-ub-content-toggle\" id=\"ub-content-toggle-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\"data-mobilecollapse=\"true\" data-desktopcollapse=\"true\">\n<div id=\"\" class=\"wp-block-ub-content-toggle-accordion\"\">\n                <div class=\"wp-block-ub-content-toggle-accordion-title-wrap\" aria-expanded=\"false\" aria-controls=\"ub-content-toggle-panel-0-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\" tabindex=\"0\">\n                    <p class=\"wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\"><strong>1. alibaba fastjson \u53bb\u9032\u884c json object \u8207\u5b57\u4e32\u578b\u5225\u8f49\u63db<\/strong><\/p><div class=\"wp-block-ub-content-toggle-accordion-toggle-wrap right\"><span class=\"wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down\"><\/span>\n                    <\/div><\/div><div role=\"region\" class=\"wp-block-ub-content-toggle-accordion-content-wrap ub-hide\" id=\"ub-content-toggle-panel-0-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\">\n\n<pre class=\"wp-block-code\"><code lang=\"\" class=\"\">&lt;!--&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/mvnrepository.com\/artifact\/com.alibaba\/fastjson\" target=\"_blank\">https:\/\/mvnrepository.com\/artifact\/com.alibaba\/fastjson<\/a>&nbsp;--&gt;\n&lt;dependency&gt;\n  &lt;groupId&gt;com.alibaba&lt;\/groupId&gt;\n  &lt;artifactId&gt;fastjson&lt;\/artifactId&gt;\n  &lt;version&gt;1.2.79&lt;\/version&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n\n<\/div><\/div>\n\n<div id=\"\" class=\"wp-block-ub-content-toggle-accordion\"\">\n                <div class=\"wp-block-ub-content-toggle-accordion-title-wrap\" aria-expanded=\"false\" aria-controls=\"ub-content-toggle-panel-1-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\" tabindex=\"0\">\n                    <p class=\"wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\"><strong>2.<\/strong> <strong>apache codec \u5354\u52a9\u505a hash<\/strong><\/p><div class=\"wp-block-ub-content-toggle-accordion-toggle-wrap right\"><span class=\"wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down\"><\/span>\n                    <\/div><\/div><div role=\"region\" class=\"wp-block-ub-content-toggle-accordion-content-wrap ub-hide\" id=\"ub-content-toggle-panel-1-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\">\n\n<pre class=\"wp-block-code\"><code lang=\"\" class=\"\">&lt;!--&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/mvnrepository.com\/artifact\/commons-codec\/commons-codec\" target=\"_blank\">https:\/\/mvnrepository.com\/artifact\/commons-codec\/commons-codec<\/a>&nbsp;--&gt;\n&lt;dependency&gt;\n  &lt;groupId&gt;commons-codec&lt;\/groupId&gt;\n  &lt;artifactId&gt;commons-codec&lt;\/artifactId&gt;\n  &lt;version&gt;1.15&lt;\/version&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n\n<\/div><\/div>\n\n<div id=\"\" class=\"wp-block-ub-content-toggle-accordion\"\">\n                <div class=\"wp-block-ub-content-toggle-accordion-title-wrap\" aria-expanded=\"false\" aria-controls=\"ub-content-toggle-panel-2-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\" tabindex=\"0\">\n                    <p class=\"wp-block-ub-content-toggle-accordion-title ub-content-toggle-title-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\"><strong>3. \u7a0b\u5f0f\u78bc &lt;Java><\/strong><\/p><div class=\"wp-block-ub-content-toggle-accordion-toggle-wrap right\"><span class=\"wp-block-ub-content-toggle-accordion-state-indicator wp-block-ub-chevron-down\"><\/span>\n                    <\/div><\/div><div role=\"region\" class=\"wp-block-ub-content-toggle-accordion-content-wrap ub-hide\" id=\"ub-content-toggle-panel-2-f98ecfa1-3ca6-4dba-99b0-8fe62d709096\">\n\n<pre title=\"JkosSignUtil.java\" class=\"wp-block-code\"><code lang=\"java\" class=\"language-java line-numbers\">package com.jko.sign;\n\u200b\nimport com.alibaba.fastjson.JSONObject;\nimport com.alibaba.fastjson.serializer.SerializerFeature;\nimport org.apache.commons.codec.digest.DigestUtils;\n\u200b\nimport java.nio.charset.StandardCharsets;\nimport java.util.*;\n\u200b\npublic class JkosSignUtil {\n    private static final String CLIENT_ID = \"client_id\";\n    private static final String METHOD = \"method\";\n    private static final String SIGN = \"sign\";\n    private static final String SIGNMETHOD = \"sign_method\";\n    private static final String TIMESTAMP = \"timestamp\";\n    private static final String ACCESS_TOKEN = \"access_token\";\n\u200b\n    private static final Map&lt;String, Boolean&gt; generalKey = new HashMap(){\n        {\n            put(CLIENT_ID, true);\n            put(METHOD, true);\n            put(SIGN, true);\n            put(SIGNMETHOD, true);\n            put(TIMESTAMP, true);\n            put(ACCESS_TOKEN, true);\n        }\n    };\n\u200b\n    public static String getJkosSign(Map&lt;String, Object&gt; params, String secret) {\n        String signBodyString = getSignBodyFromParams(params);\n        long currentMilliSeconds = Long.parseLong(params.get(TIMESTAMP).toString());\n        return sign(secret, signBodyString, currentMilliSeconds);\n    }\n\u200b\n    private static String getSignBodyFromParams(Map&lt;String, Object&gt; params) {\n        Map&lt;String, Object&gt; signBody = new LinkedHashMap&lt;&gt;();\n\u200b\n        signBody.put(CLIENT_ID, params.get(CLIENT_ID));\n        if (Objects.nonNull(params.get(ACCESS_TOKEN))) {\n            signBody.put(ACCESS_TOKEN, params.get(ACCESS_TOKEN));\n        }\n\u200b\n        List&lt;String&gt; signKeyList = new ArrayList();\n        params.forEach(\n                (k,v) -&gt; {\n                    if (generalKey.containsKey(k)) {\n                        return ;\n                    }\n                    signKeyList.add(k);\n                });\n\u200b\n        Collections.sort(signKeyList);\n\u200b\n        signKeyList.forEach(key -&gt; signBody.put(key, params.get(key)));\n        signBody.put(TIMESTAMP, params.get(TIMESTAMP));\n        return new JSONObject(signBody).toString(SerializerFeature.WriteMapNullValue);\n    }\n\u200b\n    private static String sign(String secret, String jsonBody, long timestamp) {\n        StringBuilder sb = new StringBuilder();\n        sb.append(secret).append(jsonBody).append(timestamp \/ 1000 \/ 86400);\n        String body = sb.toString();\n        return getSHA256(body.toLowerCase()).toUpperCase();\n    }\n\u200b\n    private static String getSHA256(String body) {\n        return DigestUtils.sha256Hex(body.getBytes(StandardCharsets.UTF_8));\n    }\n\u200b\n}\n\/*\n&lt;!-- https:\/\/mvnrepository.com\/artifact\/com.alibaba\/fastjson --&gt;\n&lt;dependency&gt;\n\t&lt;groupId&gt;com.alibaba&lt;\/groupId&gt;\n\t&lt;artifactId&gt;fastjson&lt;\/artifactId&gt;\n\t&lt;version&gt;1.2.79&lt;\/version&gt;\n&lt;\/dependency&gt;\n\u200b\n&lt;!-- https:\/\/mvnrepository.com\/artifact\/commons-codec\/commons-codec --&gt;\n&lt;dependency&gt;\n\t&lt;groupId&gt;commons-codec&lt;\/groupId&gt;\n\t&lt;artifactId&gt;commons-codec&lt;\/artifactId&gt;\n\t&lt;version&gt;1.15&lt;\/version&gt;\n&lt;\/dependency&gt;\n*\/<\/code><\/pre>\n\n<\/div><\/div>\n<\/div>","protected":false},"featured_media":0,"parent":1381,"menu_order":10,"comment_status":"open","ping_status":"closed","template":"","doc_tag":[],"class_list":["post-925","docs","type-docs","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/925","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs"}],"about":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/types\/docs"}],"replies":[{"embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=925"}],"version-history":[{"count":10,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/925\/revisions"}],"predecessor-version":[{"id":1610,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/925\/revisions\/1610"}],"up":[{"embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1381"}],"prev":[{"title":"JOP Gateway","link":"https:\/\/open-doc.jkos.com\/?docs=inapp-%e7%ac%ac%e4%b8%89%e6%96%b9%e6%9c%8d%e5%8b%99\/oauth\/jop-gateway","href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1450"}],"wp:attachment":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=925"}],"wp:term":[{"taxonomy":"doc_tag","embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdoc_tag&post=925"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}