{"info":{"_postman_id":"169d1216-493a-4bb8-9742-7725a7051d49","name":"API文档","description":"<html><head></head><body><h2 id=\"加密算法\">加密算法</h2>\n<ul>\n<li><p>所有的请求都需要对请求体进行加密校验</p>\n</li>\n<li><p>所有请求必须包含app_id和app_key和sign</p>\n</li>\n<li><p>app_id和app_key从用户后台获取</p>\n</li>\n<li><p>sign通过下面的加密算法计算得出</p>\n</li>\n</ul>\n<h3 id=\"加密原理\">加密原理</h3>\n<h4 id=\"1、对postdata对象键进行排序\">1、对PostData对象键进行排序</h4>\n<ul>\n<li>对请求体进行字典序排序。这是因为生成签名时, 需要确保参数的顺序一致, 以防不同的顺序导致生成不同的签名值.</li>\n</ul>\n<h4 id=\"2、拼接字符串\">2、拼接字符串</h4>\n<ul>\n<li>遍历排序后的键，将每个键和对应的值拼接成字符串. 在拼接时, 如果键的值不为空（null或空字符串）, 则将键和值进行URL编码, 并用&amp;连接.</li>\n</ul>\n<h4 id=\"3、添加商户密钥\">3、添加商户密钥</h4>\n<ul>\n<li>在查询字符串的末尾加上&amp;key=yourAppKey，其中yourAppKey是提前定义好的应用密钥。这一步是将应用密钥纳入签名的计算之中，提高签名的安全性</li>\n</ul>\n<h4 id=\"4、计算请求体md5值\">4、计算请求体MD5值</h4>\n<ul>\n<li>计算查询字符串的MD5哈希值，以生成签名。</li>\n</ul>\n<h4 id=\"5、将计算到的值添加到请求体\">5、将计算到的值添加到请求体</h4>\n<ul>\n<li>请求体添加 sign=md5值</li>\n</ul>\n<h3 id=\"php加密算法\">PHP加密算法</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-PHP\">    /**\n     * 获取数据签名\n     * @param array $data\n     * @param string $appKey\n     * @return string\n     */\n    public static function generateSignature(array $data, $appKey): string\n    {\n        unset($data['sign']);\n        ksort($data);\n        foreach ($data as $key =&gt; $val) {\n            if ($val === '') {\n                unset($data[$key]);\n            }\n        }\n        return md5(urldecode(http_build_query($data) . \"&amp;key=\" . (string)$appKey));\n    }\n\n</code></pre>\n<h3 id=\"c加密算法\">C#加密算法</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-C#\">    public static class SignatureHelper\n    {\n        public static string GenerateSignature(Dictionary&lt;string, string&gt; data, string appKey)\n        {\n            if (data.ContainsKey(\"sign\"))\n            {\n                data.Remove(\"sign\");\n            }\n            var sortedData = data.OrderBy(pair =&gt; pair.Key);\n            var sanitizedData = new Dictionary&lt;string, string&gt;();\n            foreach (var pair in sortedData)\n            {\n                if (pair.Value != null &amp;&amp; !string.IsNullOrEmpty(pair.Value.ToString()))\n                {\n                    sanitizedData.Add(pair.Key, pair.Value);\n                }\n            }\n            var queryString = string.Join(\"&amp;\", sanitizedData.Select(pair =&gt; $\"{HttpUtility.UrlEncode(pair.Key)}={HttpUtility.UrlEncode(pair.Value.ToString())}\"));\n            queryString += $\"&amp;key={appKey}\";\n            return CalculateMd5Hash(HttpUtility.UrlDecode(queryString));\n        }\n        private static string CalculateMd5Hash(string input)\n        {\n            using MD5 md5 = MD5.Create();\n            byte[] inputBytes = Encoding.UTF8.GetBytes(input);\n            byte[] hashBytes = md5.ComputeHash(inputBytes);\n            StringBuilder sb = new StringBuilder();\n            for (int i = 0; i &lt; hashBytes.Length; i++)\n            {\n                sb.Append(hashBytes[i].ToString(\"X2\"));\n            }\n            return sb.ToString().ToLower();\n        }\n    }\n\n</code></pre>\n<h3 id=\"postman-pre-request-script\">PostMan Pre-request Script</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-javascript\">// 初始化一个空对象来存储POST参数\nlet postData = {};\npm.request.body.urlencoded.each((param) =&gt; {\n    postData[param.key] = param.value;\n});\n// 检查app_key是否存在\nif (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\n    throw new Error(\"app_key is missing from the POST parameters.\");\n}\nlet appKey = postData['app_key']; // 从POST参数中获取appKey\n// 删除sign键（如果存在）\nif (postData.hasOwnProperty('sign')) {\n    delete postData['sign'];\n}\n// 对postData的键进行排序并构建查询字符串\nlet sortedKeys = Object.keys(postData).sort();\nlet queryString = \"\";\nsortedKeys.forEach((key, index) =&gt; {\n    if (postData[key] !== null &amp;&amp; postData[key] !== \"\") {\n        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index &lt; sortedKeys.length - 1 ? '&amp;' : ''}`;\n    }\n});\n// 添加appKey\nqueryString += `&amp;key=${appKey}`;\n// 计算MD5\nconst crypto = require('crypto-js');\nlet hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\nconsole.log(\"Generated Signature: \" + hash);\n// 将sign添加到POST参数中\npm.request.body.urlencoded.add({key: \"sign\", value: hash});\n\n</code></pre>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"39427840","collectionId":"169d1216-493a-4bb8-9742-7725a7051d49","publishedId":"2sAY4viP6a","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2024-11-01T06:49:33.000Z"},"item":[{"name":"查询余额","event":[{"listen":"prerequest","script":{"exec":["// 初始化一个空对象来存储POST参数\r","let postData = {};\r","pm.request.body.urlencoded.each((param) => {\r","    // 使用pm.variables.get获取实际的变量值，而不是直接使用param.value\r","    postData[param.key] = pm.variables.get(param.key) || param.value;\r","});\r","\r","// 检查app_key是否存在\r","if (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\r","    throw new Error(\"app_key is missing from the POST parameters.\");\r","}\r","\r","let appKey = postData['app_key']; // 从POST参数中获取appKey\r","\r","// 删除sign键（如果存在）\r","if (postData.hasOwnProperty('sign')) {\r","    delete postData['sign'];\r","}\r","\r","// 对postData的键进行排序并构建查询字符串\r","let sortedKeys = Object.keys(postData).sort();\r","let queryString = \"\";\r","\r","sortedKeys.forEach((key, index) => {\r","    if (postData[key] !== null && postData[key] !== \"\") {\r","        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index < sortedKeys.length - 1 ? '&' : ''}`;\r","    }\r","});\r","\r","// 添加appKey\r","queryString += `&key=${appKey}`;\r","\r","// 计算MD5\r","const crypto = require('crypto-js');\r","let hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\r","\r","console.log(\"Generated Signature: \" + hash);\r","\r","// 将sign添加到POST参数中\r","pm.request.body.urlencoded.add({key: \"sign\", value: hash});"],"type":"text/javascript","packages":{},"id":"f33d25cb-90d7-40ff-ac24-d1769a7a7fae"}}],"id":"2f360e27-5c72-4131-9e8e-ec4a2af52130","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"app_id","value":"{{app_id}}","description":"<p>商户ID</p>\n","type":"text"},{"key":"app_key","value":"{{app_key}}","description":"<p>商户密钥</p>\n","type":"text"},{"key":"sign","value":"","description":"<p>算法请参考文档或者Pre-request Script</p>\n","type":"text","disabled":true}]},"url":"{{host}}/shared/authentication/connect","description":"<h1 id=\"查询余额返回数据说明\">查询余额返回数据说明</h1>\n<ul>\n<li>查询余额</li>\n<li>测试通讯</li>\n</ul>\n<p>接口成功返回的基础信息包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>code</td>\n<td>int</td>\n<td>状态码，200 表示成功</td>\n</tr>\n<tr>\n<td>msg</td>\n<td>string</td>\n<td>响应消息</td>\n</tr>\n<tr>\n<td>data</td>\n<td>object</td>\n<td>店铺信息</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"data-店铺信息\">data 店铺信息</h2>\n<p>店铺对象包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>shopName</td>\n<td>string</td>\n<td>商店名称</td>\n</tr>\n<tr>\n<td>balance</td>\n<td>float</td>\n<td>账户余额</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["shared","authentication","connect"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"2f360e27-5c72-4131-9e8e-ec4a2af52130"},{"name":"商品列表","event":[{"listen":"prerequest","script":{"exec":["// 初始化一个空对象来存储POST参数\r","let postData = {};\r","pm.request.body.urlencoded.each((param) => {\r","    // 使用pm.variables.get获取实际的变量值，而不是直接使用param.value\r","    postData[param.key] = pm.variables.get(param.key) || param.value;\r","});\r","\r","// 检查app_key是否存在\r","if (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\r","    throw new Error(\"app_key is missing from the POST parameters.\");\r","}\r","\r","let appKey = postData['app_key']; // 从POST参数中获取appKey\r","console.log(appKey)\r","// 删除sign键（如果存在）\r","if (postData.hasOwnProperty('sign')) {\r","    delete postData['sign'];\r","}\r","\r","// 对postData的键进行排序并构建查询字符串\r","let sortedKeys = Object.keys(postData).sort();\r","let queryString = \"\";\r","\r","sortedKeys.forEach((key, index) => {\r","    if (postData[key] !== null && postData[key] !== \"\") {\r","        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index < sortedKeys.length - 1 ? '&' : ''}`;\r","    }\r","});\r","\r","// 添加appKey\r","queryString += `&key=${appKey}`;\r","\r","// 计算MD5\r","const crypto = require('crypto-js');\r","let hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\r","\r","console.log(\"Generated Signature: \" + hash);\r","\r","// 将sign添加到POST参数中\r","pm.request.body.urlencoded.add({key: \"sign\", value: hash});"],"type":"text/javascript","packages":{},"id":"2af2f210-6389-4c76-bec9-9e2c9f989e39"}}],"id":"1c25da7c-1cd2-42b3-b033-ced13bb0b2ca","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"app_id","value":"{{app_id}}","description":"<p>商户ID</p>\n","type":"text"},{"key":"app_key","value":"{{app_key}}","description":"<p>商户密钥</p>\n","type":"text"},{"key":"sign","value":"","description":"<p>算法请参考文档或者Pre-request Script</p>\n","type":"text","disabled":true}]},"url":"{{host}}/shared/commodity/items","description":"<h1 id=\"商品列表接口返回数据说明\">商品列表接口返回数据说明</h1>\n<ul>\n<li>返回所有商品信息</li>\n<li>数据有5分钟缓存</li>\n</ul>\n<p>接口成功返回的基础信息包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>code</td>\n<td>int</td>\n<td>状态码，200 表示成功</td>\n</tr>\n<tr>\n<td>msg</td>\n<td>string</td>\n<td>响应消息</td>\n</tr>\n<tr>\n<td>data</td>\n<td>array</td>\n<td>分类列表</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"data-分类列表\">data 分类列表</h2>\n<p>每个对象包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>int</td>\n<td>分类ID</td>\n</tr>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>分类名称，如\"海外邮箱账户\"</td>\n</tr>\n<tr>\n<td>sort</td>\n<td>int</td>\n<td>排序权重，数字越小排序越靠前</td>\n</tr>\n<tr>\n<td>icon</td>\n<td>string</td>\n<td>图标的路径</td>\n</tr>\n<tr>\n<td>children</td>\n<td>array</td>\n<td>子项数组，包含此项下的子项目</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"children-分类数组内商品的字段说明\">children 分类数组内商品的字段说明</h3>\n<p>商品对象包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>int</td>\n<td>唯一标识</td>\n</tr>\n<tr>\n<td>category_id</td>\n<td>int</td>\n<td>分类ID，指示该项属于哪个父类</td>\n</tr>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>名称，描述具体项目或服务</td>\n</tr>\n<tr>\n<td>description</td>\n<td>string</td>\n<td>描述，可包含HTML标签</td>\n</tr>\n<tr>\n<td>cover</td>\n<td>string</td>\n<td>封面图片路径</td>\n</tr>\n<tr>\n<td>price</td>\n<td>float</td>\n<td>价格(未登录)</td>\n</tr>\n<tr>\n<td>user_price</td>\n<td>float</td>\n<td>会员价</td>\n</tr>\n<tr>\n<td>status</td>\n<td>int</td>\n<td>状态，通常1表示启用，0表示禁用</td>\n</tr>\n<tr>\n<td>create_time</td>\n<td>string</td>\n<td>创建时间，格式为\"YYYY-MM-DD HH:MM:SS\"</td>\n</tr>\n<tr>\n<td>api_status</td>\n<td>int</td>\n<td>API对接：0=关闭，1=启用</td>\n</tr>\n<tr>\n<td>code</td>\n<td>string</td>\n<td>商品代码(API对接)</td>\n</tr>\n<tr>\n<td>delivery_way</td>\n<td>int</td>\n<td>发货方式：0=自动发货，1=手动发货/插件发货</td>\n</tr>\n<tr>\n<td>config</td>\n<td>string</td>\n<td>配置文件</td>\n</tr>\n<tr>\n<td>minimum</td>\n<td>int</td>\n<td>最小购买量, 0表示不限制</td>\n</tr>\n<tr>\n<td>maximum</td>\n<td>int</td>\n<td>最大购买量, 0表示不限制</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["shared","commodity","items"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"1c25da7c-1cd2-42b3-b033-ced13bb0b2ca"},{"name":"查询库存","event":[{"listen":"prerequest","script":{"exec":["// 初始化一个空对象来存储POST参数\r","let postData = {};\r","pm.request.body.urlencoded.each((param) => {\r","    // 使用pm.variables.get获取实际的变量值，而不是直接使用param.value\r","    postData[param.key] = pm.variables.get(param.key) || param.value;\r","});\r","\r","// 检查app_key是否存在\r","if (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\r","    throw new Error(\"app_key is missing from the POST parameters.\");\r","}\r","\r","let appKey = postData['app_key']; // 从POST参数中获取appKey\r","\r","// 删除sign键（如果存在）\r","if (postData.hasOwnProperty('sign')) {\r","    delete postData['sign'];\r","}\r","\r","// 对postData的键进行排序并构建查询字符串\r","let sortedKeys = Object.keys(postData).sort();\r","let queryString = \"\";\r","\r","sortedKeys.forEach((key, index) => {\r","    if (postData[key] !== null && postData[key] !== \"\") {\r","        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index < sortedKeys.length - 1 ? '&' : ''}`;\r","    }\r","});\r","\r","// 添加appKey\r","queryString += `&key=${appKey}`;\r","\r","// 计算MD5\r","const crypto = require('crypto-js');\r","let hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\r","\r","console.log(\"Generated Signature: \" + hash);\r","\r","// 将sign添加到POST参数中\r","pm.request.body.urlencoded.add({key: \"sign\", value: hash});"],"type":"text/javascript","packages":{},"id":"fda1b83f-9641-4bb7-aff8-0c42360efbe2"}}],"id":"a19b1c02-9b0b-4277-857f-f240ef18ffb1","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"app_id","value":"{{app_id}}","description":"<p>商户ID</p>\n","type":"text"},{"key":"app_key","value":"{{app_key}}","description":"<p>商户密钥</p>\n","type":"text"},{"key":"sign","value":"","description":"<p>算法请参考文档或者Pre-request Script</p>\n","type":"text","disabled":true},{"key":"sharedCode","value":"44A7F5F28A8B1635","description":"<p>商品代码(API对接)</p>\n","type":"text"},{"key":"race","value":"","description":"<p>型号编码</p>\n","type":"text"}]},"url":"{{host}}/shared/commodity/inventory","description":"<h1 id=\"商品库存接口返回数据\">商品库存接口返回数据</h1>\n<p>接口成功返回的基础信息包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>code</td>\n<td>int</td>\n<td>状态码，200 表示成功</td>\n</tr>\n<tr>\n<td>msg</td>\n<td>string</td>\n<td>响应消息</td>\n</tr>\n<tr>\n<td>data</td>\n<td>object</td>\n<td>商品信息</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"data-商品信息\">data 商品信息</h2>\n<p>每个对象包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>count</td>\n<td>int</td>\n<td>库存</td>\n</tr>\n<tr>\n<td>delivery_way</td>\n<td>int</td>\n<td>发货方式：0=自动发货，1=手动发货/插件发货</td>\n</tr>\n<tr>\n<td>price</td>\n<td>float</td>\n<td>价格(未登录)</td>\n</tr>\n<tr>\n<td>user_price</td>\n<td>float</td>\n<td>会员价</td>\n</tr>\n<tr>\n<td>config</td>\n<td>string</td>\n<td>配置文件</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["shared","commodity","inventory"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"a19b1c02-9b0b-4277-857f-f240ef18ffb1"},{"name":"查询库存是否充足","event":[{"listen":"prerequest","script":{"exec":["// 初始化一个空对象来存储POST参数\r","let postData = {};\r","pm.request.body.urlencoded.each((param) => {\r","    // 使用pm.variables.get获取实际的变量值，而不是直接使用param.value\r","    postData[param.key] = pm.variables.get(param.key) || param.value;\r","});\r","\r","// 检查app_key是否存在\r","if (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\r","    throw new Error(\"app_key is missing from the POST parameters.\");\r","}\r","\r","let appKey = postData['app_key']; // 从POST参数中获取appKey\r","\r","// 删除sign键（如果存在）\r","if (postData.hasOwnProperty('sign')) {\r","    delete postData['sign'];\r","}\r","\r","// 对postData的键进行排序并构建查询字符串\r","let sortedKeys = Object.keys(postData).sort();\r","let queryString = \"\";\r","\r","sortedKeys.forEach((key, index) => {\r","    if (postData[key] !== null && postData[key] !== \"\") {\r","        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index < sortedKeys.length - 1 ? '&' : ''}`;\r","    }\r","});\r","\r","// 添加appKey\r","queryString += `&key=${appKey}`;\r","\r","// 计算MD5\r","const crypto = require('crypto-js');\r","let hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\r","\r","console.log(\"Generated Signature: \" + hash);\r","\r","// 将sign添加到POST参数中\r","pm.request.body.urlencoded.add({key: \"sign\", value: hash});"],"type":"text/javascript","packages":{},"id":"faf63138-4963-4116-8a0d-1da20ddc8cc6"}}],"id":"dffcbe85-3d90-4a47-9811-bada57685602","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"app_id","value":"{{app_id}}","description":"<p>商户ID</p>\n","type":"text"},{"key":"app_key","value":"{{app_key}}","description":"<p>商户密钥</p>\n","type":"text"},{"key":"sign","value":"","description":"<p>算法请参考文档或者Pre-request Script</p>\n","type":"text","disabled":true},{"key":"shared_code","value":"C70559555DD4E863","description":"<p>商品代码(API对接)</p>\n","type":"text"},{"key":"race","value":"","description":"<p>型号编码</p>\n","type":"text"},{"key":"num","value":"1","description":"<p>购买数量</p>\n","type":"text"}]},"url":"{{host}}/shared/commodity/inventoryState","description":"<h1 id=\"查询库存是否充足返回数据\">查询库存是否充足返回数据</h1>\n<ul>\n<li>交易前通过调用此接口查询库存是否充足, 是否超出购买数量限制等</li>\n<li>此接口没有缓存</li>\n</ul>\n<p>接口成功返回的基础信息包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>code</td>\n<td>int</td>\n<td>状态码，200 表示成功</td>\n</tr>\n<tr>\n<td>msg</td>\n<td>string</td>\n<td>响应消息</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["shared","commodity","inventoryState"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"dffcbe85-3d90-4a47-9811-bada57685602"},{"name":"交易","event":[{"listen":"prerequest","script":{"exec":["// 初始化一个空对象来存储POST参数\r","let postData = {};\r","pm.request.body.urlencoded.each((param) => {\r","    // 使用pm.variables.get获取实际的变量值，而不是直接使用param.value\r","    postData[param.key] = pm.variables.get(param.key) || param.value;\r","});\r","\r","// 检查app_key是否存在\r","if (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\r","    throw new Error(\"app_key is missing from the POST parameters.\");\r","}\r","\r","let appKey = postData['app_key']; // 从POST参数中获取appKey\r","\r","// 删除sign键（如果存在）\r","if (postData.hasOwnProperty('sign')) {\r","    delete postData['sign'];\r","}\r","\r","// 对postData的键进行排序并构建查询字符串\r","let sortedKeys = Object.keys(postData).sort();\r","let queryString = \"\";\r","\r","sortedKeys.forEach((key, index) => {\r","    if (postData[key] !== null && postData[key] !== \"\") {\r","        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index < sortedKeys.length - 1 ? '&' : ''}`;\r","    }\r","});\r","\r","// 添加appKey\r","queryString += `&key=${appKey}`;\r","\r","// 计算MD5\r","const crypto = require('crypto-js');\r","let hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\r","\r","console.log(\"Generated Signature: \" + hash);\r","\r","// 将sign添加到POST参数中\r","pm.request.body.urlencoded.add({key: \"sign\", value: hash});"],"type":"text/javascript","packages":{},"id":"7903f8c7-c771-4c8c-aa93-e35cad00f526"}}],"id":"ec65b788-7735-468d-8451-d498ee6df27f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"app_id","value":"{{app_id}}","description":"<p>商户ID</p>\n","type":"text"},{"key":"app_key","value":"{{app_key}}","description":"<p>商户密钥</p>\n","type":"text"},{"key":"sign","value":"","description":"<p>算法请参考文档或者Pre-request Script</p>\n","type":"text","disabled":true},{"key":"shared_code","value":"1236507194413838336","description":"<p>商品代码(API对接)</p>\n","type":"text"},{"key":"race","value":"","description":"<p>型号编码</p>\n","type":"text"},{"key":"num","value":"1","description":"<p>数量</p>\n","type":"text"}]},"url":"{{host}}/shared/commodity/trade","description":"<h1 id=\"交易返回数据\">交易返回数据</h1>\n<p>接口成功返回的基础信息包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>code</td>\n<td>int</td>\n<td>状态码，200 表示成功</td>\n</tr>\n<tr>\n<td>msg</td>\n<td>string</td>\n<td>响应消息</td>\n</tr>\n<tr>\n<td>data</td>\n<td>object</td>\n<td>订单信息</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"data-商品信息\">data 商品信息</h2>\n<p>每个对象包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>int</td>\n<td>订单ID</td>\n</tr>\n<tr>\n<td>amount</td>\n<td>float</td>\n<td>订单金额</td>\n</tr>\n<tr>\n<td>tradeNo</td>\n<td>string</td>\n<td>订单编号</td>\n</tr>\n<tr>\n<td>secret</td>\n<td>string</td>\n<td>卡密</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["shared","commodity","trade"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"ec65b788-7735-468d-8451-d498ee6df27f"},{"name":"查询订单列表","event":[{"listen":"prerequest","script":{"exec":["// 初始化一个空对象来存储POST参数\r","let postData = {};\r","pm.request.body.urlencoded.each((param) => {\r","    postData[param.key] = param.value;\r","});\r","\r","// 检查app_key是否存在\r","if (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\r","    throw new Error(\"app_key is missing from the POST parameters.\");\r","}\r","\r","let appKey = postData['app_key']; // 从POST参数中获取appKey\r","\r","// 删除sign键（如果存在）\r","if (postData.hasOwnProperty('sign')) {\r","    delete postData['sign'];\r","}\r","\r","// 对postData的键进行排序并构建查询字符串\r","let sortedKeys = Object.keys(postData).sort();\r","let queryString = \"\";\r","\r","sortedKeys.forEach((key, index) => {\r","    if (postData[key] !== null && postData[key] !== \"\") {\r","        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index < sortedKeys.length - 1 ? '&' : ''}`;\r","    }\r","});\r","\r","// 添加appKey\r","queryString += `&key=${appKey}`;\r","\r","// 计算MD5\r","const crypto = require('crypto-js');\r","let hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\r","\r","console.log(\"Generated Signature: \" + hash);\r","\r","// 将sign添加到POST参数中\r","pm.request.body.urlencoded.add({key: \"sign\", value: hash});"],"type":"text/javascript","packages":{},"id":"ecbb3dd5-26de-4110-85ec-6bac6e6bf50b"}}],"id":"0ff425c9-38b1-46ed-b0d3-499a32adb781","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"app_id","value":"3028","description":"<p>商户ID</p>\n","type":"text"},{"key":"app_key","value":"634F790AA82F0015","description":"<p>商户密钥</p>\n","type":"text"},{"key":"sign","value":"","description":"<p>算法请参考文档或者Pre-request Script</p>\n","type":"text"},{"key":"page","value":"1","description":"<p>页码</p>\n","type":"text"},{"key":"limit","value":"20","description":"<p>每页数量</p>\n","type":"text"}]},"url":"{{host}}/shared/commodity/orderList","description":"<h1 id=\"查询余额返回数据说明\">查询余额返回数据说明</h1>\n<ul>\n<li>查询余额</li>\n<li>测试通讯</li>\n</ul>\n<p>接口成功返回的基础信息包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>code</td>\n<td>int</td>\n<td>状态码，200 表示成功</td>\n</tr>\n<tr>\n<td>msg</td>\n<td>string</td>\n<td>响应消息</td>\n</tr>\n<tr>\n<td>data</td>\n<td>object</td>\n<td>店铺信息</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"data-店铺信息\">data 店铺信息</h2>\n<p>店铺对象包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>shopName</td>\n<td>string</td>\n<td>商店名称</td>\n</tr>\n<tr>\n<td>balance</td>\n<td>float</td>\n<td>账户余额</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["shared","commodity","orderList"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"0ff425c9-38b1-46ed-b0d3-499a32adb781"},{"name":"下载卡密","event":[{"listen":"prerequest","script":{"exec":["// 初始化一个空对象来存储POST参数\r","let postData = {};\r","pm.request.body.urlencoded.each((param) => {\r","    postData[param.key] = param.value;\r","});\r","\r","// 检查app_key是否存在\r","if (!postData.hasOwnProperty('app_key') || postData['app_key'] === '') {\r","    throw new Error(\"app_key is missing from the POST parameters.\");\r","}\r","\r","let appKey = postData['app_key']; // 从POST参数中获取appKey\r","\r","// 删除sign键（如果存在）\r","if (postData.hasOwnProperty('sign')) {\r","    delete postData['sign'];\r","}\r","\r","// 对postData的键进行排序并构建查询字符串\r","let sortedKeys = Object.keys(postData).sort();\r","let queryString = \"\";\r","\r","sortedKeys.forEach((key, index) => {\r","    if (postData[key] !== null && postData[key] !== \"\") {\r","        queryString += `${encodeURIComponent(key)}=${encodeURIComponent(postData[key])}${index < sortedKeys.length - 1 ? '&' : ''}`;\r","    }\r","});\r","\r","// 添加appKey\r","queryString += `&key=${appKey}`;\r","\r","// 计算MD5\r","const crypto = require('crypto-js');\r","let hash = crypto.MD5(decodeURIComponent(queryString)).toString(crypto.enc.Hex).toLowerCase();\r","\r","console.log(\"Generated Signature: \" + hash);\r","\r","// 将sign添加到POST参数中\r","pm.request.body.urlencoded.add({key: \"sign\", value: hash});"],"type":"text/javascript","packages":{},"id":"f1e22234-e6b6-4851-817f-50d0242e7816"}}],"id":"38aa590e-eea0-4fea-b261-19fc7eea46c5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"app_id","value":"3028","description":"<p>商户ID</p>\n","type":"text"},{"key":"app_key","value":"634F790AA82F0015","description":"<p>商户密钥</p>\n","type":"text"},{"key":"sign","value":"","description":"<p>算法请参考文档或者Pre-request Script</p>\n","type":"text"},{"key":"id","value":"190575","description":"<p>订单ID</p>\n","type":"text"}]},"url":"{{host}}/shared/commodity/secretDownload","description":"<h1 id=\"查询余额返回数据说明\">查询余额返回数据说明</h1>\n<ul>\n<li>查询余额</li>\n<li>测试通讯</li>\n</ul>\n<p>接口成功返回的基础信息包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>code</td>\n<td>int</td>\n<td>状态码，200 表示成功</td>\n</tr>\n<tr>\n<td>msg</td>\n<td>string</td>\n<td>响应消息</td>\n</tr>\n<tr>\n<td>data</td>\n<td>object</td>\n<td>店铺信息</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"data-店铺信息\">data 店铺信息</h2>\n<p>店铺对象包含以下字段：</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>字段名称</th>\n<th>类型</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>shopName</td>\n<td>string</td>\n<td>商店名称</td>\n</tr>\n<tr>\n<td>balance</td>\n<td>float</td>\n<td>账户余额</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["shared","commodity","secretDownload"],"host":["{{host}}"],"query":[],"variable":[]}},"response":[],"_postman_id":"38aa590e-eea0-4fea-b261-19fc7eea46c5"}]}