Skip to content

Commit

Permalink
Add README for examples app (#1383)
Browse files Browse the repository at this point in the history
- Add instructions for install and configuration
- Provide overview of Google Pay demo
  • Loading branch information
mshafrir-stripe committed Aug 15, 2019
1 parent 6bdf038 commit cf7211c
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 39 deletions.
78 changes: 78 additions & 0 deletions example/README.md
@@ -0,0 +1,78 @@
# Stripe Examples App

## Install
1. Clone the `stripe-android` repository.
2. Open the project in Android Studio.
3. After configuring, build and run the project.

## Configure

### Deploy example backend to Heroku
1. [Create a Heroku account](https://signup.heroku.com/) if you don't have one.
2. Navigate to the [example mobile backend repo](https://github.com/stripe/example-ios-backend)
and click "Deploy to Heroku".
3. Set an _App Name_ of your choice (e.g. Stripe Example Mobile Backend).
4. Under _Config Vars_, set your Stripe testmode secret key for the `STRIPE_TEST_SECRET_KEY` field.
5. Click "Deploy for Free".

### Configure app
1. Set [Settings.PUBLISHABLE_KEY](example/src/main/java/com/stripe/example/Settings.kt)
to your [test publishable key](https://dashboard.stripe.com/test/apikeys).

For example,
```
const val PUBLISHABLE_KEY = "pk_test_12345"
```

2. Set [Settings.BASE_URL](samplestore/src/main/java/com/stripe/samplestore/Settings.kt)
to the URL of the example backend deployed to Heroku.

For example,
```
const val BASE_URL = "https://my-example-app.herokuapp.com"
```

## Examples

### Google Pay

#### Source
[PayWithGoogleActivity.kt](https://github.com/stripe/stripe-android/blob/master/example/src/main/java/com/stripe/example/activity/PayWithGoogleActivity.kt)

#### Overview
1. Check that Google Pay is available and ready in `isReadyToPay()`.
2. Create a Google Pay `PaymentDataRequest` in `createGooglePayRequest()`.
- Optionally, require Billing Address (`isBillingAddressRequired`),
Phone Number (`isPhoneNumberRequired`),
and Email (`isEmailRequired`)
3. Display Google Pay sheet in `payWithGoogle()`.
4. After user selects a payment method, `Activity#onActivityResult()` is called.
Handle result in `handleGooglePayResult()`.
5. Create a `PaymentMethodCreateParams` object from the Google Pay
`PaymentData` object using
`PaymentMethodCreateParams.createFromGooglePay()`.

```
val paymentData = PaymentData.getFromIntent(data) ?: return
val paymentMethodParams = PaymentMethodCreateParams.createFromGooglePay(
JSONObject(paymentData.toJson())
)
```

6. Create a Stripe Payment Method object with the `PaymentMethodCreateParams`
object using `Stripe#createPaymentMethod()`.

```
stripe.createPaymentMethod(paymentMethodCreateParams,
object : ApiResultCallback<PaymentMethod> {
override fun onSuccess(paymentMethod: PaymentMethod) {
// do something with paymentMethod
}
override fun onError(e: Exception) {
// handle error
}
})
}
```
Binary file added example/images/heroku.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/images/run.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Expand Up @@ -51,14 +51,9 @@ class PayWithGoogleActivity : AppCompatActivity() {
isReadyToPay()
}

private fun payWithGoogle() {
AutoResolveHelper.resolveTask(
paymentsClient.loadPaymentData(createGooglePayRequest()),
this@PayWithGoogleActivity,
LOAD_PAYMENT_DATA_REQUEST_CODE
)
}

/**
* Check that Google Pay is available and ready
*/
private fun isReadyToPay() {
progressBar.visibility = View.VISIBLE
val request = IsReadyToPayRequest.newBuilder()
Expand Down Expand Up @@ -89,6 +84,17 @@ class PayWithGoogleActivity : AppCompatActivity() {
}
}

/**
* Launch the Google Pay sheet
*/
private fun payWithGoogle() {
AutoResolveHelper.resolveTask(
paymentsClient.loadPaymentData(createGooglePayRequest()),
this@PayWithGoogleActivity,
LOAD_PAYMENT_DATA_REQUEST_CODE
)
}

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == LOAD_PAYMENT_DATA_REQUEST_CODE) {
when (resultCode) {
Expand Down Expand Up @@ -119,67 +125,75 @@ class PayWithGoogleActivity : AppCompatActivity() {
}

private fun handleGooglePayResult(data: Intent) {
progressBar.visibility = View.VISIBLE

val paymentData = PaymentData.getFromIntent(data) ?: return
val paymentMethodCreateParams =
PaymentMethodCreateParams.createFromGooglePay(JSONObject(paymentData.toJson()))

stripe.createPaymentMethod(paymentMethodCreateParams,
object : ApiResultCallback<PaymentMethod> {
override fun onSuccess(result: PaymentMethod) {
progressBar.visibility = View.INVISIBLE
Toast.makeText(this@PayWithGoogleActivity,
"Created PaymentMethod ${result.id}", Toast.LENGTH_LONG)
.show()
}

override fun onError(e: Exception) {
progressBar.visibility = View.INVISIBLE
Toast.makeText(this@PayWithGoogleActivity,
"Exception: " + e.localizedMessage, Toast.LENGTH_LONG)
.show()
}
})
}

/**
* @param isBillingAddressRequired see `billingAddressRequired` and `billingAddressParameters`
* at https://developers.google.com/pay/api/android/reference/object#CardParameters
* @param isBillingAddressRequired Set to `true` if you require a billing address.
* A billing address should only be requested if it's required to process the transaction.
* Additional data requests can increase friction in the checkout process and lead to a lower conversion rate.
*
* If `true`, `billingAddressParameters` will be set to `FULL`.
*
* See [CardParameters#billingAddressRequired](https://developers.google.com/pay/api/android/reference/object#CardParameters) and
* [CardParameters#billingAddressParameters](https://developers.google.com/pay/api/android/reference/object#CardParameters)
*
* @param isPhoneNumberRequired Set to `true` if a phone number is required to process the transaction.
* See [BillingAddressParameters.phoneNumberRequired](https://developers.google.com/pay/api/android/reference/object#BillingAddressParameters)
*
* @param isEmailRequired Set to `true` to request an email address.
* See [PaymentDataRequest#emailRequired](https://developers.google.com/pay/api/android/reference/object#PaymentDataRequest)
*/
private fun createGooglePayRequest(
isBillingAddressRequired: Boolean = true,
isPhoneNumberRequired: Boolean = true,
isEmailRequired: Boolean = true
): PaymentDataRequest {
/**
* Billing address format required to complete the transaction.
*
* `MIN`: Name, country code, and postal code (default).
* `FULL`: Name, street address, locality, region, country code, and postal code.
*/
val billingAddressFormat = if (isBillingAddressRequired) {
"FULL"
} else {
"MIN"
}

val billingAddressParams = JSONObject()
.put("phoneNumberRequired", isPhoneNumberRequired)
.put("format", billingAddressFormat)

val cardPaymentMethodParams = JSONObject()
.put("allowedAuthMethods", JSONArray()
.put("PAN_ONLY")
.put("CRYPTOGRAM_3DS"))
.put("allowedCardNetworks",
JSONArray()
.put("AMEX")
.put("DISCOVER")
.put("JCB")
.put("MASTERCARD")
.put("VISA"))
.put("billingAddressRequired", isBillingAddressRequired)
.put("billingAddressParameters", billingAddressParams)

val cardPaymentMethod = JSONObject()
.put("type", "CARD")
.put(
"parameters",
JSONObject()
.put("allowedAuthMethods", JSONArray()
.put("PAN_ONLY")
.put("CRYPTOGRAM_3DS"))
.put("allowedCardNetworks",
JSONArray()
.put("AMEX")
.put("DISCOVER")
.put("JCB")
.put("MASTERCARD")
.put("VISA"))
.put("billingAddressRequired", isBillingAddressRequired)
.put(
"billingAddressParameters",
JSONObject()
.put("format", billingAddressFormat)
.put("phoneNumberRequired", isPhoneNumberRequired)
)
"parameters", cardPaymentMethodParams
)
.put("tokenizationSpecification", GooglePayConfig().tokenizationSpecification)

Expand All @@ -196,6 +210,7 @@ class PayWithGoogleActivity : AppCompatActivity() {
.put("merchantName", "Example Merchant"))
.put("emailRequired", isEmailRequired)
.toString()

return PaymentDataRequest.fromJson(paymentDataRequest)
}

Expand Down

0 comments on commit cf7211c

Please sign in to comment.