如何通过 webhook 在 PayPal API 中确认每月订阅的计费?

Posted

技术标签:

【中文标题】如何通过 webhook 在 PayPal API 中确认每月订阅的计费?【英文标题】:How to confirm billing of a monthly subscription in PayPal API via webhook? 【发布时间】:2021-07-20 01:08:56 【问题描述】:

我正在尝试实现 PayPal 订阅流程,用户点击我通过仪表板创建的 PayPal 订阅按钮

在后端,我监听订阅计费成功时触发的PAYMENT.SALE.COMPLETED webhook。不幸的是,webhook 没有向我发送太多信息,因此我可以在我的数据库中检索与刚刚计费的订阅相关联的用户和项目。 这将使我能够安全地向该用户显示私人内容

这是 payPal 发送的 webhook 内容(抱歉,篇幅较长):

const response = 
        id: 'WH-4W487015EX264720U-32N35125TV248784B',
        event_version: '1.0',
        create_time: '2021-04-26T08:24:41.436Z',
        resource_type: 'sale',
        event_type: 'PAYMENT.SALE.COMPLETED',
        summary: 'Payment completed for EUR 6.9 EUR',
        resource: 
            billing_agreement_id: 'I-T2HP99MJTS1T',
            amount: 
                total: '6.90',
                currency: 'EUR',
                details: 
                    subtotal: '6.90'
                
            ,
            payment_mode: 'INSTANT_TRANSFER',
            update_time: '2021-04-26T08:23:59Z',
            create_time: '2021-04-26T08:23:59Z',
            protection_eligibility_type: 'ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE',
            transaction_fee: 
                currency: 'EUR',
                value: '0.48'
            ,
            protection_eligibility: 'ELIGIBLE',
            links: [
                
                    method: 'GET',
                    rel: 'self',
                    href: 'https://api.sandbox.paypal.com/v1/payments/sale/6R7481343K8159132'
                ,
                
                    method: 'POST',
                    rel: 'refund',
                    href: 'https://api.sandbox.paypal.com/v1/payments/sale/6R7481343K8159132/refund'
                
            ],
            id: '6R7481343K8159132',
            state: 'completed',
            invoice_number: ''
        ,
        links: [
            
                href: 'https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4W487015EX264720U-32N35125TV248784B',
                rel: 'self',
                method: 'GET'
            ,
            
                href: 'https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-4W487015EX264720U-32N35125TV248784B/resend',
                rel: 'resend',
                method: 'POST'
            
        ],
    

我尝试过GET/v1/payments/sale/:id,但它没有给我带来太多信息。

我还检查了有关该主题的其他堆栈溢出线程,但没有任何帮助。 我也不想使用前端 SDK 中提供的成功回调,因为它们不如 webhook 安全(连接可以在触发回调之前关闭see this gitlab issue)

我怎样才能知道用户已为其订阅付费?

【问题讨论】:

【参考方案1】:

我们终于找到了一种解决方法,让我们的后端检索买家和商品。

前端

在订阅按钮代码上,经过多次尝试/错误后,我们注意到createSubscription 方法接受承诺,并且我们可以使用它在继续付款之前将subscriptionId 发送到后端:

paypal.Buttons(
    style: ...,
    createSubscription: function (data, actions) 
        return actions.subscription.create(
            /* Creates the subscription */
            plan_id: 'P-26J60279VA924454WMCBPBSA',
        ).then(subscriptionId =>  // subscriptionId == I-9DH5L3A3JAEB
            return new Promise((res, rej) => 
                // here we send the subscriptionId to the back-end
                // and create a pending subscription
                const body = subscriptionId, userId, itemId;
                apiCall('POST', '/subscription', body,() => 
                    // allow to return subscriptionId to paypal
                    resolve(subscriptionId); 
                )
            );
        );
    ,
    onApprove: function (data, actions) 
       // this function was of NO USE
       // it is not safe to call your backend here
       // as connexion can close and paypal doesn't
       // wait after this function to capture payment
       // thus leading to orphaned subscriptions 
       // (paid but not linked to your backend)
    ,
).render('#paypal-button');

后端(webhook 处理程序)

后端等待确认 webhook,其中webhookResponse.resource.billing_agreement_id 是订阅 ID,并允许验证之前创建的订阅。我不太明白为什么billing_agreement_id 没有被命名为subscrition_id...

如果不清楚,请告诉我。我让它作为答案,直到有更好的方法来做到这一点:)

【讨论】:

您将监听“subscription created” webhook 事件以在您的数据库中创建订阅。但另外你必须监听每笔完成的付款,在你的数据库中注册交易,并为用户扩展访问权限,对吧? @JCarlosR 如果我没记错的话,我们习惯这样做(在completed_payment webhook 上收听),它还允许您每月确认订阅是否正确续订。

以上是关于如何通过 webhook 在 PayPal API 中确认每月订阅的计费?的主要内容,如果未能解决你的问题,请参考以下文章

PayPal + RESTful API + WebHooks + 自签名证书

我应该将 webhook 与 PayPal 的 V2 API 一起使用吗?

在 Zapier 中使用 Webhooks 和 PayPal API 从特定 PayPal 交易中获取交易信息

关于无法从开发者沙箱触发 Paypal REST API webhook 事件

PayPal API 购物车和 Webhooks?

PayPal Rest API (PHP SDK) webhook 未显示在沙盒事件列表中