Android push provisioning Invite Only

     

    Learn how to provide your users with an Add to Google Pay button

    Users can already add their Stripe Issuing cards to Google Pay by going to the Google Pay app and entering the card number manually.

    If you’re distributing an app, push provisioning allows you to display a single Add to Google Pay button, that guides them through adding their card to Google Pay without having to enter the card number.

    Outline of your work

    Stripe provides a wrapper SDK around a private Google library for push provisioning. To distribute your app on the Google Pay Store with push provisioning capability you will need to:

    Integrating Stripe’s SDK

    Stripe provides a wrapper SDK around a private Google library for push provisioning. To distribute your app on the Google Pay Store with push provisioning capability you will need to:

    • Import Google’s private SDK following their guide

    • Import Stripe’s SDK from maven:

    • dependencies {
        [... your dependencies]
        implementation 'com.stripe:stripe-android-issuing-push-provisioning:1.0.0'
      }
      
    • Prepare your backend to create ephemeral keys for your cards See section below

    • Prepare an EphemeralKeyProvider that extends PushProvisioningEphemeralKeyProvider. Because this ephemeral key provider will be passed to another activity, it also needs to implement Parcelable (see Android docs about Parcelable).

    • Implement the Add to Google Pay button according to Google’s specifications

    • When a user clicks on the button, launch Stripe’s PushProvisioningActivity using the PushProvisioningActivityStarter:

    • new PushProvisioningActivityStarter(
        this, // The Activity or Fragment you are initiating the push provisioning from
        new PushProvisioningActivityStarter.Args(
        "Stripe Card", // The name that will appear on the push provisioning UI
        ephemeralKeyProvider, // Your instance of EphemeralKeyProvider
        false // If you want to enable logs or not
      )).startForResult();
      
    • This prepares the push provisioning and launches the UI to add the card to the wallet. Implement the callback in your onActivityResult:

    • protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (requestCode == PushProvisioningActivityStarter.REQUEST_CODE) {
          if (resultCode == PushProvisioningActivity.RESULT_OK) {
            PushProvisioningActivityStarter.Result success = PushProvisioningActivityStarter.Result.fromIntent(data);
          } else if (resultCode == PushProvisioningActivity.RESULT_ERROR) {
            PushProvisioningActivityStarter.Error error = PushProvisioningActivityStarter.Error.fromIntent(data);
          }
        }
      }
      

    If the provisioning was successful, you’ll receive a PushProvisioningActivityStarter.Result containing a cardTokenId which is Google’s ID for the card in the active wallet. You can use the rest of the wallet functions with this ID.

    If the provisioning encountered an error, a PushProvisioningActivityStarter.Error will be returned with a code and a message. The message is a developer-friendly text explaining the error. The code can have the following values:

    Enum Meaning
    USER_CANCELED The user canceled the provisioning.
    CARD_CANCELED The card has been canceled or is lost or stolen and cannot be provisioned.
    EPHEMERAL_KEY_ERROR There was an error retrieving the ephemeral key.
    TAP_AND_PAY_UNAVAILABLE The TapAndPay library can’t be used, most likely because the app is not whitelisted.
    NO_STABLE_HARDWARE_ID This can happen in the emulator, the app can’t retrieve the stable hardware ID.
    NO_ACTIVE_WALLET_FOUND No active wallet available. Note that emulators generally don’t have Google Pay.
    PUSH_PROVISIONING_ENCRYPTED_PAYLOAD_ERROR There was an error contacting Stripe’s servers to get the encrypted payload for the push provisioning.
    UNKNOWN_ERROR An unexpected error occurred, hopefully the message will have additional information.

    Backend changes

    The push provisioning implementation exposes methods that expect you to communicate with your own server backend to create a Stripe Ephemeral Key and return it to your app. This key is a short-lived API credential that can be used to retrieve the encrypted card details for just a single instance of an Issuing Card object. To ensure that the object returned by the Stripe API is compatible with the version of the iOS/Android SDK you’re using, our SDK will tell you what API version it prefers, and then you must explicitly pass this API version to our API when creating the key on your backend. Your app is responsible for determining which Card object to use. Typically this would involve finding the Issuing Cardholder object that is associated with your logged-in user and returning their first active Card.

    # Sinatra
    post path do
      stripe_version = params['api_version']
      # issuingCardID should be the ID of the Issuing Card you'd like to use for push provisioning.
      key = Stripe::EphemeralKey.create(
        {issuing_card: issuing_card_id},
        {stripe_version: stripe_version}
      )
      key.to_json
    end
    
    # Flask
    from flask import Flask, session, jsonify, request
    
    @app.route(path, methods=['POST'])
      def issue_key():
      api_version = request.args['api_version']
      # issuing_card_id should be the ID of the Issuing Card you'd like to use for push provisioning.
      key = stripe.EphemeralKey.create(issuing_card=issuing_card_id, api_version=api_version)
      return jsonify(key)
    
    if (!isset($_POST['api_version']))
    {
      exit(http_response_code(400));
    }
    try {
      // $issuingCardID should be the ID of the Issuing Card you'd like to use for push provisioning.
      $key = \Stripe\EphemeralKey::create(
        ["issuing_card" => $issuingCardID],
        ["stripe_version" => $_POST['api_version']]
      );
      header('Content-Type: application/json');
      exit(json_encode($key));
    } catch (Exception $e) {
      exit(http_response_code(500));
    }
    
    // Express
    app.post(path, (req, res) => {
      const stripe_version = req.query.api_version;
      if (!stripe_version) {
        res.status(400).end();
        return;
      }
      // issuingCardID should be the ID of the Issuing Card you'd like to use for push provisioning.
      stripe.ephemeralKeys.create(
        {issuing_card: issuingCardID},
        {stripe_version: stripe_version}
      ).then((key) => {
        res.status(200).json(key);
      }).catch((err) => {
        res.status(500).end();
      });
    });
    
    // Using Spark framework (http://sparkjava.com)
    post(new Route(path) {
      @Override
      public Object handle(final Request request,
        final Response response) {
        String apiVersion = request.queryParams("api_version");
        RequestOptions requestOptions = (new RequestOptions.RequestOptionsBuilder())
          .setStripeVersion(apiVersion)
          .build();
    
        try {
          // issuingCardID should be the ID of the Issuing Card you'd like to use for push provisioning.
          Map<String, Object> options = new HashMap<String, Object>();
          options.put("issuing_card", issuingCardID);
    
          EphemeralKey key = EphemeralKey.create(options, requestOptions);
          return key.getRawJson();
        } catch (StripeException e) {
          response.status(500);
          return e;
        }
      }
    });
    
    // net/http
    // The issuingCardID parameter should be the ID of the Issuing Card you'd like to use for push provisioning.
    func issueKeyHandler(w http.ResponseWriter, r *http.Request, issuingCardID string) {
      r.ParseForm()
      stripeVersion := r.Form.Get("api_version")
      if stripeVersion == "" {
        log.Printf("Stripe-Version not found\n")
        w.WriteHeader(400)
        return
      }
      params := &stripe.EphemeralKeyParams{
        IssuingCard: stripe.String(issuingCardID),
        StripeVersion: stripe.String(stripeVersion),
      }
      key, err := ephemeralkey.New(params)
      if err != nil {
        log.Printf("Stripe bindings call failed, %v\n", err)
        w.WriteHeader(500)
        return
      }
      w.Write(key.RawJSON)
    }
    

    Was this page helpful?

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page