Skip to content

InAppPayments

Andreas Schildbach edited this page Jun 7, 2015 · 15 revisions

How to integrate in-app payments in your Android app.

Introduction

You might want to send Bitcoins from your app. A common example is a donation button.

Check out the code from the repository. There are two subprojects for in-app payments:

  • integration-android: A tiny library for integrating Bitcoin payments into your own Android app (e.g. donations, in-app purchases).
  • sample-integration-android: A minimal example app to demonstrate integration of Bitcoin payments into your Android app.

Using Maven

<dependency>
    <groupId>de.schildbach.wallet</groupId>
    <artifactId>integration-android</artifactId>
    <version>2.0</version>
</dependency>

Using Gradle

dependencies {
    compile 'de.schildbach.wallet:integration-android:2.0'
}

License

The integration-android library and the examples on this page are licensed under Apache License Version 2.0.

Requesting coins using a Bitcoin-URI (BIP21)

Have a look at the Javadoc for the class BitcoinIntegration.

class de.schildbach.wallet.integration.android.BitcoinIntegration

/**
 * Request specific amount of Bitcoins from user,
 * without feedback from the app.
 */
static void request(Context context, String address, long amount);

/**
 * Request specific amount of Bitcoins from user,
 * with feedback from the app.
 */    
static void requestForResult(Activity activity, int requestCode,
                             String address, long amount);

Methods for requests without amount are also available!

The above methods send an intent to any Bitcoin app which listens to it.

action = android.intent.action.VIEW
data = bitcoin:1PZmMahjbfsTy6DsaRyfStzoWTPppWwDnZ?amount=0.1

The URI is formatted according to BIP21.

Retrieving the result

Some apps return a result through onActivityResult() after the user has gone through the sending process. In this case you can read some useful extras:

resultCode = OK|CANCELED
extras[transaction_hash] = c8a9e036ecbbe75c...

You can use this convenience method to fetch the hash:

class de.schildbach.wallet.integration.android.BitcoinIntegration

/**
 * Get transaction hash from result intent.
 */
static String transactionHashFromResult(final Intent result);

This is an example of code for using the result:

protected void onActivityResult(int requestCode, int resultCode, Intent result)
{
    if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK)
    {
        String txHash = BitcoinIntegration.transactionHashFromResult(result);
        if (txHash != null)
        {
            // thank you!
            // (but: no guarantees)
        }
    }
    else if (resultCode == Activity.RESULT_CANCELED)
    {
        // cancelled
    }
    else
    {
        // something went wrong
    }
}

Requesting coins using a payment request message (BIP70)

You can also pass a payment request message into the wallet app. This is mainly meant for fetching a payment request from a server and passing it into the app. You're responsible for formatting the ProtoBuf message yourself. Payment requests can be signed by the server which can make them more secure than BIP21 URI-based requests.

/**
 * Request payment from user, without feedback from the app.
 */
static void request(Context context, byte[] paymentRequest);

/**
 * Request payment from user, with feedback from the app.
 */
static void requestForResult(Activity activity, int requestCode, byte[] paymentRequest)

Apps will return a payment message in the result intent. Use this method to retrieve it:

/**
 * Get BIP70 payment message from result intent.
 */
static byte[] paymentFromResult(Intent result)

If you pass this message to your server, it can verify the payment more quickly. Again, here is an example of code for using the result:

protected void onActivityResult(int requestCode, int resultCode, Intent result)
{
    if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK)
    {
        byte[] paymentMessage = BitcoinIntegration.paymentFromResult(result);
        if (paymentMessage != null)
        {
            // thank you!
            // (but: no guarantees)
        }
    }
    else if (resultCode == Activity.RESULT_CANCELED)
    {
        // cancelled
    }
    else
    {
        // something went wrong
    }
}

The messages are formatted according to BIP70.