fastapi(十六)-依赖关系

基于若依RuoYi-Vue3-FastAPI 的 Docker 部署记录 最近在参与导师项目开发过程中,我选择基于作为系统框架,通过 Docker 实现前后端、数据库和缓存环境的容器化部署。 阅读详情

fastapi是一个非常强大而又直观的依赖注入系统
它被设计得使用起来非常简单,同时让开发人员可以轻松得将其他组件与fastapi集成在一起。
什么时依赖注入
依赖注入意味着在编码得时候,在你得代码中会留一条通道给你去声明需要用到依赖,(即:要想你得代码成功运行必须得先成功运行依赖函数。有点类似于装饰器)
在你做以下操作得时候将会非常有用:

  • 使用共享逻辑(一遍又一遍得使用相同得代码)
  • 共享数据连接
  • 强制安全,授权,角色需要等

第一步:
让我们先看一个例子,这个例子在实际应用中根本没什么用,但是可以关注一下依赖注入是如何运行得。
首先建立被依赖得函数,它仅仅是一个函数它可以拥有所有得路径函数得参数

from fastapi import Depends, FastAPI

app = FastAPI()


async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
    return {"q": q, "skip": skip, "limit": limit}


@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    return commons


@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
    return commons

它和路径操作函数拥有相同得结构,你甚至可以理解为,它就是没有装饰器得路径操作函数。
并且它可以返回你想要得任何东西,
在这个例子中被依赖函数将希望接收:
1、一个可选择得查询参数q,str类型
2、一个带有默认值为0得skip查询参数,int类型
3、一个带有默认值为100得limit查询参数,int类型
然后将他们转换为字典再返回

声明依赖,
依赖得声明就和Body,Query等一样,需要使用Depends。
但是他们也有一些不同得地方:
depends中只有一个被依赖得参数,
无论什么时候请求到达后,fastapi将做一下操作:
1、调用依赖函数,并使用正确得参数。
2、从函数中得到返回。
3、分配返回结果给你得路径操作函数得参数。

简单得使用
和所有得web框架一样,路径操作函数被声明来匹配路径,然后fastapi将调用函数并传入正确得参数,并处理响应。
你并不会直接得调用这些函数,他们被框架调用。
在依赖注入系统中,你可以告诉fastapi你得路径操作函数依赖于其他得东西。并且fastapi将自动处理并注入结果。
其它使用依赖注入思想的条目:

  • resource
  • providers
  • services
  • injectables
  • components

简单而强大
尽管依赖注入系统定义和使用上都非常简单,但是它却非常的强大。
你可以嵌套依赖,
最后,构建了层次结构的依赖关系树,并且依赖关系注入系统将为您解决所有这些依赖关系(及其子依赖关系)并在每个步骤中提供(注入)结果。

例如,假设您有4个API端点(path操作):

/items/public/
/items/private/
/users/{user_id}/activate
/items/pro/
那么您可以为每个依赖项和子依赖项添加不同的权限要求:

在这里插入图片描述
类作为依赖项
直到现在,所使用的都是依赖被声明为函数。
但是那并不是唯一的依赖声明。
实际上依赖只要能被“callable”就行。
在python中这叫鸭子类型,只要实现了__call__()函数的所有类型都可以是callable。

from fastapi import Depends, FastAPI

app = FastAPI()


fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


class CommonQueryParams:
    def __init__(self, q: str = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit


@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip : commons.skip + commons.limit]
    response.update({"items": items})
    return response

这些类中的初始化参数都是从requests中获得。

type annotation vs depends

以上的例子中commons定义:
commons: CommonQueryParams=Depends(CommonQueryParams)

实际可以使用:
commons=Depends(CommonQueryParams)
以及:
commons: CommonQueryParams = Depends()
都是一样的效果。

子依赖
你可以创建依赖嵌套,而且想嵌套多少层都可以。
eg:

from fastapi import Cookie, Depends, FastAPI

app = FastAPI()


def query_extractor(q: str = None):
    return q


def query_or_cookie_extractor(
    q: str = Depends(query_extractor), last_query: str = Cookie(None)
):
    if not q:
        return last_query
    return q


@app.get("/items/")
async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):
    return {"q_or_cookie": query_or_default}

多次使用相同依赖
例如,如果为同一个路径操作多次声明一个依赖项,例如,多个依赖项具有一个公共的子依赖项,则FastAPI将知道每个请求仅调用一次该子依赖项。

并且它将返回的值保存在“缓存”中,并将其传递给该特定请求中需要它的所有“依赖项”,而不是针对同一请求多次调用依赖项。

在高级场景中,您需要在同一请求中的每个步骤(可能多次)上调用依赖项,而不是使用“ cached”值,可以use_cache=False在使用时设置参数Depends:

async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
return {“fresh_value”: fresh_value}

依赖在路径操作装饰器中

有时候你的依赖中其实并不需要返回值。在这种情况下你可以将依赖添加到路径操作装饰器中的list。

from fastapi import Depends, FastAPI, Header, HTTPException

app = FastAPI()


async def verify_token(x_token: str = Header(...)):
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="X-Token header invalid")


async def verify_key(x_key: str = Header(...)):
    if x_key != "fake-super-secret-key":
        raise HTTPException(status_code=400, detail="X-Key header invalid")
    return x_key


@app.get("/items/", dependencies=[Depends(verify_token), Depends(verify_key)])
async def read_items():
    return [{"item": "Foo"}, {"item": "Bar"}]

这些依赖将会被执行,但是他们的返回值将不会传入路径操作函数中。
Dependencies with yield
fastapi支持依赖在结束的时候执行一些额外的步骤。
为了实现此功能,需要将return换成yield,然后写入额外的步骤。
例如:
你可以创建数据库连接然后在完成的时候关闭它。

async def get_db():
    db = DBSession()
    try:
        yield db
    finally:
        db.close()

Dependencies with yield and HTTPException

上一个例子中你可以看到,可以使用yield语句并且使用try去捕获异常。
你也许想要去抛出HTTPException或退出码,在yeild中,但是这将不会起作用。
在这里插入图片描述
只有一种response将会被发送到客户端,那就是error response 或者路径操作的response。一旦这些response被发送后,其他的response将不会被发送到客户端。

上下文管理器

什么是上下文管理器,其实就是多有的可以使用with语句的python对象:

with open("./somefile.txt") as f:
    contents = f.read()
    print(contents)

当with 块结束后,可以保证关闭文件,即使有异常。

当你使用yield语句创建依赖,fastapi将会在内部将它转换为上下文管理器,并将它与其他一些相关联的工具相结合。
Using context managers in dependencies with yield
在python中你可以创建上下文管理器,通过在对象内部定义__enter__()和__exit__()方法。

class MySuperContextManager:
    def __init__(self):
        self.db = DBSession()

    def __enter__(self):
        return self.db

    def __exit__(self, exc_type, exc_value, traceback):
        self.db.close()


async def get_db():
    with MySuperContextManager() as db:
        yield db

你也可以在fastapi中的with或者async with语句中使用yield来定义依赖函数。
其他的定义上下文管理器的方式:
@contextlib.contextmanager
@contextlib.asynccontextmanager
使用这些装饰器并使用yield做返回。但是在fastapi中你不需要使用装饰器,直接使用yield语句。

高级依赖
参数依赖
我们看到的所有依赖项都是固定的函数或类。
但是在某些情况下,您可能希望能够在依赖项上设置参数,而不必声明许多不同的函数或类。
假设我们想要一个依赖项来检查查询参数是否q包含一些固定内容。
但是我们希望能够参数化该固定内容。

from fastapi import Depends, FastAPI

app = FastAPI()


class FixedContentQueryChecker:
    def __init__(self, fixed_content: str):
        self.fixed_content = fixed_content

    def __call__(self, q: str = ""):
        if q:
            return self.fixed_content in q
        return False


checker = FixedContentQueryChecker("bar")


@app.get("/query-checker/")
async def read_query_check(fixed_content_included: bool = Depends(checker)):
    return {"fixed_content_in_query": fixed_content_included}

__call__就是FastAPI将用于检查其他参数和子依赖项的方法,并且稍后将调用该方法将值传递给路径操作函数中的参数。

Matlab2018a崩溃解决的办法No sandbox or build area path Matlab 2018a (No sandbox or build area path)出现崩溃后需要使用terminal进行如下操作: cd /home/david/MySoft/MATLAB/R2018a/bin/glnxa64 (你的matlab路径) mkdir exclude mv libfreetype* exclude/ 执行后图片如下: 如果你用的Windows系统,请手动按照上面步骤剔除了dll。 Matlab 2018a (No sandbox or build are 阅读详情

相关推荐

CSR-DCF视频目标跟踪源码运行笔记

论文基本信息 论文标题:Discriminative Correlation Filter with Channel and Spatial Reliability 论文作者:Alan Lukezic等 论文出处:CVPR 2017 文章链接:https://arxiv.org/abs/1611.08461 补充材料:https://www.semanticscholar.org/paper/D...

越野者的博客 3400

基于python FastAPI + Vue的一套CMS开源源码模板

FastAPI-Vue是个人开发并使用的CURD模板之一,代码功能不难,主要是减少浪费时间在用户系统的开发。fastAPI的性能在Python中还算挺不错的,使用起来也很方便。github上也有其他fastAPI和vue组合的代码,个人觉得不是很符合我自己,然后就自己开发了一套,现开源共享出来。后端项目的目录结构借鉴了Django的目录结构。前端Vue代码使用了Ruoyi的Vue代码。大部分功能和若依相似,但是在原基础上删除了我个人认为用得很少的 部门 模块。

sinat_34149445的博客 1万+

OpenCode:终端开源AI编程助手,多模型接入与实战指南

AI编程助手正在从IDE侧边栏走向终端环境。其核心原理是让模型直接读取项目文件、执行命令、查看报错,形成从诊断到修复的完整闭环,从而解决传统插件上下文割裂的问题。技术价值在于开源透明、模型无关,既可接入OpenAI等云端服务,也能通过Ollama连接本地模型,兼顾数据安全与离线场景。在工程实践中,它适用于长时间驻留项目、自动修Bug、团队统一AI工具链等需求。OpenCode正是这样一款终端AI助手,支持灵活配置第三方API密钥,提供免费档与Go套餐,并通过Skills技能系统让模型遵循标准操作流程。同时,

weixin_28745821的博客 327

RuoYi-Vue(前后端分离板)数据权限控制示例

部门编号应该是106,需要与sys_dept 部门表对应的,这里我写错了。这里使用若依的代码生成功能实现,生成代码完成后根据需要修改一下代码即可。因为两个用户都是普通角色,所以修改普通角色的数据权限就可以了。设置ry用户和lewis用户的权限为只能看本部门及以下权限。在若依的数据库中建立设备表:equipment。关于生成代码的使用可以参考我的这篇博客。admin用户具有超级权限,不需要设置。Mapper层增加数据过滤。主要使用这三个用户进行测试。service层增加代码。admin用户添加数据。

qq_64042847的博客 1055

GNSS-RTK/INS紧组合里,那个‘杆臂改正’到底怎么算?一个公式讲清INS与天线位置的关系

本文深入解析GNSS-RTK/INS紧组合导航系统中的杆臂改正(Lever Arm Correction)原理与实现方法。详细介绍了杆臂效应的物理本质、数学建模及误差扰动分析,揭示了IMU与GNSS天线位置关系的核心公式,并提供了工程实现中的常见误区与验证方法。通过Python代码示例和紧组合量测模型处理流程,帮助开发者准确理解并应用这一关键技术。

weixin_33137081的博客 357

【ORB_SLAM系列4】—— 一文搞定如何在Ubuntu20.04中安装运行ORB_SLAM3(包含ROS版本和非ROS版本)

ORB-SLAM3是一款基于特征点的实时单目SLAM系统,是SLAM领域的研究热点之一。它的核心算法是结合了ORB特征点提取和描述子匹配、单目RGB相机的深度估计、运动估计和地图优化等步骤,能够在实时性和精度之间取得平衡,适用于各种环境下的定位和建图任务。在各种应用领域都有广泛的应用。本教程主要是介绍了关于在ubuntu20.04中运行ORB_SLAM3的所有依赖的库的安装过程,和所遇到的一些报错的解决方法。有什么问题,可以评论区里面交流讨论

2401_82458959的博客 5039

【免费下载】 RuoYi-Vue3-FastAPI:基于Vue3与FastAPI的高效后台管理系统搭建教程

**RuoYi-Vue3-FastAPI** 是一个整合了现代前端技术 Vue.js 3 和高性能后端框架 FastAPI 的开源项目。该项目旨在提供一个快速开发企业级应用的解决方案,它继承了 RuoYi 系列的传统优势,同时利用 Vue3 的新特性以及 FastAPI 的简洁高效,实现了前后端分离的高性能Web应用框架。该项目特别适合那些寻求快速构建可扩展、安全且交互性强的管理系统的开发者。

gitblog_00401的博客 3120

JAVA + 海康威视SDK + FFmpeg+ SRS 实现海康威视摄像头二次开发

海康威视SDK接入方案摘要 本文介绍了使用海康威视官方SDK开发物联网平台摄像头接入功能的完整方案。系统采用Java后端集成HCNetSDK控制摄像头,通过FFmpeg将RTSP流转为RTMP推送到SRS流媒体服务器,前端基于HTTP-FLV协议实现视频播放。文章详细说明了开发准备工作,包括SDK下载、SRS部署、FFmpeg安装等关键步骤,并提供了数据库表设计和接口定义。核心部分展示了如何集成海康SDK,包括提取必要代码、加载DLL文件、配置打包插件等具体实现细节,最终形成了一套支持实时预览、回放和下载的

2401_83057947的博客 2265

RuoYi-Vue3-FastAPI框架的功能实现(上)

RuoYi-Vue3-FastAPI框架是一个基于Vue2+ElementUI+FastAPI开发的中后台管理框架,支持代码生成开发。本文档详细介绍了该框架的安装与运行步骤,包括前端和后端的配置与启动。前端部分涉及依赖安装和服务启动,后端部分则包括数据库配置、依赖安装和运行。文档还提供了代码生成功能的实现方法,包括数据库表的建立、代码生成界面的操作、前后端文件的复制与路由配置,以及菜单管理的编辑。通过这些步骤,用户可以快速搭建和定制自己的中后台管理系统,实现表单生成、数据更新等功能。

Single_minde的博客 2799

ArcGIS基础:点要素分割线要素和提取线要素的交点

第一个实验:【点要素分割线要素】看下原始数据:下图所示,2个红点和一条绿线,用2个点去分割这条线。 找到【数据管理工具】,在找到【要素】,再找到【在点处分割线】,如下图所示。 输入线、点要素,然后在【搜索半径】里输入5米,查看一下结果。 查看结果发现,线段被分割了2段,我们查看一下原因。 发现第2个点与线有一段距离,肯定是大于5米的,所以分割没有成功。可以量测一下距离,重新输入搜索半径。 我们把搜索半径改为200米,勘察结果,被点分割了3段。 接下来使用另外一个工具【在折点处分割线】,如下所示。

yuanYW7556的博客 1万+

基于STM32的智能婴儿床设计(蓝牙通信+摄像头监控)_315

本项目设计并实现了一款基于STM32微控制器的智能婴儿床系统,通过多种传感器和智能控制模块为家长提供更便捷和高效的婴儿照护解决方案。系统包括婴儿哭泣检测、湿度监测、空气质量检测、温度监控等多项功能,并通过蓝牙与手机APP进行数据传输和远程控制。婴儿床内置摇摇床和安抚音乐播放功能,能够在婴儿哭泣时自动启动摇摇床并播放安抚音乐。此外,系统还支持摄像头远程监控,让家长实时查看婴儿的状态。整个系统采用STM32F103RCT6作为核心控制单元,结合声音传感器、湿度传感器、MQ135空气质量传感器。

865

基于Python的FastAPI后端开发框架如何使用(十六)

我在随笔《》中介绍过如何使用PyInstaller 进行打包处理的一些过程和事项。我们基于Python的FastAPI后端应用,在实际开发的时候,直接运行main.py 进行调试即可,但是部署的时候,我们就需要把它们进行打包处理,这里首选PyInstaller 进行打包。本文详细介绍了,使其能够在目标环境中以独立可执行文件的形式运行,无需安装 Python 解释器或额外依赖。文章面向希望将 FastAPI 服务打包为独立运行服务的开发者,特别适用于企业内部系统或需要简化部署的场景。

xzaTfLt7f的博客 1008

Wi-Fi物理帧间隔概念简介

物理帧间隔概念简介。

1042484520@qq.com(邮箱) 1779

FastAPI 学习之路(十六)Form表单

Form表单

mr~li的博客 1335

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

FastAPI 学习之路(五十六)将token缓存到redis

在之前的文章中,FastAPI 学习之路(二十九)使用(哈希)密码和 JWT Bearer 令牌的 OAuth2,FastAPI 学习之路(二十八)使用密码和 Bearer 的简单 OAuth2,FastAPI 学习之路(三十四)数据库多表操作,我们分享了基于jwt认证token和基于数据库创建用户,那么我们今天把这些代码整理下,形成基于数据库用户名密码,登陆验证token存储到redis中。实际上就是把之前的方法柔和到新的方法中,需要调整下之前的创建用户,把登录实现了。接下来,我们调用登录api。

mr~li的博客 1214

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

FastAPI框架入门教程

FastAPI 凭借四大核心优势成为 Python API 开发的优选:其一,依托类型提示与自动文档功能,大幅减少重复工作,提升开发效率;其二,采用异步架构,具备优异的高并发处理能力,适配生产环境需求;其三,社区生态快速增长,兼容 Starlette 与 Pydantic 扩展,扩展性强;其四,学习门槛低,Python 开发者掌握基础类型提示即可快速构建 API。

stc_ljc的博客 1434

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Python开发从入门到精通:Web框架FastAPI实战

本文介绍了Python Web框架FastAPI的实战应用,重点内容包括:FastAPI的高性能特性、简单易用的API设计、自动文档生成功能;快速入门指南展示了如何创建第一个FastAPI应用并运行;详细讲解了路由定义(基本路由、路径参数、查询参数、请求体)、请求处理(表单数据、文件上传)、响应处理(状态码、响应模型、错误处理);还介绍了中间件实现和依赖注入机制。通过具体代码示例,帮助开发者快速掌握FastAPI的核心功能,适合从入门到精通的系统学习。

编程世界如山海,探索不止。 1万+

FastAPI 学习之路(二十六)全局依赖项

fastapi全局依赖

mr~li的博客 886

FastAPI 学习之路(三十六)引入APIRouter

我们可以使用APIRouter来声明路径操作,我们先看下如何去使用。 我们根据选择划分为users和items来细分。具体实现如下:①先看items实现 下面是users的实现方式 我们最后看下main文件 其中,我们暂时把create_db方法提取到__init__.py中,否则会引起循环引用的错误,如下: 重新启动我们的服务,测试下是否可以我们的接口请求还是正确的,证明我们的改造是没有问题的。如果想要给每一个路由都加一个通用的路径前缀标识,并且每个都有对应的tag,如下即可实现:

mr~li的博客 514

fastapi-依赖注入

如何用最简单的方式解释依赖注入?依赖注入是如何实现解耦的? FastApi学习-06 fastapi(十六)-依赖关系 fastapi教程-进阶九(Dependencies-1) 什么是依赖注入 依赖注入听起来好像很复杂,但是实际上炒鸡简单,一句话说就是:本来我接受各种参数来构造一个对象,现在只接受一个参数——已经实例化的对象。 也就是说我对对象的『依赖』是注入进来的,而和它的构造方式解耦了。构造它这个『控制』操作也交给了第三方,也就是控制反转。 不举抽象的什么造汽车或者小明玩儿手机的例子了。一个很实际的例

xys430381_1的专栏 1487

FastAPI框架对包含特殊字符的URL的转码处理

监控页的URL:“https://live.polyv.net/#/channel/2357792/monitoring-v3” 这个URL本身是没啥问题的,比较特别的无非是中间多了个’#‘号,呵, 问题就出在’#'号上!--------后端框架FastAPI的URL解析器会将其视为截断,于是URL截断成了"https://live.polyv.net/",后续流程旧报错了。 于是我们编写一个函数来对目标字符进行查询,如果属于特定字符,则返回:%加上该字符的ASCII 十六进制编码 def do_you_n

梦马韶华 1326

fastapi教程翻译(搬运自用)

fastapi教程翻译(一):了解FastAPI结构 fastapi教程翻译(二):Path参数 fastapi教程翻译(三):Query参数 fastapi教程翻译(四):Request Body(请求体) fastapi教程翻译(五):Query参数 & 字符串验证 fastapi教程翻译(六):Path参数 & 数值验证 fastapi教程翻译(七):Body -...

恰排骨芸豆包嘛的博客 2891

fastapi官方文档翻译 -目录

fastapi官方文档翻译 warmsirius 最新发布 最新评论 目录 fastapi教程翻译(前言):安装和运行 fastapi教程翻译(一):了解FastAPI结构 fastapi教程翻译(二):Path参数 fastapi教程翻译(三):Query参数 fastapi教程翻译(四):Request Body(请求体) fastapi教程翻译(五):Query参数 &amp...

Hiking_Yu的专栏 1万+

从请求到响应:把 Python 的 FastAPI 和 Uvicorn 讲透

这不是一篇“照着官网抄一遍 Hello World”的入门文。 如果你想真正搞明白:FastAPI 到底解决了什么问题、Uvicorn 到底扮演什么角色、两者如何配合、项目上线时该怎么设计与避坑,那这篇文章就是写给你的。

jiet_h的博客 938

Awesome FastAPI二维码生成:Segno与服务集成

你是否还在为项目中的二维码生成功能繁琐配置而烦恼?是否需要一个轻量级、高性能的二维码解决方案?本文将带你通过FastAPI与Segno库快速构建企业级二维码服务,无需复杂依赖,5分钟即可上线可用。读完本文你将掌握:Segno核心特性与安装、FastAPI接口设计最佳实践、参数化二维码生成技巧,以及完整服务部署方案。 ## Segno:轻量级二维码生成引擎 Segno是一个纯Python编写的二...

gitblog_00463的博客 1070

FastAPI 从入门到精通 — 完整实战教程

《FastAPI从入门到生产环境实战指南》 摘要: 本文全面讲解FastAPI框架的核心知识点,提供从零开始的完整学习路径。内容涵盖环境搭建、路由参数、请求体验证、数据库集成、JWT认证、WebSocket等核心功能,每个概念均配有可运行的代码示例。通过对比Flask/Django等框架,突出FastAPI在性能(基于Starlette)、开发效率(自动文档生成)和类型安全(Pydantic驱动)方面的优势。文章采用渐进式结构,从基础API开发到生产级项目部署(Docker+Gunicorn),包含测试、错

r13574651213的博客 568
上一篇: fastapi(十五)-Body update
下一篇: fastapi(十七)-安全
vanexph
博客等级 码龄15年 4015粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值