【问题标题】:How do i notify the user about a webhook In django我如何在 django 中通知用户有关 webhook 的信息
【发布时间】:2020-04-08 16:10:19
【问题描述】:

您好,我在 django 中遇到了网络挂钩问题到我的网络钩子我如何向用户显示它以通知它是否成功

我的代码是:这是用户将结帐详细信息发送到我的服务器的地方 跳跃添加一个等待的微调器,根据用户是否已付款,解析为滴答声或 X

<script>
        document.getElementById("checkout-btn").addEventListener('click', analyzeText());
        function analyzeText(){
            var wallet = document.getElementById('wallet').value;
            var phone = document.getElementById('phone').value;
            var order_id = document.getElementById('order_id').value;
            $.ajax({
                type: "POST",
                url: "{% url 'orders:Checkout' %}",   /* Call python function in this script */
                data: {csrfmiddlewaretoken: '{{ csrf_token }}',
                        wallet: wallet,
                        phone:phone,
                        order_id:order_id,
                                        },   /* Passing the text data */
                success: callback
            });
        }
        function callback(response){
            console.log(response);
        }
</script>

发送到的视图执行此操作,它基本上只是调用结帐 API,如果成功或失败,该 API 现在处理结帐,应将 webhook 发送到我的回调 url

def processOrder(request):
    def spektraCheckoutLink(amount, reference, transaction_id, order_id):
        url = "https://api.spektra.co/api/v1/payments/pay-in"

        # request payload
        # spektraAccountName is Optional, used for subaccount-specific payments
        payload = {
            "amount": amount,
            "account": phone,
            "currency": "KES",
            "description": reference,

        }
        # pass authorization token obtained during authentication in headers
        authcode = str(auth())
        headers = {
            'Content-Type': "application/json",
            'Authorization': "Bearer " + authcode
        }
        response = requests.request("POST", url, data=json.dumps(payload), headers=headers)
        # Print response data
        print(response.json())
        data = response.json()
        return True

    if request.method == "POST":
        global order_id
        try:
            order_id = request.POST['order_id']
        except Exception  as e:
            print(e)
            print(traceback.format_exc())

            raise HttpResponseServerError()
        order = Order.objects.get(id=order_id)
        try:
            wallet = request.POST['wallet']
            order.wallet = wallet
        except Exception  as e:
            print(e)
            print(traceback.format_exc())

            raise HttpResponseServerError()
        try:
            phone = request.POST['phone']
            order.phone = phone
        except Exception as e:
            print(e)
            print(traceback.format_exc())

            raise HttpResponseServerError()
        order.save()
    try:
        current_user = get_user_model().objects.get(id=request.user.id)
        Transaction.objects.get_or_create(user=current_user, order=order, amount=order.price, phone=order.phone)
        trans = Transaction.objects.get(order=order)
        link = spektraCheckoutLink(order.price, order.order_reference, trans.id, order.id)
        return redirect(link)
    except Exception as e:
        print(e)
        print(traceback.format_exc())

        # redirect to 404
        raise HttpResponseServerError()

我不知道当回调到达时我将如何更改用户前端的微调器状态以通知他们交易是否成功

这是我的 webhook 视图,它更新了支付订单我的问题是我如何在他的浏览器中通知用户付款已完成我不知道该怎么做

def processOrderStatus(request):
    # updates transaction number and status
    data = json.loads(request.body)
    order = Order.objects.get(phone=data['account'])
    order.order_status = order.PAID
    order.save
    id = request.user.id
    return redirect('orders:Orders', user_id=id)

【问题讨论】:

  • WC to SO,你能解释一下你想如何通知用户吗?使用电子邮件?更改订单状态?向用户发出警报?包含一些代码(你的 webhook)会很棒
  • 嗨,我更改了它添加了更多详细信息
  • 如果我理解得很好,用户将被发送到“spektra”结帐,当用户完成该过程时,它会被发送回您的站点吗?
  • 基本上是的,但我现在想要的是不使用结帐链接,而是根据回调 url 中给出的数据状态更改状态的微调器,我不知道该怎么做

标签: django notifications webhooks


【解决方案1】:

了解您的需求我将尝试为您提供几种可能的方法来完成您的需求,第一种方法是使用 javascript 间隔和 ajax 调用每 5 秒获取一次订单状态,第二种方法将使用长轮询策略。

以下代码必须根据您的需要进行调整,并且未经测试,请作为指导。

使用 5 秒间隔的 AJAX 请求

在您的 django 应用程序中创建一个视图,该视图将接收订单 PK 并以 json 格式返回其状态

{
    'pk': XX,
    'status': ['processing_payment', 'paid', 'refused', ...]
}

(自行调整状态值)

Python 视图

class OrderStatusView(View):
    """ just return a json with the current status of the order """        
    def get(self, request, *args, **kwargs):
        order_pk = kwargs.get('pk')
        order = Order.objects.get(pk=order_pk)
        ret_values = {'pk': order.pk, 'status': order.status}
        return HttpResponse(json.dumps(ret_values))

javascript部分

var check_order_status = function (order_pk) {
    $.ajax({
        url: '/ajax/order/' + order_pk + '/status/',
        dataType: 'json',
        success: function (data) {
            switch (data['status']) {
               case 'processing_payment':
                   // just keep the spinner on
               break;
               case 'paid':
                   // Change the spinner to a green check or whatever you prefer
                   // Stop sending requests
                   clearInterval(order_status_interval);
               break;
               case 'refused':
                   // Change the spinner to a red cross or whatever fit better to your app
                   // Stop sending requests
                   clearInterval(order_status_interval);
               break;
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {}
    });

};
$(function () {
    var order_status_interval = setInterval(function() { check_order_status(ORDER_PK); }, 5000);
});

如您所见,我们将每 5 秒向服务器发送一次请求,如果它返回像 paidrefused 这样的“结束”状态,您应该更新您的布局并且不要再发出请求,否则,请继续查看换一个。

长轮询

使用长轮询策略类似,但不是每 5 秒向后端发送一次请求,您的视图应该实现睡眠时间并检查状态变化,保持线程与客户端打开,如果超时是提出,前端必须重新发送请求。

你的视图看起来像这样

class OrderStatusView(View):
    """ Wait until order status changes to paid or refused to long poll for a change """

    def get(self, request, *args, **kwargs):
        order_pk = kwargs.get('pk')
        order = Order.objects.get(pk=order_pk)
        while order.status not in ['paid', 'refused']:
            time.sleep(5)  # sleep for 5 seconds
            order = Order.objects.get(pk=order_pk)
        # order status is a final one
        ret_values = {'pk': order.pk, 'status': order.status}
        return HttpResponse(json.dumps(ret_values))

您的 javascript 代码应控制是否返回超时,在这种情况下,请执行新请求。

var check_order_status = function (order_pk) {
    $.ajax({
        url: '/ajax/order/' + order_pk + '/status/',
        dataType: 'json',
        success: function (data) {
            switch (data['status']) {
               case 'processing_payment':
                   // just keep the spinner on
               break;
               case 'paid':
                   // Change the spinner to a green check or whatever you prefer
                   // Stop sending requests
                   clearInterval(order_status_interval);
               break;
               case 'refused':
                   // Change the spinner to a red cross or whatever fit better to your app
                   // Stop sending requests
                   clearInterval(order_status_interval);
               break;
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            switch (jqXHR.status) {
                // timeout http codes
                // 408 Request timeout
                // 504 Gateway timeout
                case 408:
                case 504:
                    check_order_status(ORDER_PK);
                break;
                default:
                    // Throw some error
            }
        }
    });

};
$(function () {
    check_order_status(ORDER_PK);
});

请记住,这种方法可能会在高流量条件下消耗大量线程,这有时会影响您的服务器性能。


WebSockets

最开销的选项是使用 django-channels 或 centrifugo 实现 websockets,但我不会为此尝试。


最简单的一个

由于您不知道什么时候会调用您的 webhook,请考虑向您的用户发送一封电子邮件,通知付款结果并在订单详细信息中附上 CTA,我认为这是让您留住用户的最简单方法通知。


希望这能让你走上正确的道路

【讨论】:

  • 非常感谢你不知道这段代码对我有多大帮助
  • 很高兴为您提供帮助!如果您认为我的回答对进一步参考有用,请不要犹豫将其标记为已接受!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-22
  • 2012-01-27
  • 1970-01-01
  • 2020-02-02
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多