﻿## 使用说明

支付宝 SDK 对商家的请求支付数据处理完成后，会将结果同步反馈给商家 App 端。

注意：同步返回的数据，商家可以按照下文描述的方式在服务端验证。验证通过后，可以认为本次用户付款成功。有些时候会出现商家 App 在支付宝付款阶段被关闭、导致无法正确收到同步结果的情况，此时支付结果可以通过服务端异步通知获取。为了简化集成流程，商家可以将同步结果仅作为一个支付结束通知，实际支付是否成功以服务端异步通知为准。

## 回调返回方法

- iOS：参考 [iOS 集成流程](https://ideservice.alipay.com/cms/site/0izcsf) 的配置返回 URL 处理方法打印输出回调信息。对于 iOS 平台而言，返回参数是一个 `NSDictionary` 对象。
- Android：参考 [Android 集成流程](https://ideservice.alipay.com/cms/site/0izcsg) 中“支付结果获取和处理”的同步返回打印输出回调信息。对于 Android 平台而言，返回参数是一个 map 结构体。

## 返回结果示例

同步返回的回调信息包含 3 个 key：

- `memo`：描述信息，类型为字符串。
- `result`：处理结果，类型为 JSON 结构字符串。
- `resultStatus`：结果码，类型为字符串。

```json
{
  "memo": "xxxxx",
  "result": "{
    \"alipay_trade_app_pay_response\": {
      \"code\": \"10000\",
      \"msg\": \"Success\",
      \"app_id\": \"2014072300007148\",
      \"out_trade_no\": \"081622560194853\",
      \"trade_no\": \"2016081621001004400236957647\",
      \"total_amount\": \"9.00\",
      \"seller_id\": \"2088702849871851\",
      \"charset\": \"utf-8\",
      \"timestamp\": \"2016-10-11 17:43:36\"
    },
    \"sign\": \"NGfStJf3i3ooWBuCDIQSumOpaGBcQz+aoAqyGh3W6EqA/gmyPYwLJ2REFijY9XPTApI9YglZyMw+ZMhd3kb0mh4RAXMrb6mekX4Zu8Nf6geOwIa9kLOnw0IMCjxi4abDIfXhxrXyj********\",
    \"sign_type\": \"RSA2\"
  }",
  "resultStatus": "9000"
}
```

## result 返回参数说明

| 参数 | 类型 | 是否必选 | 最大长度 | 描述 | 示例值 |
| --- | --- | --- | --- | --- | --- |
| `out_trade_no` | String | 必选 | 64 | 商家网站唯一订单号。 | 70501111111S001111119 |
| `trade_no` | String | 必选 | 64 | 该交易在支付宝系统中的交易流水号。 | 2014112400001000340011111118 |
| `app_id` | String | 必选 | 32 | 支付宝分配给开发者的应用 APPID。 | 2014072300007148 |
| `total_amount` | Price | 必选 | 11 | 该笔订单的资金总额，单位为 RMB-Yuan。取值范围 `[0.01, 100000000.00]`，精确到小数点后两位。 | 9.00 |
| `seller_id` | String | 必选 | 16 | 收款支付宝账号对应的支付宝唯一用户号，以 2088 开头的纯 16 位数字。 | 20886894 |
| `msg` | String | 必选 | 16 | 处理结果的描述，信息来自于 `code` 返回结果的描述。 | success |
| `charset` | String | 必选 | 16 | 编码格式。 | utf-8 |
| `timestamp` | String | 必选 | 32 | 时间。 | 2016-10-11 17:43:36 |
| `code` | String | 必选 | 16 | 结果码，详情可查看[公共错误码](https://ideservice.alipay.com/cms/site/02km9f)。 | 10000 |

## resultStatus 结果码含义

| 返回码 | 含义 |
| --- | --- |
| `9000` | 订单支付成功。 |
| `8000` | 正在处理中，支付结果未知，有可能已经支付成功。请查询商家订单列表中订单的支付状态。 |
| `4000` | 订单支付失败。 |
| `5000` | 重复请求。 |
| `6001` | 用户中途取消。 |
| `6002` | 网络连接出错。 |
| `6004` | 支付结果未知，有可能已经支付成功。请查询商家订单列表中订单的支付状态。 |
| 其它 | 其它支付错误。 |

## 同步通知验证

为了帮助开发者调用开放接口，支付宝提供了[开放平台服务端 DEMO&SDK](https://ideservice.alipay.com/cms/site/02no46)，包含 Java、PHP、Python、NodeJS 和 .NET 五种语言版本，封装了签名、验签、HTTP 接口请求等基础功能。强烈建议先下载对应语言版本的 SDK 并引入开发工程进行快速接入。

若未使用支付宝 SDK，可按以下步骤完成同步通知验签：

1. 在返回数据 `resultStatus` 为 `9000` 的情况下，解析 `result` 结果进行[同步返回验签](https://ideservice.alipay.com/cms/site/02mse7)。
2. 提取 `alipay_trade_app_pay_response` 字段值，其代表签名原始字符串，示例如下：

```json
{
  "code": "10000",
  "msg": "Success",
  "app_id": "2014072300007148",
  "out_trade_no": "081622560194853",
  "trade_no": "2016081621001004400236957647",
  "total_amount": "9.00",
  "seller_id": "2088702849871851",
  "charset": "utf-8",
  "timestamp": "2016-10-11 17:43:36"
}
```

3. 提取 `sign_type` 字段值，其代表签名类型，示例如下：

```text
RSA2
```

4. 提取 `sign` 字段值，其代表签名结果，示例如下：

```text
NGfStJf3i3ooWBuCDIQSumOpaGBcQz+aoAqyGh3W6EqA/gmyPYwLJ2REFijY9XPTApI9YglZyMw+ZMhd3kb0mh4RAXMrb6mekX4Zu8Nf6geOwIa9kLOnw0IMCjxi4abDIfXhxrXyj********
```

5. 验证签名是否合法。使用各自语言对应的 SHA256WithRSA 签名验证函数，传入签名原始字符串、支付宝公钥、签名类型 RSA、签名字符进行合法性验证。
6. 在签名验证通过后，必须严格按照如下描述校验通知参数的合法性：

| 校验项 | 校验说明 |
| --- | --- |
| `out_trade_no` | 校验该通知数据中的 `out_trade_no` 是否为商家系统中创建的订单号。 |
| `total_amount` | 判断 `total_amount` 是否确实为该订单的实际金额，即商家订单创建时的金额。 |
| `seller_id` / `seller_email` | 校验通知中的 `seller_id` 或 `seller_email` 是否为 `out_trade_no` 这笔单据对应的操作方。 |
| `app_id` | 验证 `app_id` 是否为该商家本身。 |

上述任一校验项不通过，则表明同步校验结果无效。只有全部验证通过后，才可以认定买家付款成功。

## 客户端报错处理方案

商家客户端唤起支付宝客户端后，支付宝客户端中可能弹窗提示“支付失败”等报错信息。

### 系统交互流程

```mermaid
sequenceDiagram
    actor 用户
    participant 商户客户端
    participant 支付宝AppSDK as 支付宝 app SDK
    participant 支付宝服务端
    participant 商户服务端

    用户->>商户客户端: 1. 使用支付宝付款
    商户客户端->>商户服务端: 2. 请求商户服务端，获取签名后的订单信息
    商户服务端-->>商户客户端: 3. 返回签名后的订单信息
    商户客户端->>支付宝AppSDK: 4. 调用 alipay.trade.app.pay 接口唤起支付宝 app
    支付宝AppSDK->>支付宝服务端: 5. 支付请求
    支付宝服务端->>支付宝服务端: 6. 验签以及其他处理

    rect rgb(255, 240, 240)
    Note left of 用户: ATL 验签或参数校验失败
    支付宝服务端->>支付宝AppSDK: 7. 返回错误信息
    支付宝AppSDK->>用户: 8. 弹窗提示错误信息
    用户->>支付宝AppSDK: 9. 点击确认按钮，关闭支付宝 app
    end

    支付宝AppSDK->>商户客户端: 10. 返回详细错误信息
```

### 错误信息格式样例

![错误信息格式样例](https://gw.alipayobjects.com/zos/skylark-tools/public/files/ea95904c8c74165bcd9d051493a6fde2.png)

### result 错误处理方案

当 `resultStatus` 返回非 `9000` 状态，且 `result` 返回的 `sub_code` 和 `sub_msg` 含有具体错误原因时，可查看 [alipay.trade.app.pay（App 支付接口 2.0 接口）](https://ideservice.alipay.com/cms/site/02e7gq)错误码进行排查和解决。如在开发过程中碰到其他问题，可以在[文档中心](https://opendocs.alipay.com/home)搜索查找相关问题。

注意：部分报错没有显示具体报错信息，例如 `{resultStatus=6001, result=, memo=用户取消}`，无法判断是用户取消支付导致还是报错导致，建议按照客户端页面显示的报错信息进行查询定位。

常见报错信息及解决方案如下：

| 客户端报错 | 解决方案 |
| --- | --- |
| 商家订单参数异常，请尝试返回后重新付款或联系商家确认 | 可能原因包括：请求 APPID 应用未上线；应用类型为第三方应用；未开通 App 支付或未添加 App 支付功能包；`sign_type` 填写错误，必须为 `RSA2`；签名方式使用错误，若应用接口加签方式为公钥证书，则代码必须为证书模式加签（含 `app_cert_sn` 和 `alipay_root_cert_sn`），若接口加签方式为公钥，则代码必须为普通公钥加签；请求参数问题，建议只传必传参数测试核实（沙箱调试客户端请开启沙箱联调代码）；代码中设置的私钥和应用中上传的应用公钥不匹配。 |
| 卖家账户状态异常，请联系卖家解决。（T1） | 商家收款账号存在异常，建议商家拨打联系电话 `4007585858` 处理。 |
| 系统繁忙，请稍后再试 | 请按照[常见问题](https://ideservice.alipay.com/cms/site/0izct7)中客户端返回具体报错定位。 |
| 订单已付款成功，请勿重复提交。(ALIN42279) | 该笔订单已支付完成，不可使用相同的商家订单号再次发起请求。 |
| 花呗分期暂不可用，请更换付款方式 | 可能原因包括：用户尚未开通花呗或花呗可用额度不足；花呗分期额度过小或超支，建议设置 200 元测试；收款账号未开通花呗分期协议或接口不支持花呗分期收款；账号存在风险；接口设置了支付渠道，禁用花呗分期。 |
| 订单已超时，请重新下单后再发起付款(ALIN47094) | 接口传入了超时参数，未在交易超时前支付，建议更换新的订单号 `out_trade_no` 重新请求。 |
