Stripe:未找到与使用 Django 的有效负载的预期签名相匹配的签名
Stripe: No signatures found matching the expected signature for payload using Django
我在 Stripe 调用定义的 Web 挂钩时遇到以下错误
No signatures found matching the expected signature for payload
我正在关注这篇文章:https://stripe.com/docs/billing/subscriptions/checkout#provision-and-monitor
我有以下代码:
@csrf_exempt
def saaswebhookview(request):
try:
stripe.api_key = settings.STRIPE_SECRET_KEY
webhook_secret = 'stripe_key'
request_data = request.POST
if webhook_secret:
try:
signature = request.headers.get('stripe-signature')
# signature = request.META['stripe-signature']
event = stripe.Webhook.construct_event(
payload=request.POST, sig_header=signature, secret=webhook_secret)
data = event['data']
except Exception as e:
print(str(e))
return JsonResponse({'status': 'error', 'error': str(e)})
event_type = event['type']
else:
data = request_data['data']
event_type = request_data['type']
data_object = data['object']
if event_type == 'checkout.session.completed':
print(data)
elif event_type == 'invoice.paid':
print(data)
elif event_type == 'invoice.payment_failed':
print(data)
else:
print('Unhandled event type {}'.format(event_type))
return JsonResponse({'status': 'success'}, safe=False)
except Exception as e:
return JsonResponse({'status': 'success', 'error': str(e)}, safe=False)
但奇怪的是,这会抛出错误,不知道为什么?
Stripe 库需要用于签名验证的 webhook 请求的原始主体才能工作。看起来您提供的是 request.POST
,这是正文的修改版本。
如果您改用 request.body
,它应该可以正常工作。
使用生成的签名
验证您的 Stripe Webhook API 的脚本
import hmac
import time
from hashlib import sha256
import requests
import stripe
webhook_url = 'https://your-site/api/stripe/webhook/'
stripe_secret = 'YOUR_STRIPE_WEBHOOK_SIGN_SECRET' # whsec_..
webhook_json_file = 'PATH_TO_JSON_FILE_WITH_WH_DATA/webhook_example.json'
def generate_stripe_signature_header(payload: str):
timestamp_utc = int(time.time())
signed_payload = "%d.%s" % (timestamp_utc, payload)
v1_sig = compute_signature(signed_payload, secret=stripe_secret)
return f't={timestamp_utc},v1={v1_sig}'
def compute_signature(payload: str, secret):
"""Take from stripe"""
mac = hmac.new(
secret.encode("utf-8"),
msg=payload.encode("utf-8"),
digestmod=sha256,
)
return mac.hexdigest()
with open(webhook_json_file, 'r') as f:
payload = f.read()
signature = generate_stripe_signature_header(payload=payload)
headers = {
'STRIPE-SIGNATURE': signature,
'Content-Type': 'application/json',
}
session = requests.Session()
session.headers.update(**headers)
response = session.post(webhook_url, data=payload)
print(response.content)
print(response.status_code)
response.raise_for_status()
P.S. 如果您想将它用于 单元测试 / Django 测试客户端,需要在签名头添加HTTP_前缀
signature = generate_stripe_signature_header(payload=payload)
headers = {
'HTTP_STRIPE-SIGNATURE': signature,
'Content-Type': 'application/json',
}
self.client.post(webhook_url, data=payload, **headers)
就我而言,为了解决我的问题,我对正文进行了解码:
payload = request.body.decode('utf-8')
我在 Stripe 调用定义的 Web 挂钩时遇到以下错误
No signatures found matching the expected signature for payload
我正在关注这篇文章:https://stripe.com/docs/billing/subscriptions/checkout#provision-and-monitor
我有以下代码:
@csrf_exempt
def saaswebhookview(request):
try:
stripe.api_key = settings.STRIPE_SECRET_KEY
webhook_secret = 'stripe_key'
request_data = request.POST
if webhook_secret:
try:
signature = request.headers.get('stripe-signature')
# signature = request.META['stripe-signature']
event = stripe.Webhook.construct_event(
payload=request.POST, sig_header=signature, secret=webhook_secret)
data = event['data']
except Exception as e:
print(str(e))
return JsonResponse({'status': 'error', 'error': str(e)})
event_type = event['type']
else:
data = request_data['data']
event_type = request_data['type']
data_object = data['object']
if event_type == 'checkout.session.completed':
print(data)
elif event_type == 'invoice.paid':
print(data)
elif event_type == 'invoice.payment_failed':
print(data)
else:
print('Unhandled event type {}'.format(event_type))
return JsonResponse({'status': 'success'}, safe=False)
except Exception as e:
return JsonResponse({'status': 'success', 'error': str(e)}, safe=False)
但奇怪的是,这会抛出错误,不知道为什么?
Stripe 库需要用于签名验证的 webhook 请求的原始主体才能工作。看起来您提供的是 request.POST
,这是正文的修改版本。
如果您改用 request.body
,它应该可以正常工作。
使用生成的签名
验证您的 Stripe Webhook API 的脚本import hmac
import time
from hashlib import sha256
import requests
import stripe
webhook_url = 'https://your-site/api/stripe/webhook/'
stripe_secret = 'YOUR_STRIPE_WEBHOOK_SIGN_SECRET' # whsec_..
webhook_json_file = 'PATH_TO_JSON_FILE_WITH_WH_DATA/webhook_example.json'
def generate_stripe_signature_header(payload: str):
timestamp_utc = int(time.time())
signed_payload = "%d.%s" % (timestamp_utc, payload)
v1_sig = compute_signature(signed_payload, secret=stripe_secret)
return f't={timestamp_utc},v1={v1_sig}'
def compute_signature(payload: str, secret):
"""Take from stripe"""
mac = hmac.new(
secret.encode("utf-8"),
msg=payload.encode("utf-8"),
digestmod=sha256,
)
return mac.hexdigest()
with open(webhook_json_file, 'r') as f:
payload = f.read()
signature = generate_stripe_signature_header(payload=payload)
headers = {
'STRIPE-SIGNATURE': signature,
'Content-Type': 'application/json',
}
session = requests.Session()
session.headers.update(**headers)
response = session.post(webhook_url, data=payload)
print(response.content)
print(response.status_code)
response.raise_for_status()
P.S. 如果您想将它用于 单元测试 / Django 测试客户端,需要在签名头添加HTTP_前缀
signature = generate_stripe_signature_header(payload=payload)
headers = {
'HTTP_STRIPE-SIGNATURE': signature,
'Content-Type': 'application/json',
}
self.client.post(webhook_url, data=payload, **headers)
就我而言,为了解决我的问题,我对正文进行了解码:
payload = request.body.decode('utf-8')