android - Error de suscripción en la compra dentro de la aplicación en la Validación de API de Google (Suscripción no renovable/Prepago)
Quiero ofrecer suscripciones que no se renueven automáticamente para los usuarios dentro de mi aplicación y compras en Google Play. Tengo todo configurado, pero las transacciones relacionadas no pueden ser verificadas correctamente por mi función en la nube.
Estoy usando androidpublisher_v3 de "googleapis" dentro de una función de typescript/nodejs.
Cuando intento validar una suscripción que no se renueva, la verificación del servidor (Purchases.products:get) genera un error 404:
could not verify the purchase because of error GaxiosError: The document type is not supported.
at Gaxios._request (/workspace/node_modules/gaxios/build/src/gaxios.js:136:23)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async JWT.requestAsync (/workspace/node_modules/google-auth-library/build/src/auth/oauth2client.js:408:18)
at async GooglePlayPurchaseHandler.handleNonSubscription (/workspace/lib/google-play.purchase-handler.js:85:30)
at async /workspace/node_modules/firebase-functions/lib/common/providers/https.js:458:26
.
.
.
code: 404,
errors: [
{
message: 'The document type is not supported.',
domain: 'androidpublisher',
reason: 'unsupportedDocType',
location: 'token',
locationType: 'parameter'
}
[Symbol(gaxios-gaxios-error)]: '6.5.0'"
El token es válido, igual que en la Gestión de Pedidos de Google, cuyo pago aparece cargado.
Si intento validar la suscripción no renovable utilizando Purchases.subscription:get, se genera un error 404 "Su solicitud no es válida para esta compra de suscripción.", lo cual parece correcto, ya que se espera usar Purchases.products:get para suscripciones prepagadas, según la documentación.
He estado luchando durante una semana y he intentado diferentes formas de manejarlo sin éxito.
La suscripción renovable y los productos no consumibles de una sola vez funcionan correctamente (Purchases.subscription:get/Purchases.products:get).
Mi código:
export class GooglePlayPurchaseHandler extends PurchaseHandler {
private androidPublisher: AndroidPublisherApi.Androidpublisher;
constructor(private dbCalls: dbCalls) {
super();
this.androidPublisher = new AndroidPublisherApi.Androidpublisher({
auth: new GoogleAuth({
credentials,
scopes: ["https://www.googleapis.com/auth/androidpublisher"],
}),
});
}
async handleSubscription(
userId: string, productData: ProductData, token: string, productID: string
) : Promise<boolean> {
console.warn(
"called Google handleSubscription"
);
console.warn(
`ANDROID_PACKAGE_ID: ("${ANDROID_PACKAGE_ID}")`
);
console.warn(
`productID: ("${productID}")`
);
console.warn(
`token: ("${token}")`
);
try {
const response = await this.androidPublisher.purchases.subscriptions.get({
packageName: ANDROID_PACKAGE_ID,
subscriptionId: productID,
token,
});
if (!response.data.orderId) {
console.error("Could not handle purchase without order id");
return false;
}
console.log("mapped orderId handleSubscription");
// Update order id if necessary
let orderId = response.data.orderId;
const orderIdMatch = /^(.+)?[.]{2}[0-9]+$/g.exec(orderId);
if (orderIdMatch) {
orderId = orderIdMatch[1];
}
console.log("called SubscriptionPurchase handleSubscription Google Play");
const purchaseData: SubscriptionPurchase = {
iapSource: "google_play",
orderId: orderId,
productId: productID,
userId: userId,
purchaseDate: new Date(parseInt(response.data.startTimeMillis ?? "0", 10)),
type: "SUBSCRIPTION",
expiryDate: new Date(parseInt(response.data.expiryTimeMillis ?? "0", 10)),
status: [
"PENDING",
"ACTIVE",
"ACTIVE",
"PENDING",
"EXPIRED",
][response.data.paymentState ?? 4] as SubscriptionStatus,
};
if (userId) {
await this.dbCalls.insertPurchaseInfo(
{...purchaseData, userId} as Purchase
);
} else {
await this.dbCalls.updatePurchaseInfo(
purchaseData as Purchase
);
}
return true;
} catch (e) {
console.log("could not verify the purchase because of error", e);
return false;
}
}
Mis dependencias:
"dependencies": {
"firebase-admin": "^12.1.0",
"firebase-functions": "^4.9.0",
"google-auth-library": "^9.8.0",
"googleapis": "^134.0.0",
"node-apple-receipt-verify": "^1.13.0"
},
Gracias a todos de antemano.
Respuesta #1
Después de un mes, Google respondió a mi ticket:
Esto debería estar funcionando como se pretende, ya que el plan de suscripción de tipo Prepagado era parte del nuevo flujo de trabajo de Suscripciones migradas indicado aquí. La antigua API de Suscripción no es compatible para devolver respuestas de carga útil para aquellos productos que utilizan los nuevos atributos o características. Para mitigar el problema, por favor asegúrese de usar la API SubscriptionV2 en este caso.
Para más detalles sobre los cambios, por favor consulte nuestra documentación.
No probé eso debido al retraso (he optado por continuar con la renovación de la suscripción), pero espero que funcione para aquellos que se enfrenten a lo mismo que yo enfrenté.