
Grok Bot Stripe 的组合正在成为 AI 代购 / 自动下单类应用里非常典型的一套技术方案。用户只需要在聊天窗口发一句“帮我买一个 256G 的黑色手机”Bot 就能自动理解商品、数量、地址再通过绑定的 Stripe 卡完成扣款。本文用一个可运行的 demo 项目完整拆解从 Grok API 接入到 Stripe 卡绑定支付的实现流程覆盖核心代码、运行验证、常见报错和生产环境建议。不管你是刚开始接触大模型 API 的后端开发者还是已经做过支付对接、想了解 AI 与支付如何结合的工程师本文都会给出可以直接参考的闭环方案。1. 背景与核心概念1.1 什么是 Grok BotGrok Bot 指的是基于 Grok 模型能力构建的对话机器人。Grok 是 xAI 推出的语言模型官方提供 API 服务且 API 风格兼容 OpenAI 的 Chat Completions 接口。这意味着你可以使用常见的 OpenAI SDK把 base_url 指向 Grok 的 API 地址然后正常发送 messages 得到模型回复。在代购场景中Grok Bot 承担的核心任务不是简单的“聊天”而是从用户口语化的表达里提取结构化订单信息。比如用户说“帮我在日本买两支那款限量钢笔送到上海”Bot 需要识别出商品限量钢笔数量2目的地上海这类信息如果靠关键词正则解析很容易漏字段或识别错。而大模型在意图理解和信息抽取上明显更稳定这也是把 Grok 放进代购流程的原因之一。1.2 Stripe 卡支付在代购流程中的位置Stripe 是一套成熟的支付服务支持银行卡、钱包等多种支付方式。在海外代购场景中用户需要提前绑定一张可用于国际支付的银行卡然后由平台发起扣款。Stripe 的常见支付流程是用户在前端输入卡号、有效期、CVC。前端调用 Stripe 生成 PaymentMethod 对象。后端拿到 PaymentMethod 后创建 PaymentIntent 并确认支付。如果卡片需要 3DS 验证Stripe 返回 requires_action 状态需要用户完成额外验证。支付成功后Stripe 通过 Webhook 通知后端更新订单状态。这种模式可以避免后端直接接触明文卡号减少安全风险。1.3 为什么要把 Grok Bot 和 Stripe 集成代购类产品本质上是“人找货 下单 支付”的流程。传统做法是用户手动搜索商品、填写地址卡号流程长转化率低。接入 Grok Bot 后用户可以用自然语言完成下单大幅降低操作门槛。集成 Stripe 则能把支付环节闭环。否则 Bot 只能完成“对话”和“生成订单”无法真正收钱。对开发者来说这两个系统的对接逻辑清晰、官方文档完善非常适合作为 AI 应用落地的首选场景。2. 环境准备与整体架构2.1 运行环境与依赖版本本文的示例代码使用 Python 3.9 编写主要依赖如下依赖用途建议版本openai通过 OpenAI 兼容接口调用 Grok API1.x 以上stripe调用 Stripe Payment Intent API9.x 以上fastapi接收 Webhook 和 API 请求0.110 以上uvicorn启动 FastAPI 服务0.29 以上python-dotenv读取 .env 配置文件1.0 以上pydantic请求参数校验2.x 以上版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。2.2 整体技术架构系统的核心链路如下用户消息 - FastAPI 接口 - Grok API 解析订单意图 - 本地 SQLite 存储订单 - Stripe 绑定卡 - 创建 PaymentIntent - 扣款 - Webhook 接收支付结果 - 更新订单状态架构并不复杂但代码层面的模块边界要清晰。本文会把代码拆成以下几个模块config读取环境变量。grok_client封装 Grok API 调用负责解析订单。order_service创建订单、查询订单。payment_service封装 Stripe 相关操作。mainFastAPI 路由和 Webhook 接收。2.3 示例项目结构grok-shop-bot/ ├── app/ │ ├── __init__.py │ ├── config.py │ ├── grok_client.py │ ├── order_service.py │ ├── payment_service.py │ ├── models.py │ └── main.py ├── .env.example ├── requirements.txt └── README.md代码会尽量简化但足够跑通一条完整的下单和支付链路。3. 核心原理拆解3.1 Grok API 的调用方式Grok API 兼容 OpenAI 的请求结构。核心调用示例如下from openai import OpenAI client OpenAI( api_key你的 GROK_API_KEY, base_urlhttps://api.x.ai/v1, ) resp client.chat.completions.create( modelgrok-3-mini, messages[ {role: system, content: 你是一个代购助手。}, {role: user, content: 帮我在日本买两支限量钢笔送到上海}, ], ) print(resp.choices[0].message.content)这里有两个关键点base_url必须指向 Grok 的兼容地址而不是 OpenAI 默认地址。model名称要以你账号实际可用的模型名为准可以通过环境变量配置。Grok 在本文中主要做“意图抽取”。为了让输出稳定会让模型返回 JSON。为了提升解析成功率需要把输出约束到只有 JSON 内容不包含多余解释性文字。3.2 Stripe PaymentMethod 与 PaymentIntentStripe 的 PaymentMethod 代表一种支付方式比如一张卡。PaymentIntent 代表一笔支付意图。最简流程是创建 PaymentMethod。创建 PaymentIntent 并关联该 PaymentMethod。使用 confirm 参数直接确认支付。# 创建 PaymentMethod payment_method stripe.PaymentMethod.create( typecard, card{ number: 4242424242424242, exp_month: 12, exp_year: 2035, cvc: 314, }, ) # 创建并确认 PaymentIntent payment_intent stripe.PaymentIntent.create( amount19900, currencyusd, payment_methodpayment_method.id, confirmTrue, )需要注意Stripe 的金额单位是“最小货币单位”。USD 场景下19900 代表 199.00 美元。这个细节很容易踩坑。另外如果持卡银行要求 3DS 验证PaymentIntent 会返回requires_action状态而不是直接成功。生产环境必须处理这个状态。3.3 Webhook 的作用支付确认结果不能完全依赖接口同步返回。当用户跳转 3DS 页面完成验证后Stripe 会发送payment_intent.succeeded事件到后端 Webhook 地址。后端必须在 Webhook 里校验签名再更新本地订单状态。为什么需要 Webhook因为前端流程可能中断用户可能关闭页面服务器需要拿到最终的支付结果。4. 完整实战案例4.1 创建项目并安装依赖先创建项目目录mkdir grok-shop-bot cd grok-shop-bot mkdir app然后创建requirements.txtopenai1.0.0 stripe9.0.0 fastapi0.110.0 uvicorn0.29.0 python-dotenv1.0.0 pydantic2.0.0安装依赖pip install -r requirements.txt4.2 配置环境变量创建.env.example文件GROK_API_KEY你的Grok密钥 GROK_BASE_URLhttps://api.x.ai/v1 GROK_MODELgrok-3-mini STRIPE_SECRET_KEY你的Stripe密钥 STRIPE_WEBHOOK_SECRET你的Webhook签名密钥 DATABASE_PATH./shop.db把这文件复制成.envcp .env.example .env注意.env不要提交到 Git 仓库。这是包含密钥的敏感文件。4.3 编写配置模块文件路径app/config.pyimport os from dotenv import load_dotenv load_dotenv() GROK_API_KEY os.getenv(GROK_API_KEY) GROK_BASE_URL os.getenv(GROK_BASE_URL, https://api.x.ai/v1) GROK_MODEL os.getenv(GROK_MODEL, grok-3-mini) STRIPE_SECRET_KEY os.getenv(STRIPE_SECRET_KEY) STRIPE_WEBHOOK_SECRET os.getenv(STRIPE_WEBHOOK_SECRET) DATABASE_PATH os.getenv(DATABASE_PATH, ./shop.db)这样后续其他模块通过config.GROK_API_KEY读取配置不用重复加载环境变量。4.4 编写数据库访问层文件路径app/models.py这里使用 SQLite 存储订单和支付关联信息。之所以选择 SQLite是因为 demo 不需要单独部署数据库便于演示。生产环境建议替换成 PostgreSQL 或 MySQL。import sqlite3 from . import config def get_conn(): conn sqlite3.connect(config.DATABASE_PATH) conn.row_factory sqlite3.Row return conn def init_db(): conn get_conn() conn.execute( CREATE TABLE IF NOT EXISTS orders ( order_id TEXT PRIMARY KEY, user_id TEXT NOT NULL, item TEXT NOT NULL, quantity INTEGER NOT NULL, address TEXT NOT NULL, amount_cents INTEGER NOT NULL, currency TEXT NOT NULL DEFAULT usd, payment_intent_id TEXT, payment_method_id TEXT, status TEXT NOT NULL DEFAULT created ) ) conn.commit() conn.close()订单表记录用户、商品、金额和支付状态。paymend_intent_id用来关联 Stripe 侧的支付单。4.5 封装订单服务文件路径app/order_service.pyimport uuid from . import models def create_order(user_id, item, quantity, address, amount_cents, currencyusd): order_id ORD- uuid.uuid4().hex[:16].upper() conn models.get_conn() conn.execute( INSERT INTO orders (order_id, user_id, item, quantity, address, amount_cents, currency, status) VALUES (?, ?, ?, ?, ?, ?, ?, created) , (order_id, user_id, item, quantity, address, amount_cents, currency), ) conn.commit() conn.close() return order_id def get_order(order_id): conn models.get_conn() row conn.execute( SELECT * FROM orders WHERE order_id ?, (order_id,) ).fetchone() conn.close() return dict(row) if row else None def update_order_payment(order_id, payment_intent_id, payment_method_id): conn models.get_conn() conn.execute( UPDATE orders SET payment_intent_id ?, payment_method_id ?, status pending_payment WHERE order_id ? , (payment_intent_id, payment_method_id, order_id), ) conn.commit() conn.close() def update_order_status(order_id, status): conn models.get_conn() conn.execute( UPDATE orders SET status ? WHERE order_id ?, (status, order_id), ) conn.commit() conn.close()4.6 封装 Grok 客户端文件路径app/grok_client.py这里通过 OpenAI SDK 调用 Grok API让模型从用户消息中提取订单字段。import json from openai import OpenAI from . import config class GrokClient: def __init__(self): self.client OpenAI( api_keyconfig.GROK_API_KEY, base_urlconfig.GROK_BASE_URL, ) self.model config.GROK_MODEL def parse_order(self, user_message: str) - dict: prompt f 你是一个代购订单解析助手。 请从用户消息中提取以下字段并只输出 JSON不要输出任何额外解释。 字段说明 - item: 商品名称string - quantity: 数量integer - address: 收货地址string - currency: 币种默认 usd - amount_cents: 预估金额以最小货币单位表示。若无法确定可以根据普通商品市场价估算不要给出 0。 用户消息 {user_message} response self.client.chat.completions.create( modelself.model, messages[ {role: system, content: 你只输出合法 JSON。}, {role: user, content: prompt}, ], temperature0.1, ) content response.choices[0].message.content.strip() # 去掉可能出现的 Markdown 代码块包裹 if content.startswith(): content content.strip() if content.startswith(json): content content[4:] return json.loads(content)需要特别注意的是大模型可能返回 Markdown 代码块。为了稳一点我在代码里做了简单清理。更工程化的做法是使用函数调用或 structured output 能力这取决于 API 版本支持情况。4.7 封装 Stripe 支付服务文件路径app/payment_service.pyimport stripe from . import config stripe.api_key config.STRIPE_SECRET_KEY def create_payment_method(card_number, exp_month, exp_year, cvc): 创建 PaymentMethod。 注意生产环境建议使用 Stripe Elements/Payment Element 收集卡信息 后端不要直接接收明文卡号。 payment_method stripe.PaymentMethod.create( typecard, card{ number: card_number, exp_month: exp_month, exp_year: exp_year, cvc: cvc, }, ) return payment_method.id def create_payment_intent(amount_cents, currency, payment_method_id, order_id): payment_intent stripe.PaymentIntent.create( amountamount_cents, currencycurrency, payment_methodpayment_method_id, confirmTrue, metadata{order_id: order_id}, ) return payment_intent这里把confirmTrue直接放在创建 PaymentIntent 的调用里等于创建后立即尝试扣款。如果卡片需要 3DS返回结果的status会是requires_action。4.8 编写主服务接口文件路径app/main.pyfrom fastapi import FastAPI, Request, HTTPException from pydantic import BaseModel from . import config, models from .grok_client import GrokClient from .order_service import ( create_order, get_order, update_order_payment, update_order_status, ) from .payment_service import ( create_payment_method, create_payment_intent, ) import stripe app FastAPI() grok_client GrokClient() class ChatMessage(BaseModel): user_id: str user_message: str class CardBindRequest(BaseModel): user_id: str order_id: str card_number: str exp_month: int exp_year: int cvc: str app.on_event(startup) def startup(): models.init_db() app.post(/api/grok/parse-order) def parse_order(message: ChatMessage): 接收用户消息使用 Grok 解析订单信息并创建本地订单。 try: parsed grok_client.parse_order(message.user_message) item parsed[item] quantity int(parsed[quantity]) address parsed[address] amount_cents int(parsed[amount_cents]) currency parsed.get(currency, usd) except Exception as e: raise HTTPException(status_code400, detailfGrok 解析订单失败: {str(e)}) order_id create_order( user_idmessage.user_id, itemitem, quantityquantity, addressaddress, amount_centsamount_cents, currencycurrency, ) return { order_id: order_id, item: item, quantity: quantity, address: address, amount_cents: amount_cents, currency: currency, status: created, message: 订单已创建请绑定支付卡完成支付。, } app.post(/api/orders/pay) def pay_order(payload: CardBindRequest): 绑定 Stripe 卡并完成订单扣款。 order get_order(payload.order_id) if not order: raise HTTPException(status_code404, detail订单不存在) payment_method_id create_payment_method( card_numberpayload.card_number, exp_monthpayload.exp_month, exp_yearpayload.exp_year, cvcpayload.cvc, ) payment_intent create_payment_intent( amount_centsorder[amount_cents], currencyorder[currency], payment_method_idpayment_method_id, order_idorder[order_id], ) update_order_payment( order_idorder[order_id], payment_intent_idpayment_intent.id, payment_method_idpayment_method_id, ) if payment_intent.status succeeded: update_order_status(order[order_id], paid) return {status: paid, payment_intent_id: payment_intent.id} if payment_intent.status requires_action: return { status: requires_action, message: 需要完成 3DS 验证, client_secret: payment_intent.client_secret, } return {status: payment_intent.status} app.post(/webhook/stripe) async def stripe_webhook(request: Request): 接收 Stripe Webhook确认支付结果。 body await request.body() sig_header request.headers.get(stripe-signature) try: event stripe.Webhook.construct_event( payloadbody, sig_headersig_header, secretconfig.STRIPE_WEBHOOK_SECRET, ) except ValueError: raise HTTPException(status_code400, detailInvalid payload) except stripe.error.SignatureVerificationError: raise HTTPException(status_code400, detailInvalid signature) if event[type] payment_intent.succeeded: payment_intent event[data][object] order_id payment_intent[metadata][order_id] update_order_status(order_id, paid) return {status: ok}Demo 里为了演示方便直接在接口中接收卡号。实际项目严禁这样做应该使用 Stripe.js、Stripe Elements 或 Stripe Payment Element 在前端完成卡信息收集后端只接收payment_method_id。4.9 启动服务在项目根目录创建run.pyimport uvicorn if __name__ __main__: uvicorn.run(app.main:app, host0.0.0.0, port8000, reloadTrue)启动命令python run.py正常启动会看到类似输出INFO: Uvicorn running on http://0.0.0.0:8000 INFO: Application startup complete.4.10 使用 curl 验证完整流程先调用 Grok 解析接口curl -X POST http://localhost:8000/api/grok/parse-order \ -H Content-Type: application/json \ -d { user_id: user_001, user_message: 帮我在美国买一个苹果耳机数量1个送到上海浦东新区 }预期返回类似{ order_id: ORD-ABCD1234EFGH5678, item: 苹果耳机, quantity: 1, address: 上海浦东新区, amount_cents: 19900, currency: usd, status: created }拿到order_id后调用支付接口。Stripe 测试卡用4242424242424242curl -X POST http://localhost:8000/api/orders/pay \ -H Content-Type: application/json \ -d { user_id: user_001, order_id: ORD-ABCD1234EFGH5678, card_number: 4242424242424242, exp_month: 12, exp_year: 2035, cvc: 314 }如果一切正常返回{ status: paid, payment_intent_id: pi_xxx }5. 常见问题与排查思路问题现象常见原因解决思路GROK_API_KEY 报错或返回 401环境变量未正确加载检查.env文件位置确认使用from dotenv import load_dotenv; load_dotenv()Grok 返回内容无法解析成 JSON模型输出了额外文字或 Markdown 包裹清理响应文本尝试在 prompt 中强调只输出 JSON或使用结构化输出能力Stripe 返回amount金额错误金额单位不正确确认使用最小货币单位例如 100 代表 1.00 USD支付后返回requires_action发卡行要求 3DS 验证使用 Stripe 前端 SDK 配合client_secret完成认证Webhook 验签失败STRIPE_WEBHOOK_SECRET配置错误或请求头缺失重新复制 Stripe 后台的 Webhook 签名密钥检查请求头stripe-signature支付成功但订单状态未更新Webhook 未配置或 metadata 未传递确认 Webhook 地址正确创建 PaymentIntent 时在 metadata 中写入订单号使用真实卡测试被拒绝测试环境不支持真实扣款切换到 Stripe 测试密钥并使用官方测试卡号5.1 关于 3DS 验证的处理3DS 验证是 Stripe 遇到风险较高的卡或银行要求时必须处理的流程。同步接口创建 PaymentIntent 后状态可能是requires_action。此时需要把client_secret返回给前端由 Stripe.js 发起认证。一个可行的方式是在前端渲染 Stripe 提供的认证弹窗用户确认后 Stripe 自动继续完成支付。由于本文重点是后端集成这部分只做提示。5.2 关于 Webhook 重试Stripe 对 Webhook 发送有重试机制。如果本地接口处理慢或者返回非 2xx 状态码Stripe 会按策略重新发送事件。因此 Webhook 处理逻辑必须保持幂等比如同一个payment_intent.succeeded事件重复处理时更新订单状态不会报错。6. 最佳实践与工程建议6.1 不要在后端直接接收明文卡号Demo 为了展示完整支付链路把卡号写进了接口。真实项目里这样的做法有严重安全隐患。正确方案是前端引入 Stripe.js。使用 Payment Element 渲染卡输入框。Stripe 把用户输入的卡转换成 PaymentMethod。前端只把payment_method.id传给后端。这样后端完全不接触明文卡号能极大降低数据泄露风险。6.2 密钥管理STRIPE_SECRET_KEY、STRIPE_WEBHOOK_SECRET、GROK_API_KEY都必须放在服务端环境变量或密钥管理系统中。尤其是STRIPE_SECRET_KEY一旦泄露攻击者可以用它创建退款或查询用户流水。建议使用独立的测试密钥和正式密钥。生产密钥只允许部分服务访问。定期轮换密钥。6.3 支付创建注意幂等Stripe 允许在创建 PaymentIntent 时传入idempotency_key。如果用户网络超时后重试没有幂等键可能会创建多笔扣款。建议为每次支付操作绑定唯一幂等键。import uuid payment_intent stripe.PaymentIntent.create( amountamount_cents, currencycurrency, payment_methodpayment_method_id, confirmTrue, idempotency_keyorder_id - uuid.uuid4().hex, )6.4 Webhook 必须校验签名在/webhook/stripe接口中一定要使用stripe.Webhook.construct_event校验签名。不要直接信任请求体。攻击者可以伪造支付成功通知如果不校验签名本地订单会错误标记为已支付。6.5 日志记录与脱敏支付相关日志不要打印完整卡号、CVC。建议只记录payment_method_id的后几位或者只记录payment_intent.id。同时Grok API 返回的用户消息可能包含地址、姓名等信息日志中也要做好脱敏。6.6 代购业务的合法合规代购业务涉及跨境商品、税务、关税、商品许可证等复杂合规要求。本文只讨论技术实现实际线下运营时需要结合目标市场法律确认哪些商品可以代购哪些品类需要特殊资质。技术方案本身不能被用来规避法律或平台规则。6.7 生产环境数据存储SQLite 适合 demo 和单机部署。一旦订单量上来建议迁移到 PostgreSQL 或 MySQL增加事务和行锁避免多实例同时更新订单状态。同时订单金额和商品信息应该做审计日志方便后续追溯。7. 总结与下一步本文实现了一个最小可运行的 Grok Bot 代购支付系统。核心链路已经跑通用户发送自然语言消息Grok 解析订单意图FastAPI 保存订单用户绑定 Stripe 卡PaymentIntent 完成扣款Webhook 同步最终支付状态。如果你打算继续往下深入建议按这个顺序进阶先把支付卡信息收集迁移到 Stripe Payment Element去掉后端明文卡号的代码。为系统增加用户体系把订单和 Stripe Customer 绑定。增加商品价格表让 Grok 从商品库中查询真实价格而不是让模型估算金额。接入 PostgreSQL把订单服务和支付服务拆成独立模块。增加退款接口和售后处理流程。这套 demo 里最容易忽略的风险是支付状态不一致和密钥泄露。实际部署前建议先在 Stripe 测试环境完整跑一遍“创建订单 → 3DS 验证 → Webhook 通知 → 订单更新”的链路再把密钥切换到正式环境。Grok Bot 加 Stripe 的组合本质上是在做一个“智能导购 支付中台”的雏形。把这两个系统打通后后面接物流系统、库存系统、售后系统都会更容易。从这个角度看这套代码不只是演示也可以成为你后续业务开发的起点。