Trigger.IO pagos en la aplicación duplicados callbacks mismo orderid con distinta firma

Hemos encontrado un extraño problema en el módulo de pago de trigger.io. El flujo funciona perfectamente con los pagos de ios, pero en android, algunos callbacks de pago en la aplicación se llaman dos veces en el mismo segundo. Las firmas de recepción son diferentes, pero el orderid, notificationid, purchasetoken y developerPayload permanecen todos iguales. Cuando tratamos de validar el recibo resulta ser cierto y correcto. Pero cuando nos fijamos en el informe financiero, sólo vemos un pago en lugar de dos (porque es probablemente sólo un pago, pero ¿por qué las firmas diferentes?).

¿Por qué trigger.io llama a la devolución de llamada dos veces lo que lleva al producto que se compra dos veces? ¿Por qué android devuelve 2 recibos diferentes y confirmables para un pago? ¿Es esto un error en el lado andorid o trigger.io lado, porque no tengo forma de llamar a la devolución de llamada usando javascipt? O es un intento de hackeo conocido?

También encontramos un caso en el que no se llamaba en absoluto, mientras que la tarjeta de crédito se cobró con éxito. ¿Es esto un error o hay alguna solución para este caso?

Aquí está el código que estoy iniciando una compra:

if(forge.is.android()) forge.payments.purchaseProduct("someproductname", paymentSuccess, paymentError); 

Y aquí está la función de devolución de llamada:

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

Esto se llama un ataque de repetición. Normalmente, actualizará su base de datos si ha recibido un pago (devolución de llamada, por ejemplo, IPN para PayPal). Si llaman al mismo orden una y otra vez, el ataque fallará porque el estado ya está establecido en true.

En días anteriores esto era un ataque común.

Lea los artículos siguientes:

Edit: Supongo que hacer un inserto en su base de datos después de la devolución de llamada? Es mejor insertar la orden antes de la devolución de llamada (antes de la comprobación real) y crear un campo de estado en su tabla que se establece por defecto como false. Cuando se realiza la devolución de llamada, debe actualizar el estado y establecerlo en true.

P.ej. Quiero pedir una pizza (el dueño pone mi pedido en el sistema). Mi recibo es mi comprobante de pago (devolución de llamada). Cuando la pizza está lista, la como, pero sigo con hambre. Regreso al pizzaboy y pido uno nuevo (podría repetirlo mil veces). Una solución simple sería destruir mi recibo o poner una firma en él (estado de actualización) y yo no sería capaz de ordenar la misma pizza de nuevo.

Editar editar: Cuando acepte PayPal, tenga en cuenta el "ataque" de devolución de cargos ( http://forums.whirlpool.net.au/archive/2214159 ).

13/05/2014 : Lo único que veo en este momento es que su AJAX data property tiene un formato incorrecto. Esto no es una cadena sino un objeto. El no es probablemente el verdadero problema. Si no siempre recibes una devolución de llamada y estás seguro de que tu solicitud llega a los servidores de Google supongo que es un problema de su lado (o Trigger.IO). Le aconsejo que se ponga en contacto con Trigger.IO para asegurarse de que su solicitud realmente llega a sus servidores. Si lo hace, puede ponerse en contacto con Google acerca de este problema y ver si reciben todas sus solicitudes.

 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(); } }); 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.