python Stripe:使用Django未找到与预期有效负载签名匹配的签名

m528fe3b  于 2023-01-24  发布在  Python
关注(0)|答案(4)|浏览(174)

Stripe调用定义的Web挂钩时出现以下错误
未找到与负载的预期签名匹配的签名
我正在关注这篇文章: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)

但奇怪的是,这给我带来了错误,不知道为什么?

watbbzwu

watbbzwu1#

Stripe库需要webhook请求的原始主体才能进行签名验证。看起来您提供的是request.POST,这是主体的修改版本。
如果使用request.body,它应该按预期工作。

zxlwwiss

zxlwwiss2#

使用生成的签名验证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_ prefix添加到签名标头

signature = generate_stripe_signature_header(payload=payload)
headers = {
    'HTTP_STRIPE-SIGNATURE': signature,  
    'Content-Type': 'application/json',
}
self.client.post(webhook_url, data=payload, **headers)
3z6pesqy

3z6pesqy3#

在我的例子中,为了解决我的问题,我解码了身体:

payload = request.body.decode('utf-8')
moiiocjp

moiiocjp4#

在我的情况下,我使用的秘密从stripe-cli。
相反,去webhook部分,点击你的webhook,最后点击reveal secret。这将显示你想要的秘密。

相关问题