托管模式
本文详细描述了如何通过托管模式实现银行卡支付方式的集成。托管模式能够有效保护您免受支付卡行业数据安全标准(PCI-DSS)合规要求的限制。这是因为买家的敏感支付数据不会经过您的服务器进行处理或存储,从而避免了潜在的安全风险和数据泄露隐患。此外,该模式无需您单独进行 PCI 合规认证,节约了运营和技术成本,同时提升了支付系统的部署效率。
在托管模式中,APO 为您生成并提供了一个用户友好的支付信息收集页面。买家在支付流程中将被安全地重定向至该页面,用于输入其支付信息。APO 在接受到买家提交的信息后,会对其进行安全处理并将相关数据存储为加密的卡令牌(cardToken)。该卡令牌是支付卡信息的安全映射,可以在后续支付流程中被使用。借助托管模式,您无需直接接触买家的支付数据,同时也能够在保障安全性合规性的前提下,为买家提供无缝和可靠的支付体验。
用户体验
以下图示展示了首次支付和已保存的银行卡支付的用户体验。
首次支付
Web 用户体验
已存卡支付
Web 用户体验
支付流程
对于托管模式下的银行卡支付,支付流程包括以下步骤。
- 买家进入选择支付方式页面。
- 发起支付请求。
买家选择支付方式并提交订单后,商户服务端根据支付信息调用 支付 接口来发起支付请求。 - 跳转至支付 URL。
商户客户端跳转至支付请求返回的 URL 页面完成支付。 - 获取授权支付结果。
商户服务端会接收支付平台返回的支付结果通知,并根据结果进行相应的业务处理。 - 请款并获取请款通知。
您需要在授权支付成功后发起请款。之后您可以通过以下两种方法之一获取请款结果:
注意:若您在多机构下开通了同一个支付方式,请在 APO Dashboard 完成路由配置。若不配置,则 APO 会采取随机路由规则。
集成准备
集成 APO 服务端 SDK 资源包,并完成接口库安装和请求示例初始化。具体操作参见服务端 SDK。
集成步骤
大多数银行卡支付遵循 APO 提供的通用支付流程和集成过程。请按照以下步骤开始集成:
- 显示支付方式
- 授权支付
- (可选)跳转至支付推进链接
- 获取授权支付结果
- 请款和获取请款结果
注意:韩国卡存在认证和非认证两种支付类型。韩国卡的非认证支付遵循常规银行卡支付流程,但韩国卡的认证支付涉及额外的操作步骤。
步骤 1:显示支付方式
首次支付
您可以添加您计划集成的支付方式的标识和名称,这使得买家在首次支付时可以轻松选择他们更喜欢的支付方式。您可以通过联系 APO 技术支持来获取标识和名称。
添加支付方式后的页面效果如下所示:
步骤 2:授权支付
当买家选择支付方式时,您需要收集关键订单信息,如买家的支付方式信息、订单信息、设备信息和支付金额等,并需要调用 支付 接口提交支付请求。
1. 调用支付接口
以下示例代码展示了如何调用 支付 接口:
public static void payByCard() {
AlipayPayRequest alipayPayRequest = new AlipayPayRequest();
alipayPayRequest.setProductCode(ProductCodeType.CASHIER_PAYMENT);
// 替换为您的 paymentRequestId
String paymentRequestId = UUID.randomUUID().toString();
alipayPayRequest.setPaymentRequestId(paymentRequestId);
// 设置金额
Amount amount = Amount.builder().currency("SGD").value("4200").build();
alipayPayRequest.setPaymentAmount(amount);
// 设置支付方式
PaymentMethod paymentMethod = PaymentMethod.builder().paymentMethodType("CARD").build();
alipayPayRequest.setPaymentMethod(paymentMethod);
// 卡信息
Map<String, Object> paymentMethodMetaData = new HashMap<String, Object>();
paymentMethodMetaData.put("tokenizeMode", ASKFORCONSENT);
paymentMethod.setPaymentMethodMetaData(paymentMethodMetaData);
// 替换为您的 orderId
String orderId = UUID.randomUUID().toString();
// 设置买家信息
Buyer buyer = Buyer.builder().referenceBuyerId("yourBuyerId").build();
// 设置订单信息
Order order = Order.builder().referenceOrderId(orderId)
.orderDescription("antom testing order").orderAmount(amount).buyer(buyer).build();
alipayPayRequest.setOrder(order);
// 设置设备环境信息
Env env = Env.builder().terminalType(TerminalType.WEB).clientIp("1.2.3.4").build();
alipayPayRequest.setEnv(env);
// 设置授权请款支付模式
PaymentFactor paymentFactor = PaymentFactor.builder().isAuthorization(true).build();
alipayPayRequest.setPaymentFactor(paymentFactor);
// 替换为您的通知地址
alipayPayRequest.setPaymentNotifyUrl("https://www.yourNotifyUrl.com");
// 替换为您的跳转地址
alipayPayRequest.setPaymentRedirectUrl("https://www.yourMerchantWeb.com");
// 支付
AlipayPayResponse alipayPayResponse = null;
try {
alipayPayResponse = CLIENT.execute(alipayPayRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// 处理错误情况
}
}
2. 发起支付请求
以下是支付请求参数重点字段:
参数名称 | 首次支付场景是否必需 | 已存卡支付场景是否必需 | 描述 |
productCode | 是 | 是 | 在此场景中,值设置为 CASHIER_PAYMENT 。 |
paymentRequestId | 是 | 是 | 授权支付的请求 ID,每次都需要唯一。 |
paymentAmount.value | 是 | 是 | 支付金额。 |
paymentAmount.currency | 是 | 是 | 支付币种。 |
settlementStrategy.settlementCurrency | 否 | 否 | 支付请求的结算策略的结算币种。 |
paymentMethodMetaData | 否 | 否 | 某些特定支付方式需要的额外信息。 |
paymentMethodMetaData.tokenizeMode | 否 | 否 | 卡信息存储模式。需要存储买家的卡信息时,请指定此参数。
|
paymentMethod.paymentMethodType | 是 | 是 | 商户或收单机构提供给买家可选择的支付方式。固定传 |
paymentMethod.paymentMethodId | 否 | 是 | 商户或收单机构提供给买家可选择的支付方式的 ID。需传入首次支付时返回的 cardToken。
|
paymentFactor.isAuthorization | 是 | 是 | 支付模式。固定传 |
paymentFactor.captureMode | 否 | 否 | 请款模式。此参数不传默认为 |
productCode | 是 | 是 | 产品码。此场景下该字段的值固定为 |
paymentExpiryTime | 否 | 否 | 支付有效期。 |
paymentRedirectUrl | 是 | 是 | 支付完成后,买家被重定向到的商户页面链接。需要 HTTPS 地址,根据支付结果对应渲染。 |
paymentNotifyUrl | 否 | 否 | 授权结果的通知地址。需要 HTTPS 地址,如通过 APO Dashboard 配置,则该字段可不传。 |
env.terminalType | 是 | 是 | 指定买家发起交易的端类型。有效值为:
|
env.clientIp | 是 | 是 | 买家当前的 IP。 |
order.orderAmount | 是 | 是 | 商户端订单金额。 |
order.referenceOrderId | 是 | 是 | 商户端订单号。 |
order.orderDescription | 是 | 是 | 商户端订单描述。 |
order.buyer | 是 | 是 | 商户端买家信息。至少需要提供以下三者其中一个信息:
|
paymentMethod.paymentMethodMetaData.is3DSAuthentication | 否 | 否 | 表示交易认证类型是否为 3D 安全。有效值为:
|
有关完整参数的更多信息,请参阅 支付 接口。
以下代码展示了支付请求报文的示例:
{
"env": {
"clientIp": "112.80.248.78",
"deviceId": "eYOIkvFpZzztgO0Yu6USdprBQZCWxDhiUAHCiK8K/cH9mT6wMaMO****",
"deviceLanguage": "zh_CN",
"terminalType": "WEB"
},
"order": {
"buyer": {
"buyerEmail": "alipay@alipay.com",
"buyerName": {
"firstName": "De***",
"fullName": "De*** Skr Liu",
"lastName": "Liu",
"middleName": "Skr"
},
"buyerPhoneNo": "1234567****",
"referenceBuyerId": "test1234****"
},
"orderAmount": {
"currency": "HKD",
"value": "30000"
},
"orderDescription": "Cappuccino #grande (Mika's coffee shop)",
"referenceOrderId": "ORDER_2022111414171****"
},
"paymentAmount": {
"currency": "HKD",
"value": "30000"
},
"paymentFactor": {
"isAuthorization": true
},
"paymentMethod": {
"paymentMethodType": "CARD"
},
"paymentNotifyUrl": "https://www.alipay.com/notify",
"paymentRedirectUrl": "https://www.alipay.com",
"paymentRequestId": "13eIlShXoOg0S9jd3pMWzg3iOBwoXCv1YuEUy****",
"productCode": "CASHIER_PAYMENT",
"settlementStrategy": {
"settlementCurrency": "EUR"
}
}
以下是部分响应报文示例:
{
"authExpiryTime": "2025-02-27T15:15:57+08:00",
"normalUrl": "https://ac.alipay.com/page/sandbox/stone-infostaging.html?paymentId=20250220194010800190188000014991264&code=golcashier99ed8d93-efcf-4fe7-b9a1-4bb1152d6ad4sandbox&golSandbox=true&pspName=CARD&county=SG",
"paymentActionForm": "{\"method\":\"GET\",\"paymentActionFormType\":\"RedirectActionForm\",\"redirectUrl\":\"https://ac.alipay.com/page/sandbox/stone-infostaging.html?paymentId=20250220194010800190188000014991264&code=golcashier99ed8d93-efcf-4fe7-b9a1-4bb1152d6ad4sandbox&golSandbox=true&pspName=CARD&county=SG\"}",
"paymentAmount": {
"currency": "HKD",
"value": "30000"
},
"paymentCreateTime": "2025-02-20T15:15:57+08:00",
"paymentId": "2025022019401080019018800001499****",
"paymentRequestId": "13eIlShnRH5mKYtqFa2kvfht2IXdx1XoOg0S9jd3pMWzg3iOBwoXCv1YuEUy****",
"redirectActionForm": {
"method": "GET",
"redirectUrl": "https://ac.alipay.com/page/sandbox/stone-infostaging.html?paymentId=20250220194010800190188000014991264&code=golcashier99ed8d93-efcf-4fe7-b9a1-4bb1152d6ad4sandbox&golSandbox=true&pspName=CARD&county=SG"
},
"result": {
"resultCode": "PAYMENT_IN_PROCESS",
"resultMessage": "Payment is processing.",
"resultStatus": "U"
}
}
下表展示了响应报文中 result.resultStatus 字段可能返回的值,请您根据指引进行处理:
result.resultStatus | 信息 | 下一步操作 |
| 表示授权支付成功。 | 后续可发起请款。 |
| 表示授权支付失败。 | 请关闭当前交易或重新更换paymentRequestId 再次下单。 |
| 表示授权支付进行中。 |
|
注意:如果您未收到响应报文,可能是网络超时所致。您可选择主动调用 支付结果查询 接口获取支付结果,或者等待支付结果通知。
步骤 3:(可选)跳转到支付推进链接
当商户服务端拿到 APO normalUrl 后,将该 normalUrl 传递给前端,由商户前端跳转至 APO 的 normalUrl 。
获取 normalUrl 后,您需要在浏览器将页面重定向至 APO normalUrl,或在新标签页打开。
if (serverResponse.normalUrl != null) {
window.open(serverResponse.normalUrl, '_blank');
}
步骤 4:获取授权支付结果
1. 设置接收通知的 webhook URL
您可以选择以下两种方法中的一种来设置接受通知的 webhook URL:
- 若您的每个订单都有单独的通知 URL,建议您在每笔请求中设置 webhook URL。您可以通过 支付 接口请求的 paymentNotifyUrl 字段传入该笔订单的接收异步通知 URL。
- 若您的所有订单都有一个统一的通知 URL,您则可以在 APO Dashboard > 开发者 > 通知地址 中设置 webhook URL。
注意:
- 若您在接口和 APO Dashboard 里都设置了 webhook URL,则以接口设置为准。
- 若跳转 3D URL 后买家未核实身份,APO 则需要等订单关闭后才发异步通知,默认关单时间以各收单机构为准。
以下代码展示了通知请求的示例:
{
"acquirerReferenceNo":"pay_6tmvamfcxp5ujbbfjeopyz6v7q",
"result":{
"resultStatus":"S",
"resultCode":"SUCCESS",
"resultMessage":"success."
},
"notifyType":"PAYMENT_RESULT",
"paymentId":"2025031719401089010011160025568****",
"paymentRequestId":"G15320250317102252****",
"paymentResultInfo":{
"lastFour":"1358",
"funding":"CREDIT",
"issuerName":"ORIENT CORPORATION",
"expiryMonth":"**",
"threeDSResult":{
"cavv":"",
"xid":"649335d6-1858-4532-8a6e-0579e1b7****",
"threeDSType":"INTERNAL",
"eci":"05",
"threeDSVersion":"2.2.0"
},
"expiryYear":"**",
"cardNo":"************1358",
"cardBin":"428067",
"holdName":"NIHEI SHUNSUKE",
"issuingCountry":"JP",
"avsResultRaw":"I",
"fingerprint":"a28f7dd0713e2f1d4e9ccae8853f5c0abca5154a03a6559cd985eb409857****",
"networkTransactionId":"46507608833****",
"cardBrand":"VISA",
"cvvResultRaw":""
},
"paymentTime":"2025-03-16T19:27:17-07:00",
"acquirerInfo":{
"referenceRequestId":"202503171903130000060027882****",
"acquirerTransactionId":"pay_6tmvamfcxp5ujbbfjeopyz****",
"acquirerMerchantId":"pc_6cpbmm5qderubjraxrygje****",
"acquirerName":"CHECKOUT"
},
"paymentAmount":{
"currency":"JPY",
"value":"120"
},
"paymentCreateTime":"2025-03-16T19:26:42-07:00"
}
您可能会收到请求报文中 result.resultStatus 字段的不同值,请您根据下表指引进行处理:
result.resultStatus | 信息 | 下一步操作 |
| 表示授权支付成功。 | 后续可发起请款,同时存储 paymentId 用于后续的请款和退款。 |
| 表示授权支付失败。 | 关闭当前交易或重新更换 paymentRequestId 再次下单。
|
常见问题
问:何时会发送通知?
答:这取决于支付是否完成。如果支付完成后,在收到收单机构的通知后 APO 会立即发送异步通知。
问:异步通知会被重新发送吗?
答:是的,对于以下情况,异步通知会在 24 小时内自动重新发送:
- 如果由于网络原因未收到异步通知。
- 如果您收到来自 APO 的异步通知,但您没有按照处理通知的示例代码格式对通知做出响应。
通知最多可以重发 8 次,或者直到收到正确的响应以终止发送。发送间隔如下:0 分钟,2 分钟,10 分钟,10 分钟,1 小时,2 小时,6 小时和 15 小时。
问:我在通知中需要使用哪些关键参数?
答:请注意以下关键参数:
- result:表示订单的支付结果。
- paymentRequestId:商户生成的支付请求号,用于查询、撤销、对账。
- paymentId:APO 生成的支付单号,用于退款、对账。
- paymentAmount:如有金额核对的需求,可以消费这个字段。
- acquirerInfo:表示收单机构的相关信息。
问:是否需要保存收单机构信息?
答:建议保存收单机构 acquirerInfo 相关信息,具体原因请查看单号说明。
2. 异步通知验签
若您收到 APO 的异步通知,需要您在返回中按照示例代码格式返回响应,但无需做加签处理。
您需要对 APO 发送的支付通知进行验签。
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.global.api.model.Result;
import com.alipay.global.api.model.ResultStatusType;
import com.alipay.global.api.response.AlipayResponse;
import com.alipay.global.api.tools.WebhookTool;
@RestController
public class PaymentNotifyHandleBySDK {
/**
* alipay public key, used to verify signature
*/
private static final String SERVER_PUBLIC_KEY = "";
/**
* payment result notify processor
* using <a href="https://spring.io">Spring Framework</a>
*
* @param request HttpServletRequest
* @param notifyBody notify body
* @return
*/
@PostMapping("/payNotify")
public Object payNotifyHandler(HttpServletRequest request, @RequestBody String notifyBody) {
// 从 http 请求中获取所需参数
String requestUri = request.getRequestURI();
String requestMethod = request.getMethod();
// 从请求头中获取所需参数
String requestTime = request.getHeader("request-time");
String clientId = request.getHeader("client-id");
String signature = request.getHeader("signature");
Result result;
AlipayResponse response = new AlipayResponse();
try {
// 通知验签
boolean verifyResult = WebhookTool.checkSignature(requestUri, requestMethod, clientId, requestTime, signature, notifyBody, SERVER_PUBLIC_KEY);
if (!verifyResult) {
throw new RuntimeException("Invalid notify signature");
}
// 反序列化通知主体
// 根据通知结果更新订单状态
// 响应服务端已接收通知
result = new Result("SUCCESS", "success", ResultStatusType.S);
} catch (Exception e) {
String errorMsg = e.getMessage();
// 处理错误情况
result = new Result("ERROR", errorMsg, ResultStatusType.F);
}
response.setResult(result);
return ResponseEntity.ok().body(response);
}
}
您无需对响应通知结果做加签处理,但是对于每个通知请求均需按以下固定格式响应,与订单支付成功与否无关。
{
"result": {
"resultCode": "SUCCESS",
"resultStatus": "S",
"resultMessage": "success"
}
}
步骤 5:请款和获取请款结果
您可以通过配置 支付 接口中的 paymentFactor.captureMode 字段选择全款自动请款或全额手动请款。您可以在请款后通过异步通知或主动查询来获取请款结果。参见请款了解更多详情。
建议您保存收单机构相关信息( acquirerInfo 参数),具体原因请查看单号说明。以下代码展示了主动查询请款结果的响应报文示例:
{
"paymentResultCode":"SUCCESS",
"paymentRequestId":"G15320250317102252****",
"paymentResultInfo":{
"lastFour":"1358",
"funding":"CREDIT",
"issuerName":"ORIENT CORPORATION",
"expiryMonth":"**",
"threeDSResult":{
"cavv":"",
"xid":"649335d6-1858-4532-8a6e-0579e1b7****",
"threeDSType":"INTERNAL",
"eci":"05",
"threeDSVersion":"2.2.0"
},
"expiryYear":"**",
"cardNo":"************1358",
"cardBin":"428067",
"holdName":"NIHEI SHUNSUKE",
"issuingCountry":"JP",
"avsResultRaw":"I",
"fingerprint":"a28f7dd0713e2f1d4e9ccae8853f5c0abca5154a03a6559cd985eb409857****",
"networkTransactionId":"46507608833****",
"cardBrand":"VISA",
"cvvResultRaw":""
},
"transactions":[
{
"transactionType":"CAPTURE",
"transactionStatus":"SUCCESS",
"transactionRequestId":"G15320250317102252****",
"transactionAmount":{
"currency":"JPY",
"value":"120"
},
"transactionTime":"2025-03-16T19:27:17-07:00",
"acquirerInfo":{
"referenceRequestId":"202503171903130100060027884****",
"acquirerTransactionId":"act_yv3fchmu3bre3l3tui5y35****",
"acquirerMerchantId":"pc_6cpbmm5qderubjraxrygje****",
"acquirerName":"CHECKOUT"
},
"transactionId":"2025031719401089010011160025567****",
"transactionResult":{
"resultStatus":"S",
"resultCode":"SUCCESS",
"resultMessage":"success"
}
}
],
"paymentAmount":{
"currency":"JPY",
"value":"120"
},
"acquirerReferenceNo":"pay_6tmvamfcxp5ujbbfjeopyz****",
"result":{
"resultStatus":"S",
"resultCode":"SUCCESS",
"resultMessage":"success."
},
"paymentId":"2025031719401089010011160025568****",
"paymentResultMessage":"success.",
"paymentTime":"2025-03-16T19:27:17-07:00",
"acquirerInfo":{
"referenceRequestId":"202503171903130000060027882****",
"acquirerTransactionId":"pay_6tmvamfcxp5ujbbfjeopyz****",
"acquirerMerchantId":"pc_6cpbmm5qderubjraxrygje****",
"acquirerName":"CHECKOUT"
},
"paymentStatus":"SUCCESS",
"paymentCreateTime":"2025-03-16T19:26:42-07:00"
}
支付后操作
查询授权支付结果
除了可以通过异步通知的功能获取授权支付结果,同时也支持您通过主动查询服务来获取对应的结果。您可以调用 支付结果查询 接口,使用支付的 paymentRequestId 查询授权支付状态。
以下代码展示了如何调用 支付结果查询 接口:
public static void inquiryPayment() {
AlipayPayQueryRequest alipayPayQueryRequest = new AlipayPayQueryRequest();
// 替换为您的 paymentRequestId
alipayPayQueryRequest.setPaymentRequestId("yourPaymentRequestId");
AlipayPayQueryResponse alipayPayQueryResponse = null;
try {
alipayPayQueryResponse = CLIENT.execute(alipayPayQueryRequest);
} catch (AlipayApiException e) {
String errorMsg = e.getMessage();
// 处理错误情况
}
}
以下代码展示了一个请求报文的示例:
{
"paymentRequestId": "REQUEST_2024100821261****"
}
建议保存收单机构相关信息( acquirerInfo 参数),具体原因请查看单号说明。以下代码展示了响应报文的示例:
{
"paymentResultCode": "SUCCESS",
"paymentRequestId": "G15320250317102252****",
"paymentResultInfo": {
"lastFour": "1358",
"funding": "CREDIT",
"issuerName": "ORIENT CORPORATION",
"expiryMonth": "**",
"threeDSResult": {
"cavv": "",
"xid": "649335d6-1858-4532-8a6e-0579e1b7****",
"threeDSType": "INTERNAL",
"eci": "05",
"threeDSVersion": "2.2.0"
},
"expiryYear": "**",
"cardNo": "************1358",
"cardBin": "428067",
"holdName": "NIHEI SHUNSUKE",
"issuingCountry": "JP",
"avsResultRaw": "I",
"fingerprint": "a28f7dd0713e2f1d4e9ccae8853f5c0abca5154a03a6559cd985eb409857****",
"networkTransactionId": "46507608833****",
"cardBrand": "VISA",
"cvvResultRaw": ""
},
"paymentAmount": {
"currency": "JPY",
"value": "120"
},
"acquirerReferenceNo": "pay_6tmvamfcxp5ujbbfjeopyz****",
"result": {
"resultStatus": "S",
"resultCode": "SUCCESS",
"resultMessage": "success."
},
"actualPaymentAmount": {
"currency": "JPY",
"value": "120"
},
"paymentId": "2025031719401089010011160025568****",
"paymentResultMessage": "success.",
"paymentTime": "2025-03-16T19:27:17-07:00",
"acquirerInfo": {
"referenceRequestId": "202503171903130000060027882****",
"acquirerTransactionId": "pay_6tmvamfcxp5ujbbfjeopyz****",
"acquirerMerchantId": "pc_6cpbmm5qderubjraxrygje****",
"acquirerName": "CHECKOUT"
},
"paymentStatus": "SUCCESS",
"paymentCreateTime": "2025-03-16T19:26:42-07:00"
}
您可能会收到响应报文中 paymentStatus 字段的不同值,请您根据下表指引进行处理:
paymentStatus | 信息 | 下一步操作 |
| 表示授权支付成功。 | 您可以发起请款。 |
| 表示授权支付失败。 | 请关闭订单或更换 paymentRequestId 再次尝试。 |
| 表示授权支付进行中。 | 您可以继续查询或在关单时间后查询。 |
常见问题
问:我应该多久调用一次 支付结果查询 接口?
答:以 2 秒的间隔持续调用 支付结果查询 接口,从发起下单 支付 接口后立即发起轮询直到获取最终的支付结果或收到异步支付结果通知为止。
问:我在查询中需要使用哪些关键参数?
答:请注意以下关键参数:
- paymentStatus : 您需要根据 paymentStatus 来判断授权支付状态。
- paymentAmount :表示支付的金额。
取消交易
如果需要取消某笔交易,您可以在支持的取消窗口期内通过 取消支付 接口进行操作,详情请参见取消交易。
退款
若您需要了解 APO 的退款规则及如何对成功的交易发起退款,详情请参见退款。
争议
若买家选择使用卡支付方式,会涉及到争议相关的集成,详情请参见争议。
对账
交易完成后,使用 APO 提供的财务报告进行对账。有关如何对账和 APO 结算规则的更多信息,请参阅对账。