我们在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);
这是回调函数:
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();
}
答案 0 :(得分:1)
这称为重播攻击。通常,如果您收到付款(回调,例如PayPal的IPN),您将更新数据库。如果他们一次又一次地调用相同的命令,则攻击将失败,因为状态已经设置为true。
在早些时候,这是一种常见的攻击。
阅读以下文章:
编辑:我猜你在回调后在数据库中插入?最好在回调之前插入订单(在实际结账之前),并在表中创建一个设置为默认为false的状态字段。回调成功后,您必须更新状态并将其设置为true。
EG。我想点一份比萨饼(老板把我的订单放在系统里)。我的收据是我的付款证明(回拨)。披萨准备好了,我吃了它,但我还是饿了。我回到pizzaboy,我要求一个新的(我可以重复这一千次)。一个简单的解决方案是销毁我的收据或在其上签名(更新状态),我将无法再次订购相同的披萨。
修改编辑:当您接受PayPal时,请注意退款'攻击'(http://forums.whirlpool.net.au/archive/2214159)。
13/05/2014 :我目前唯一看到的是AJAX data property
格式错误。这不是一个字符串而是一个对象。这不是真正的问题。如果你并不总是收到回叫,并且你确定你的请求到达谷歌服务器,我想这是他们身边的问题(或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();
}
});