在共享大型数据集或向客户与合作伙伴交付生产数据等场景下,若希望将访问数据所产生的流量和请求费用等转移给请求者,可以为存储空间(Bucket)开启请求者付费模式。该模式会将数据访问成本(如流量、请求次数)完全由请求者承担,Bucket 拥有者则仅需支付存储等固定费用。
无地域属性存储空间不支持开启请求者付费模式。
工作原理
请求者付费模式的核心是将特定操作的费用归属从 Bucket 拥有者转移到发起请求的请求者。开启请求者付费模式后,匿名访问将被禁用,所有请求必须经过身份验证。OSS 按以下逻辑处理请求:
请求中包含
x-oss-request-payer: requester请求头:OSS 对请求者进行身份验证,流量和请求等费用由请求者承担。请求中不包含
x-oss-request-payer: requester请求头请求者为 Bucket 拥有者:请求成功,费用由 Bucket 所有者承担。
请求者非 Bucket 拥有者:请求被拒绝。
Bucket 拥有者配置请求者付费
步骤一:开启请求者付费
控制台
登录OSS管理控制台。
单击Bucket 列表,然后单击目标Bucket名称。
在左侧导航栏,选择。
在请求者付费页面,打开请求者付费开关。
在弹出的对话框,单击确定。
SDK
以下仅列举常见SDK的设置请求者付费模式的代码示例。关于其他SDK的设置请求者付费模式的代码示例,请参见SDK简介。
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
public class Demo {
    public static void main(String[] args) throws Exception{
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";
        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();
        try {
            // 设置请求者付费模式。
            Payer payer = Payer.Requester;
            ossClient.setBucketRequestPayment(bucketName, payer);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (Throwable ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            // 关闭OSSClient。
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}const OSS = require('ali-oss')
const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // yourBucketName填写Bucket名称。
  bucket: 'yourBucketName',
});
async function setBucketRequestPayment(bucket, Payer) {
  try {
    // bucket填写需要设置请求者付费模式的存储空间名称。
    // Payer取值为Requester或BucketOwner。
    // Payer设置为Requester,表明该存储空间已开启请求者付费模式,由请求者支付读取存储空间(Bucket)内数据时产生的流量费用和请求费用。
    // Payer设置为BucketOwner,表明该存储空间不开启请求者付费模式(默认状态),即请求产生的费用由数据拥有者(BucketOwner)来支付。
    const result = await client.putBucketRequestPayment(bucket, Payer);
    console.log(result);
  } catch (e) {
    console.log(e);
  }
}
setBucketRequestPayment('bucketName', 'Requester')using Aliyun.OSS;
using Aliyun.OSS.Common;
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称。
var bucketName = "examplebucket";
// 填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。
const string region = "cn-hangzhou";
// 创建ClientConfiguration实例,按照您的需要修改默认参数。
var conf = new ClientConfiguration();
// 设置v4签名。
conf.SignatureVersion = SignatureVersion.V4;
// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
    // 设置请求者付费模式。
    var request = new SetBucketRequestPaymentRequest(bucketName, RequestPayer.Requester);
    client.SetBucketRequestPayment(request);
    Console.WriteLine("Set bucket:{0} RequestPayment succeeded ", bucketName);
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
    /*初始化OSS账号信息。*/
    
    /*yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    
    / *yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn - hangzhou。 * /
    std::string Region = "yourRegion";
    
    /*填写Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";
    /*初始化网络等资源。*/
    InitializeSdk();
    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);
    /*设置请求者付费模式。*/
    SetBucketRequestPaymentRequest request(BucketName);
    request.setRequestPayer(RequestPayer::Requester);
    auto outcome = client.SetBucketRequestPayment(request);
    if (!outcome.isSuccess()) {
        /*异常处理。*/
        std::cout << "SetBucketRequestPayment fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }
    /*释放网络等资源。*/
    ShutdownSdk();
    return 0;
}package main
import (
	"context"
	"flag"
	"log"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
// 定义全局变量
var (
	region     string // 存储区域
	bucketName string // 存储空间名称
)
// init函数用于初始化命令行参数
func init() {
	flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}
func main() {
	// 解析命令行参数
	flag.Parse()
	// 检查bucket名称是否为空
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}
	// 检查region是否为空
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}
	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)
	// 创建OSS客户端
	client := oss.NewClient(cfg)
	// 创建设置存储空间请求支付方式的请求
	putRequest := &oss.PutBucketRequestPaymentRequest{
		Bucket: oss.Ptr(bucketName), // 存储空间名称
		PaymentConfiguration: &oss.RequestPaymentConfiguration{
			Payer: oss.Requester, // 设置请求支付方为请求者
		},
	}
	// 发送设置存储空间请求支付方式的请求
	putResult, err := client.PutBucketRequestPayment(context.TODO(), putRequest)
	if err != nil {
		log.Fatalf("failed to put bucket request payment %v", err)
	}
	// 打印设置存储空间请求支付方式的结果
	log.Printf("put bucket request payment result:%#v\n", putResult)
}
import argparse
import alibabacloud_oss_v2 as oss
# 创建命令行参数解析器,并描述脚本用途:设置存储空间(Bucket)的请求支付配置
parser = argparse.ArgumentParser(description="put bucket request payment sample")
# 定义命令行参数,包括必需的区域、存储空间名称、可选的endpoint以及支付方
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--payer', help='Indicates who pays the download and request fees. Possible values: "Requester" or "BucketOwner"', required=True)
def main():
    # 解析命令行参数,获取用户输入的值
    args = parser.parse_args()
    # 从环境变量中加载访问凭证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    # 使用SDK默认配置创建配置对象,并设置认证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    # 设置配置对象的区域属性,根据用户提供的命令行参数
    cfg.region = args.region
    # 如果提供了自定义endpoint,则更新配置对象中的endpoint属性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint
    # 使用上述配置初始化OSS客户端,准备与OSS交互
    client = oss.Client(cfg)
    # 发送请求以设置指定存储空间的请求支付配置
    result = client.put_bucket_request_payment(oss.PutBucketRequestPaymentRequest(
            bucket=args.bucket,  # 存储空间名
            request_payment_configuration=oss.RequestPaymentConfiguration(
                payer=args.payer,  # 支付方,可以是 "Requester" 或 "BucketOwner"
            ),
    ))
    # 打印操作结果的状态码和请求ID,以便确认请求状态
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          )
# 当此脚本被直接执行时,调用main函数开始处理逻辑
if __name__ == "__main__":
    main()  # 脚本入口点,控制程序流程从这里开始<?php
require_once __DIR__ . '/../vendor/autoload.php'; // 引入自动加载文件,加载依赖库
use AlibabaCloud\Oss\V2 as Oss;
// 定义命令行参数描述
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // 地域是必填项,存储空间所在的地域,例如 oss-cn-hangzhou。
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 访问域名是可选项,其他服务可以用来访问OSS的域名。
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // 存储空间名称是必填项。
];
$longopts = \array_map(function ($key) {
    return "$key:"; // 每个参数后面加冒号,表示需要值
}, array_keys($optsdesc));
// 解析命令行参数
$options = getopt("", $longopts); 
// 检查必填参数是否缺失
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help'];
        echo "Error: the following arguments are required: --$key, $help"; // 提示用户缺少必填参数
        exit(1); 
    }
}
// 获取命令行参数值
$region = $options["region"]; // 存储空间所在地域。
$bucket = $options["bucket"]; // 存储空间名称。
// 使用环境变量加载凭证信息(AccessKeyId 和 AccessKeySecret)
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider(); 
// 使用SDK的默认配置
$cfg = Oss\Config::loadDefault(); // 加载SDK的默认配置。
$cfg->setCredentialsProvider($credentialsProvider); // 设置凭证提供者。
$cfg->setRegion($region); // 设置地域。
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // 如果提供了访问域名,则设置访问域名。
}
// 创建OSS客户端实例
$client = new Oss\Client($cfg); 
// 创建设置存储空间请求支付方式的请求对象
$request = new Oss\Models\PutBucketRequestPaymentRequest(
    $bucket,
    new Oss\Models\RequestPaymentConfiguration('Requester') 
);
// 调用putBucketRequestPayment方法设置存储空间请求支付方式
$result = $client->putBucketRequestPayment($request); 
// 打印返回结果
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP响应状态码。
    'request id:' . $result->requestId // 请求的唯一标识。
);
命令行工具ossutil
您可以使用命令行工具ossutil来设置请求者付费模式,ossutil的安装请参见安装ossutil。
以下示例展示了如何为存储空间examplebucket 设置请求者付费模式。
ossutil api put-bucket-request-payment --bucket examplebucket --request-payment-configuration "{\"Payer\":\"Requester\"}"如果您想了解该命令的更多信息,请参见put-bucket-request-payment。
API
如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutBucketRequestPayment。
步骤二:为请求者授予访问权限
通过Bucket Policy或 RAM policy 精确授权请求者访问您的数据。切勿将自己账号下的 RAM 用户 AccessKey 提供给对方,否则费用依然请求费用仍需要您(请求者)来支付。
如果请求者通过扮演 Bucket 拥有者账户下的RAM角色访问开启了请求者付费模式的Bucket,那么产生的费用将由请求者的账户承担。
请求者携带x-oss-request-payer头访问
当需要访问一个已开启请求者付费模式的 Bucket 时:必须携带x-oss-request-payer头信息以明确费用承担方。
应用于生产环境
预签名 URL 陷阱:
错误做法:由 Bucket 拥有者使用身份凭证(AccessKey 或 STS 临时凭证)生成预签名 URL 并对外分享。无论 URL 是否包含请求者付费参数,请求都会以Bucket 拥有者身份发起,相关费用由Bucket 拥有者承担。
正确做法:由请求方使用身份凭证(AccessKey 或 STS 临时凭证)生成预签名 URL。
兼容性风险:此功能与静态网站托管功能不兼容。开启请求者付费会破坏静态网站托管依赖的匿名访问机制,导致网站无法正常工作。
计费说明
Bucket开启请求者付费前,所有费用均由Bucket拥有者支付。Bucket开启请求者付费模式后,由Bucket拥有者支付的计费项将产生变化。Bucket拥有者以及请求者支付的详细说明如下:
费用  | 计费项  | 支付者  | 
标准存储(本地冗余)容量  | Bucket拥有者  | |
标准存储(同城冗余)容量  | Bucket拥有者  | |
低频访问(本地冗余)容量  | Bucket拥有者  | |
低频访问(同城冗余)容量  | Bucket拥有者  | |
归档(本地冗余)容量  | Bucket拥有者  | |
归档(同城冗余)容量  | Bucket拥有者  | |
冷归档(本地冗余)容量  | Bucket拥有者  | |
深度冷归档(本地冗余)容量  | Bucket拥有者  | |
低频访问(本地冗余)不足规定时长容量  | Bucket拥有者  | |
归档存储(本地冗余)不足规定时长容量  | Bucket拥有者  | |
归档存储(同城冗余)不足规定时长容量  | Bucket拥有者  | |
冷归档存储不足规定时长容量  | Bucket拥有者  | |
深度冷归档存储不足规定时长容量  | Bucket拥有者  | |
无地域属性存储容量  | Bucket拥有者  | |
外网流出流量  | 请求者  | |
外网流入流量  | 免费  | |
内网流出流量  | 免费  | |
内网流入流量  | 免费  | |
CDN回源流出流量  | 请求者  | |
跨区域复制流量  | Bucket拥有者  | |
①请求费用  | Put类型请求次数  | 请求者  | 
Get类型请求次数  | 请求者  | |
取回请求  | Bucket拥有者  | |
图片处理  | 请求者  | |
图片高级压缩  | Bucket拥有者  | |
视频截帧  | 请求者  | |
Select扫描数据量  | Bucket拥有者  | |
低频访问数据取回容量  | 请求者  | |
归档存储数据取回容量  | 请求者  | |
归档直读数据取回容量  | Bucket拥有者  | |
冷归档存储数据取回容量  | Bucket拥有者  | |
深度冷归档存储数据取回容量  | Bucket拥有者  | |
对象标签  | Bucket拥有者  | |
传输加速AccM2MIn  | Bucket拥有者  | |
传输加速AccM2MOut  | Bucket拥有者  | |
传输加速AccM2OIn  | Bucket拥有者  | |
传输加速AccM2OOut  | Bucket拥有者  | |
传输加速AccO2MIn  | Bucket拥有者  | |
传输加速AccO2MOut  | Bucket拥有者  | |
传输加速AccO2OIn  | Bucket拥有者  | |
传输加速AccO2OOut  | Bucket拥有者  | |
临时存储容量(本地冗余)  | Bucket拥有者  | |
高防资源预留费用  | Bucket拥有者  | |
高防资源提前释放费用  | Bucket拥有者  | |
高防流量防护费用  | Bucket拥有者  | |
高防请求防护费用  | Bucket拥有者  | |
Meta管理费  | 公测阶段,免费  | |
Bucket查询费  | 公测阶段,免费  | |
敏感数据保护扫描容量  | Bucket拥有者  | |
OSS加速器容量  | Bucket拥有者  | |
元数据管理  | Bucket拥有者  | |
跨区域复制RTC  | Bucket拥有者  | 
①如果请求者未在请求中(GET、HEAD或POST)声明请求者付费的请求头x-oss-request-payer,则由Bucket拥有者支付Put类和Get类请求次数费用。