# 查询

获取订单的最新状态。

**适用场景**：
1. 调用预下单接口（precreate）预下单成功后，需要调用查询接口发起轮询
2. 调用支付接口（pay）支付后没有得到订单的最终状态
3. 调用退款接口（refund）发起退款后没有得到退款最终状态
4. 调用撤单接口（revoke/cancel）发起撤单或冲正之后没有得到撤单的最终状态
5. 手动查询，预防单边账

**重要**：sn与client_sn不能同时为空，优先按照sn查找订单，如果没有，再按照client_sn查询。

## 接口说明

- 请求方式：`POST`
- 请求地址：`https://vsi-api.shouqianba.com/upay/v2/query`
- Operation ID：`query`

## 请求参数

无请求参数。

## 请求体

| 字段名 | 类型 | 必填 | 描述 |
| --- | --- | --- | --- |
| client_sn | string | 否 | 商户自己的订单号。和sn二选一（不能同时为空） |
| refund_request_no | string | 否 | 退款序列号。调用退款接口时传入的值，可用于多次部分退款场景下查询某次部分退款的结果 |
| sn | string | 否 | 收钱吧系统订单号。和client_sn二选一（不能同时为空），优先使用sn |
| terminal_sn | string | 是 | 收钱吧终端ID |

## 请求示例

```json
{
  "sn": "7894259244061958",
  "terminal_sn": "010382829292929"
}
```

## 响应体

| 字段名 | 类型 | 必填 | 描述 |
| --- | --- | --- | --- |
| biz_response | object | 否 |  |
| biz_response.data | object | 否 | 查询业务数据（业务成功时返回） |
| biz_response.data.channel_finish_time | string | 否 | 上次操作在支付平台完成的时间（时间戳）。只有支付成功、退款成功、撤单成功才有值返回 |
| biz_response.data.client_sn | string | 是 | 商户订单号 |
| biz_response.data.finish_time | string | 否 | 上次操作在收钱吧的完成时间（时间戳）。只有支付成功、退款成功、撤单成功才有值返回 |
| biz_response.data.net_amount | string | 是 | 剩余金额。实收金额减退款金额 |
| biz_response.data.operator | string | 是 | 执行上次业务动作的操作员 |
| biz_response.data.order_status | string | 是 | 订单状态 |
| biz_response.data.payer_uid | string | 是 | 付款人id |
| biz_response.data.payment_list | array[object] | 否 | 活动优惠信息概览 |
| biz_response.data.payment_list[].amount | string | 是 | 此次交易变更的金额 |
| biz_response.data.payment_list[].amount_total | string | 是 | 活动出资总金额 |
| biz_response.data.payment_list[].type | string | 是 | 活动类型。见附录《活动优惠类型列表》 |
| biz_response.data.payway | string | 是 | 支付方式 |
| biz_response.data.payway_name | string | 是 | 支付方式名称 |
| biz_response.data.provider_response | object | 否 | 优惠详情。格式为json，内容有两部分：goods_details为核销单品信息数组，voucher_details为核销券信息数组。 |
| biz_response.data.provider_response.goods_details | array[object] | 否 |  |
| biz_response.data.provider_response.voucher_details | array[object] | 否 |  |
| biz_response.data.settlement_amount | string | 否 | 本次操作金额。订单支付时等于本次支付金额，订单退款时等于本次操作退款金额 |
| biz_response.data.sn | string | 是 | 收钱吧唯一订单号 |
| biz_response.data.status | string | 是 | 流水状态 |
| biz_response.data.subject | string | 是 | 商品概述 |
| biz_response.data.terminal_sn | string | 是 | 收钱吧终端ID |
| biz_response.data.total_amount | string | 是 | 原始交易实收金额 |
| biz_response.data.trade_no | string | 是 | 支付平台的订单凭证号 |
| biz_response.error_code | string | 否 | 业务执行错误码。业务执行失败时返回。 |
| biz_response.error_message | string | 否 | 业务执行错误信息。 |
| biz_response.result_code | string | 是 | 业务执行响应码。SUCCESS：成功；FAIL：失败；INPROGRESS：进行中；ERROR：未知。具体取值见附录《业务数据响应码列表》 |
| error_code | string | 否 | 通讯错误码。通讯失败时返回。见附录《公共错误码》 |
| error_message | string | 否 | 通讯错误信息描述。通讯失败时返回。 |
| result_code | string | 是 | 通讯响应码。200：通讯成功；400：客户端错误；500：服务端错误 |

## 响应示例

```json
{
  "biz_response": {
    "data": {
      "client_sn": "test",
      "client_tsn": "726d47ded14818c906cd1a006d4e5050",
      "ctime": "1498446309605",
      "description": "[{\"id\":\"\",\"name\":\"未命名商品\",\"num\":\"1\",\"price\":\"3000\"}]\n",
      "net_amount": "0",
      "operator": "test",
      "order_status": "PAID",
      "payment_list": [
        {
          "amount_total": "1",
          "type": "BANKCARD_DEBIT"
        },
        {
          "amount_total": "100",
          "type": "DISCOUNT_CHANNEL_MCH"
        }
      ],
      "payway": "2",
      "sn": "7895259867120667",
      "status": "SUCCESS",
      "store_id": "test",
      "sub_payway": "1",
      "subject": "test",
      "terminal_id": "a2369b8b-546f-42e1-baec-e1d54690bab8",
      "total_amount": "300000"
    },
    "result_code": "SUCCESS"
  },
  "result_code": "200"
}
```

## 示例代码

### cURL

```bash
curl -X POST "https://vsi-api.shouqianba.com/upay/v2/query" \
  -H "Authorization: 100000000000000000 0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"sn":"7894259244061958","terminal_sn":"010382829292929"}'
```

### Python

```python
import requests

url = "https://vsi-api.shouqianba.com/upay/v2/query"
headers = {"Content-Type": "application/json",
    "Authorization": "100000000000000000 0123456789abcdef0123456789abcdef",
}
json_data = {
    "sn": "7894259244061958",
    "terminal_sn": "010382829292929"
}

response = requests.post(
    url,
    headers=headers,
    json=json_data,
)

print(response.json())
```

### Java

```java
// 查询
OkHttpClient client = new OkHttpClient();
String json = "{\"sn\":\"7894259244061958\",\"terminal_sn\":\"010382829292929\"}";
RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));

Request request = new Request.Builder()
    .url("https://vsi-api.shouqianba.com/upay/v2/query")
    .addHeader("Authorization", "100000000000000000 0123456789abcdef0123456789abcdef")
    .post(body)
    .build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
```

### Go

```go
package main

import (
    "fmt"
    "io"
    "net/http"
    "bytes"
)

func main() {
	jsonBody := []byte(`{"sn":"7894259244061958","terminal_sn":"010382829292929"}`)
	reqBody := bytes.NewBuffer(jsonBody)
	req, err := http.NewRequest("POST", "https://vsi-api.shouqianba.com/upay/v2/query", reqBody)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "100000000000000000 0123456789abcdef0123456789abcdef")
	resp, err := (&http.Client{}).Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	respBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(respBytes))
}
```

### Node.js

```javascript
const https = require("https");

const options = {
  method: "POST",
  hostname: "vsi-api.shouqianba.com",
  path: "/upay/v2/query",
  headers: {
    "Authorization": "100000000000000000 0123456789abcdef0123456789abcdef",
    "Content-Type": "application/json"
  }
};

const postData = JSON.stringify({"sn":"7894259244061958","terminal_sn":"010382829292929"});

const req = https.request(options, (res) => {
  let data = "";
  res.on("data", (chunk) => { data += chunk; });
  res.on("end", () => { console.log(JSON.parse(data)); });
});
req.write(postData);
req.end();
```
