Integrating PayPal Payments In an Android Application

Posted By : Keshav Gupta | 09-Feb-2018

PayPal is an international acclaimed payment gateway that supports payment across the globe.The user can go for payment using PayPal account and can use its debit credit card.Now I am going to explain how we can go for PayPal enabled the android application.

Server Side Configuration:

Step1.Create an application at PayPal site and get your clientid for the PayPal sandbox account.We will be using this in application integration.

https://developer.paypal.com/developer/accounts/

Application Side Configuration :

Step1: We will first need to integrate PayPal SDK in android application.For this, we need to add the following dependency in app/build.gradle

dependencies {
    compile 'com.paypal.sdk:paypal-android-sdk:2.14.3'
  }

Step2: We need to declare following payments upholding screens in AndroidManifest.xml.So that SDK can pick relevant screen when required from payment initialization to payment completion.We will be declaring some CardIoActivity to accept card payment.It will be like

 <service

            android:name="com.paypal.android.sdk.payments.PayPalService"

            android:exported="false" />


        <activity android:name="com.paypal.android.sdk.payments.PaymentActivity" />

        <activity android:name="com.paypal.android.sdk.payments.LoginActivity" />

        <activity android:name="com.paypal.android.sdk.payments.PaymentMethodActivity" />

        <activity android:name="com.paypal.android.sdk.payments.PaymentConfirmActivity" />

        <activity android:name="com.paypal.android.sdk.payments.PayPalFuturePaymentActivity" />

        <activity android:name="com.paypal.android.sdk.payments.FuturePaymentConsentActivity" />

        <activity android:name="com.paypal.android.sdk.payments.FuturePaymentInfoActivity" />

        <activity android:name="com.paypal.android.sdk.payments.PayPalProfileSharingActivity" />

        <activity android:name="com.paypal.android.sdk.payments.ProfileSharingConsentActivity" />

        <activity

            android:name="io.card.payment.CardIOActivity"

            android:configChanges="keyboardHidden|orientation" />

        <activity android:name="io.card.payment.DataEntryActivity" />

Step3: We will config PayPal environment.For that, we will put it in Sandbox.Then we will declare clientId created above.Note that It should be from sandbox account.

Step4: Then we will define requestCode for payment, profilesharing.But here we are only using payment.

Step5: We will further wrap the whole configuration using PayPal wrapper class named as PayPalConfiguration by instantiating it.

 private static final String TAG = "PayPalPaymentExample";

    // sample price value
    private float totalPrice=100;
    //private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_NO_NETWORK;

    private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_SANDBOX;

   // private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_PRODUCTION;

    // Development COnfig Paypal
  private static final String CONFIG_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    //Live Config Paypal
   // private static final String CONFIG_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    private static final int REQUEST_PAY_PAYMENT = 1;
    private static final int REQUEST_PAY_FUTURE_PAYMENT = 2;
    private static final int REQUEST_PAY_PROFILE_SHARING = 3;

    private static PayPalConfiguration paypalConfig = new PayPalConfiguration()
            .environment(CONFIG_ENVIRONMENT)
            .clientId(CONFIG_CLIENT_ID)
            
          .merchantName("Sample Paypal")
            .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
            .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));

Step6: Then we will initiate PayPal service to communicate with PayPal server by this code in onCreate() method of activity class

Step7: Then activity class will be having button view to initiate PayPal interface.

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.subscription_upgradeplans);

        Intent intent = new Intent(this,PayPalService.class);
        intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, paypalConfig);
        startService(intent);

        Button button=new Button(this);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                if (netInfo != null && netInfo.isConnectedOrConnecting())  {
                    // code to initiate paypal user interface loading screen

                    PayPalPayment thingToBuy = getThingToBuy(PayPalPayment.PAYMENT_INTENT_SALE);
                    Intent intent = new Intent(PaypalConfigurationActivity.this,PaymentActivity.class);

                    // send the same configuration for restart resiliency
                    intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, paypalConfig);

                    intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);

                    startActivityForResult(intent, REQUEST_PAY_PAYMENT);

                } else {
                    Toast.makeText(PaypalConfigurationActivity.this,"Internet available",Toast.LENGTH_SHORT).show();
                }

            }
        });
    }

Step8: There will be one more method which will work like wrap what to buy context which will return PayPalPayment object

private PayPalPayment getThingToBuy(String paymentIntent) {
        return new PayPalPayment(new BigDecimal(totalPrice), "EUR", "sample item",
                paymentIntent);
    }

Step9: Finally we will be having payment callback code which will give success or failure token based on that we will verify our payment to our local server through a REST API call.As PayPal will return a paymentId token after payment is successfully completed.Then we have to send that PayPal and other information required by the local server to local server for further verification for payment at their end.

    @Override
    protected void onActivityResult(int request, int result, Intent paydata) {
        if (request == REQUEST_PAY_PAYMENT) {
            if (result == Activity.RESULT_OK) {
                PaymentConfirmation confirmations =
                        paydata.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
                if (confirmations != null) {
                    try {
                   

                        String paymentId = confirmations.toJSONObject().getJSONObject("response").getString("id");

                        String state = confirmations.toJSONObject().getJSONObject("response").getString("state");

                        String payment_client = confirmations.getPayment().toJSONObject().toString();


                      
                       if(paymentId!=null){
                            if(!paymentId.equalsIgnoreCase(""))
                            {
                                ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                                if (netInfo != null && netInfo.isConnectedOrConnecting())  {
                                    // api call to update local server for payment confirmation
                                } else {
                                    Toast.makeText(PaypalConfigurationActivity.this,"Internet available",Toast.LENGTH_SHORT).show();
                                }
                            }
                        }

                    } catch (JSONException e) {
                        Log.e("tag", "failure occurred: ", e);
                        Toast.makeText(getApplicationContext(), "PaymentConfirmation info received from PayPal", Toast.LENGTH_LONG).show();
                    }
                }
            } else if (result == Activity.RESULT_CANCELED) {
                Log.i(TAG, "payment is cancelled by user");
            } else {
                Log.i(TAG, "invalid configurations submitted");
            }
        }
    }

Step10: Final code for this class we wil be like.

package com.sirius.activity;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.paypal.android.sdk.payments.PayPalConfiguration;
import com.paypal.android.sdk.payments.PayPalPayment;
import com.paypal.android.sdk.payments.PayPalService;
import com.paypal.android.sdk.payments.PaymentActivity;
import com.paypal.android.sdk.payments.PaymentConfirmation;
import com.sirius.R;

import org.json.JSONException;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * Created by keshav on 9/2/18.
 */

public class PaypalConfigurationActivity extends AppCompatActivity {
    private static final String TAG = "PayPalPaymentExample";

    // sample price value
    private float totalPrice=100;
    //private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_NO_NETWORK;

    private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_SANDBOX;

   // private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_PRODUCTION;

    // Development COnfig Paypal
  private static final String CONFIG_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    //Live Config Paypal
   // private static final String CONFIG_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    private static final int REQUEST_PAY_PAYMENT = 1;
    private static final int REQUEST_PAY_FUTURE_PAYMENT = 2;
    private static final int REQUEST_PAY_PROFILE_SHARING = 3;

    private static PayPalConfiguration paypalConfig = new PayPalConfiguration()
            .environment(CONFIG_ENVIRONMENT)
            .clientId(CONFIG_CLIENT_ID)
          
            .merchantName("Sample Paypal")
            .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy"))
            .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal"));

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.subscription_upgradeplans);

        Intent intent = new Intent(this,PayPalService.class);
        intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, paypalConfig);
        startService(intent);

        Button button=new Button(this);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                if (netInfo != null && netInfo.isConnectedOrConnecting())  {
                    // code to initiate paypal user interface loading screen

                    PayPalPayment thingToBuy = getThingToBuy(PayPalPayment.PAYMENT_INTENT_SALE);
                    Intent intent = new Intent(PaypalConfigurationActivity.this,PaymentActivity.class);

                    // send the same configuration for restart resiliency
                    intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, paypalConfig);

                    intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);

                    startActivityForResult(intent, REQUEST_PAY_PAYMENT);

                } else {
                    Toast.makeText(PaypalConfigurationActivity.this,"Internet available",Toast.LENGTH_SHORT).show();
                }

            }
        });
    }


    private PayPalPayment getThingToBuy(String paymentIntent) {
        return new PayPalPayment(new BigDecimal(totalPrice), "EUR", "sample item",
                paymentIntent);
    }

    @Override
    protected void onActivityResult(int request, int result, Intent paydata) {
        if (request == REQUEST_PAY_PAYMENT) {
            if (result == Activity.RESULT_OK) {
                PaymentConfirmation confirmations =
                        paydata.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
                if (confirmations != null) {
                    try {
                   

                       String paymentId = confirmations.toJSONObject().getJSONObject("response").getString("id");

                        String state = confirmations.toJSONObject().getJSONObject("response").getString("state");

                        String payment_client = confirmations.getPayment().toJSONObject().toString();


                        
                       if(paymentId!=null){
                            if(!paymentId.equalsIgnoreCase(""))
                            {
                                ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                                if (netInfo != null && netInfo.isConnectedOrConnecting())  {
                                    // api call to update local server for payment confirmation
                                } else {
                                    Toast.makeText(PaypalConfigurationActivity.this,"Internet available",Toast.LENGTH_SHORT).show();
                                }
                            }
                        }

                    } catch (JSONException e) {
                     
                       Toast.makeText(getApplicationContext(), "PaymentConfirmation info received from PayPal", Toast.LENGTH_LONG).show();
                    }
                }
            } else if (result == Activity.RESULT_CANCELED) {
                Log.i(TAG, "payment is cancelled by user");
            } else {
                Log.i(TAG, "invalid configurations submitted");
            }
        }
    }
}

Note: When you are going to put your application into production.You need to change your config environment to Production and ConfigClientId to realone

That's all you have to do.

 

About Author

Author Image
Keshav Gupta

Keshav Gupta is Android Developer in Oodles, he always look forward for new tasks and new things to learn more.

Request for Proposal

Name is required

Comment is required

Sending message..