¿Cómo verifico las transacciones de Android en la aplicación de la aplicación en mi servidor?

StackOverflow https://stackoverflow.com/questions/8379819

  •  28-10-2019
  •  | 
  •  

Pregunta

He hecho una aplicación de Android donde los artículos se pueden comprar usando en la aplicación. Cuando se compra un artículo, la transacción se puede sincronizar fácilmente entre Android Market y el teléfono, que se utilizará en la aplicación. Pero, necesito que mi servidor esté al tanto de la compra. La decisión de entregar datos específicos de la aplicación debe tomarse en mi servidor, no en la aplicación del cliente.

P.ej

  1. El usuario compra el artículo X del mercado de Android.
  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 ofrece contenido Si Y es válido. ¿Cómo se puede lograr esto?

P: ¿Cómo verifico que los datos de transacciones provenientes del cliente de Android (presumiblemente que se originan en los servidores de Google) no es falso? Es decir, un hacker no generó los datos.

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

Quizás esto sea más una pregunta de PHP que cualquier otra cosa. ¿Qué debe hacer exactamente mi script de servidor (PHP) para verificar que los datos recuperados sean reales?

¿Fue útil?

Solución

Use OpenSSL_verify ($ Data, $ Signature, $ Key)

Las variables $ datos y $ firma deben enviarse desde el cliente Android a su servidor PHP utilizando HTTPS. La transacción contiene ambos elementos. Envíelo a sus servidores antes de reconocer la transacción en el cliente (consulte la documentación aquí - http://developer.android.com/guide/market/billing/billing_integrate.html)

La clave variable $ es su clave pública de Google disponible en su cuenta de editor desde el panel de facturación de licencias y en la aplicación. Copie la clave pública y úselo en su código PHP, preferiblemente utilizando un archivo de configuración que instale en sus servidores en lugar de en su código PHP real.

Si el éxito de la llamada OpenSSL_verify, debe almacenar los números de pedido en sus servidores y asegurarse de que sean únicos para que no puedan ser reproducidos. Tenga en cuenta que un solo recibo de datos y un par de firmas podrían contener muchos números de pedido, aunque generalmente es un pedido.

Otros consejos

Nosotros 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 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 anteriores que llaman a su clase que realmente hablará con su 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 
    }

}

Los datos de transacción se firman con una clave privada específica para su aplicación. También hay una nonce para evitar repeticiones (es decir, enviar los mismos datos válidos, 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. Verifique la parte sobre IAB de Esta presentación de Google IO para una discusión.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top