腾讯千帆云市场自动交付接入方案

简介

本文档描述了 SaaS 应用接入到云市场所需实现的接口定义,服务商通过提供以下接口,即可获得商品购买成功的信息,并将成功信息返回给云市场展示给用户。

术语信息

文中涉及相关术语解释如下:发货 URL: 由服务商开发,用于接收云市场实例相关消息的地址。 Token:由服务商提供,用于校验发货 URL 有效性(Token 应用于云市场和服务商间鉴权时使用,需谨慎保存)。openId:当服务商的应用接入腾讯云开放平台后,可获得的腾讯云用户的唯一标识。周期类商品:按周期计费的商品,例如:按年、月、日计费计量类商品:按时间或数量计费的商品,例如:100元/50分钟、100元/50次、100元/2000MB。

准备工作

在一个 SaaS 商品正式通过审核上架前,服务商需要进行以下准备工作:1. 云市场发货接口开发(必选)。2. 控制台的参数配置(必选)。3. 接入腾讯云 OAuth(可选)。

接口开发

接口要求

在进行接口开发前,请了解以下相关要求:

项目 说明
传输协议 仅支持 HTTPS 传输协议(443端口)
提交方式 均采用 POST 方法提交
数据格式 提交和响应均为 JSON 格式
字符编码 统一使用 UTF-8 字符编码
签名算法 SHA256
签名要求 云市场的通知会使用签名
请求超时时间 5s(为保证网络畅通,推荐接口层服务器使用腾讯云广州区域。)

服务商在控制台配置发货接口 URL 和 Token 后,云市场会以 URL PARAMS(GET 参数)的方式添加到接口 URL 上,携带的参数如下:

参数 类型 说明
signature String 加密签名,signature 结合了服务商填写的 Token 参数和请求中的 timestamp 参数、eventId 等参数。
timestamp Integer UNIX 时间戳(单位秒)
eventId Integer 随机数

接口调试规则

接口创建成功后需要进行对应的调试才可以发布接口,上架 SaaS 交付类商品。在服务商管理控制台的 在线接口调试 页面编辑调试 URL 和调试Token,并进行对应的接口调试,发布接口前必须将“创建实例”、“续费实例”、“实例过期”、“实例销毁”等接口调试成功,“实例配置变更”,“计量查询”、“预警设置”、“计量提醒”可选择性进行调试。“创建实例”、“续费实例”、“实例过期”、“实例销毁”这个四个接口是必须调试通过的,如果未调试通过会影响商品正常的销售。如果商品没有试用版,则可跳过“实例配置变更”接口调试。另如果没有发布计量类商品的需求,则可跳过“计量查询”、“预警设置”、“计量提醒”接口调试。接口调试通过后需点击发布接口按钮进行接口发布,发布后调试 URL 和调试 Token 信息会更新并保存到发货 URL 和发货 Token。

签名规则

服务商通过对 signature 进行校验(校验方式如下)。加密/校验流程如下:1. 判断 timestamp 是否已经超时(签名推荐超时为30s,免登校验推荐为120s)。2. 将 Token、timestamp、eventId 三个参数进行字典序排序。3. 将三个参数字符串,拼接成一个字符串进行 SHA256 加密。4. 服务商将加密后的字符串与 signature 对比即可。检验 signature 的 PHP 示例代码:

function checkSignature($signature, $token, $timestamp, $eventId){    $currentTimestamp = time();    if ($currentTimestamp - $timestamp > 30) {      return false;    }    $timestamp = (string)$timestamp;    $eventId = (string)$eventId;    $params = array($token, $timestamp, $eventId);    sort($params, SORT_STRING);    $str = implode('', $params);    $requestSignature = hash('sha256', $str);    return $signature === $requestSignature;}

接口验证过程



身份校验接口

接口名:verifyInterface。接口说明:用户在 云市场服务商管理控制台 更改发货 URL 和 Token 时,后台会调用接口 URL 对 Token 进行实时校验,校验通过才可以设置成功。

请求参数说明

参数名 类型 是否必须 描述
action String verifyInterface
requestId String 接口请求标识,主要应用于问题排查。
echoback String 随机字符串。

响应参数说明

参数名 类型 是否必须 描述
echoback String 请求中的 echoback 参数的值。

请求示例

curl -X POST -H 'Content-Type: application/json' 'https://{isv/interface}?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"verifyInterface","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a", "echoback":"Albert Einstein"}'

注意请求示例里的 {isv/interface} 需替换为服务商发货地址。

响应示例

{"echoback": "Albert Einstein"}

注意响应示例里的 echoback 应返回请求参数里的 echoback 值。

实例创建通知接口

接口名:createInstance。接口说明:用户购买商品并支付后,云市场将通过实例创建通知接口发送信息至发货 URL。

请求参数说明

参数名 类型 是否必须 描述
action String createInstance
orderId String 订单 ID。
accountId String 购买者的腾讯云账号 ID。
openId String 用户在腾讯云开放平台的标识,此标识对于同一服务商是相同的,对于不同服务商是不同的,长度为32位。如果没有接入开放平台,此字段为空。
productId Integer 云市场产品 ID。
resourceId String 云市场的实例 ID。
requestId String 接口请求标识,主要应用于问题排查。
productInfo JSON 产品信息。
productInfo.productName String 购买的产品名称。
productInfo.isTrial Bool 是否为试用,true:是;false:否。
productInfo.spec String 产品规格,是试用时为空。
productInfo.timeSpan Integer 购买时长,是试用时为空。
productInfo.timeUnit String 购买时长单位(y、m、d、h、t 分别代表年、月、日、时、次),是试用时为空。注:这里所描述的年、月为自然年、自然月的概念。举例:02月01日买的包月商品,03月01日到期
productInfo.flowSpan String 计量数量,仅当是计量类商品才存在。
productInfo.flowUnit String 计量单位,仅当是计量类商品才存在。
productInfo.cycleNum Integer 批量购买的规格数量,默认为1。
extendInfo JSON 扩展字段,支持 comment 等字段。
extendInfo.comment String 备注信息。

响应参数说明

参数名 类型 是否必须 描述
signId String 实例标识 ID,服务商侧的实例唯一标识。不可为空,长度最长为11位。当为”0″时,系统会认为是异步发货。异步发货下,云市场会一直重试该接口,直至返回非0。
appInfo JSON 应用信息。
appInfo.website String 服务商的网站。
appInfo.authUrl String 服务商提供给客户的免登地址。
additionalInfo JSON 自定义数据,会显示在实例详情中。格式为[{"name":"","value":""}]

请求示例

curl -X POST -H 'Content-Type: application/json' 'https://{isv/interface}?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"createInstance","orderId":"20170109199524","accountId":"123545678","openId":"xz_D4XL_u7hKY5zt","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a","productId":1024,"resourceId":"market-78123as","productInfo":{"productName":"云服务市场测试商品","isTrial":false,"spec":"普通版","timeSpan":2,"timeUnit":"m"}}'

响应示例

{"signId": "36441d902ba", "appInfo": {"website":"http://www.example.com", "authUrl": "http://www.example.com/oauth/login"},"additionalInfo":[{"name":"注意","value":"这是一条注意"},{"name":"说明","value":"这是说明"}]}

注意:服务商需保证该接口的幂等性。针对新购接口调用失败的情况,云市场会每隔1s、5s、10s、30s、1m、2m、3m、4m、5m、6m、7m、8m、9m、10m、20m、30m、1h、2h调用一次后停止调用。若服务商接口问题在4小时45分调用时间内解决,则在下一次调用接口响应成功,订单开通成功;若服务商接口问题在4小时45分调用后仍未解决,则判断实例创建失败,系统将自动取消该订单,并会为用户返还款项。

实例续费通知接口

接口名:renewInstance接口说明:用户续费商品后,云市场将通过实例续费通知接口发送消息至发货 URL。该接口需要服务商立即返回响应。

请求参数说明

参数名 类型 是否必须 描述
action String renewInstance
orderId String 订单 ID。
accountId String 购买者的腾讯云账号 ID。
openId String 用户在腾讯云开放平台的标识,此标识对于同一服务商是相同的,对于不同服务商是不同的,长度为32位;如果没有接入开放平台,此字段为空。
productId Integer 云市场产品 ID。
resourceId String 云市场的实例 ID。
requestId String 接口请求的 ID。
signId String 实例标识 ID。
instanceExpireTime DateTime 新的实例到期时间(yyyy-MM-dd HH:mm:ss)。
productInfo JSON 产品信息。
productInfo.productName String 购买的产品名称。
productInfo.spec String 产品规格。
productInfo.timeSpan Integer 购买时长。
productInfo.timeUnit String 购买时长单位(y、m、d、h、t 分别代表年、月、日、时、次)。注:这里所描述的年、月为自然年、自然月的概念。举例:02月01日买的包月商品,03月01日到期。
productInfo.flowSpan String 计量数量,仅当是计量类商品才存在。
productInfo.flowUnit String 计量单位,仅当是计量类商品才存在。
extendInfo JSON 扩展字段,支持 comment 等字段。
extendInfo.comment String 备注信息。

响应参数说明

参数名 类型 是否必须 描述
success String true/false

请求示例

curl -X POST -H 'Content-Type: application/json' 'https://{isv/interface}?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"renewInstance","orderId":"20170109199524","accountId":"123545678","openId":"xz_D4XL_u7hKY5zt","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a","productId":1024,"resourceId":"market-asd12asd","signId":"kjsadkjhdskjh3k","instanceExpireTime":"2017-02-09 19:59:59","productInfo":{"productName":"云服务市场测试商品","spec":"普通版","timeSpan":2,"timeUnit":"m"}}'

响应示例

{"success":"true"}

注意服务商需保证该接口的幂等性。

实例配置变更通知接口

接口名:modifyInstance。接口说明:用户将实例从试用版转为正式版时,云市场将通过实例配置变更通知接口发送消息至发货 URL。说明如果用户仅是配置变更,则参数中只会包含实例的新规格,而不会包含实例价格参数。

请求参数说明

参数名 类型 是否必须 描述
action String modifyInstance
orderId String 订单 ID。
accountId String 购买者的腾讯云账号 ID。
openId String 用户在腾讯云开放平台的标识,此标识对于同一服务商是相同的,对于不同服务商是不同的,长度为32位。如果没有接入开放平台,此字段为空。
productId Integer 云市场产品 ID。
requestId String 接口请求的 ID。
resourceId String 云市场的实例 ID。
signId String 实例标识 ID。
spec String 实例新规格。
timeSpan Integer 购买时长,仅在试用版转为正式购买时传递。
timeUnit String 购买时长单位(y、m、d、h、t 分别代表年、月、日、时、次),是试用时为空 。注:这里所描述的年、月为自然年、自然月的概念。
举例:02月01日买的包月商品,03月01日到期。
instanceExpireTime Datetime 新的实例到期时间,仅在试用版转为正式购买时传递。
productInfo JSON 产品信息。
productInfo.productName String 购买的产品名称。
productInfo.spec String 产品规格,与外层 spec 一致。
productInfo.timeSpan Integer 购买时长,与外层 timeSpan 一致。
productInfo.timeUnit String 购买时长单位(y、m、d、h、t 分别代表年、月、日、时、次),是试用时为空 。注:这里所描述的年、月为自然年、自然月的概念。
举例:02月01日买的包月商品,03月01日到期。
extendInfo JSON 扩展字段,支持 comment 等字段。
extendInfo.comment String 备注信息。

响应参数说明

参数名 类型 是否必须 描述
success String true/false
appInfo JSON 新的应用信息。
appInfo.authUrl String 新的免登地址。

请求示例

curl -X POST -H 'Content-Type: application/json' 'http://isv/interface?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"modifyInstance","orderId":"20170109199524","accountId":"123545678","openId":"xz_D4XL_u7hKY5zt","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a","productId":1024,"resourceId":"market-asd12asd","signId":"kjsadkjhdskjh3k","spec":"高级版","timeSpan":2,"timeUnit":"m","instanceExpireTime":"2021-02-09 19:59:59","productInfo":{"productName":"云服务市场测试商品","spec":"普通版","timeSpan":2,"timeUnit":"m"}}'

响应示例

{"success":"true"}

注意:服务商需保证该接口的幂等性。

实例过期通知接口

接口名:expireInstance。接口说明:实例到期后(用户最后操作后的 instanceExpireTime),云市场将通过实例过期通知接口发送消息至发 货URL,服务商收到该通知后需对资源进行隔离。

请求参数说明

参数名 类型 是否必须 描述
action String expireInstance
accountId String 购买者的腾讯云账号 ID。
openId String 用户在腾讯云开放平台的标识,此标识对于同一服务商是相同的,对于不同服务商是不同的,长度为32位。如果没有接入开放平台,此字段为空。
productId Integer 云市场产品 ID。
requestId String 接口请求标识。
resourceId String 云市场的实例 ID。
signId String 实例标识 ID,服务商提供的实例唯一标识。长度最长为11位。
orderId String 订单 ID。

响应参数规范

参数名 类型 是否必须 描述
success String true/false

请求示例

curl -X POST 'https://{isv/interface}?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"expireInstance","accountId":"123545678","openId":"xz_D4XL_u7hKY5zt","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a","productId":1024,"resourceId":"market-asd12","signId":"kjsadkjhdskjh3k", "orderId":"20170109199524"}'

响应示例

{"success":"true"}

注意:服务商需保证该接口的幂等性。服务商务必需要实现该接口,以便在实例过期时及时收到云市场通知,并对资源进行隔离。

实例销毁通知接口

接口名:destroyInstance。接口说明:当用户退款实例到期后的七天内用户没有进行续费操作时,云市场会通过实例销毁接口发送消息至发货 URL,服务商收到通知后应及时对资源进行回收。

请求参数说明

参数名 类型 是否必须 描述
action String destroyInstance
orderId String 订单 ID。
accountId String 购买者的腾讯云账号 ID。
openId String 用户在腾讯云开放平台的标识,此标识对于同一服务商是相同的,对于不同服务商是不同的,长度为32位。如果没有接入开放平台,此字段为空。
productId Integer 云市场产品 ID。
requestId String 接口请求标识。
resourceId String 云市场的实例 ID。
signId String 实例标识 ID,服务商提供的唯一标识。长度最长为11位。
destroyType String 销毁类型。refund:退款触发的销毁。lifeCycle:生命周期触发的销毁。

响应参数说明

参数名 类型 是否必须 描述
success String true/false

请求示例

curl -X POST 'https://{isv/interface}?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"destroyInstance","orderId":"20170109199524","accountId":"123545678","openId":"xz_D4XL_u7hKY5zt","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a","productId":1024,"resourceId":"market-asd12asd","signId":"kjsadkjhdskjh3k"}'

响应示例

{"success":"true"}

注意:服务商需保证该接口的幂等性。服务商务必需要实现该接口,以便在用户退款实例过期7天后及时收到云市场通知,并对资源进行回收。针对接口调用失败的情况,云市场会持续调用并告警7天后停止调用。如因接口响应失败,导致用户过期后仍能正常使用所造成的资源损失,由服务商自行承担。

计量商品计量信息查询接口

说明:该接口仅会应用于计量类 SaaS 商品。周期类商品不需实现该接口。接口名:flowQuery。接口说明:当用户查询已购买实例的计量信息时,云市场会通过该接口发送消息至服务商发货 URL 查询。

请求参数说明

参数名 类型 是否必须 描述
action String flowQuery
accountId String 购买者的腾讯云账号 ID。
openId String 用户在腾讯云开放平台的标识,此标识对于同一服务商是相同的,对于不同服务商是不同的,长度为32位。如果没有接入开放平台,此字段为空。
requestId String 接口请求标识。
resourceId String 云市场的实例 ID。
signId String 实例标识 ID,服务商提供的唯一标识。长度最长为11位。
productId Integer 云市场产品 ID。

响应参数说明

参数名 类型 是否必须 描述
success String true/false
totalFlow String 总流量。
costFlow String 已消耗流量,没有消耗时返回”0″。
flowUnit String 流量单位,取值范围m/h/Mb/Gb,分别代表分钟/小时/Mb/Gb。

请求示例

curl -X POST 'http://isv/interface?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"flowQuery","accountId":"123545678","openId ":"xz_D4XL_u7hKY5zt","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a","productId":1024,"resourceId":"market-4odto1yji","signId":"kjsadkjhdskjh3k"}'

响应示例

{"success":true,"totalFlow":"2000","costFlow":"600","flowUnit":"Mb"}

计量商品通知阈值设置接口

说明:该接口仅会应用于计量类 SaaS 商品。周期类商品不需实现该接口。接口名:flowSetting接口说明:计量类的商品用户在购买之后,可以通过此接口设置计量提醒阈值。云市场会通过该接口发送消息至发货 URL。接收到该通知后,服务商需记录该阈值,并且在阈值到达时回调云市场接口 计量商品流量告警通知接口 FlowProductRemind。

请求参数说明

参数名 类型 是否必须 描述
action String flowSetting
accountId String 购买者的腾讯云账号 ID。
openId String 用户在腾讯云开放平台的标识,此标识对于同一服务商是相同的,对于不同服务商是不同的,长度为32位。如果没有接入开放平台,此字段为空。
requestId String 接口请求的 ID。
resourceId String 云市场的实例 ID。
signId String 实例标识 ID,服务商提供的唯一标识。长度最长为11位。
warnSpan String 告警阈值。
warnUnit String 告警阈值单位。
switch String 告警开关,表示是否开启告警。ON 表示开启。OFF 表示关闭。

响应参数说明

参数名 类型 是否必须 描述
success String true/false
info String 错误信息。

请求示例

curl -X POST 'https://{isv/interface}?signature=e3k9ierw&timestamp=1483944926&eventId=1780012140' --data '{"action":"flowSetting","accountId":"123545678","openId ":"xz_D4XL_u7hKY5zt","requestId":"6a02a01f-d420-43d9-be38-fd8eed6bb53a","resourceId":"market-4odto1yji","signId":"kjsadkjhdskjh3k","warnSpan":"1200","warnUnit":"Mb","switch":"ON"}'

响应示例

{"success":"true"}

参数配置

在完成了相关开发后,服务商可登录 云市场服务商管理控制台,在开发配置 > SaaS 接入设置页面中,填写相关信息:
注意:为保证数据的安全,发货 URL 必须为 HTTPS 协议,且发货 URL 不能包含查询字符串。如果配置保存失败,请检查 verifyInterface 接口是否正常。

在线接口调试

在接口开发过程中,您可以登录 云市场服务商管理控制台,在开发配置 > 在线接口调试中,可使用在线调试功能,用于模拟各种类型的发货行为。注意:此为调试环境,请勿使用正式环境的接口 URL 或数据库对接。

接入腾讯云 OAuth

为了提升用户使用 SaaS 产品的体验,建议服务商将应用接入腾讯云开放平台 OAuth ,实现用户在腾讯云控制台登录后,直接免登访问 SaaS 应用管理后台。

申请接入开放平台

由于腾讯云暂未开放申请腾讯云开放平台的入口,因此申请者需要先发邮件至:mqcloud@tencent.com 协助开通。邮件内容如下:腾讯云账户的 ID:您的账号 ID 可在 腾讯云控制台 总览页面右上角处查看。平台名称:平台名称会展示在授权页面。平台 Logo:建议尺寸:260 x 48,PNG 格式,Logo 将会展示在授权页面中。平台官网地址:您可以跳转到的第三方平台官网,即服务商的 SaaS 地址。平台回调地址:去掉 HTTP[s] 的域名部分,不能只是顶级域名,例如可以为api.example.com,而不允许为 example.com。申请成功后您将会得到如下的信息:AppId:第三方平台唯一标识。AppSecretId/AppSecretKey :用来请求腾讯云 API 时的密钥对。EncryKey:用来校验回调地址中带入的 code 参数。

OAuth 接入说明

账号打通
云市场在发货通知中加入用户在腾讯云的标识 OpenID (对于不同服务商用户 OpenID 不同),服务商在获取到 OpenID 之后需要首先要查询该用户是否已与本地系统某个账户绑定,如果已经绑定,则直接处理发货逻辑;若未绑定,则应该在本地系统生成一个账号并与 OpenID 绑定。免登校验
服务商对于发货的响应数据中应该返回一个authUrl,该 URL 最终会展示给用户。用户单击该 URL 后,服务商应该让用户登录到控制台以进行资源相关操作。授权流程说明
服务商授权过程如下:
1. 用户单击authUrl(假设为:http://example.com/qcloud/auth) 后,若未检测到用户登录,则跳转(302跳转)到:https://cloud.tencent.com/open/authorize?scope=login&app_id=123456789012&redirect_url=https%3A%2F%2Fexample.com%2Fapi%2Foauth%2Fqcloud%2Fcallback&state=1234 ,其中app_id为申请 OAuth 后获得的第三方平台唯一标识redirect_url为提交腾讯云开放平台的平台回调地址域名。2. 用户在腾讯云开放平台页面进行登录并且授权。3. 页面跳转回第三方网站地址redirect_url,并且带上参数 code 和 signature ,类似:https://example.com/api/oauth/qcloud/callback?code=04f82b0d6fcfc0c2d967d808e6010bd8&signature=eafc9653bd5c17c6adea55bb516ba8b9&state=123, 其中 signature = md5(code+EncryKey) 。说明:为了防止暴力破解,signature 参数对 code 的合法性做了一个校验。该 code 一次性有效,并且有效期为6分钟。4. 获取 code 并且校验合法之后,调用 code 校验接口,获取用户的以下信息:userOpenId:用户在该第三方平台下的身份唯一标识。userOpenId即为用户在腾讯云的 OpenID (不同第三方平台获取的标识不同)。userUnionId:如果同一个腾讯云账户有多个第三方平台,用户在这些第三方平台的 userUnionId 一致。userAccessToken:用户访问 Token。 expiresAt:用户访问 Token 过期时间(时间戳,当前时间 + 2小时)。userRefreshToken:刷新 Token ,有效期为60天。

code 校验接口

1. 接口描述

接口请求域名:open.tencentcloudapi.com接口说明:用于获取用户第三方开放平台的 access token

2. 输入参数

以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见 公共请求参数。该接口使用分配给第三方平台的密钥调用。

参数名称 必选 类型 描述
Action String 公共参数,本接口取值:GetUserAccessToken。
Version String 公共参数,本接口取值:2018-12-25。
Region String 公共参数,本接口不需要传递此参数。
UserAuthCode String auth code
3. 输出参数
参数名称 类型 描述
AppId String App ID
UserOpenId String 第三方 openId。
UserUnionId String 第三方 unionId。
UserAccessToken String 第三方 access token。
ExpiresAt Integer 过期时间。
UserRefreshToken String refresh token
Scope String 授权范围。
RequestId String 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
4. 示例

输入示例:

https://open.tencentcloudapi.com/?Action=GetUserAccessToken&UserAuthCode=testCode&

输出示例:

{  "Response": {      "AppId": "10******99",      "UserOpenId": "391f920b807ecbaa38f7e77ef5260cd4",      "UserUnionId": "438344612f5e181dbb76d2fcf2634a7b",      "UserAccessToken": "a649830709416d07be8f0dba1c7675ce",      "ExpiresAt": 1581670707,      "UserRefreshToken": "607202ece53c20a8ad91fa3512fa8ac7",      "Scope": "login",      "RequestId": "5bc7a27e-ba54-4b68-b37e-aaee60a2c5e2"  }}



对千帆云市场解决方案有疑惑?想了解解决方案收费? 联系解决方案专家

腾讯云限时活动1折起,即将结束: 马上收藏

同尘科技为腾讯云授权服务中心,购买腾讯云享受折上折,更有现金返利:同意关联,立享优惠

阿里云解决方案也看看?: 点击对比阿里云的解决方案