@@ -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> | |||
</template> | |||
<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-group> | |||
</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: "/", | |||
component: Layout, | |||
redirect: "/myRecharge", | |||
@@ -210,6 +193,17 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
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> |