@@ -0,0 +1,39 @@ | |||||
import request from "@/utils/request.js"; | |||||
/** | |||||
* @description 服务端api签名指南 | |||||
* @params | |||||
* @returns | |||||
*/ | |||||
export function getAvailableApiGuideApi() { | |||||
return request({ | |||||
url: `/api/apiGuide/getAvailableApiGuide`, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
/** | |||||
* @description 开放接口列表 | |||||
* @params | |||||
* @returns | |||||
*/ | |||||
export function apiMenuApi() { | |||||
return request({ | |||||
url: `/api/apiMenu/list`, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
/** | |||||
* @description 获取接口详情 | |||||
* @params | |||||
* @returns | |||||
*/ | |||||
export function getContentApi(id) { | |||||
return request({ | |||||
url: `/api/apiMenu/get?id=${id}`, | |||||
method: 'get' | |||||
}) | |||||
} |
@@ -62,7 +62,7 @@ | |||||
<span>{{ $t("cooperate.title") }}</span> | <span>{{ $t("cooperate.title") }}</span> | ||||
</template> | </template> | ||||
<el-menu-item-group> | <el-menu-item-group> | ||||
<el-menu-item index="1-1">{{ $t("cooperate.api.title") }}</el-menu-item> | |||||
<el-menu-item index="1-1" @click="router.push('/api')">{{ $t("cooperate.api.title") }}</el-menu-item> | |||||
<el-menu-item index="1-2" @click="router.push('/privatization')">{{ $t("cooperate.privatization.title") }} </el-menu-item> | <el-menu-item index="1-2" @click="router.push('/privatization')">{{ $t("cooperate.privatization.title") }} </el-menu-item> | ||||
</el-menu-item-group> | </el-menu-item-group> | ||||
</el-sub-menu> | </el-sub-menu> | ||||
@@ -109,23 +109,6 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||||
}, | }, | ||||
], | ], | ||||
}, { | }, { | ||||
path: "/", | |||||
component: Layout, | |||||
redirect: "/myAPI", | |||||
children: [ | |||||
{ | |||||
path: "myAPI", | |||||
component: () => import("@/views/myAPI/index.vue"), | |||||
name: "myAPI", | |||||
meta: { | |||||
title: "myAPI", | |||||
icon: "homepage", | |||||
affix: true, | |||||
name: "API.title", | |||||
}, | |||||
}, | |||||
], | |||||
},{ | |||||
path: "/", | path: "/", | ||||
component: Layout, | component: Layout, | ||||
redirect: "/myRecharge", | redirect: "/myRecharge", | ||||
@@ -210,6 +193,17 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||||
name: "separation.title", | name: "separation.title", | ||||
}, | }, | ||||
}, | }, | ||||
{ | |||||
path: "/api", | |||||
component: () => import("@/views/api/index.vue"), | |||||
name: "api", | |||||
meta: { | |||||
title: "api", | |||||
icon: "homepage", | |||||
affix: true, | |||||
name: "separation.title", | |||||
}, | |||||
}, | |||||
], | ], | ||||
}, | }, | ||||
@@ -0,0 +1,141 @@ | |||||
<!DOCTYPE html> | |||||
<html lang="en"> | |||||
<head> | |||||
<meta charset="UTF-8"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||||
<title>Document</title> | |||||
<style> | |||||
* { | |||||
padding: 0; | |||||
margin: 0; | |||||
} | |||||
.page { | |||||
padding: 50px | |||||
} | |||||
h1 { | |||||
font-size: 20px; | |||||
font-weight: 600; | |||||
margin-bottom: 0.8em; | |||||
} | |||||
p { | |||||
margin-bottom: 0.5em; | |||||
font-size: 14px; | |||||
line-height: 1.6; | |||||
} | |||||
.table { | |||||
margin-top: 50px; | |||||
} | |||||
.table .table-wrp { | |||||
margin: 1em 0 3em; | |||||
overflow-x: auto; | |||||
max-width: 100%; | |||||
} | |||||
.table table { | |||||
display: table; | |||||
width: 100%; | |||||
border-collapse: collapse; | |||||
border-spacing: 0; | |||||
overflow: auto; | |||||
font-size: 14px; | |||||
} | |||||
.table table th { | |||||
font-weight: 600; | |||||
text-align: left; | |||||
border-bottom: 1px solid #888; | |||||
padding: 10px 20px; | |||||
white-space: nowrap; | |||||
color: #888; | |||||
} | |||||
.table table td { | |||||
color: #353535; | |||||
text-align: left; | |||||
border-bottom: 1px solid #e5e5e5; | |||||
padding: 20px 20px; | |||||
height: 62px; | |||||
box-sizing: border-box; | |||||
word-break: normal; | |||||
} | |||||
.style .code{ | |||||
background-color: #f9f9fa; | |||||
margin: 1em 0; | |||||
border-radius: 4px | |||||
} | |||||
</style> | |||||
</head> | |||||
<body> | |||||
<div class="page"> | |||||
<!-- 文字 --> | |||||
<div class="text"> | |||||
<h1>概述</h1> | |||||
<p>在小程序管理后台开启api加密后,开发者需要对原APl的请求内容 加密 与签名,同时AP的回包内容需要开发者验签 与 解密 。支持的api可参考接口调用。</p> | |||||
<p>目前支持以下几种算法,可在MP管理页配置。</p> | |||||
</div> | |||||
<!-- 表格 --> | |||||
<div class="table"> | |||||
<h1>API请求处理</h1> | |||||
<div class="table-wrp"> | |||||
<table> | |||||
<thead> | |||||
<tr> | |||||
<th>参数</th> | |||||
<th>类型</th> | |||||
<th>默认值</th> | |||||
<th>必填</th> | |||||
<th>备注</th> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr> | |||||
<td>iv</td> | |||||
<td>string</td> | |||||
<td></td> | |||||
<td>是</td> | |||||
<td>初始向量,为16字节base64字符串(解码后为12字节随机字符串)</td> | |||||
</tr> | |||||
<tr> | |||||
<td>data</td> | |||||
<td>string</td> | |||||
<td></td> | |||||
<td>是</td> | |||||
<td>加密后的密文,使用base64编码</td> | |||||
</tr> | |||||
<tr> | |||||
<td>authtag</td> | |||||
<td>string</td> | |||||
<td></td> | |||||
<td>是</td> | |||||
<td>GCM模式输出的认证信息,使用base64编码</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</div> | |||||
<!-- 样式 --> | |||||
<div class="style"> | |||||
<h1>样式</h1> | |||||
<div class="code"> | |||||
<pre class="language-json"> | |||||
<code> | |||||
<span>{</span> | |||||
<span>"Sn"</span><span>:</span> <span>"fa05fe1e5bcc79b81ad5ad4b58acf787"</span><span>,</span> | |||||
<span>"Key"</span><span>:</span> <span>"otUpngOjU+nVQaWJIC3D/yMLV17RKaP6t4Ot9tbnzLY="</span> | |||||
<span>}</span> | |||||
</code> | |||||
</pre> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</body> | |||||
</html> |
@@ -0,0 +1,125 @@ | |||||
<template> | |||||
<div class="page"> | |||||
<div class=""> | |||||
<el-menu | |||||
default-active="1-1" | |||||
class="sidebar" | |||||
@open="handleOpen" | |||||
@close="handleClose" | |||||
> | |||||
<el-sub-menu index="1"> | |||||
<template #title> | |||||
<span>开发前必读</span> | |||||
</template> | |||||
<el-menu-item index="1-1" @click="guide">服务端API签名指南</el-menu-item> | |||||
</el-sub-menu> | |||||
<el-sub-menu index="2"> | |||||
<template #title> | |||||
<span>开发接口</span> | |||||
</template> | |||||
<el-menu-item v-for="item in apiMenuList" :key="item.id" :index="item.id" @click="getContent(item.id)">{{ item.name }}</el-menu-item> | |||||
</el-sub-menu> | |||||
</el-menu> | |||||
</div> | |||||
<div class="content"> | |||||
<div v-html="content"></div> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script setup> | |||||
import { getAvailableApiGuideApi, apiMenuApi, getContentApi } from '@/apis/api.js' | |||||
const handleOpen = (key, keyPath) => { | |||||
console.log(key, keyPath) | |||||
if (key === '2') { | |||||
getMenu() | |||||
} | |||||
} | |||||
const handleClose = (key, keyPath) => { | |||||
console.log(key, keyPath) | |||||
} | |||||
const content = ref(''); | |||||
// 签名指南 | |||||
const guide = () => { | |||||
getAvailableApiGuideApi().then(res => { | |||||
if(res.code === 200) { | |||||
content.value = res.data.content | |||||
} | |||||
}) | |||||
} | |||||
// 开发接口 | |||||
const apiMenuList = ref([]) | |||||
const getMenu = () => { | |||||
apiMenuApi().then(res => { | |||||
if (res.code === 200) { | |||||
apiMenuList.value = res.data | |||||
} | |||||
}) | |||||
} | |||||
// 详情 | |||||
const getContent = (id) => { | |||||
getContentApi(id).then(res => { | |||||
if (res.code === 200) { | |||||
content.value = res.data.content || '' | |||||
} | |||||
}) | |||||
} | |||||
onMounted(() => { | |||||
guide() | |||||
}); | |||||
</script> | |||||
<style> | |||||
.sidebar.el-menu--vertical .el-sub-menu__title:hover { | |||||
background-color: #fff !important; | |||||
} | |||||
.sidebar.el-menu--vertical .el-menu-item:hover { | |||||
background-color: #fff !important; | |||||
} | |||||
</style> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
display: flex; | |||||
width: 100%; | |||||
overflow: hidden; | |||||
overflow-y: scroll; | |||||
background-color: #f5f5f5; | |||||
border-radius: 25px 0 0 0; | |||||
min-height: calc(100vh - 80px); | |||||
// text-align: center; | |||||
.title { | |||||
font-size: 50px; | |||||
} | |||||
.sidebar { | |||||
position: absolute; | |||||
width: 340px; | |||||
top: 0; | |||||
bottom: 0; | |||||
overflow: auto; | |||||
padding: 40px 30px; | |||||
box-sizing: border-box; | |||||
z-index: 1; | |||||
} | |||||
.content{ | |||||
position: absolute; | |||||
left: 340px; | |||||
right: 0; | |||||
top: 0; | |||||
bottom:0; | |||||
background: #fff; | |||||
padding: 40px 30px; | |||||
overflow: auto; | |||||
} | |||||
} | |||||
:deep(.el-submenu .el-menu:hover) { | |||||
background: transparent; | |||||
color: #d75b5f; | |||||
} | |||||
</style> |
@@ -1,67 +0,0 @@ | |||||
<template> | |||||
<div class="page"> | |||||
<!-- <div class="title">{{ $t("API.comingSoon") }}</div> --> | |||||
<!-- 左侧名称 --> | |||||
<div class="left"> | |||||
<div class="scrollBox"> | |||||
<p>啊实打实大</p> | |||||
</div> | |||||
</div> | |||||
<!-- 右侧介绍 --> | |||||
<div class="right"> | |||||
<div class="scrollBox"></div> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script setup> | |||||
// import { ref } from 'vue' | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
display: flex; | |||||
width: 100%; | |||||
overflow: hidden; | |||||
overflow-y: scroll; | |||||
background-color: #f5f5f5; | |||||
border-radius: 25px 0 0 0; | |||||
min-height: calc(100vh - 80px); | |||||
// text-align: center; | |||||
.title { | |||||
font-size: 50px; | |||||
} | |||||
} | |||||
.left { | |||||
height: calc(100vh - 80px); | |||||
width: 30%; | |||||
padding: 30px 15px 30px 30px; | |||||
font-size: 20px; | |||||
background-color: #f5f5f5; | |||||
.scrollBox { | |||||
padding: 20px; | |||||
height: calc(100vh - 80px - 60px); | |||||
width: 100%; | |||||
overflow-y: scroll; | |||||
background-color: #fff; | |||||
border-radius: 20px; | |||||
box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px; | |||||
} | |||||
} | |||||
.right { | |||||
height: calc(100vh - 80px); | |||||
width: 80%; | |||||
padding: 30px 30px 30px 15px; | |||||
background-color: #f5f5f5; | |||||
.scrollBox { | |||||
padding: 20px; | |||||
height: calc(100vh - 80px - 60px); | |||||
width: 100%; | |||||
overflow-y: scroll; | |||||
background-color: #fff; | |||||
border-radius: 20px; | |||||
box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px; | |||||
} | |||||
} | |||||
</style> |