如何在django中通知用户有关Webhook的信息 [英] How do i notify the user about a webhook In django

查看:71
本文介绍了如何在django中通知用户有关Webhook的信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我在Django中出现了Web挂钩问题,我需要一种方法来通知用户,他/她已经成功付款,并且收到了有关Web挂钩成功的通知,方法是将URL添加到我的发送付款成功请求的处理器中到我的网页挂钩中,如何向用户显示此内容以通知其成功

Hello ive been having problems with web hooks in django i need a way to notify a user that he/she has made a successful payment am notified about a successful web hook from adding a URL to my processor that sends a payment successful request to my web hook how can i show this to the user to notify if its successful

我的代码是:这是用户向我的服务器发送结帐详细信息的地方希望添加一个等待的微调器,该微调器会根据用户是否付款而解析为刻度或X.

my code is: this is where the user sends checkout details to my server hopping to add a waiting spinner that resolves to a tick or an X depending if the user has paid

<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>

发送到该视图的视图将执行此操作,它基本上只是调用checkout API,该API现在可以处理是否成功将Webhook发送到我的回调URL的checkout

the view this is sent to does this and its basically just calling the checkout API which now deals with the checkout if succesful or failed a webhook should be sent to my callback 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()

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

what i don't know is how i'm going to change the spinner status on the users front end when the callback arrives to notify them if the transaction was successful or not

这是我的webhook视图,它更新了付款顺序,我的问题是我如何才能在浏览器中通知用户付款已完成,我不知道怎么做

this is my webhook view which updates the order to paid my question is how can i notify the user in his browser that the payment is complete i dont know how to do it

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)

推荐答案

了解您的需求,我将尝试通过几种可能的方式来满足您的需求,第一种是将JavaScript间隔与and ajax调用结合使用为了每5秒获取一次订单状态,第二种方法将使用长轮询策略.

Knowing your needs I will try to put you on a couple of possible ways to accomplish what you need, the first one is using a javascript interval with and ajax call to get the order status every 5 seconds, the second approach will use a long-polling strategy.

以下代码必须适合您的需求,并且未经测试,请以其为指导.

The following code must be adapted to your needs and it's not tested, take it as a guide.

AJAX请求的间隔时间为5秒

在您的Django应用中创建一个视图,该视图将接收订单PK并以json之类的形式返回其状态

Create a view in your django app which will receive an order PK and return it's status in a json like

{
    '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部分

The javascript part

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秒钟向服务器发送一个请求,如果它返回结束"状态(如 paid refused ),则应更新布局而不做进一步的请求,否则,请继续寻找更改.

As you can see we will send a request to the server every 5 seconds, if it returns an 'ending' status like paid or refused you should update your layout and not do further requests, otherwise, keep looking for a change.

长轮询

使用长轮询策略将是类似的,但是您的视图应该实现睡眠时间并检查状态更改,以使线程在客户端处于打开状态(如果超时),而不是每5秒向后端发送一次请求,,前端必须再次重新发送请求.

Using a long-polling strategy will be similar but instead of sending a request to your backend every 5 seconds, your view should implement a sleep time and check for a status change keeping the thread with the client open, if a timeout is raised, the front-end must re-send the request again.

您的视图支架看起来像这样

Your view shold look something like this

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代码应控制是否返回超时,在这种情况下,请执行新请求.

Your javascript code should control if a timeout is returned, in that case, do a new request.

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);
});

请记住,这种方法会在高流量情况下消耗大量线程,这有时会影响服务器性能.

Keep in mind that this approach can consume lot's of threads in high traffic conditions which can, at some point, affect your server performance.

WebSockets

最麻烦的选择是使用django-channels或centrifugo实现websocket,但我不会为此尝试一下.

The most over-head option will be to implement websockets using django-channels or centrifugo but I will not give it a try just for this.

最简单的人

由于您不知道何时调用网络挂钩,请考虑仅向用户发送一封电子邮件,告知付款结果,并在订单详细信息中附上CTA,我认为这是保持用户身份的最简单方法知情的.

Since you don't know when your webhook will be called, consider to just send an email to your user notifying the payment result and with a CTA to the order details, I think that this is the easiest way to keep you user informed.

希望这能使U处于正确的状态

Hope this puts U on the right way

这篇关于如何在django中通知用户有关Webhook的信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆