mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-06-27 04:48:19 +08:00
redpacket_api_test.sh
This commit is contained in:
parent
5d38a92123
commit
e23a07c9c0
284
scripts/test/redpacket_api_test.sh
Executable file
284
scripts/test/redpacket_api_test.sh
Executable file
@ -0,0 +1,284 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# 红包 HTTP 接口测试:create_order / created_callback
|
||||
#
|
||||
# 路由(与 internal/api/router.go 一致):
|
||||
# POST ${HOST}/redpacket/create_order
|
||||
# POST ${HOST}/redpacket/created_callback
|
||||
#
|
||||
# 鉴权:两接口均不在白名单,需在 Header 携带 token(见 protocol/constant constant.Token = "token")。
|
||||
# 追踪:Header 需携带 operationID。
|
||||
#
|
||||
# 依赖:curl、jq;自动拉管理员 token 时另需 python3。
|
||||
#
|
||||
# 用法示例:
|
||||
# chmod +x scripts/test/redpacket_api_test.sh
|
||||
# GROUP_ID=你的群ID USER_ID=你的用户ID ./scripts/test/redpacket_api_test.sh
|
||||
# ./scripts/test/redpacket_api_test.sh --host http://127.0.0.1:10002 --group-id xxx --try-callback
|
||||
# TOKEN=已有用户token GROUP_ID=xxx ./scripts/test/redpacket_api_test.sh --skip-token-smoke
|
||||
#
|
||||
# 说明:
|
||||
# - create_order 在 packetType=0(拼手气固定份)时要求 scopeType=GROUP 且当前用户在该群内。
|
||||
# - 若 RPC 侧未配置 EVM chain client,created_callback 可走「离线」路径:传任意非空 txHash,
|
||||
# 并在 body 中提供与订单一致的 packetID(见 internal/rpc/redpacket resolveCreatedPacket EVM 分支)。
|
||||
# - 生产环境若已接链,created_callback 需真实上链交易哈希,此时请自行设置 TX_HASH / PACKET_ID。
|
||||
# ============================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
HOST="${HOST:-http://127.0.0.1:10002}"
|
||||
USER_ID="${USER_ID:-5694418935}"
|
||||
PLATFORM_ID="${PLATFORM_ID:-2}"
|
||||
ADMIN_TOKEN="${ADMIN_TOKEN:-}"
|
||||
OPENIM_SECRET="${OPENIM_SECRET:-openIM123}"
|
||||
ADMIN_USER_ID="${ADMIN_USER_ID:-imAdmin}"
|
||||
TOKEN="${TOKEN:-}"
|
||||
|
||||
GROUP_ID="${GROUP_ID:-}"
|
||||
CHAIN_TYPE="${CHAIN_TYPE:-EVM}"
|
||||
CHAIN_ID="${CHAIN_ID:-0}"
|
||||
SCOPE_TYPE="${SCOPE_TYPE:-GROUP}"
|
||||
PACKET_TYPE="${PACKET_TYPE:-0}"
|
||||
CREATOR_WALLET="${CREATOR_WALLET:-0x0000000000000000000000000000000000000001}"
|
||||
TOKEN_ADDR="${TOKEN_ADDR:-0x0000000000000000000000000000000000000000}"
|
||||
TOTAL_AMOUNT="${TOTAL_AMOUNT:-100}"
|
||||
TOTAL_SHARES="${TOTAL_SHARES:-5}"
|
||||
EXPIRY_AT="${EXPIRY_AT:-0}"
|
||||
REMARK="${REMARK:-api-test}"
|
||||
|
||||
TRY_CALLBACK="${TRY_CALLBACK:-0}"
|
||||
TX_HASH="${TX_HASH:-0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}"
|
||||
CALLBACK_PACKET_ID="${CALLBACK_PACKET_ID:-}"
|
||||
|
||||
SKIP_TOKEN_SMOKE="${SKIP_TOKEN_SMOKE:-0}"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--host) HOST="$2"; shift 2 ;;
|
||||
--user-id) USER_ID="$2"; shift 2 ;;
|
||||
--platform-id) PLATFORM_ID="$2"; shift 2 ;;
|
||||
--group-id) GROUP_ID="$2"; shift 2 ;;
|
||||
--token) TOKEN="$2"; shift 2 ;;
|
||||
--try-callback) TRY_CALLBACK="1"; shift ;;
|
||||
--skip-token-smoke) SKIP_TOKEN_SMOKE="1"; shift ;;
|
||||
*)
|
||||
echo "未知参数: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
need_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "缺少依赖命令: $1"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
need_cmd curl
|
||||
need_cmd jq
|
||||
|
||||
op_id() {
|
||||
echo "redpacket-test-$$-$(date +%s%N)"
|
||||
}
|
||||
|
||||
get_admin_token() {
|
||||
local uid body resp token last_resp
|
||||
local -a candidates=("${ADMIN_USER_ID}" "openIM123456" "imAdmin")
|
||||
last_resp=""
|
||||
|
||||
for uid in "${candidates[@]}"; do
|
||||
body="{\"secret\":\"${OPENIM_SECRET}\",\"userID\":\"${uid}\"}"
|
||||
resp="$(curl -sS -X POST "${HOST}/auth/get_admin_token" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "operationID: $(op_id)" \
|
||||
-d "$body")"
|
||||
last_resp="$resp"
|
||||
|
||||
token="$(python3 - <<'PY' "$resp"
|
||||
import json
|
||||
import sys
|
||||
|
||||
raw = sys.argv[1]
|
||||
try:
|
||||
obj = json.loads(raw)
|
||||
except Exception:
|
||||
print("")
|
||||
raise SystemExit(0)
|
||||
|
||||
token = ""
|
||||
if isinstance(obj, dict):
|
||||
data = obj.get("data")
|
||||
if isinstance(data, dict):
|
||||
token = data.get("token") or data.get("Token") or ""
|
||||
if not token:
|
||||
token = obj.get("token") or obj.get("Token") or ""
|
||||
print(token)
|
||||
PY
|
||||
)"
|
||||
if [[ -n "$token" ]]; then
|
||||
echo "自动获取管理员 token 成功,userID=${uid}" >&2
|
||||
printf '%s' "$token"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
echo "get_admin_token raw response: $last_resp" >&2
|
||||
echo "自动获取管理员 token 失败,请检查 HOST/OPENIM_SECRET/ADMIN_USER_ID 或直接设置 ADMIN_TOKEN" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
resolve_user_token() {
|
||||
if [[ -n "${TOKEN}" ]]; then
|
||||
echo "使用环境变量/参数 TOKEN(跳过 get_user_token)" >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
need_cmd python3
|
||||
|
||||
if [[ -z "${ADMIN_TOKEN}" ]]; then
|
||||
echo "==> ADMIN_TOKEN 未设置,尝试自动获取管理员 token" >&2
|
||||
ADMIN_TOKEN="$(get_admin_token)"
|
||||
fi
|
||||
|
||||
echo "==> 获取用户 token(userID=${USER_ID})" >&2
|
||||
local TOKEN_RESP
|
||||
TOKEN_RESP=$(curl -sS -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "operationID: $(op_id)" \
|
||||
-H "token: ${ADMIN_TOKEN}" \
|
||||
-d "{\"userID\":\"${USER_ID}\",\"platformID\":${PLATFORM_ID}}" \
|
||||
"${HOST}/auth/get_user_token")
|
||||
|
||||
local ERR_CODE
|
||||
ERR_CODE=$(echo "${TOKEN_RESP}" | jq -r '.errCode // "null"')
|
||||
if [[ "${ERR_CODE}" != "0" ]]; then
|
||||
echo "获取用户 token 失败: ${TOKEN_RESP}" >&2
|
||||
exit 1
|
||||
fi
|
||||
TOKEN=$(echo "${TOKEN_RESP}" | jq -r '.data.token // empty')
|
||||
if [[ -z "${TOKEN}" ]]; then
|
||||
echo "token 为空: ${TOKEN_RESP}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "用户 token 获取成功" >&2
|
||||
}
|
||||
|
||||
# ─── 用例:无 token 应被 GinParseToken 拒绝 ─────────────────
|
||||
if [[ "${SKIP_TOKEN_SMOKE}" != "1" ]]; then
|
||||
echo "==> 用例:POST /redpacket/create_order 无 token(应返回 errCode != 0)"
|
||||
NO_TOKEN_RESP=$(curl -sS -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "operationID: $(op_id)" \
|
||||
-d '{"chainType":"EVM","chainID":1,"groupID":"x","scopeType":"GROUP","packetType":0,"token":"0x0000000000000000000000000000000000000000","totalAmount":"1","totalShares":1,"creatorWallet":"0x0000000000000000000000000000000000000001"}' \
|
||||
"${HOST}/redpacket/create_order")
|
||||
echo "${NO_TOKEN_RESP}" | jq .
|
||||
NT_ERR=$(echo "${NO_TOKEN_RESP}" | jq -r '.errCode // "null"')
|
||||
if [[ "${NT_ERR}" == "0" ]]; then
|
||||
echo "预期无 token 时 errCode != 0,实际 errCode=0" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "无 token 用例通过(errCode=${NT_ERR})"
|
||||
else
|
||||
echo "==> 跳过无 token 用例(SKIP_TOKEN_SMOKE=1 或 --skip-token-smoke)"
|
||||
fi
|
||||
|
||||
if [[ -z "${GROUP_ID}" ]]; then
|
||||
echo "错误:未设置 GROUP_ID。固定份红包(packetType=0)需要 scopeType=GROUP 且 group_id 非空。" >&2
|
||||
echo "示例:GROUP_ID=你的群ID USER_ID=在群内的用户 ./scripts/test/redpacket_api_test.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
resolve_user_token
|
||||
|
||||
echo "==> POST /redpacket/create_order"
|
||||
CREATE_BODY=$(jq -n \
|
||||
--arg chainType "${CHAIN_TYPE}" \
|
||||
--argjson chainID "${CHAIN_ID}" \
|
||||
--arg groupID "${GROUP_ID}" \
|
||||
--arg scopeType "${SCOPE_TYPE}" \
|
||||
--argjson packetType "${PACKET_TYPE}" \
|
||||
--arg token "${TOKEN_ADDR}" \
|
||||
--arg totalAmount "${TOTAL_AMOUNT}" \
|
||||
--argjson totalShares "${TOTAL_SHARES}" \
|
||||
--argjson expiryAt "${EXPIRY_AT}" \
|
||||
--arg remark "${REMARK}" \
|
||||
--arg creatorWallet "${CREATOR_WALLET}" \
|
||||
'{
|
||||
chainType: $chainType,
|
||||
chainID: $chainID,
|
||||
groupID: $groupID,
|
||||
scopeType: $scopeType,
|
||||
packetType: $packetType,
|
||||
token: $token,
|
||||
totalAmount: $totalAmount,
|
||||
totalShares: $totalShares,
|
||||
expiryAt: $expiryAt,
|
||||
remark: $remark,
|
||||
creatorWallet: $creatorWallet
|
||||
}')
|
||||
|
||||
CREATE_RESP=$(curl -sS -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "operationID: $(op_id)" \
|
||||
-H "token: ${TOKEN}" \
|
||||
-d "${CREATE_BODY}" \
|
||||
"${HOST}/redpacket/create_order")
|
||||
|
||||
echo "${CREATE_RESP}" | jq .
|
||||
|
||||
CO_ERR=$(echo "${CREATE_RESP}" | jq -r '.errCode // "null"')
|
||||
if [[ "${CO_ERR}" != "0" ]]; then
|
||||
echo "create_order 失败(errCode=${CO_ERR})。请确认 USER_ID/TOKEN 对应用户在 GROUP_ID 群内,且 totalAmount 可被 totalShares 整除(固定份)。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BIZ_ID=$(echo "${CREATE_RESP}" | jq -r '.data.bizID // empty')
|
||||
if [[ -z "${BIZ_ID}" ]]; then
|
||||
echo "create_order 返回 errCode=0 但 data.bizID 为空: ${CREATE_RESP}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "create_order 成功,bizID=${BIZ_ID}"
|
||||
|
||||
if [[ "${TRY_CALLBACK}" != "1" ]]; then
|
||||
echo "==> 未调用 created_callback(设置 TRY_CALLBACK=1 或传入 --try-callback 以继续)"
|
||||
echo " 离线 EVM:可设置 CALLBACK_PACKET_ID(默认用时间戳十进制字符串);TX_HASH 可用环境变量 TX_HASH 覆盖。"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -z "${CALLBACK_PACKET_ID}" ]]; then
|
||||
CALLBACK_PACKET_ID="$(date +%s)"
|
||||
fi
|
||||
|
||||
echo "==> POST /redpacket/created_callback(bizID=${BIZ_ID}, packetID=${CALLBACK_PACKET_ID})"
|
||||
CALLBACK_BODY=$(jq -n \
|
||||
--arg bizID "${BIZ_ID}" \
|
||||
--arg txHash "${TX_HASH}" \
|
||||
--arg packetID "${CALLBACK_PACKET_ID}" \
|
||||
--arg groupID "${GROUP_ID}" \
|
||||
--arg scopeType "${SCOPE_TYPE}" \
|
||||
'{
|
||||
bizID: $bizID,
|
||||
txHash: $txHash,
|
||||
packetID: $packetID,
|
||||
groupID: $groupID,
|
||||
scopeType: $scopeType
|
||||
}')
|
||||
|
||||
CALLBACK_RESP=$(curl -sS -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "operationID: $(op_id)" \
|
||||
-H "token: ${TOKEN}" \
|
||||
-d "${CALLBACK_BODY}" \
|
||||
"${HOST}/redpacket/created_callback")
|
||||
|
||||
echo "${CALLBACK_RESP}" | jq .
|
||||
|
||||
CB_ERR=$(echo "${CALLBACK_RESP}" | jq -r '.errCode // "null"')
|
||||
if [[ "${CB_ERR}" != "0" ]]; then
|
||||
echo "created_callback 失败(errCode=${CB_ERR})。若已配置链上客户端,请使用真实交易哈希或关闭 TRY_CALLBACK。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "created_callback 成功,红包状态应已更新为 ACTIVE(视部署与链配置而定)。"
|
||||
echo "测试通过: /redpacket/create_order + /redpacket/created_callback"
|
||||
Loading…
x
Reference in New Issue
Block a user