How do I verify Android in-app-billing transactions on MY server?

后端 未结 3 1496
慢半拍i
慢半拍i 2020-12-23 11:29

I have made an Android app where items can be purchased using in-app-billing. When an item is purchased the transaction can easily be synced between Android Market and the p

相关标签:
3条回答
  • 2020-12-23 12:07

    Transaction data is signed with a private key specific to your app. There is also a nonce to prevent replays (i.e, sending the same, valid, data multiple times). If you verify that the nonce is unique and the signature is valid at your server, you can be reasonably sure that it's not fake. Check the part about IAB of this Google IO presentation for a discussion.

    0 讨论(0)
  • 2020-12-23 12:29

    We used AndroidBillingLibrary.

    Install that as a project in Eclipse and let your project import it as a library.

    We implemented BillingController.IConfiguration, something like

    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";
        }
    }
    

    Then for our application, we extended Application:

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

    AndroidManifest includes this (and all the other stuff)

    <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>
    

    We implemented 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;
        }
    
    }
    

    It's the last few lines above that call your class that will actually talk to your server.

    Our PhoneServerLink starts out something like this:

    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 
        }
    
    }
    
    0 讨论(0)
  • 2020-12-23 12:32

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

    The variables $data and $signature should be sent from the android client to your php server using https. The transaction contains both of these items. Send that to your servers before you acknowledge the transaction on the client.(see documentation here - http://developer.android.com/guide/market/billing/billing_integrate.html)

    The variable $key is your google public key available from your publisher account from the Licensing & In-app Billing panel. Copy the public key and use that in your php code, preferably using a config file you install on your servers rather than in your actual php code.

    If the openssl_verify call succeeds you should store the order numbers on your servers and ensure they are unique so they cannot be replayed. Be aware that a single data receipt and signature pair could contain many order numbers though its usually one order.

    0 讨论(0)
提交回复
热议问题