App2App integration on android with server side

From Barion Documentation
Jump to navigation Jump to search


This type of integration requires developments on your own server-side. Your server-side will communicate with the Barion System and your server-side will communicate with your mobile application. The mobile applications don't have to communicate with the Barion System directly and you don't have to add authentication information to your mobile application. Another adventage of this method is, that you can log the network communication on your server-side, and you can control the communication with your mobile application.

Downloads, examples

You can download the example project from this.

This project contains the models and error handling processes, so in this description we won't talk about it.

Flow chart

Server-side developments

You can see above on the flow chart, the two types of calls that must be capable on your server-side:

You can use any languages and technology, in the case of PHP you can use our library which you can download from Barion's GitHub page. The Barion System using JSON format in the requests and responses.

Integration steps

0. step - Server-side requests

For the server-side requests, you can use the examples directory in our PHP library on Barion's GitHub page].

In this example we assume the following:

  • For the payment initiator request, we will send the list of products with a POST request under the Items key
  • For the payment's status, we will use a GET request.

Add server-side endpoints to your mobile application:

   public static final String URL_STARTPAYMENT = "https://your-domain.com/generate_barion_payment.php";   
   public static final String URL_GETPAYMENTSTATE = "https://your-domain.com/get_barion_payment_state.php";

1. step - Edit AndroidManifest.xml file

At first, you need to edit the AndroidManifest.xml file.

1.1. step - Providing internet access

For the communication your application needs internet access, so add the internet access permission to your AndroidManifest file:

   <?xml version="1.0" encoding="utf-8"?>
   <manifest
      xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.barion.example.app2app.nativeintegration">

         <uses-permission android:name="android.permission.INTERNET" />

         <!-- The rest of your AndroidManifest.xml -->

   </manifest>

1.2. step - Add redirect scheme

In order to redirect from the Barion application into the integrator application, a redirect scheme is needed. You can choose anything, but it should be unique. In example this is myredirecturl. It is IMPORTANT, that this scheme must be the same as the redirectUrl property of the Payment/Start request. You need to add this scheme in intent-filter into your result activity section.

   <activity
      android:name=".activities.PaymentResultActivity"
      android:label="@string/app_name">
      <intent-filter>
         <action android:name="android.intent.action.VIEW" />

         <category android:name="android.intent.category.DEFAULT" />
         <category android:name="android.intent.category.BROWSABLE" />

         <data android:scheme="myredirecturl" />
      </intent-filter>
   </activity>

2. step - Initiate payment

At any point in the mobile application - where the products you want to pay are available - you should call the previously made server-side call, that will initiate payment in the Barion System.

This is one of the many possible solutions:

   progressDialog = ProgressDialog.show(getActivity(), null, getString(R.string.preparingpayment), true, false);
   new AsyncTask<Void, Void, String>() {
      @Override
      protected String doInBackground(Void... params) {
         HttpClient httpClient = new DefaultHttpClient();
         HttpPost post = new HttpPost(URL_STARTPAYMENT);
         try {
            JSONArray productsArray = new JSONArray();
            for(int i = 0; i < products.size(); ++i) {
               Product p = products.get(i);
               JSONObject productJson = new JSONObject();
               productJson
                  .put("Name", p.getName())
                  .put("Description", p.getDescription())
                  .put("Quantity", p.getQuantity())
                  .put("Unit", p.getUnit())
                  .put("UnitPrice", p.getPrice())
                  .put("ItemTotal", p.getPrice())
                  .put("SKU", p.getSKU());
               productsArray.put(productJson);
            }

            JSONObject holderJson = new JSONObject();
            holderJson.put("Items", productsArray);

            post.setHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8");
            post.setEntity(new StringEntity(holderJson.toString(), "UTF-8"));

            HttpResponse response = httpClient.execute(post);
            InputStream stream = response.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            StringBuilder builder = new StringBuilder();

            String line;
            while((line = reader.readLine()) != null) {
               builder.append(line);
            }

            return builder.toString();
         } catch (Exception x) {
            return null;
         }
      }

      @Override
      protected void onPostExecute(String s) {
         if(s == null) networkError();
         try {
            JSONObject resultObject = new JSONObject(s);
            BarionStartPaymentResponse response = BarionStartPaymentResponse.fromJsonObject(resultObject);
            if(response.getErrors().size() != 0) processBarionErrors(response.getErrors());
            else navigateUserToBarion(response);
         } catch (JSONException e) {
            networkError();
         }
      }
   }.execute();

3. step - Redirect and get the result

If the payment initiation was successful you need to redirect the user to the Barion mobile application or to Barion's website.

In order for the user to be redirected to the Barion mobile application the following requirements must be met:

  • The device must have Barion mobile application installed.
  • The installed Barion mobile application version must be above of 3.1.0.

If these conditions are not met you need to redirect the user to Barion's website. You can use these helper methods to check the requirements:

   public static boolean canPayWithBarionApp(Context context) {
      PackageManager packageManager = context.getPackageManager();
      try {
         PackageInfo barionInfo = packageManager.getPackageInfo("barion.app", PackageManager.GET_META_DATA);
         String barionVersion = barionInfo.versionName;
         String requiredVersion = "3.1.0";
         return isVersionAReachedB(barionVersion, requiredVersion);
      } catch (PackageManager.NameNotFoundException e) {
         return false;
      }
   }
 
   private static boolean isVersionAReachedB(String versionA, String versionB){
      int a = Integer.valueOf(versionA.replaceAll("[^0-9]", ""));
      int b = Integer.valueOf(versionB.replaceAll("[^0-9]", ""));
      return a >= b;
   }

3.1.1. step - Redirect to the Barion mobile application

After you successfully initiated the payment, you got a PaymentId parameter. Start the Bairon mobile application with that PaymentId by the following:

   private int PAYMENT_REQUEST_CODE = 42;
   
   private void navigateUserToBarion(final BarionStartPaymentResponse response) {
      Intent intent = new Intent(Intent.ACTION_VIEW);
      paymentId = response.getPaymentId();
      intent.setData(Uri.parse("barion:?pid=" + paymentId + "&action=returntoapp"));
      startActivityForResult(intent, PAYMENT_REQUEST_CODE);
   }

3.1.2. step - Get payment's status

In the Barion mobile application the user can pay or reject the payment, and after this the application closes itself. Then the user will be redirected to the integrator mobile application and you need to request the payment's status from your server:

   @Override
   public void onActivityResult(int requestCode, int resultCode, Intent data) {
      if(requestCode == PAYMENT_REQUEST_CODE) {
         progressDialog = ProgressDialog.show(this, null, getString(R.string.loading), true, false);
         new AsyncTask<String, Void, String>() {
            @Override
            protected String doInBackground(String... params) {
               try {
                  String urlString = URL_GETPAYMENTSTATE + "?PaymentId=" + paymentId;
                  URL url = new URL(urlString);
                  URLConnection connection = url.openConnection();
                  InputStream stream = connection.getInputStream();
                  BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                  StringBuilder builder = new StringBuilder();

                  String line;
                  while ((line = reader.readLine()) != null) {
                     builder.append(line);
                  }

                  return builder.toString();
               } catch (Exception e) {
                  return null;
               }
            }

            @Override
            protected void onPostExecute(String s) {
               if (s == null) networkError();
               else {
                  try {
                     JSONObject object = new JSONObject(s);
                     BarionGetPaymentStateResponse response = BarionGetPaymentStateResponse.fromJsonObject(object);
                     if (response.getErrors().size() != 0)
                        processBarionErrors(response.getErrors());
                     else processPaymentState(response.getPaymentState());
                  } catch (JSONException e) {
                     networkError();
                  }
               }
            }
         }.execute(paymentId);
      }
   }

3.2.1. step - Redirect to Barion's website

The integrator application must handle the case when the Barion mobile application isn't installed on the user's device. In this case, you need to load Barion's website in a WebView.

3.2.1.1. step - Add new Activity to your AndroidManifest.xml file

Add this Activity to your AndroidManifest.xml file:

   <activity
      android:name=".activities.WebViewActivity"
      android:label="@string/app_name" />
3.2.1.2. step - Create the XML layout for the new Activity
   <?xml version="1.0" encoding="utf-8"?>
   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical">

         <WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

   </LinearLayout>
3.2.1.3. step - Create Activity

Create a new Activity class. This activity will get the PaymentId parameter through Intent and you need to call Barion's website with this parameter. After the payment is closed, Barion will redirect the user to your scheme.

   public class WebViewActivity extends Activity {

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

         WebView webView = (WebView) findViewById(R.id.webView);
         webView.setWebViewClient(new WebViewClient());
         webView.getSettings().setJavaScriptEnabled(true);
         webView.getSettings().setDomStorageEnabled(true);

         BarionStartPaymentResponse response = (BarionStartPaymentResponse) getIntent().getSerializableExtra(KEY_STARTRESPONSE);
         webView.loadUrl("https://barion.com/Pay?id=" + response.getPaymentId());
      }
   }
3.2.1.4. step - Requesting the payment's result

You can get the payment id in the PaymentResultActivity like this:

   public class PaymentResultActivity extends Activity {
      @Override
      protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_result);

         Intent intent = getIntent();
         String paymentId = intent.getDataString().replace(Preferences.REDIRECT_URL + "?paymentId=", "");
      }
   }

With this payment id you can get the payment's result, you can use the example code from 3.1.2 step

3.3. step - Processing the result

You have everything in BarionGetPaymentStateResponse object about the payment.