You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python urllib.request请求Stripe API的身份认证问题

使用urllib.request调用Stripe API时的身份认证问题

我尝试用Python的urllib.request调用Stripe的结账会话API来获取JSON响应,但API需要身份认证,不知道怎么在请求里添加认证信息。

对应的可正常工作的curl请求如下:

curl https://api.stripe.com/v1/checkout/sessions   -u pk_test_51LoUz3BgfM0E8ZiCV8UO79gw8zw7fhSgHUEAVj4wS7igs5D4kKiNsxXGeKQEUhorImNUiCxCNNtidwNkhFPUHP4i0060lsvsbw:   -d success_url="http://127.0.0.1:5500/pages/success.html"   -d cancel_url="http://127.0.0.1:5500/pages/nosuccess.html"   -d "line_items[0][price]"=price_1LvNRkBgfM0E8ZiCTSiaNvNL   -d "line_items[0][quantity]"=1 -d mode=subscription -d client_reference_id="123" -d customer_email="email@email.com" -d client_reference_id="tokenized" -d phone_number_collection["enabled"]=true

这个curl请求通过-u参数做身份认证,值为publishable key加冒号,表示无需密码,能成功创建结账会话并返回JSON。

但我的Python代码执行时返回401未授权错误:

Traceback (most recent call last):
  File "/home/pau/Desktop/bsnbl/Backend/borrar.py", line 17, in <module>
    respuesta = urllib.request.urlopen(request)
  File "/usr/lib/python3.8/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.8/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/lib/python3.8/urllib/request.py", line 640, in http_response
    response = self.parent.error(
  File "/usr/lib/python3.8/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 401: Unauthorized

我的Python代码如下:

import urllib.request
import json

# Debido a cambios en la libreria ahora se deben pasar algunos cabeceros html
paymentInfo = '-u pk_test_51LoUz3BgfM0E8ZiCV8UO79gw8zw7fhSgHUEAVj4wS7igs5D4kKiNsxXGeKQEUhorImNUiCxCNNtidwNkhFPUHP4i0060lsvsbw:   -d success_url=&quot;http://127.0.0.1:5500/pages/success.html&quot;   -d cancel_url=&quot;http://127.0.0.1:5500/pages/nosuccess.html&quot;   -d &quot;line_items[0][price]&quot;=price_1LvNRkBgfM0E8ZiCTSiaNvNL   -d &quot;line_items[0][quantity]&quot;=1 -d mode=subscription -d client_reference_id=&quot;123&quot; -d customer_email=&quot;abrix07@gmail.com&quot; -d client_reference_id=&quot;tokenized&quot; -d phone_number_collection[&quot;enabled&quot;]=true'
res = bytes(paymentInfo,'utf-8')
print(str(type(res))) 
request = urllib.request.Request(
    'https://api.stripe.com/v1/checkout/sessions',
    data=res,
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
    }
)
respuesta = urllib.request.urlopen(request)
print('1. ',respuesta)
cuerpo_respuesta = respuesta.read()
print(cuerpo_respuesta)
#Procesamos la respuesta json
json_respuesta = json.loads(cuerpo_respuesta.decode(&quot;utf-8&quot;))
print(json_respuesta)

注:为安全起见,使用了Stripe账户的publishable key,若测试代码需使用secret key,此处无法提供,敬请谅解。


问题分析与解决方案

错误原因

你的代码把curl的命令行参数直接当作请求数据发送,完全不符合HTTP请求规范。Stripe的-u参数对应的是HTTP Basic认证,需要将密钥编码后添加到请求头中;同时请求数据需要是标准的表单编码格式,而非curl命令参数。

正确实现步骤

  1. 处理Basic认证:将你的publishable key(注意:创建结账会话实际应该使用Stripe的secret key,这里按你提供的密钥演示)加上冒号,进行Base64编码,然后添加到Authorization请求头,格式为Basic <编码后的字符串>。
  2. 构造正确的表单数据:把curl中-d的参数转换成键值对,再编码成application/x-www-form-urlencoded格式。
  3. 设置正确的请求头:添加Content-Type: application/x-www-form-urlencoded,确保服务端能正确解析请求数据。

修正后的代码

import urllib.request
import json
import base64
import urllib.parse

# 1. 配置认证信息
stripe_key = "pk_test_51LoUz3BgfM0E8ZiCV8UO79gw8zw7fhSgHUEAVj4wS7igs5D4kKiNsxXGeKQEUhorImNUiCxCNNtidwNkhFPUHP4i0060lsvsbw"
# 构造Basic认证的编码字符串:密钥加冒号,然后base64编码
auth_str = f"{stripe_key}:"
auth_bytes = auth_str.encode('utf-8')
auth_base64 = base64.b64encode(auth_bytes).decode('utf-8')

# 2. 构造表单数据
form_data = {
    "success_url": "http://127.0.0.1:5500/pages/success.html",
    "cancel_url": "http://127.0.0.1:5500/pages/nosuccess.html",
    "line_items[0][price]": "price_1LvNRkBgfM0E8ZiCTSiaNvNL",
    "line_items[0][quantity]": "1",
    "mode": "subscription",
    "client_reference_id": "tokenized",  # 你之前重复设置了该参数,这里保留最后一个值
    "customer_email": "abrix07@gmail.com",
    "phone_number_collection[enabled]": "true"
}
# 将表单数据编码为urlencoded格式
encoded_data = urllib.parse.urlencode(form_data).encode('utf-8')

# 3. 创建请求对象
request = urllib.request.Request(
    'https://api.stripe.com/v1/checkout/sessions',
    data=encoded_data,
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36',
        'Authorization': f'Basic {auth_base64}',
        'Content-Type': 'application/x-www-form-urlencoded'
    }
)

# 发送请求并处理响应
try:
    respuesta = urllib.request.urlopen(request)
    cuerpo_respuesta = respuesta.read()
    json_respuesta = json.loads(cuerpo_respuesta.decode("utf-8"))
    print(json_respuesta)
except urllib.error.HTTPError as e:
    print(f"请求错误: {e.code} - {e.read().decode('utf-8')}")

额外提示

Stripe官方推荐使用官方的Python SDK来调用API,比直接用urllib更简单且不易出错。如果可以的话,建议安装stripe库后使用以下方式实现:

import stripe

stripe.api_key = "你的secret key"

session = stripe.checkout.Session.create(
    success_url="http://127.0.0.1:5500/pages/success.html",
    cancel_url="http://127.0.0.1:5500/pages/nosuccess.html",
    line_items=[
        {
            "price": "price_1LvNRkBgfM0E8ZiCTSiaNvNL",
            "quantity": 1,
        },
    ],
    mode="subscription",
    client_reference_id="tokenized",
    customer_email="abrix07@gmail.com",
    phone_number_collection={"enabled": True},
)

print(session)

内容的提问来源于stack exchange,提问作者user19851042

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:55:18