{"id":137923,"date":"2021-09-29T00:00:00","date_gmt":"2021-09-29T00:00:00","guid":{"rendered":"https:\/\/adapty.io\/es-android-in-app-purchases-part-4-billing-library-error-codes-and-how-not-to-fail-testing\/"},"modified":"2025-06-26T13:05:05","modified_gmt":"2025-06-26T13:05:05","slug":"android-in-app-purchases-part-4-billing-library-error-codes-and-how-not-to-fail-testing","status":"publish","type":"post","link":"https:\/\/adapty.io\/es\/blog\/android-in-app-purchases-part-4-billing-library-error-codes-and-how-not-to-fail-testing\/","title":{"rendered":"Las compras dentro de la aplicaci\u00f3n de Android, parte 4: facturaci\u00f3n de los C\u00f3digos de Error de la Biblioteca y c\u00f3mo no fallar en las pruebas."},"content":{"rendered":"\n

Hoy hablaremos de los c\u00f3digos de error<\/a> que podemos obtener de la Biblioteca de Facturaci\u00f3n en el m\u00e9todo getResponseCode()<\/a>.<\/p>\n\n\n\n

Puedes encontrar un ejemplo de c\u00f3mo pasamos los errores en nuestras devoluciones de llamada en este art\u00edculo<\/a>. Ya hemos considerado uno de los errores en art\u00edculos anteriores: se trata de USER_CANCELED<\/strong><\/a> cuando un usuario cierra el di\u00e1logo de compra sin comprar nada. Conozcamos a los dem\u00e1s.<\/p>\n\n\n\n\n\n

ERROR y DEVELOPER_ERROR<\/h2>\n\n\n\n

Empecemos con los errores llamados ERROR<\/strong><\/a> (responseCode 6) y DEVELOPER_ERROR<\/strong><\/a> (responseCode 5). Para el primer caso, Google escribe en la documentaci\u00f3n \u00abError fatal durante la acci\u00f3n de la API\u00bb, para el segundo – \u00abArgumentos no v\u00e1lidos proporcionados a la API\u00bb. Por ejemplo, pude obtener un DEVELOPER_ERROR cuando pas\u00e9 una cadena vac\u00eda al constructor en setType()<\/a> para la solicitud querySkuDetailsAsync()<\/a>.<\/p>\n\n\n\n

Pero no es tan simple. Fui m\u00e1s all\u00e1 y en el m\u00e9todo launchBillingFlow()<\/a> utilic\u00e9 el SkuDetails modificado (extraje el json de SkuDetails<\/a> del producto real, cambi\u00e9 el productID en \u00e9l y lo pas\u00e9 al nuevo constructor SkuDetails). De hecho, es un argumento no v\u00e1lido, y esperaba obtener un DEVELOPER_ERROR<\/strong>, pero … Tengo un ERROR<\/strong>.<\/p>\n\n\n\n

Esto, por supuesto, era un ejemplo artificial. El caso en el que Google rechaz\u00f3 el pago es mucho m\u00e1s cercano a la realidad. Si seleccionas \u00abtarjeta de prueba, siempre rechazada\u00bb en el di\u00e1logo de compra al probar las compras con una tarjeta de prueba, de lo que te hablaremos al final del art\u00edculo, tambi\u00e9n volver\u00e1 el ERROR<\/strong>, pero con un texto adecuado.<\/p>\n\n\n\n

En el tercer art\u00edculo<\/a>, donde se describ\u00eda el cambio de suscripci\u00f3n, aumentamos el precio de una suscripci\u00f3n anual casi 3 veces para uno de los modos de prorrateo, pero no dijimos qu\u00e9 error deber\u00eda haber habido si no hubi\u00e9ramos hecho eso. Estamos reparando los da\u00f1os.<\/p>\n\n\n\n

Como resulta que all\u00ed se especifica un modo de prorrateo err\u00f3neo, l\u00f3gicamente deber\u00edamos obtener el mismo DEVELOPER_ERROR<\/strong>. En su lugar, obtenemos SERVICE_UNAVAILABLE<\/strong><\/a> (responseCode 2). Tambi\u00e9n lo conseguimos si introducimos cualquier n\u00famero inadecuado como modo de prorrateo (esto es int, no enum, nadie nos lo impedir\u00e1), y si especificamos un PurchaseToken incorrecto. Consultamos la documentaci\u00f3n sobre SERVICE_UNAVAILABLE<\/strong> y … espera, \u00bfqu\u00e9? Vemos que la \u00abConexi\u00f3n de red est\u00e1 inactiva\u00bb.<\/p>\n\n\n\n

Al mismo tiempo, tambi\u00e9n vemos un extra\u00f1o di\u00e1logo:<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

Otra cosa interesante en el caso del ERROR <\/strong>es que al cerrar el di\u00e1logo NO <\/strong>a trav\u00e9s del bot\u00f3n \u00abOK\u00bb (es decir, por medios que se interpretan como \u00abnavegar de vuelta\u00bb), el ERROR <\/strong>llega a onPurchasesUpdated()<\/a>, y en el caso de SERVICE_UNAVAILABLE<\/strong> en una situaci\u00f3n similar llega USER_CANCELED<\/strong> (pero si se hace clic en \u00abOK\u00bb en el di\u00e1logo, recibiremos SERVICE_UNAVAILABLE<\/strong>, como se esperaba).<\/p>\n\n\n\n

Y en el caso de p\u00e9rdida de conexi\u00f3n a Internet, de hecho, viene SERVICIO_DISPONIBLE<\/strong>.<\/p>\n\n\n\n

C\u00f3digos de error<\/h2>\n\n\n\n

Aqu\u00ed hay m\u00e1s c\u00f3digos de error con peque\u00f1os comentarios, por as\u00ed decirlo, menciones honor\u00edficas.<\/p>\n\n\n\n