studio purchase play inapp google app php android in-app-billing

php - purchase - ¿Cómo verifico las transacciones de facturación en la aplicación de Android en MI servidor?



in app billing subscription android (3)

Creé una aplicación de Android donde los artículos se pueden comprar usando in-app-billing integrada in-app-billing . Cuando se compra un artículo, la transacción se puede sincronizar fácilmente entre Android Market y el teléfono, para ser utilizado en la aplicación. Pero, necesito que MI servidor sepa de la compra. La decisión de entregar datos específicos de la aplicación se debe hacer en mi servidor, no en la aplicación del cliente.

P.ej

  1. El usuario compra el elemento X de Android Market.
  2. Los datos de transacción Y se envían al cliente.
  3. El cliente envía Y a mi servidor.
  4. El cliente le pide al servidor que entregue contenido para X.
  5. El servidor entrega contenido si Y es válido . ¿Cómo se puede lograr esto?

P: ¿Cómo verifico que los datos de transacción provenientes del cliente de Android (presumiblemente originados en los servidores de Google) no son falsos? Es decir, un hacker no generó los datos.

Servidor de Google -> Cliente de Android -> Mi servidor -> Cliente de Android

Tal vez esto es más una pregunta de PHP que cualquier otra cosa. Exactamente, ¿qué debería hacer mi script de servidor (PHP) para verificar que los datos recuperados son reales?


Los datos de la transacción se firman con una clave privada específica para su aplicación. También hay un nonce para evitar repeticiones (es decir, enviar los mismos datos válidos varias veces). Si verifica que el nonce es único y la firma es válida en su servidor, puede estar razonablemente seguro de que no es falso. Consulte la parte sobre IAB de esta presentación de Google IO para una discusión.


Usamos AndroidBillingLibrary .

Instale eso como un proyecto en Eclipse y deje que su proyecto lo importe como una biblioteca.

Implementamos BillingController.IConfiguration, algo así como

import net.robotmedia.billing.BillingController; public class PhoneBillingConfiguration implements BillingController.IConfiguration{ @Override public byte[] getObfuscationSalt() { return new byte[] {1,-2,3,4,-5,6,-7,theseshouldallberandombyteshere,8,-9,0}; } @Override public String getPublicKey() { return "superlongstringhereIforgothowwemadethis"; } }

Luego, para nuestra aplicación, extendimos la Application :

public class LocalizedApplication extends Application { @Override public void onCreate() { super.onCreate(); // BillingController.setDebug(true); BillingController.setConfiguration(new PhoneBillingConfiguration()); } }

AndroidManifest incluye esto (y todas las demás cosas)

<application android:icon="@drawable/icon" android:label="@string/app_name" android:name=".LocalizedApplication" <!-- use your specific Application --> android:largeHeap="true" android:hardwareAccelerated="true" > <!-- For billing --> <service android:name="net.robotmedia.billing.BillingService" /> <receiver android:name="net.robotmedia.billing.BillingReceiver"> <intent-filter> <action android:name="com.android.vending.billing.IN_APP_NOTIFY" /> <action android:name="com.android.vending.billing.RESPONSE_CODE" /> <action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" /> </intent-filter> </receiver>

Implementamos ISignatureValidator

public class PhoneSignatureValidator implements ISignatureValidator { private final String TAG = this.getClass().getSimpleName(); private PhoneServerLink mServerLink; private BillingController.IConfiguration configuration; public PhoneSignatureValidator(Context context, BillingController.IConfiguration configuration, String our_product_sku) { this.configuration = configuration; mServerLink = new PhoneServerLink(context); mServerLink.setSku(our_product_sku); } @Override public boolean validate(String signedData, String signature) { final String publicKey; if (configuration == null || TextUtils.isEmpty(publicKey = configuration.getPublicKey())) { Log.w(BillingController.LOG_TAG, "Please set the public key or turn on debug mode"); return false; } if (signedData == null) { Log.e(BillingController.LOG_TAG, "Data is null"); return false; } // mServerLink will talk to your server boolean bool = mServerLink.validateSignature(signedData, signature); return bool; } }

Son las últimas líneas de arriba las que llaman a tu clase y que realmente hablarán con tu servidor.

Nuestro PhoneServerLink comienza algo como esto:

public class PhoneServerLink implements GetJSONListener { public PhoneServerLink(Context context) { mContext = context; } public boolean validateSignature(String signedData, String signature) { return getPurchaseResultFromServer(signedData, signature, false); } private boolean getPurchaseResultFromServer(String signedData, String signature, boolean async) { // send request to server using whatever protocols you like } }


Use openssl_verify ($ data, $ signature, $ key)

Las variables $ data y $ signature deben enviarse desde el cliente de Android a su servidor php usando https. La transacción contiene ambos elementos. Envíelo a sus servidores antes de confirmar la transacción en el cliente (consulte la documentación aquí - http://developer.android.com/guide/market/billing/billing_integrate.html )

La tecla $ variable es su clave pública de Google disponible desde su cuenta de editor desde el panel Facturación e In-app Facturación. Copie la clave pública y utilícela en su código php, preferentemente utilizando un archivo de configuración que instale en sus servidores en lugar de en su código php real.

Si la llamada openssl_verify tiene éxito, debe almacenar los números de orden en sus servidores y asegurarse de que sean únicos para que no puedan volver a reproducirse. Tenga en cuenta que un único par de recibo y firma de datos podría contener muchos números de orden, aunque generalmente es un pedido.