Integrating PayButton
You can integrate PayButton by using these instructions to install, set up, and perform a payment.
Supported Versions
The current SDK version 2.52.0 supports Xcode 14 or higher projects with targets set as low as iOS 15. If you want integrate the mPOS SDK in a Swift App, see the additional information and restrictions.
Installing PayButton
Add the following code to your
Podfile
and then run
pod install
:
source 'https://github.com/CocoaPods/Specs.git' source 'https://github.com/visa/mpos.sdk.ios.pods.git' use_frameworks! target :"<your-app-target>" do pod 'payworks', '2.52.0' pod 'payworks.paybutton', '2.52.0' 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 higher.
  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
    values 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
Currently, the
merchantIdentifier
and
merchantSecretKey
values 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:
  • The
    merchantIdentifier
    and
    merchantSecretKey
    values, which identify to which merchant the payment is routed. You can create new merchants and get their credentials in the Gateway Manager.
  • Whether the merchant is a
    TEST
    or
    LIVE
    merchant.
  • 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 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. 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 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.
Obtaining Open Source Code
The software included in this product may contain binary code governed by the GPL or other open source licenses that give you the right to receive source code for that binary (“Licenses”). You may obtain the source code you are entitled to under the Licenses by sending a money order or check for US$50 to:
Payworks GmbH
Dingolfingerstr. 15
81673 Munich
Germany
Your request should include your contact information as well as the name and version number of the binary for which you are requesting the source code.
This offer is valid for (i) a period of three years after our last shipment of this product or (ii) for code licensed under AGPLv3, GPLv3, or LGPLv3, for as long as Payworks offers customer support for the product.
For more information about the use of open source software, contact Customer Support.
Integrating PayButton
To integrate PayButton, use the following instructions to install and perform a payment.
Installing PayButton
The PayButton integration requires setting
minSdkVersion 21
or higher and
compileSdkVersion 29
in your
build.gradle
file.
Add the repository to your project
build.gradle
:
allprojects { repositories { jcenter() maven { url "https://repo.visa.com/mpos-releases/" } } }
Add these build dependencies as classpaths. Note that Kotlin version 1.6 or higher and Android Gradle version 7.2 or higher are required.
buildscript { repositories { google() jcenter() } dependencies { classpath "com.android.tools.build:gradle:7.2.2" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }
For version
2.45.0
and higher, 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.57.0' // Add these three dependencies if you want to use a Miura card reader implementation 'io.payworks:mpos.java.accessories.miura:2.57.0' implementation 'io.payworks:mpos.android.comlinks.bluetooth:2.57.0' implementation 'io.payworks:mpos.java.comlinks.tcp:2.57.0' }
If you want to use ProGuard with your application, 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
    values. These values 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 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 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);
1 2 3
Customizing Receipts
You are required to offer an email or printed payment receipt to the shopper. 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 simply 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 disable this behavior, 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 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.
Obtaining Open Source Code
The software included in this product may contain binary code governed by the GPL or other open source licenses that give you the right to receive source code for that binary (“Licenses”). You may obtain the source code you are entitled to under the Licenses by sending a money order or check for US$50 to:
Payworks GmbH
Dingolfingerstr. 15
81673 Munich
Germany
Your request should include your contact information as well as the name and version number of the binary for which you are requesting the source code.
This offer is valid for (i) a period of three years after our last shipment of this product or (ii) for code licensed under AGPLv3, GPLv3, or LGPLv3, for as long as Payworks offers customer support for the product.
For more information about the use of open source software, contact Customer Support.