Android integration

Use these guidelines to incorporate the mobile SDK into your Android mobile app. See the Android API for additional details about implementing each screen.

  1. Prepare for integration.
  2. Add the SDK to your project.
  3. Add permissions.
  4. Add the Amount screen. (optional)
  5. Add the Customer Info screen. (recommended)
  6. Add the Card Entry screen. (required)
  7. Add the Signature screen. (optional)

You should also review the orientation guidelines.

Note: If you’re using Xamarin to build your Android app, you must perform the steps in the Xamarin integration for Android first.

1: Prepare for integration

Before you begin:

2: Add the SDK to your project

You must add the SDK to your project before you can start working with it. For more information, contact AffiniPay Support.

3: Add permissions

To support an AffiniPay mobile card reader, you must add the RECORD_AUDIO and WRITE_EXTERNAL_STORAGE permissions to your AndroidManifest.xml file, within the manifest section and before the application section. These permissions are required for an audio-jack card reader.

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

4: Add the Amount screen

The Amount screen (which is optional) enables the merchant to input the amount to be charged.

To add the Amount screen:

  1. Obtain AmountSelectionFragment from ViewProvider.
    val fragmentTransaction = fragmentManager.beginTransaction()
    val amountSelectionFragment = ViewProvider.getAmountSelectionView()
    fragmentTransaction.replace(R.id.fragment_container, amountSelectionFragment)
    fragmentTransaction.commit()
    

  2. Implement the AmountRequester interface.
    override fun onAmountReceived(amountResult: AmountResult) {
      amount = amountResult.amount
      val requiredFieldTypes = arrayListOf(CustomerInfoType.EMAIL, CustomerInfoType.POSTAL_CODE, CustomerInfoType.ADDRESS1)
      val params = CustomerInfoParams(requiredFieldTypes)
      goToScreen(ViewProvider.getCustomerInfoView(params))
    }
    private fun goToScreen(newView: Fragment) {
      val fragmentTransaction = fragmentManager.beginTransaction()
      fragmentTransaction.replace(R.id.fragment_container, newView).addToBackStack(newView.tag)
      fragmentTransaction.commit()
    }

5: Add the Customer Info screen

The Customer Info screen (which is recommended) enables the merchant to input information about the cardholder. Be sure to gather the appropriate cardholder details.

To add the Customer Info screen:

  1. Obtain CustomerInfoFragment from ViewProvider.
    val mandatoryFields = arrayListOf(CustomerInfoType.NAME, CustomerInfoType.EMAIL, CustomerInfoType.POSTAL_CODE,
         CustomerInfoType.CITY, CustomerInfoType.PHONE, CustomerInfoType.REFERENCE, CustomerInfoType.ADDRESS1,
         CustomerInfoType.STATE, CustomerInfoType.COUNTRY)
    val customerInfo = CustomerInfo(
         name = "AffiniPay User",
         email = "user@affinipay.com",
         phone = "123-456-7890",
         reference = "A Reference",
         address1 = "3700 N Capital of Texas Hwy",
         address2 = "#300",
         city = "Austin",
         postalCode = "78746",
         country = "US"
    )
    val params = CustomerInfoParams(mandatoryFields, customerInfo)
    val fragment = ViewProvider.getCustomerInfoView(params)
    val fragmentTransaction = fragmentManager.beginTransaction()
    fragmentTransaction.add(R.id.fragment_container, fragment)
    fragmentTransaction.commit()

    Note: The CustomerInfoParams parameter is optional and enables you to pre-fill fields with your own values.

  2. Implement the CustomerInfoRequester interface.
    override fun onCustomerInfoReceived(customerInfoResult: CustomerInfoResult) {
      goToScreen(ViewProvider.getCardEntryView(ChargeParams(customerInfoResult.customerInfo, publicKey, amount)))
    }
    private fun goToScreen(newView: Fragment) {
      val fragmentTransaction = fragmentManager.beginTransaction()
      fragmentTransaction.replace(R.id.fragment_container, newView).addToBackStack(newView.tag)
      fragmentTransaction.commit()
    }

6: Add the Card Entry screen

The Card Entry screen (which is required) enables the merchant to either swipe to provide card information or manually enter the card details. This screen is required to charge with the AffiniPay Payment Gateway.

Note: When the AffiniPay card reader is used to make an EMV charge, you must submit a signature to finalize the charge. You can obtain a signature using either the mobile SDK signature screen or your own screen. See Add the Signature screen for implementation information.

To add the Card Entry screen:

  1. Obtain CardEntryFragment from ViewProvider.
    val customerInfo = CustomerInfo()
    customerInfo.name = "John Doe"
    customerInfo.address = "123 Easy St"
    customerInfo.email = "jdoe@affinipay.com"
    val chargeParams = ChargeParams(customerInfo, publicKey, amount)
    val fragment = ViewProvider.getCardEntryView(chargeParams)
    val fragmentTransaction = fragmentManager.beginTransaction()
    fragmentTransaction.add(R.id.fragment_container, fragment)
    fragmentTransaction.commit()
    

  2. Implement the ChargeRequester interface.
    override fun onManualChargeDataReceived(manualChargeResult: ChargeResult) {
      chargeModel.makeCharge(publicKey, accountId, manualChargeResult.oneTimeToken, manualChargeResult.amount).subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread()).subscribe({
        charge ->
        fragment.completionCallback(true)
        handleChargeCompletedReceipt(charge)
      }, {
        error ->
        fragment.completionCallback(false)
        print(error.message)
      })
    }
    
    override fun onSwipeChargeDataReceived(swipeChargeResult: ChargeResult) {
      chargeModel.makeCharge(publicKey, accountId, swipeChargeResult.oneTimeToken, swipeChargeResult.amount).subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread()).subscribe({
        charge ->
        fragment.completionCallback(true)
        handleChargeCompletedReceipt(charge)
      }, {
        error ->
        fragment.completionCallback(false)
        print(error.message)
      })
    }
    
    override fun onEMVChargeDataReceived(emvChargeResult: ChargeResult) {
      chargeModel.makeEMVCharge(publicKey, accountId, emvChargeResult.oneTimeToken, emvChargeResult.amount, emvChargeResult.paymentDataSource,
          emvChargeResult.pointOfSale as PointOfSale).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe({
        charge ->
        fragment.completionCallback(true)
        handleChargeCompletedReceipt(charge)
      }, {
        error ->
        fragment.completionCallback(false)
        print(error.message)
      })
    }
    
    fun handleChargeCompletedReceipt(charge: Charge) {
      val chargeId = charge.chargeDetails?.id
      val dialog = AlertDialog.Builder(this)
      dialog.setTitle("Charge Receipt")
          .setMessage(charge.toString())
          .setPositiveButton("Sign", { _: DialogInterface, _: Int ->
            val signIntent = Intent(this, SignatureActivity::class.java)
            signIntent.putExtra(SignatureActivity.ARG_PUBLIC_KEY, publicKey)
            signIntent.putExtra(SignatureActivity.ARG_ACCOUNT_ID, accountId)
            signIntent.putExtra(SignatureActivity.ARG_CHARGE_ID, chargeId)
            signIntent.putExtra(SignatureFragment.ARG_AMOUNT, amount)
            startActivity(signIntent)
          }).show()
    }

Note: Upon receiving a response from your server, you should notify the SDK via the completionCallback method on the CardEntryFragment (sending true for success or false for failure). This will allow the view to show an appropriate success or failure message. If the SDK doesn’t receive any response from the callback, it will automatically assume the charge has failed after a certain amount of time has passed.

To submit a charge:

After the CardEntryFragment returns the ChargeResult object via the ChargeRequester interface:

  1. Your mobile app must pass the ChargeResult (or the details it contains) to your backend server.
  2. Your backend server must POST the charge details and other required information (such as the merchant’s secret key) to the charges endpoint of the AffiniPay Payment Gateway.

Note: To ensure the security of payment details, never make a call to the AffiniPay Payment Gateway directly from your mobile app.

See AffiniPay’s sample mobile and backend apps for an example of how this can be implemented.

7: Add the Signature screen

The Signature screen (which is optional) enables the cardholder to sign and confirm the charge.

To add the Signature screen:

  1. Obtain SignatureFragment from ViewProvider.
    val amount = "246"
    val accountName = "Central Texas Association"
    val fragment = ViewProvider.getSignatureView(SignatureParams(accountName, amount))
    val fragmentTransaction = fragmentManager.beginTransaction()
    fragmentTransaction.add(R.id.fragment_container, fragment)
    fragmentTransaction.commit()
    

  2. Implement the SignatureRequester interface.
    override fun onSignatureReceived(signatureResult: SignatureResult) {
      val chargeId = intent.extras.getString(ARG_CHARGE_ID)
      val accountId = intent.extras.getString(ARG_ACCOUNT_ID)
      val publicKey = intent.extras.getString(ARG_PUBLIC_KEY)
      chargeModel.addSignature(chargeId, accountId, signatureResult.signature, publicKey).subscribe({
     val receiptIntent = Intent(this, ReceiptActivity::class.java)
     receiptIntent.putExtra(ReceiptActivity.ARG_AMOUNT, intent.getStringExtra(SignatureFragment.ARG_AMOUNT))
     startActivity(receiptIntent)
      })
    }
    

After the SignatureFragment fragment returns the SignatureResult object:

  1. Your mobile app must pass the SignatureResult object (or the details it contains) to your backend server.
  2. Your backend server must POST the signature details and other required information (such as the merchant’s secret key) to the /v1/transactions/{transactionID}/sign endpoint of the AffiniPay Payment Gateway.

Note: To ensure the security of payment details, never make a call to the AffiniPay Payment Gateway directly from your mobile app.

See AffiniPay’s sample mobile and backend apps for an example of how this can be implemented.

Orientation guidelines

Use the following orientation guidelines.

ViewDeviceOrientations
Amountmobile
tablet
Portrait
All
Customer Infomobile
tablet
Portrait
All
Card Entrymobile
tablet
Portrait
All
Signaturemobile
tablet
Landscape
All