Todos los artículos
Deep dive7 min de lectura

Tu app puede mostrar una hoja de solicitud de reembolso dentro de la app, y esto es lo que hace Apple cuando el cliente toca enviar

La solicitud de reembolso dentro de la app de Apple permite que un cliente pida un reembolso sin salir de tu app, en una hoja que Apple construye y revisa. Esto es lo que devuelve beginRefundRequest, los relojes de CONSUMPTION_REQUEST y de 48 horas que arranca en tu servidor, y si vale la pena publicar el botón.

Una mano sosteniendo un smartphone que muestra una pantalla de ajustes de cuenta junto a un recibo de papel y una moneda, ilustrando una solicitud de reembolso dentro de la app que un cliente puede iniciar sin salir de la app

Puntos clave

  • beginRefundRequest de Apple es un método de StoreKit 2 que presenta la propia hoja de reembolso de Apple dentro de tu app. El cliente ve los detalles de su compra y una lista de códigos de motivo, elige uno, y la solicitud va a Apple. Tú no construyes el formulario ni decides el resultado.
  • La llamada devuelve un estado de success o userCancelled, o lanza duplicateRequest o failed. Un estado success significa que el App Store recibió la solicitud, no que la aprobó. Nunca muestres un reembolso confirmado en tu interfaz cuando devuelva success.
  • Después de que el cliente envía, Apple tarda hasta 48 horas en aprobar o denegar. Para compras consumibles, primero envía un CONSUMPTION_REQUEST a tu servidor, y tienes las habituales 12 horas para responder con datos de uso si el cliente dio su consentimiento.
  • El resultado llega a tu servidor como un App Store Server Notification, el mismo flujo que ya recibes. La aprobación es una notificación REFUND, la denegación es REFUND_DECLINED. La solicitud dentro de la app se enruta a ese flujo exactamente como un reembolso iniciado en la página reportaproblem de Apple.
  • El botón está disponible desde iOS 15 y iPadOS 15, Mac Catalyst 15 y visionOS 1, así que cualquier app que apunte a esas versiones puede presentarlo hoy.
  • El argumento financiero es que un reembolso que puedes disputar le gana a un contracargo que no puedes. Mantener al cliente dentro del flujo de Apple activa un CONSUMPTION_REQUEST que puedes responder, en lugar de un contracargo bancario que es definitivo y conlleva una comisión.
  • La recomendación de ubicación de Apple es invocarlo desde los ajustes de cuenta o un menú de ayuda, no desde una pantalla de compra, para que un cliente descontento lo encuentre sin anunciar los reembolsos a todos los demás.

Apple permite que un cliente solicite un reembolso sin salir jamás de tu app. Una sola llamada de StoreKit, beginRefundRequest, presenta la propia hoja de reembolso de Apple justo dentro de tu interfaz, el cliente elige un motivo, y la solicitud va a Apple para su revisión. Tú no construyes el formulario, no tocas el dinero, y no decides el resultado. Lo que obtienes es una forma de poner una ruta de reembolso donde el cliente frustrado ya está, en lugar de perderlo ante su banco. Esta es la solicitud de reembolso dentro de la app, y vale la pena entenderla antes de decidir si publicas el botón.

Aquí está la parte que importa para tus ingresos. El botón no reembolsa nada por sí solo. Abre una solicitud, Apple tarda hasta 48 horas en aprobarla o denegarla, y para compras consumibles primero dispara un CONSUMPTION_REQUEST hacia tu servidor. Así que la hoja no es un regalo. Es un embudo hacia la misma revisión de reembolso que ya puedes influir, y puede recuperar una disputa de la red de tarjetas antes de que se convierta en un contracargo que no puedes disputar.

Qué es realmente la hoja de solicitud de reembolso dentro de la app

beginRefundRequest es un método de StoreKit 2 que presenta la hoja de solicitud de reembolso para una transacción en una escena de ventana. La firma es breve: func beginRefundRequest(in scene: UIWindowScene) async throws -> Transaction.RefundRequestStatus. Cuando la invocas, el sistema muestra una hoja con los detalles de la compra del cliente y una lista de códigos de motivo para que elija. Apple construye y controla esa interfaz. Tú aportas la escena y la transacción, nada más.

La recomendación de Apple sobre dónde ponerlo es explícita. Invoca esta función desde los ajustes de cuenta o un menú de ayuda, para que un cliente que quiere un reembolso lo encuentre donde buscaría soporte. Se lanzó en iOS 15 y iPadOS 15, Mac Catalyst 15 y visionOS 1, así que cualquier app que apunte a esas versiones puede presentarlo hoy.

Dos formas de abrir la hoja

Hay dos puntos de entrada. Puedes invocar beginRefundRequest(in:) sobre una transacción específica que ya tengas, lo que acota la hoja a esa única compra. También puedes abrir la hoja por identificador de producto cuando quieras que el cliente reembolse la compra de un producto dado. En cualquier caso, la hoja, la lista de motivos y la decisión pertenecen a Apple. Tu trabajo termina al presentarla y leer el resultado.

Qué devuelve la llamada, y qué puede salir mal

El método es async throws, así que o devuelve un estado o lanza un error. Ambas son listas cortas, y ambas merecen manejarse para que tu interfaz diga algo verdadero cuando la hoja se cierre.

ResultadoTipoQué significa
successRefundRequestStatusEl App Store recibió la solicitud de reembolso. Está enviada, no aprobada
userCancelledRefundRequestStatusEl cliente cerró la hoja sin enviar. No se mandó nada
duplicateRequestRefundRequestErrorEl App Store ya tiene una solicitud de reembolso para esta compra
failedRefundRequestErrorEl envío en sí falló. Deja que el cliente lo intente de nuevo

Qué pasa en tu servidor después de que el cliente toca enviar

El cierre de la hoja es el inicio del proceso, no el final. Apple revisa la solicitud y tarda hasta 48 horas en aprobarla o denegarla. Para una compra consumible dentro de la app, antes de decidir, el App Store envía una notificación CONSUMPTION_REQUEST a tu servidor pidiendo datos de uso. Si el cliente dio su consentimiento para compartir esos datos, respondes a través del endpoint Send Consumption Information. Si no lo dio, la propia instrucción de Apple es no responder a la notificación en absoluto.

Una vez que Apple decide, el resultado aterriza en tu servidor como un App Store Server Notification. Es el mismo flujo que ya recibes, y la solicitud dentro de la app se enruta a él exactamente como un reembolso que un cliente inicia en la página reportaproblem de Apple. Nada del manejo cambia solo porque la solicitud empezó dentro de tu app.

EtapaQué se disparaTu acciónReloj
El cliente envía la hojabeginRefundRequest devuelve successRegístralo, muestra pendiente, no reembolsadoInstantáneo
Solo consumibles, Apple pregunta primeronotificación CONSUMPTION_REQUESTEnvía datos de consumo si el cliente dio su consentimiento, si no, mantente en silencio12 horas para responder
Apple apruebanotificación REFUNDRevoca el derecho de esa transacciónHasta 48 horas para decidir
Apple denieganotificación REFUND_DECLINEDConserva la venta, no cambies nadaHasta 48 horas para decidir
Un reloj de arena junto a un smartphone y un recibo de papel, ilustrando la espera de hasta 48 horas después de que un cliente envía una solicitud de reembolso dentro de la app a Apple

Qué te cuesta el botón, y qué puede ahorrarte

Un reembolso que puedes disputar le gana a un contracargo que no puedes

Un cliente que no encuentra una ruta de reembolso dentro de tu app no se rinde. Va a su banco. Un contracargo de tarjeta es definitivo con el banco, conlleva una comisión de disputa, y saca la decisión de tus manos y de las de Apple. Una solicitud de reembolso dentro de la app mantiene a ese mismo cliente dentro del sistema de Apple, donde una compra consumible activa un CONSUMPTION_REQUEST que puedes responder y una decisión que puedes influir. Cambiar un contracargo indisputable por una revisión disputable de Apple es todo el argumento financiero a favor del botón.

Estás reduciendo la fricción de un reembolso

El contrapeso honesto es que una ruta de reembolso visible y de un solo toque produce más solicitudes de reembolso que un correo de soporte enterrado. Algunas de esas nunca habrían ocurrido. Ese es un costo real, y por eso Apple te dice que coloques el punto de entrada en los ajustes de cuenta o un menú de ayuda en lugar de en la pantalla de compra. Quieres que lo encuentre el cliente que ya está descontento, no el cliente que solo tiene curiosidad.

El costo que corre todo el tiempo es servir a una cuenta reembolsada

Vaya como vaya la decisión, el contador de la entrega sigue corriendo hasta que actúes sobre el resultado. Cada hora que un derecho reembolsado permanece activo, sigues pagando los costos reales detrás de él: cómputo, llamadas a la API del modelo, almacenamiento, y cualquier pago a creadores o socios ligado al uso de ese cliente. La solicitud dentro de la app no cambia eso. Revocar de inmediato con la notificación REFUND sí. El botón es tan barato como sea tu manejo de la notificación que acaba produciendo.

¿Deberías publicar la solicitud de reembolso dentro de la app?

Ponla donde vive el soporte, no donde viven las ventas

Sigue la recomendación de ubicación de Apple. Los ajustes de cuenta y un menú de ayuda son los hogares correctos. Un enlace de reembolso junto a un muro de pago entrena a la gente a esperar su dinero de vuelta, e invita al reembolso por curiosidad que nunca necesitaste ofrecer.

Prueba el flujo completo en el sandbox antes de confiar en él

Puedes simular toda la ruta en el sandbox y en las pruebas de StoreKit de Xcode, moviendo una solicitud de pendiente a aprobada o denegada. Una aprobación entrega una notificación REFUND a tu servidor, y una denegación entrega REFUND_DECLINED, así que puedes comprobar que tu manejador reacciona correctamente antes de que un cliente real toque enviar.

Maneja cada resultado, y nunca exageres

Muestra pendiente en success, ofrece un reintento en failed, di que nada cambió en userCancelled, y trata duplicateRequest como una nota discreta de que la solicitud anterior del cliente sigue en pie. El único error que duele es decirle a un cliente que su reembolso está hecho cuando todo lo que tienes es una solicitud enviada.

Cómo maneja RefundHalt lo que viene después

La hoja dentro de la app es de Apple. Lo que viene después es tuyo, y esa es la parte que RefundHalt ejecuta. Cuando un cliente envía un reembolso desde dentro de tu app, RefundHalt atrapa el CONSUMPTION_REQUEST para compras consumibles y lo responde dentro de la ventana de 12 horas con la evidencia de uso que ayuda a Apple a decidir. Cuando Apple decide, revoca en REFUND y mantiene el acceso intacto en REFUND_DECLINED, cada uno vinculado a la transacción exacta. Puedes ofrecer la ruta de reembolso más amable dentro de la app sin dejar la revisión, la evidencia o la revocación a una carrera manual.

Preguntas frecuentes

¿Qué hace beginRefundRequest?
Presenta la hoja de solicitud de reembolso de Apple dentro de tu app para una transacción específica. El cliente ve los detalles de su compra y una lista de códigos de motivo, elige uno, y la solicitud va a Apple. El método devuelve un estado de success o userCancelled, o lanza duplicateRequest o failed. No reembolsa la compra en sí, porque Apple revisa la solicitud y tarda hasta 48 horas en decidir.
¿Una solicitud de reembolso dentro de la app reembolsa el dinero de inmediato?
No. Un resultado success significa que el App Store recibió la solicitud, no que la aprobó. Apple tarda hasta 48 horas en aprobar o denegar, y para consumibles primero pide a tu servidor datos de uso mediante una notificación CONSUMPTION_REQUEST. Muestra al cliente un estado pendiente en success, nunca un reembolso confirmado.
¿Qué versión de iOS admite la solicitud de reembolso dentro de la app?
iOS 15 y iPadOS 15, Mac Catalyst 15 y visionOS 1. El método de StoreKit 2 beginRefundRequest(in:) está disponible desde esas versiones, así que cualquier app que apunte a iOS 15 o posterior puede presentar la hoja de reembolso de Apple desde dentro de la app.
¿Dónde debería poner el botón de reembolso dentro de la app?
La recomendación de Apple es invocarlo desde los ajustes de cuenta o un menú de ayuda, no desde una pantalla de compra o muro de pago. Eso coloca la ruta de reembolso donde un cliente descontento busca soporte, sin anunciar los reembolsos a clientes que no iban a pedirlo.
¿Es mejor un reembolso dentro de la app que un cliente contactando a su banco?
Normalmente sí, para tus ingresos. Un contracargo bancario es definitivo y conlleva una comisión, y saca tanto a Apple como a ti de la decisión. Una solicitud de reembolso dentro de la app mantiene al cliente en el flujo de Apple, donde una compra consumible activa un CONSUMPTION_REQUEST que puedes responder y una revisión que puedes influir. Un reembolso disputable le gana a un contracargo indisputable.

Fuentes y lecturas adicionales

RefundHalt

El piloto automático de reembolsos para App Store y Google Play

Seguir leyendo

La próxima solicitud de reembolso ya está en camino.

Configura RefundHalt en el tiempo que tardas en leer otro correo de soporte sobre un reembolso que no llegaste a impugnar.