mirror of
https://github.com/openimsdk/open-im-server.git
synced 2026-06-15 20:13:45 +08:00
262 lines
8.0 KiB
Bash
Executable File
262 lines
8.0 KiB
Bash
Executable File
#!/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
|
||
#
|
||
# 说明:
|
||
# - 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:-}"
|
||
|
||
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 ;;
|
||
*)
|
||
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
|
||
}
|
||
|
||
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"
|