如何通过 Stripe API 发送发票收据

Tho*_*din 5 stripe-payments

我想在客户的发票标记为“paid_out_of_band”时或之后向他们发送一封 Stripe 预建发票收据电子邮件。API 中似乎没有办法通过仪表板复制发票的“发送收据”按钮的行为:https://stripe.com/docs/receipts#manually-send-receipts-from-the -仪表板

我知道如果我使用发票生成的 PaymentIntent 是可能的,但这仅在发票最终确定时可用。在此用例中,用户可以编辑订单并返回结账,我希望我们不要创建多张发票并在每次发生这种情况时最终确定它们。为了解决这个问题,我使用一个单独的 PaymentIntent,更新它直到用户单击确认,然后在我们获得 Webhook 后生成发票payment_intent.succeeded。遗憾的是,您无法以这种方式链接 Invoice 和 PaymentIntent,因此我只是在两个对象的元数据中交叉引用它们。

我知道我可以发送自己的电子邮件,其中包含发票上存在的在线收据的链接,但我更喜欢使用预构建的 Stripe 版本。

bin*_*npy 3

我之前也遇到过类似的问题,我确实通过检索“charge”事件对象中可用的付款收据电子邮件 html 来处理它,然后将其作为 html 正文发送给您的电子邮件发件人。

例如,在我使用 django 和 djstripe 的情况下:

import stripe
import requests

from typing import Union
from djstripe import webhooks
from django.core.mail import EmailMessage

stripe.api_key = "xxxx"


def get_stripe_payment_receipt_html(
    invoice_or_payment_intent_data: dict,
) -> Union[str, None]:
    """
    function to retrieve the html text of payment receipt from stripe.
    :param `invoice_or_payment_intent_data` is dict of paid invoice or
            payment intent data that has "charge" or "latest_charge" id.
    :return html string or None
    """
    if (
        isinstance(invoice_or_payment_intent_data, dict)
        and invoice_or_payment_intent_data
    ):
        charge_id: Union[str, None] = invoice_or_payment_intent_data.get(
            "charge"
        ) or invoice_or_payment_intent_data.get("latest_charge")
        if not charge_id:
            return None

        try:
            charge_data = stripe.Charge.retrieve(charge_id)
            receipt_url: Union[str, None] = charge_data.get("receipt_url")
            if receipt_url:
                try:
                    response = requests.get(receipt_url, timeout=20)
                    if response.status_code == 200:
                        return response.text
                except requests.exceptions.HTTPError:
                    ...
        except (
            stripe.error.RateLimitError,
            stripe.error.InvalidRequestError,
            stripe.error.AuthenticationError,
            stripe.error.APIConnectionError,
            Exception,
        ):
            ...
    return None



@webhooks.handler("invoice.payment_succeeded")
def invoice_payment_succeeded(event, **kwargs):
    invoice_data: dict = event.data["object"]

    ...

    html_message = get_stripe_payment_receipt_html(invoice_data)
    if html_message is not None:
        try:
            message = EmailMessage(
                subject="Receipt from Foobar"
                body=html_message,
                from_email=settings.EMAIL_HOST_USER,
                to=[user.email],
                bcc=[default_email],
                reply_to=[default_email],
            )
            message.content_subtype = "html"
            message.send()
        except Exception as error:
            ...
    else:
        # using own payment receipt template
        ...



@webhooks.handler("payment_intent.succeeded")
def payment_intent_succeeded(event, **kwargs):
    payment_intent_data: dict = event.data["object"]

    ...

    html_message = get_stripe_payment_receipt_html(payment_intent_data)

    ...do the same as previous script
Run Code Online (Sandbox Code Playgroud)