Integrating the PayButton
You can integrate the PayButton by using these instructions to install, set up, and perform a payment.
Supported Versions
The current SDK version 2.43.0 only supports
Xcode 12
projects with targets set as low as
iOS 10
. If you want integrate the mPOS SDK in a Swift App, see the additional information and restrictions.
Installing the PayButton
Put this in your
Podfile
and then run
pod install
:
source 'https://github.com/CocoaPods/Specs.git' source 'https://bitbucket.org/payworks/io.payworks.repo.pods.git' use_frameworks! target :"<your-app-target>" do pod 'payworks', '2.39.1' pod 'payworks.paybutton', '2.39.1' end
Basic Set Up
  1. Open your
    App.xcworkspace.
  2. Payworks libraries contain Swift frameworks. To enable compatibility between Objective-C and Swift, create an empty Swift file in your project. Click
    create bridging header
    at the prompt that asks: "Would you like to configure an Objective-C bridging header?"
    If you want to use the SceneUI approach introduced with iOS 13, be advised that it is only compatible with iOS 13 or above.
  3. For Bluetooth devices such as Miura card readers
    : To connect as an external accessory and to receive messages while the app is running in the background, add these additional entries to your
    Info.plist
    :
    • Key: Supported external accessory protocols (
      UISupportedExternalAccessoryProtocols
      ); Value:
      com.miura.shuttle
      (for Miura readers)
    • Key: Required background modes (
      UIBackgroundModes
      ); Value: App communicates with an accessory (
      external-accessory
      )
  4. Import the header in your view controller:
@import mpos_ui
Performing a Payment in Mock Mode
This is how you start a payment in mock mode:
- (IBAction)paymentButtonClicked:(id)sender { MPUMposUi *ui = [MPUMposUi initializeWithProviderMode:MPProviderModeMOCK merchantIdentifier:@"merchantIdentifier" merchantSecret:@"merchantSecretKey"]; // Start with a mocked card reader: MPAccessoryParameters *ap = [MPAccessoryParameters mockAccessoryParameters]; // When using the Bluetooth Miura, use the following parameters: // MPAccessoryParameters *ap = [MPAccessoryParameters externalAccessoryParametersWithFamily:MPAccessoryFamilyMiuraMPI // protocol:@"com.miura.shuttle" // optionals:nil]; // When using Verifone readers via WiFi or Ethernet, use the following parameters: // MPAccessoryParameters *ap = [MPAccessoryParameters tcpAccessoryParametersWithFamily:MPAccessoryFamilyVerifoneVIPA // remote:@"192.168.254.123" // port:16107 // optionals:nil]; MPTransactionParameters *tp = [MPTransactionParameters chargeWithAmount:[NSDecimalNumber decimalNumberWithString:@"5.00"] currency:MPCurrencyEUR optionals:^(id<MPTransactionParametersOptionals> _Nonnull optionals) { optionals.subject = @"Bouquet of Flowers"; optionals.customIdentifier = @"yourReferenceForTheTransaction"; }]; ui.configuration.terminalParameters = ap; ui.configuration.summaryFeatures = MPUMposUiConfigurationSummaryFeatureSendReceiptViaEmail; // Add this if you would like to collect the customer signature on a printed merchant receipt //ui.configuration.signatureCapture = MPUMposUiConfigurationSignatureCaptureOnReceipt; UIViewController *viewController = [ui createTransactionViewControllerWithTransactionParameters:tp completed:^(UIViewController * _Nonnull controller, MPUTransactionResult result, MPTransaction * _Nullable transaction) { [self dismissViewControllerAnimated:YES completion:NULL]; UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Result" message:@"" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK",nil]; if (result == MPUTransactionResultApproved) { alert.message = @"Payment was approved!"; } else { alert.message = @"Payment was declined/aborted!"; } [alert show]; }]; UINavigationController *modalNav = [[UINavigationController alloc] initWithRootViewController:viewController]; modalNav.navigationBar.barStyle = UIBarStyleBlack; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { modalNav.modalPresentationStyle = UIModalPresentationFullScreen; } else { // Show as Form on iPad modalNav.modalPresentationStyle = UIModalPresentationFormSheet; } [self presentViewController:modalNav animated:YES completion:NULL]; }
More information on the completed transaction statuses and what they mean can be found here.
Testing with a Card Reader
To test your integration with a card reader:
  1. Order the Developer Kit.
  2. Retrieve your
    merchantIdentifier
    and
    merchantSecretKey
    through the Gateway Manager.
  3. Change the
    providerMode
    to
    MPProviderModeTEST
    .
  4. Create the
    accessoryParameters
    with the card reader family and connection you want to use.
For more information about the accessory and transaction parameters, see the SDK Integration documentation.
Loading Merchant Data from Your Backend
Right now, the
merchantIdentifier
and
merchantSecretKey
are hardcoded so all payments would be routed to the same merchant.
For a live solution, you might want to support multiple merchants, such as two restaurants, to route the payment correctly. To support multiple merchants, store the following data on your backend:
  1. The
    merchantIdentifier
    and
    merchantSecretKey
    identify which merchant the payment is routed to. You can create new merchants and get their credentials in the Gateway Manager.
  2. Whether the merchant is a
    TEST
    or
    LIVE
    merchant.
  3. The card reader model the merchant uses.
You can then fetch this data before a transaction and configure the PayButton correctly:
MPUMposUI *ui = [MPUMposUI initializeWithProviderMode:<TEST or LIVE, loaded from your backend> merchantIdentifier:<MerchantIdentifier loaded from your backend> merchantSecret:<MerchantSecretKey loaded from your backend>];
Customizing the PayButton
You can customize tint / color of the navigation bar and your receipts.
Customizing UI Colors
You can customize the UI colors, including:
  1. Set the tint of the navigation bar using
    navigationBarTint
    .
  2. Set the color of the text in the navigation bar using
    navigationBarTextColor
    .
ui.configuration.appearance.navigationBarTint = [UIColor colorWithRed:0.61 green:0.15 blue:0.69 alpha:1]; ui.configuration.appearance.navigationBarTextColor = [UIColor whiteColor];
Customizing Receipts
You are required to offer an email or printed payment receipt to the shopper. The PayButton enables the merchant to send an email payment receipt right after a transaction.
You might want to prevent this behavior if you send your own custom receipts and just want to append the required payment data. You can disable the built-in email receipts by removing
MPUMposUiConfigurationSummaryFeatureSendReceiptViaEmail
from the
summaryFeatures
options.
You can either programmatically send the same receipt that would be sent using the PayButton or you can send / print a custom receipt. For details about the information you are required to display on customized receipts, see  Custom Receipts.
Integrating the PayButton
To integrate the PayButton, use the following instructions to install and perform a payment.
Installing the PayButton
The PayButton requires
minSdkVersion 17
and
compileSdkVersion 28
.
  • Add our repository to your project
    build.gradle
    :
allprojects { repositories { jcenter() maven { url "http://releases.payworks.io/artifactory/mpos" } } }
  • Add build dependencies as classpaths:
buildscript { repositories { google() jcenter() } dependencies { classpath "com.android.tools.build:gradle:4.1.1" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }
  • For version
    2.45.0
    and above, make sure the app support Java 8 features by setting the compatibility levels:
android { ... compileOptions { sourceCompatibility = 1.8 targetCompatibility = 1.8 } buildTypes { release { // ... } debug { // Required for our internal libraries // https://developer.android.com/studio/build/dependencies#resolve_matching_errors matchingFallbacks = ['release'] } } packagingOptions { exclude 'META-INF/*' exclude 'LICENSE.txt' exclude 'asm-license.txt' } }
  • Add the following plugin definitions to your module's
    build.gradle
    :
plugins { id 'com.android.application' id 'kotlin-android' }
>
  • Add the libraries to the dependencies section of your module's
    build.gradle
    :
dependencies { implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'io.payworks:mpos.android.ui:2.53.0' // Add these three dependencies if you want to use a Miura card reader implementation 'io.payworks:mpos.java.accessories.miura:2.53.0' implementation 'io.payworks:mpos.android.comlinks.bluetooth:2.53.0' implementation 'io.payworks:mpos.java.comlinks.tcp:2.53.0' // Add these two dependencies if you want to use a Verifone card reader implementation 'io.payworks:mpos.java.accessories.vipa:2.53.0' implementation 'io.payworks:mpos.java.comlinks.tcp:2.53.0' }
If you want to use ProGuard with your application make sure to add the necessary rules to your ProGuard configuration.
  • Make sure to update your
    AndroidManifest.xml
    to enable a larger heap size by setting
    android:largeHeap="true"
    . This setting is required to accommodate situations in which an update of the terminals is required and bigger chunks of data are requested and transferred.
<application [...] android:largeHeap="true"> [...] </application>
Performing a Payment
This is how you start a payment in mock mode:
void paymentButtonClicked() { MposUi ui = MposUi.initialize(this, ProviderMode.MOCK, "merchantIdentifier", "merchantSecretKey"); ui.getConfiguration().setSummaryFeatures(EnumSet.of( // Add this line, if you do want to offer printed receipts // MposUiConfiguration.SummaryFeature.PRINT_RECEIPT, MposUiConfiguration.SummaryFeature.SEND_RECEIPT_VIA_EMAIL) ); // Start with a mocked card reader: AccessoryParameters accessoryParameters = new AccessoryParameters.Builder(AccessoryFamily.MOCK) .mocked() .build(); ui.getConfiguration().setTerminalParameters(accessoryParameters); // Add this line if you would like to collect the customer signature on the receipt (as opposed to the digital signature) // ui.getConfiguration().setSignatureCapture(MposUiConfiguration.SignatureCapture.ON_RECEIPT); /* When using the Bluetooth Miura, use the following parameters: AccessoryParameters accessoryParameters = new AccessoryParameters.Builder(AccessoryFamily.MIURA_MPI) .bluetooth() .build(); ui.getConfiguration().setTerminalParameters(accessoryParameters); */ /* When using Verifone readers via WiFi or Ethernet, use the following parameters: AccessoryParameters accessoryParameters = new AccessoryParameters.Builder(AccessoryFamily.VERIFONE_VIPA) .tcp("192.168.254.123", 16107) .build(); ui.getConfiguration().setTerminalParameters(accessoryParameters); */ TransactionParameters transactionParameters = new TransactionParameters.Builder() .charge(new BigDecimal("5.00"), io.mpos.transactions.Currency.EUR) .subject("Bouquet of Flowers") .customIdentifier("yourReferenceForTheTransaction") .build(); Intent intent = ui.createTransactionIntent(transactionParameters); startActivityForResult(intent, MposUi.REQUEST_CODE_PAYMENT);}
The result is then delivered to your activity:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == MposUi.REQUEST_CODE_PAYMENT) { if (resultCode == MposUi.RESULT_CODE_APPROVED) { // Transaction was approved Toast.makeText(this, "Transaction approved", Toast.LENGTH_LONG).show(); } else { // Card was declined, or transaction was aborted, or failed // (e.g. no internet or accessory not found) Toast.makeText(this, "Transaction was declined, aborted, or failed", Toast.LENGTH_LONG).show(); } // Grab the processed transaction in case you need it // (e.g. the transaction identifier for a refund). // Keep in mind that the returned transaction might be null // (e.g. if it could not be registered). Transaction transaction = MposUi.getInitializedInstance().getTransaction(); } }
More information on the completed transaction statuses and what they mean can be found here.
If you have problems with the
onActivityResult
not being called, this might be caused by starting the PayButton Activity from the wrong Activity / Fragment. This Stackoverflow post might help you resolve the issue.
Testing with a Card Reader
To test your integration with a real card reader:
  1. Order the Developer Kit.
  2. Retrieve your
    merchantIdentifier
    and
    merchantSecretKey
    through the Gateway Manager.
  3. Change the
    ProviderMode
    to
    ProviderMode.TEST
    .
  4. Create the
    accessoryParameters
    with the card reader family and connection you want to use.
For more information about the accessory and transaction parameters, see the SDK Integration documentation.
Loading Merchant Data from Your Backend
Right now, the
merchantIdentifier
and
merchantSecretKey
are hardcoded so all payments would be routed to the same merchant.
For a live solution, you might want to support multiple merchants, such as two restaurants, to route the payment correctly. To support multiple merchants, store the following data on your backend:
  1. The merchantIdentifier
    and
    merchantSecretKey
    identify which merchant the payment is routed to. You can create new merchants and get their credentials in the Gateway Manager.
  2. Whether the merchant is a
    TEST
    or
    LIVE
    merchant.
  3. The card reader model the merchant uses.
You can then fetch this data before a transaction and configure the PayButton correctly:
MposUi ui = MposUi.initialize(this, <ProviderMode.TEST or ProviderMode.LIVE, loaded from your backend>, <MerchantIdentifier loaded from your backend>, <MerchantSecretKey loaded from your backend>);
Customizing the PayButton
You can customize tint / color of the navigation bar and your receipts.
Customizing UI Colors
You can customize the UI colors, including:
  1. Set the color of the icon and top action bar using
    setColorPrimary
    .
  2. Set the color of the status bar using
    setColorPrimaryDark
    (Android L and later).
  3. Set the primary text color using
    setTextColorPrimary
    .
ui.getConfiguration().getAppearance() .setColorPrimary(Color.parseColor("#9c27b0")) .setColorPrimaryDark(Color.parseColor("#7b1fa2")) .setTextColorPrimary(Color.WHITE);
123
Customizing Receipts
You are required to offer an email or printed payment receipt to the shopper. The PayButton enables the merchant to send an email payment receipt immediately after a transaction.
You might want to prevent this behavior if you send your own receipts and just want to append the required payment data. You can disable the built-in email receipts by removing
MposUiConfiguration.SummaryFeature.SEND_RECEIPT_VIA_EMAIL
from the
setSummaryFeatures
EnumSet.
If you choose to remove this, you must implement another way for the merchant to send out a receipt.
You can either programmatically send the same receipt that would be sent using the PayButton or you can send / print a custom receipt. For details about the information you are required to display on customized receipts, see Custom Receipts.