{"id":759,"date":"2022-07-04T15:50:30","date_gmt":"2022-07-04T07:50:30","guid":{"rendered":"https:\/\/open-doc.jkos.com\/?docs=%e6%8e%88%e6%ac%8a%e6%89%a3%e6%ac%be-authorized-payment\/%e4%b8%b2%e6%8e%a5%e8%aa%aa%e6%98%8e-general\/%e5%8a%a0%e7%b0%bd%e5%8a%a0%e5%af%86%e8%aa%aa%e6%98%8e-signature-generation-rule"},"modified":"2025-04-25T19:05:37","modified_gmt":"2025-04-25T11:05:37","slug":"%e5%8a%a0%e7%b0%bd%e5%8a%a0%e5%af%86%e8%aa%aa%e6%98%8e-signature-generation-rule","status":"publish","type":"docs","link":"https:\/\/open-doc.jkos.com\/?docs=%e6%8e%88%e6%ac%8a%e6%89%a3%e6%ac%be-authorized-payment\/%e4%b8%b2%e6%8e%a5%e8%aa%aa%e6%98%8e-general\/%e5%8a%a0%e7%b0%bd%e5%8a%a0%e5%af%86%e8%aa%aa%e6%98%8e-signature-generation-rule","title":{"rendered":"\u52a0\u7c3d\u52a0\u5bc6\u8aaa\u660e (Signature Generation Rule)"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">\u898f\u5247\u8aaa\u660e (Description)<\/h2>\n\n\n\n<p><strong>HMAC-SHA256 \u7c3d\u7ae0\u7522\u751f\u898f\u5247\uff1a<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u53d6\u5f97\u8acb\u6c42\u5167\u5bb9<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u6839\u64da\u8acb\u6c42\u985e\u578b\uff0c\u9078\u64c7\u9069\u7576\u7684\u5167\u5bb9\u4f5c\u70ba\u8f38\u5165\u8cc7\u6599\uff1a\n<ul class=\"wp-block-list\">\n<li>GET \u8acb\u6c42\uff1a\u4f7f\u7528 Query String\uff08URL \u67e5\u8a62\u53c3\u6578\uff09\u4f5c\u70ba\u7c3d\u7ae0\u8f38\u5165\u3002<\/li>\n\n\n\n<li>POST \/ PUT \/ PATCH \u7b49\u8acb\u6c42\uff1a\u4f7f\u7528 Request Body \u5167\u5bb9\u4f5c\u70ba\u7c3d\u7ae0\u8f38\u5165\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>\u5c07\u8a72\u5167\u5bb9\u8f49\u63db\u70ba UTF-8 \u7de8\u78bc\u7684 byte \u9663\u5217\uff0c\u7a31\u70ba <code>input byte<\/code>\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u53d6\u5f97\u5bc6\u9470<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u8857\u53e3\u63d0\u4f9b\u7684 Secret key \u4e5f\u9700\u8f49\u63db\u70ba UTF-8 \u7de8\u78bc\u7684 byte \u9663\u5217\uff0c\u7a31\u70ba <code>secret key byte<\/code>\u3002<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u7522\u751f HMAC-SHA256 \u7c3d\u7ae0<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u4f7f\u7528 HMAC-SHA256 \u6f14\u7b97\u6cd5\uff0c\u8f38\u5165\u53c3\u6578\u5982\u4e0b\uff1a\n<ul class=\"wp-block-list\">\n<li>\u8f38\u5165\u8cc7\u6599\uff08message\uff09\uff1a<code>input byte<\/code><\/li>\n\n\n\n<li>\u91d1\u9470\uff08key\uff09\uff1a<code>secret key byte<\/code><\/li>\n\n\n\n<li>\u8f38\u51fa\u683c\u5f0f\uff1a32-byte (256-bit) \u7684\u96dc\u6e4a\u503c<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>\u8f49\u63db\u70ba 16 \u9032\u4f4d\u683c\u5f0f<\/strong>\n<ul class=\"wp-block-list\">\n<li>\u5c07 HMAC-SHA256 \u7684\u8f38\u51fa\u8f49\u63db\u70ba \u5c0f\u5beb 16 \u9032\u4f4d\u5b57\u4e32\uff08hex\uff09\uff0c\u7a31\u70ba <code>digest<\/code>\u3002<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u7bc4\u4f8b (Example) &#8211; Entry API (Method=Post)<\/h2>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e00\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u5b57\u4e32\u7684 request payload\u4ee5 UTF-8 \u7de8\u78bc\uff0crequest body\u7bc4\u4f8b\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">{\"platform_order_id\":\"demo-order-001\",\"store_id\":\"35f12dff-1581-11e9-a054-00505684fd45\",\"currency\": \"TWD\",\"total_price\":10,\"final_price\":10,\"unredeem\":10,\"result_display_url\":\"https:\/\/display.com\",\"result_url\":\"https:\/\/result-callback.xxx\/xxx\"}<\/code><\/pre>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e8c\uff1a<\/strong><\/p>\n\n\n\n<p>\u9808\u8207\u8857\u53e3\u652f\u4ed8\u7533\u8acb\u5e73\u53f0Secret Key\uff0c\u91d1\u9470\u7bc4\u4f8b\u70ba Secret key = <code>r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ<\/code>\uff0c\u4e26\u5c07 Secret key \u4ee5UTF-8 \u7de8\u78bc<\/p>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e09\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u6b65\u9a5f\u4e00\u7522\u751f\u7684\u5b57\u7bc0\u900f\u904e HMAC-SHA256\u6f14\u7b97\u6cd5\uff0c\u4ee5\u6b65\u9a5f\u4e8c\u7684\u5b57\u7bc0\u4f5c\u70ba\u79d8\u5bc6\u9470\u5319\u9032\u884c\u52a0\u7c3d\uff0c\u5373\u7522\u751f hexdigest \u4f5c\u70ba digest\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">{\"platform_order_id\":\"demo-order-001\",\"store_id\":\"35f12dff-1581-11e9-a054-00505684fd45\",\"currency\": \"TWD\",\"total_price\":10,\"final_price\":10,\"unredeem\":10,\"result_display_url\":\"https:\/\/display.com\",\"result_url\":\"https:\/\/result-callback.xxx\/xxx\"}\n\/*\nSecret key='r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ'\n*\/\nDIGEST: 3577609b058ab85c2d0a00a5421a991979ed6b9f549476e9a82476dc1b70d876<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u7bc4\u4f8b (Example) &#8211; Inquiry API (Method=Get)<\/h2>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e00\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u5b57\u4e32\u7684 request payload\u4ee5 UTF-8 \u7de8\u78bc\uff0crequest parameter\u7bc4\u4f8b\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">platform_order_ids=test123,demo-order-001<\/code><\/pre>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e8c\uff1a<\/strong><\/p>\n\n\n\n<p>\u9808\u8207\u8857\u53e3\u652f\u4ed8\u7533\u8acb\u5e73\u53f0Secret Key\uff0c\u91d1\u9470\u7bc4\u4f8b\u70ba Secret key = <code>r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ<\/code>\uff0c\u4e26\u5c07 Secret key \u4ee5UTF-8 \u7de8\u78bc<\/p>\n\n\n\n<p><strong>\u6b65\u9a5f\u4e09\uff1a<\/strong><\/p>\n\n\n\n<p>\u5c07\u6b65\u9a5f\u4e00\u7522\u751f\u7684\u5b57\u7bc0\u900f\u904e HMAC-SHA256\u6f14\u7b97\u6cd5\uff0c\u4ee5\u6b65\u9a5f\u4e8c\u7684\u5b57\u7bc0\u4f5c\u70ba\u79d8\u5bc6\u9470\u5319\u9032\u884c\u52a0\u7c3d\uff0c\u5373\u7522\u751f hexdigest \u4f5c\u70ba digest\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">DIGEST: 7778b95890af17c5b41e8cef957f4769e7bfecc79e9f9ee555923293ebd8e880<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u7c3d\u7ae0\u9a57\u8b49\u5de5\u5177<\/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\n<script>\n  function generateSignature() {\n    let requestType = document.getElementById(\"requestType\").value;\n    let requestData = document.getElementById(\"requestData\").value.trim();\n    let secretKey = document.getElementById(\"secretKey\").value.trim();\n    let errorDiv = document.getElementById(\"error\");\n    let output = document.getElementById(\"output\");\n    \n    errorDiv.innerHTML = \"\";\n    output.value = \"\";\n    \n    if (!secretKey) {\n      errorDiv.innerHTML = \"\u8acb\u8f38\u5165 Secret Key\";\n      return;\n    }\n    \n    if (!requestData) {\n      errorDiv.innerHTML = \"\u8acb\u8f38\u5165\u8acb\u6c42\u5167\u5bb9\";\n      return;\n    }\n    \n    try {\n      let inputData;\n      \n      if (requestType === \"GET\") {\n        \/\/ GET \u8acb\u6c42: \u76f4\u63a5\u4f7f\u7528 Query String\n        inputData = requestData;\n      } else {\n        \/\/ \u5176\u4ed6\u8acb\u6c42 (POST \/ PUT \/ PATCH): JSON \u683c\u5f0f\u5316\u8655\u7406\n        inputData = requestData;\n      }\n      \n      \/\/ \u7522\u751f HMAC-SHA256 \u7c3d\u540d\n      let signature = CryptoJS.HmacSHA256(inputData, secretKey);\n      \n      \/\/ \u8f49\u63db\u70ba 16 \u9032\u4f4d\u683c\u5f0f (\u5c0f\u5beb)\n      let digest = signature.toString(CryptoJS.enc.Hex);\n      \n      output.value = digest;\n    } catch (e) {\n      errorDiv.innerHTML = \"\u8acb\u8f38\u5165\u6b63\u78ba\u7684\u8acb\u6c42\u5167\u5bb9 (GET Query String \u6216 JSON Body)\";\n    }\n  }\n<\/script>\n\n<div class=\"w-75\">\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">\u8acb\u6c42\u985e\u578b\uff1a<\/div>\n    <select id=\"requestType\" class=\"form-control\">\n      <option value=\"GET\">GET<\/option>\n      <option value=\"POST\">POST \/ PUT \/ PATCH<\/option>\n    <\/select>\n  <\/div>\n\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">\u8acb\u6c42\u5167\u5bb9\uff1a(input byte)<\/div>\n    <textarea id=\"requestData\" class=\"form-control\" rows=\"5\" placeholder='GET: platform_order_ids=test123&#038;auth_no=123\nPOST: {\"platform_order_id\":\"demo-order-001\",\"store_id\":\"35f12dff-1581-11e9-a054-00505684fd45\",\"currency\":\"TWD\",\"total_price\":10,\"final_price\":10,\"unredeem\":10,\"result_display_url\":\"https:\/\/display.com\",\"result_url\":\"https:\/\/result-callback.xxx\/xxx\"}'><\/textarea>\n  <\/div>\n\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">Secret Key\uff1a<\/div>\n    <input id=\"secretKey\" type=\"text\" class=\"form-control\" placeholder=\"\u8f38\u5165 Secret Key\">\n  <\/div>\n\n  <button type=\"button\" class=\"btn btn-info mb-2 p-2\" onclick=\"generateSignature()\">\n    \u8a08\u7b97\u7c3d\u540d\n  <\/button>\n\n  <div class=\"mb-3\">\n    <div id=\"error\" style=\"color: red;\"><\/div>\n  <\/div>\n\n  <div class=\"mb-3\">\n    <div class=\"mb-1\">\u7c3d\u540d\u7d50\u679c\uff1a<\/div>\n    <textarea id=\"output\" class=\"form-control\" rows=\"3\" readonly><\/textarea>\n  <\/div>\n<\/div>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity is-style-wide\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">sample code<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Python<\/strong><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import hashlib<br>import hmac<br>import json<br><br>def generate_signature(payload, secret_key, is_get_request=False):<br>    # \u5224\u65b7\u4f7f\u7528 Query String\uff08GET\uff09\u6216 Request Body\uff08POST\/PUT\/PATCH\uff09<br>    input_data = payload if is_get_request else json.dumps(payload, separators=(',', ':'))<br>    <br>    # \u8f49\u63db\u6210 UTF-8 \u7de8\u78bc\u7684 byte \u9663\u5217<br>    input_bytes = input_data.encode('utf-8')<br>    secret_bytes = secret_key.encode('utf-8')<br><br>    # \u8a08\u7b97 HMAC-SHA256 \u96dc\u6e4a<br>    signature = hmac.new(secret_bytes, input_bytes, hashlib.sha256).hexdigest()<br><br>    return signature<br><br># \u6e2c\u8a66\u7bc4\u4f8b<br>secret_key = \"r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ\"<br>payload_get = \"platform_order_ids=test123&amp;auth_no=123\"<br>payload_post = {\"platform_order_id\":\"demo-order-001\",\"store_id\":\"35f12dff-1581-11e9-a054-00505684fd45\",\"currency\": \"TWD\",\"total_price\":10,\"final_price\":10,\"unredeem\":10,\"result_display_url\":\"https:\/\/display.com\",\"result_url\":\"https:\/\/result-callback.xxx\/xxx\"}<br><br>print(\"GET \u7c3d\u540d:\", generate_signature(payload_get, secret_key, is_get_request=True))<br>print(\"POST \u7c3d\u540d:\", generate_signature(payload_post, secret_key))<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>.NET Core (C#)<\/strong><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">using System;<br>using System.Security.Cryptography;<br>using System.Text;<br>using System.Text.Json;<br><br>class Program<br>{<br>    static string GenerateSignature(string payload, string secretKey)<br>    {<br>        \/\/ \u8f49\u63db\u6210 UTF-8 \u7de8\u78bc\u7684 byte \u9663\u5217<br>        byte[] inputBytes = Encoding.UTF8.GetBytes(payload);<br>        byte[] secretBytes = Encoding.UTF8.GetBytes(secretKey);<br><br>        \/\/ \u8a08\u7b97 HMAC-SHA256 \u96dc\u6e4a<br>        using (HMACSHA256 hmac = new HMACSHA256(secretBytes))<br>        {<br>            byte[] hashBytes = hmac.ComputeHash(inputBytes);<br>            return BitConverter.ToString(hashBytes).Replace(\"-\", \"\").ToLower();<br>        }<br>    }<br><br>    static void Main()<br>    {<br>        string secretKey = \"r0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ\";<br>        string payloadGet = \"platform_order_ids=test123&amp;auth_no=123\";<br>        string payloadPost = JsonSerializer.Serialize(new {\"platform_order_id\":\"demo-order-001\",\"store_id\":\"35f12dff-1581-11e9-a054-00505684fd45\",\"currency\": \"TWD\",\"total_price\":10,\"final_price\":10,\"unredeem\":10,\"result_display_url\":\"https:\/\/display.com\",\"result_url\":\"https:\/\/result-callback.xxx\/xxx\"});<br><br>        Console.WriteLine(\"GET \u7c3d\u540d: \" + GenerateSignature(payloadGet, secretKey));<br>        Console.WriteLine(\"POST \u7c3d\u540d: \" + GenerateSignature(payloadPost, secretKey));<br>    }<br>}<br><\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">PHP<\/h4>\n\n\n\n<p>\u53c3\u8003\u5de5\u5177\uff1a<a href=\"https:\/\/www.tehplayground.com\/uEl6FSUO5YaJHHVH\">https:\/\/www.tehplayground.com\/uEl6FSUO5YaJHHVH<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">$sig = hash_hmac('sha256', $string, $secret)\n\nsecretkey\uff1a\nr0odDC1e9LHXDmxuvmOv9bgaWLf2CXB2c4gMheoFucVKNMi1K0Id9zwRHJF1r-kdtAKriKgb11VDlo7Kb8R-FQ\n\ninput:\nplatform_order_ids=test123,demo-order-001\n\nresult:\n7778b95890af17c5b41e8cef957f4769e7bfecc79e9f9ee555923293ebd8e880<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">JAVA<\/h4>\n\n\n\n<p>\u53c3\u8003\u5de5\u5177\uff1a<a href=\"https:\/\/reurl.cc\/M0YKXk\">https:\/\/reurl.cc\/M0YKXk<\/a><\/p>\n\n\n\n<p><\/p>\n","protected":false},"featured_media":0,"parent":755,"menu_order":1,"comment_status":"open","ping_status":"closed","template":"","doc_tag":[],"class_list":["post-759","docs","type-docs","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/759","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=759"}],"version-history":[{"count":10,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/759\/revisions"}],"predecessor-version":[{"id":1371,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/759\/revisions\/1371"}],"up":[{"embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/755"}],"next":[{"title":"\u958b\u767c\u6d41\u7a0b\u6307\u5357 (Development Process Guide)","link":"https:\/\/open-doc.jkos.com\/?docs=%e6%8e%88%e6%ac%8a%e6%89%a3%e6%ac%be-authorized-payment\/%e4%b8%b2%e6%8e%a5%e8%aa%aa%e6%98%8e-general\/%e9%96%8b%e7%99%bc%e6%b5%81%e7%a8%8b%e6%8c%87%e5%8d%97-development-process-guide","href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/1272"}],"prev":[{"title":"API \u5354\u8b70\u898f\u5247 (API Protocol Rules)","link":"https:\/\/open-doc.jkos.com\/?docs=%e6%8e%88%e6%ac%8a%e6%89%a3%e6%ac%be-authorized-payment\/%e4%b8%b2%e6%8e%a5%e8%aa%aa%e6%98%8e-general\/api-%e5%8d%94%e8%ad%b0%e8%a6%8f%e5%89%87-api-protocol-rules","href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=\/wp\/v2\/docs\/757"}],"wp:attachment":[{"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=759"}],"wp:term":[{"taxonomy":"doc_tag","embeddable":true,"href":"https:\/\/open-doc.jkos.com\/index.php?rest_route=%2Fwp%2Fv2%2Fdoc_tag&post=759"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}