Pay Pal integration with Android APP
In this example we will be making a simple Android application which will be integrated with PayPal service, just to show how it is done through PayPal developer sandbox account.
First we will need a new Android project in Android Studio, and then we will to create an PayPal developers account. On the following link is simple step-by-step tutorial how to create the account:
https://developer.paypal.com/docs/classic/lifecycle/sb_create-accounts/
After the creating the account, very important is to see you BUSINESS account for testing, because from there we will need the client_id for receiving payment, and it will look something like this:
1 |
ASqaYY7wa1hZlAYherzvYxlvfbsdfgw34231FX83cg5nph8DvoLNcf3CADD7cT_ivoWd56h43wdsf5Zpi-fYf |
.
Next we need to create the layout for the app:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.xtrid.paypalandroid.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginEnd="45dp" android:layout_marginStart="45dp" android:orientation="vertical"> <EditText android:id="@+id/amount" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/enter_amount" android:maxLines="1"/> <Button android:id="@+id/btnPayNow" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="@string/pay_now" /> </LinearLayout> </RelativeLayout> |
Next you need to add the PayPal library to your app build.gradle:
implementation ‘com.paypal.sdk:paypal-android-sdk:2.16.0‘
NOTE: We are going to use ButterKnife Library also for binding the Views from the XML, like buttons, text views, edit text etc.
ButterKnife by Jake Wharton Library with examples
First we declare our global variables and views:
1 2 3 4 5 6 |
private PayPalConfiguration payPalConfiguration; @BindView(R.id.amount) EditText edtAmount; @BindView(R.id.btnPayNow) Button btnPayNow; private String amount = ""; |
Than in our onCreate() method we bind the view with ButterKnife and initialize the PayPal configuration for our app using the sandbox account and our client_id which is initialized in our Constants class, show later in this example.
1 2 3 4 5 6 7 8 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); payPalConfigurationInit(); } |
The Constants class:
1 2 3 4 5 6 |
public class Constants { public static final String PAYPAL_CLIENT_ID = "ASqaYY7wa1hZlAYherzvYxl9J4Uhw9p0y1rgtweg5nph8DvoLNcwergfwer7cT_ivoWde4cRSC5Zpi-fYf"; public static final int PAYPAL_REQUEST_CODE = 7171; public static final String PAYMENT_DETAILS = "payment.details"; public static final String PAYMENT_AMOUNT = "payment.amount"; } |
This is the payPalConfigurationInit() method for initilizing the PayPal where our config is addressed as sandbox and we use our previously acclaimed client_id from our developers account:
1 2 3 4 5 6 |
private void payPalConfigurationInit() { payPalConfiguration = new PayPalConfiguration() .environment(PayPalConfiguration.ENVIRONMENT_SANDBOX) .clientId(Constants.PAYPAL_CLIENT_ID); startPayPalService(); } |
The startPayPalService() method where we create new Intent witch we use to redirect our app to the PayPal service and add some extra PayPal config and previously initialized PayPalConfiguration object in our previous method:
1 2 3 4 5 |
private void startPayPalService() { Intent intent = new Intent(this, PayPalService.class); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, payPalConfiguration); startService(intent); } |
On our button click we start/process the payment:
1 2 3 4 |
@OnClick(R.id.btnPayNow) public void onPayNowButtonClick() { processPayment(); } |
In our processPayment() method we get the amount entered in our editText and check if it is not empty. If its not empty then create new PayPalPayment object to send data to the PayPal service for processing. A new intent is created and put some extra key value pairs for processing and we start that intent with startActivityForResult to get some data from the service. We add our payPalConfiguration and our paypalPayment. If the editText is empty, we show only Toast message that nothing is entered :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private void processPayment() { if (!edtAmount.getText().toString().isEmpty()) { amount = edtAmount.getText().toString(); PayPalPayment payPalPayment = new PayPalPayment(new BigDecimal(String.valueOf(amount)) , "USD" , "Donate for Wikaya" , PayPalPayment.PAYMENT_INTENT_SALE); Intent intent = new Intent(this, PaymentActivity.class); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, payPalConfiguration); intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payPalPayment); startActivityForResult(intent, Constants.PAYPAL_REQUEST_CODE); } else { Toast.makeText(this, R.string.nothing_entered, Toast.LENGTH_SHORT).show(); } } |
In our onActivityResult we get our wanted data from the service, and we get our payment confirmation wit some data received in a JSON response. Than we extract what we need from it and start our own PaymentDetailsActivity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == Constants.PAYPAL_REQUEST_CODE) { if(resultCode == RESULT_OK) { PaymentConfirmation paymentConfirmation = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION); if (paymentConfirmation != null) { try { String paymentDetails = <span id="mce_SELREST_start" style="overflow:hidden;line-height:0;">&#65279;</span>paymentConfirmation.toJSONObject().toString(4); startActivity(new Intent(this, PaymentDetailsActivity.class) .putExtra(Constants.PAYMENT_DETAILS, paymentDetails) .putExtra(Constants.PAYMENT_AMOUNT, amount)); } catch (JSONException e) { e.printStackTrace(); } } } else if (resultCode == Activity.RESULT_CANCELED){ Toast.makeText(this, R.string.cancel, Toast.LENGTH_SHORT).show(); } } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) { Toast.makeText(this, R.string.invalid, Toast.LENGTH_SHORT).show(); } } |
Finally we must stop the PayPal service in our onDestroy method:
1 2 3 4 5 |
@Override protected void onDestroy() { stopService(new Intent(this, PayPalService.class)); super.onDestroy(); } |
Here is our own custom PaymentDetailsActivity. Here we use previously acquired data from the PyPal service and do what ever we want. In this example we use data only for showing that the payment is successful:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
public class PaymentDetailsActivity extends AppCompatActivity { @BindView(R.id.txtId) TextView id; @BindView(R.id.txtAmount) TextView amount; @BindView(R.id.txtStatus) TextView status; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_payment_details); ButterKnife.bind(this); Intent intent = getIntent(); try { JSONObject jsonObject = new JSONObject(intent.getStringExtra(Constants.PAYMENT_DETAILS)); displayDetails(jsonObject.getJSONObject("response"), intent.getStringExtra(Constants.PAYMENT_AMOUNT)); } catch (JSONException e) { e.printStackTrace(); } } private void displayDetails(JSONObject response, String paymentAmount) { try { id.setText(response.getString("id")); status.setText(response.getString("state")); amount.setText(String.format("$" + paymentAmount)); } catch (JSONException e) { e.printStackTrace(); } } } // JSON Response example // { // "client": { // "environment": "live", // "paypal_sdk_version": "2.8.4", // "platform": "Android", // "product_name": "PayPal-Android-SDK" // }, // "response": { // "create_time": "2015-01-03T19:51:53Z", // "id": "PAY-...", // "intent": "sale", // "state": "approved" // }, // "response_type": "payment" // } |
And the layout for this class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.xtrid.paypalandroid.PaymentDetailsActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginEnd="45dp" android:layout_marginStart="45dp" android:orientation="vertical"> <TextView android:id="@+id/txtId" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" /> <TextView android:id="@+id/txtAmount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" /> <TextView android:id="@+id/txtStatus" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" /> </LinearLayout> </RelativeLayout> |