运行前准备什么
使用 Python 3.10 或更高版本,并确保能够正常访问互联网。示例只使用 Python 标准库,无需安装 SDK 或执行 pip 安装。将代码保存为 raysms_catalog.py。请保留 HTTPS 证书验证;连接异常时应检查原因,不要通过关闭证书验证来绕过问题。
先运行 python raysms_catalog.py,查看当前应用目录和国家目录的一部分。应用使用 code 字段,国家使用 id 字段。这些是目录标识,不是显示名称,也不是国际电话区号。不要根据号码前缀猜测国家 ID。
复制完整的只读程序
四种语言页面使用同一份代码,控制台标签与查询到的目录名称使用英文。BASE_URL 指向本站当前规范域名,不包含任何密钥。程序设置请求超时,并在错误时退出,避免一次目录查询失败演变成无限重复请求。
# Python 3.10+; standard library only. No API key is needed.
import argparse
import json
from decimal import Decimal
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
BASE_URL = "https://raysms.com"
def get_items(path, **params):
query = urlencode({k: v for k, v in params.items() if v is not None})
url = BASE_URL + "/api/" + path + ("?" + query if query else "")
request = Request(url, headers={"Accept": "application/json",
"User-Agent": "RaySMS-Catalog-Example/1.0"},
method="GET")
try:
with urlopen(request, timeout=15) as response:
result = json.load(response)
except HTTPError as error:
if error.code == 429:
delay = error.headers.get("Retry-After", "the documented interval")
raise SystemExit("Rate limited; retry later after " + delay)
raise SystemExit("API returned HTTP " + str(error.code)
+ "; check the request and service availability")
except (URLError, TimeoutError):
raise SystemExit("Network request failed; check connectivity and retry later")
except (ValueError, UnicodeError):
raise SystemExit("API response was not valid JSON")
if not isinstance(result, dict) or not isinstance(result.get("items"), list):
raise SystemExit("Unexpected API response; inspect the API documentation")
return result["items"]
def main():
parser = argparse.ArgumentParser(description="Read the RaySMS catalog; never buy numbers")
parser.add_argument("--service", help="Service code from the catalog, for example tg")
parser.add_argument("--country", help="Optional country ID from the catalog")
args = parser.parse_args()
services = get_items("catalog/services", lang="en")
countries = get_items("catalog/countries", lang="en")
names = {str(country["id"]): country["name"] for country in countries}
if not args.service:
print("Services (first 20):")
for service in services[:20]:
print(service["code"], service["name"])
print("Countries (first 10):")
for country in countries[:10]:
print(country["id"], country["name"])
return
if args.service not in {service["code"] for service in services}:
parser.error("Unknown service code; run without arguments to inspect the catalog")
if args.country is not None and args.country not in names:
parser.error("Unknown country ID; inspect the country catalog")
offers = get_items("catalog/prices", service=args.service, country=args.country)
if not offers:
print("No available offers for this selection. No purchase was made.")
return
for offer in sorted(offers, key=lambda row: int(row["price_micros"]))[:10]:
price = Decimal(str(offer["price_micros"])) / Decimal("1000000")
country = str(offer["country"])
print(country, names.get(country, country),
"USD " + format(price, ".6f"), "available:", offer["count"])
if __name__ == "__main__":
main()
选择实际存在的应用,理解返回报价
如果当前应用目录中包含 tg,可以运行 python raysms_catalog.py --service tg 查询它的可用国家。在后面加 --country 和国家目录返回的 ID,可以缩小查询范围。这些是命令格式示例,不代表某个应用或国家在你运行时一定有库存。
接口的 price_micros 使用整数微美元,1,000,000 单位等于 1 美元。程序使用 Decimal 输出价格,避免二进制浮点误差。count 表示查询时返回的可用数量;items 为空表示此次选择没有查到可用报价,不代表已经预留号码。
库存和价格可能变化。目录请求成功,不保证之后下单成功,也不保证目标应用接受号码或一定发送短信。
先处理错误,再考虑定时查询
HTTP 429 表示应降低请求频率;如果响应提供 Retry-After,请按提示等待。示例会退出,由你明确决定何时重试。网络异常、超时和 HTTP 5xx 不应触发没有间隔的循环。在更完整的程序中,先检查连接与服务状态,再采用有次数上限的退避重试。
公开目录查询不需要发送 Cookie、账户密码或 API 密钥。这段代码只用于读取数据,不是生产购买任务,因此没有充值或创建订单的调用。
明确决定购买后,再接入订单接口
开发者指南另行介绍账户鉴权、价格上限、幂等键和订单状态处理。加入 POST /api/orders 之前请先阅读该指南,因为该操作会使用钱包资金。重试必须对应同一次预期购买;结果不明确时,应核查原订单,而不是悄悄再买一单。