Trigger.IO应用内付款重复回调相同的orderid具有不同的签名

Vol*_*kut 5 android in-app-purchase trigger.io

我们在trigger.io的支付模块中遇到了一个奇怪的问题.该流程与ios支付完美配合,但在Android中,一些应用程序内支付回调在同一秒内被调用两次.收据签名不同,但orderid,notificationid,purchasetoken和developerPayload都保持不变.当我们尝试验证收据时,结果是真实和正确的.但是当我们查看财务报告时,我们只看到一个付款而不是两个(因为它可能只是一个付款,但为什么不同的签名?).

为什么trigger.io调用两次回调导致产品被买两次?为什么android会为一次付款返回2个不同且可确认的收据?这是ororid方面或trigger.io方面的错误,因为我无法使用javascipt调用回调?或者这是一个已知的黑客企图?

我们还遇到了一个根本没有调用回调的情况,而信用卡被成功收费.这是一个错误还是有这种情况的解决方法?

这是我开始购买的代码:

if(forge.is.android())
forge.payments.purchaseProduct("someproductname", paymentSuccess, paymentError);
Run Code Online (Sandbox Code Playgroud)

这是回调函数:

function paymentCallback(data, confirm){

    forge.request.ajax({
        url: "someurl.php",
        dataType: "json",
        data:"function=logPayment&action=PaymentCallbackStart",
        success: function (data) {
            hideLoader();
        },
        error: function (error) {
            hideLoader();
        }
    }); 

    var productId = data.productId;
    var orderId = data.orderId;
    var signed_data;

    if(forge.is.android())
    {
        var state = data.purchaseState;
        var receipt = encodeURIComponent(data.receipt.signature);
        signed_data = encodeURIComponent(data.receipt.data);
    }
    else if(forge.is.ios())
    {
        var state = data.PurchaseState;
        var receipt = data.receipt.data;
    }

    forge.request.ajax({
        url: "someurl.php",
        dataType: "json",
        data:"function=logPayment&data=" +  encodeURIComponent("birthday=" +  gbirthday + "&birthhour=" +  gbirthhour + "&name=" +  gname + "&gender=" + ggender + "&birthday2=" + gbirthday2 + "&birthhour2=" +  gbirthhour2 + "&name2=" +  gname2 + "&gender2=" + ggender2 + "&content=" +  text + "&ProductID=" + qs.ProductID + "&userId=" + guserId + "&data=" + JSON.stringify(data)) + "&action=PaymentCallback",
        success: function (data) {
            hideLoader();
        },
        error: function (error) {
            hideLoader();

        }
    });     

    if(state == "PURCHASED")
    {
        if(typeof gbirthday != "undefined")
        {
            var text = $('#imessagem').val();
            forge.request.ajax({
                url: "someurl.php",
                dataType: "json",
                data:"function=askQuestion&birthday=" +  encodeURIComponent(gbirthday) + "&birthhour=" +  encodeURIComponent(gbirthhour) + "&name=" +  encodeURIComponent(gname) + "&gender=" + ggender + "&birthday2=" +  encodeURIComponent(gbirthday2) + "&birthhour2=" +  encodeURIComponent(gbirthhour2) + "&name2=" +  encodeURIComponent(gname2) + "&gender2=" + ggender2 + "&content=" +  encodeURIComponent(text) + "&ProductID=" + qs.ProductID + "&userId=" + guserId + "&signed_data=" + signed_data + "&receipt=" + receipt,
                success: function (data) {
                    processPayment(productId,orderId)
                    hideLoader();
                },
                error: function (error) {
                    hideLoader();

                    forge.request.ajax({
                        url: "someurl.php",
                        dataType: "json",
                        data:"function=logPayment&data=" + encodeURIComponent(JSON.stringify(error)) + "&action=PaymentQuestionError",
                        success: function (data) {
                            hideLoader();
                        },
                        error: function (error) {
                            hideLoader();

                        }
                    });                     

                }
            }); 

            forge.request.ajax({
                url: "someurl.php",
                dataType: "json",
                data:"function=logPayment&data=" +  encodeURIComponent(JSON.stringify(data)) + "&action=Payment",
                success: function (data) {
                    hideLoader();                   },
                error: function (error) {
                    hideLoader();

                }
            });             
        }
        if(forge.is.android())
        processPayment(productId,orderId);
    }
    else
    {
        if(forge.is.ios())
        processPayment(productId,orderId);
    }
    confirm();
}   
Run Code Online (Sandbox Code Playgroud)

Guy*_*uyT 1

这称为重放攻击。通常,如果您收到付款(回调,例如 PayPal 的 IPN),您将更新您的数据库。如果他们一次又一次地调用相同的命令,攻击就会失败,因为状态已经设置为 true。

早些时候,这是一种常见的攻击。

阅读以下文章:

编辑:我想您在回调后会在数据库中插入数据吗?最好在回调之前(在实际结帐之前)插入订单,并在表中创建一个默认设置为 false 的状态字段。回调成功后,您必须更新状态并将其设置为 true。

例如。我想订一份披萨(店主将我的订单输入系统)。我的收据是我的付款证明(回调)。披萨做好后我就吃了,但我还是很饿。我回到披萨店,要了一个新的(我可以重复这个一千遍)。一个简单的解决方案是销毁我的收据或在其上签名(更新状态),这样我就无法再次订购相同的披萨。

编辑编辑:当您接受 PayPal 时,请注意退款“攻击”( http://forums.whirlpool.net.au/archive/2214159 )。

13/05/2014:我目前唯一看到的是你的AJAX data property格式错误。这不是一个字符串,而是一个对象。这可能不是真正的问题。如果您并不总是收到回调,并且您确定您的请求到达了 Google 服务器,我猜这是他们这边(或 Trigger.IO)的问题。我建议您联系 Trigger.IO,以确保您的请求确实到达他们的服务器。如果是这样,您可以联系 Google 解决此问题,看看他们是否收到您的所有请求。

forge.request.ajax({
    url: "someurl.php",
    dataType: "json",
    data:{
        function(watchOut!! 'function' is a reserved keyword!!) : 'logPayment',
        action   : 'PaymentCallbackStart'
    },
    success: function (data) {
        hideLoader();
    },
    error: function (error) {
        hideLoader();
    }
}); 
Run Code Online (Sandbox Code Playgroud)