Skip to content

Commit

Permalink
Version 2.2: Add method to prepare a checkout
Browse files Browse the repository at this point in the history
* [BUGFIX] Fix a crash when trying to re-connect to an Air/PIN+ terminal,
  see [issue #33](#33)
* [ADDED] Add `+[SumupSDK prepareForCheckout]` to prepare the SDK when
  a checkout attempt is imminent.
* [ADDED] Add `+[SumupSDK testSDKIntegration]` to validate your
  integration. Please do not call in Release builds but only in
  development.
* [IMPROVEMENT] Speed up wake on Bluetooth
* [IMPROVEMENT] Fix an issue where subsequent checkout attempts would
  keep failing when BT connection to Air/PIN+ Terminal has been lost
  during checkout

Sample application:

* [ADDED] Tapping "Next" on the keyboard when entering an amount will
  wake a connected terminal by calling `+[SumupSDK prepareForCheckout]`.
* [ADDED] Run `+[SumupSDK testSDKIntegration]` when building in
  Debug configuration.
  • Loading branch information
mollidor committed Mar 24, 2017
1 parent 0b68d2c commit 452e1ea
Show file tree
Hide file tree
Showing 97 changed files with 170 additions and 105 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# SumUp iOS SDK Changelog

## Version 2.2

* [BUGFIX] Fix a crash when trying to re-connect to an Air/PIN+ terminal,
see [issue #33](https://github.com/sumup/sumup-ios-sdk/issues/33)
* [ADDED] Add `+[SumupSDK prepareForCheckout]` to prepare the SDK when a
checkout attempt is imminent.
* [ADDED] Add `+[SumupSDK testSDKIntegration]` to validate your integration.
Please do not call in Release builds but only in development.
* [IMPROVEMENT] Speed up wake on Bluetooth
* [IMPROVEMENT] Fix an issue where subsequent checkout attempts would keep
failing when BT connection to Air/PIN+ Terminal has been lost during checkout.

Sample application:

* [ADDED] Tapping "Next" on the keyboard when entering an amount will wake a
connected terminal by calling `+[SumupSDK prepareForCheckout]`.
* [ADDED] Run `+[SumupSDK testSDKIntegration]` when building in
Debug configuration.


## Version 2.1

* [ADDED] Provide method to let merchants change their checkout preferences
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Platform](https://img.shields.io/badge/Platform-iOS-lightgrey.svg?style=flat-square)](#prerequisites)
[![Created](https://img.shields.io/badge/Made%20by-SumUp-blue.svg?style=flat-square)]()
[![Supports](https://img.shields.io/badge/Requires-iOS%206+-red.svg?style=flat-square)]()
[![Version](https://img.shields.io/badge/Version-2.1-yellowgreen.svg?style=flat-square)](CHANGELOG.md)
[![Version](https://img.shields.io/badge/Version-2.2-yellowgreen.svg?style=flat-square)](CHANGELOG.md)
[![License](https://img.shields.io/badge/License-SumUp-brightgreen.svg?style=flat-square)](LICENSE)


Expand Down Expand Up @@ -70,18 +70,22 @@ images and localizations. Please follow the steps below to prepare your project:
SumupSDK.embeddedframework/Resources/YTLibResources.bundle


> Note:
> Note:
> You can use the [sample app](https://github.com/sumup/sumup-ios-sdk/tree/master/SumupSDKSampleApp)
that is provided with the SumUp SDK as a reference project. The Xcode project contains sample apps
written in Objective-C and Swift.
> that is provided with the SumUp SDK as a reference project.
> The Xcode project contains sample apps written in Objective-C and Swift.
> In your debug setup you can also call `+[SumupSDK testSDKIntegration]`.
> It will run various checks and print its findings to the console.
> Please do not call it in your Release build.


### Supported device orientation
The SDK supports all device orientations on iPad and portrait on iPhone.
Feel free to support other orientations on iPhone but please keep in mind that
the SDK's UI will be presented in portrait on iPhone.
See `UISupportedInterfaceOrientations` in the sample app's
[Info.plist](SumupSDKSampleApp/SumupSDKSampleApp-Info.plist#L54-L60)
[Info.plist](SumupSDKSampleApp/SumupSDKSampleApp-Info.plist#L56-L67)
or the "General" tab in Xcode's Target Editor.

### Privacy Info plist keys
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
NS_ASSUME_NONNULL_BEGIN

/*
* Currency codes to be used in checkout (ISO 4217 code).
* Other currency codes are permissible in the request object,
* but are likely not to be accepted during the checkout.
* Currency codes to be used in checkout (ISO 4217 code).
* Other currency codes are permissible in the request object,
* but are likely not to be accepted during the checkout.
*/

extern NSString * const SMPCurrencyCodeBRL;
Expand All @@ -33,58 +33,58 @@ typedef NS_OPTIONS (NSUInteger, SMPPaymentOptions) {
@interface SMPCheckoutRequest : NSObject

/**
\abstract Creates a new checkout request.
\param totalAmount The total amount to be charged to a customer. Cannot be nil.
\param title An optional title to be displayed in the merchant's history and on customer receipts.
\param currencyCode Currency Code in which the total should be charged (ISO 4217 code, see SMPCurrencyCode). Cannot be nil, has to match the currency of the merchant logged in. Use [[[SumupSDK currentMerchant] currencyCode] and ensure its length is not 0.
\param options Payment options to choose a payment type(card reader, mobile payment...)
\discussion Be careful when creating the NSDecimalNumber to not
falsely use the NSNumber class creator methods.
Use SMPPaymentOptionAny to not put restrictions on the desired payment types.
\returns A new request object or nil if totalAmount or currencyCode are nil.
* Creates a new checkout request.
*
* Be careful when creating the NSDecimalNumber to not
* falsely use the NSNumber class creator methods.
* Use SMPPaymentOptionAny to not put restrictions on the desired payment types.
*
* @param totalAmount The total amount to be charged to a customer. Cannot be nil.
* @param title An optional title to be displayed in the merchant's history and on customer receipts.
* @param currencyCode Currency Code in which the total should be charged (ISO 4217 code, see SMPCurrencyCode). Cannot be nil, has to match the currency of the merchant logged in. Use [[[SumupSDK currentMerchant] currencyCode] and ensure its length is not 0.
* @param paymentOptions Payment options to choose a payment type(card reader, mobile payment...)
*
* @return A new request object or nil if totalAmount or currencyCode are nil.
*/
+ (SMPCheckoutRequest *)requestWithTotal:(NSDecimalNumber *)totalAmount
title:(nullable NSString *)title
currencyCode:(NSString *)currencyCode
paymentOptions:(SMPPaymentOptions)paymentOptions;

/**
\abstract Creates a new checkout request.
\param totalAmount The total amount to be charged to a customer. Cannot be nil.
\param title An optional title to be displayed in the merchant's history and on customer receipts.
\param currencyCode Currency Code in which the total should be charged (ISO 4217 code, see SMPCurrencyCode). Cannot be nil, has to match the currency of the merchant logged in. Use [[[SumupSDK currentMerchant] currencyCode] and ensure its length is not 0.
\discussion Be careful when creating the NSDecimalNumber to not
falsely use the NSNumber class creator methods.
\returns A new request object or nil if totalAmount or currencyCode are nil.
* Creates a new checkout request.
*
* Be careful when creating the NSDecimalNumber to not
* falsely use the NSNumber class creator methods.
*
* @param totalAmount The total amount to be charged to a customer. Cannot be nil.
* @param title An optional title to be displayed in the merchant's history and on customer receipts.
* @param currencyCode Currency Code in which the total should be charged (ISO 4217 code, see SMPCurrencyCode). Cannot be nil, has to match the currency of the merchant logged in. Use [[[SumupSDK currentMerchant] currencyCode] and ensure its length is not 0.
*
* @return A new request object or nil if totalAmount or currencyCode are nil.
*/
+ (SMPCheckoutRequest *)requestWithTotal:(NSDecimalNumber *)totalAmount
title:(nullable NSString *)title
currencyCode:(NSString *)currencyCode;

/**
\abstract The total amount to be charged to a customer.
\note Will not be nil if the instance was created using either
requestWithTotal:title:currencyCode:paymentOptions: or
requestWithTotal:title:currencyCode:
* The total amount to be charged to a customer.
*
* @note Will not be nil if the instance was created using either
* requestWithTotal:title:currencyCode:paymentOptions: or
* requestWithTotal:title:currencyCode:
*/
@property (strong, readonly, nullable) NSDecimalNumber *totalAmount;

/// A title to be displayed in the merchant's history and on customer receipts.
@property (strong, readonly, nullable) NSString *title;

/**
\abstractCurrency Code in which the total should be charged (ISO 4217 code, see SMPCurrencyCode).
\note Will not be nil if the instance was created using either
requestWithTotal:title:currencyCode:paymentOptions: or
requestWithTotal:title:currencyCode:
* Currency code in which the total should be charged (ISO 4217 code, see SMPCurrencyCode).
*
* @note Will not be nil if the instance was created using either
* requestWithTotal:title:currencyCode:paymentOptions: or
* requestWithTotal:title:currencyCode:
*/
@property (strong, readonly, nullable) NSString *currencyCode;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,87 +27,90 @@ typedef void (^SMPCheckoutCompletionBlock)(SMPCheckoutResult * _Nullable result
@interface SumupSDK : NSObject

/**
\abstract Enables the sandbox mode. Default is NO.
\discussion
Needs to be called prior to calling +setupWithAPIKey: otherwise does nothing.
\warning
You are responsible to ensure that you do not do enable the sandbox
mode in production code. Cards will not be charged in sandbox mode.
* Enables the sandbox mode. Default is NO.
*
* Needs to be called prior to calling +setupWithAPIKey: otherwise does nothing.
*
* @warning You are responsible to ensure that you do not do enable the sandbox
* mode in production code. Cards will not be charged in sandbox mode.
*/
+ (void)setSandboxModeEnabled:(BOOL)enabled DEPRECATED_MSG_ATTRIBUTE("The sandbox environment is not supported anymore. Please get in touch and we will create a sandboxed test account for you.");

/**
\return YES if sandbox mode is enabled. Default is NO.
* @return YES if sandbox mode is enabled. Default is NO.
*/
+ (BOOL)isSandboxModeEnabled DEPRECATED_MSG_ATTRIBUTE("see setSandboxModeEnabled:");

/**
\abstract Sets up the SumupSDK for use in your app.
\param apiKey Your application's API Key for the SumupSDK.
\returns YES if setup was successful. NO otherwise or if SDK has been set up before.
\discussion
Needs to be called at some point before starting interaction with the SDK.
As this might ask for the user's location it should not necessarily be part
of the app launch. Make sure to only setup once per app lifecycle.
If the user did not previously grant your app the permission to use her location,
calling this method will prompt the user to grant such permission.
Please make sure to include the Info.plist localized key 'NSLocationUsageDescription' (the SDK also
uses this key on iOS5). The localized string for that key will be displayed in the alertview
requesting the user's permission. It is recommended to include a reference to the use of
the user's location during the payment process.
Recommendation: "To provide a secure payment service, we need to know your location.
Without location information, you cannot accept payments using this app."
* Sets up the SumupSDK for use in your app.
*
* Needs to be called at some point before starting interaction with the SDK.
* As this might ask for the user's location it should not necessarily be part
* of the app launch. Make sure to only setup once per app lifecycle.
*
* If the user did not previously grant your app the permission to use her location,
* calling this method will prompt the user to grant such permission.
*
* @param apiKey Your application's API Key for the SumupSDK.
* @return YES if setup was successful. NO otherwise or if SDK has been set up before.
*/
+ (BOOL)setupWithAPIKey:(NSString *)apiKey;


/**
\abstract Presents the login modally from the given view controller.
\param fromViewController The UIViewController instance from which the login should be presented modally.
\param animated Pass YES to animate the transition.
\param completionBlock The completion block is called after each login attempt.
\discussion
The login is automatically dismissed if login was successful or cancelled by the user.
If error is nil and success is NO, the user cancelled the login.
Errors are handled internally and usually do not need any display to the user.
Does nothing if merchant is already logged in (calls completion block with success=NO, error=nil).
* Presents the login modally from the given view controller.
*
* The login is automatically dismissed if login was successful or cancelled by the user.
* If error is nil and success is NO, the user cancelled the login.
* Errors are handled internally and usually do not need any display to the user.
* Does nothing if merchant is already logged in (calls completion block with success=NO, error=nil).
*
* @param fromViewController The UIViewController instance from which the login should be presented modally.
* @param animated Pass YES to animate the transition.
* @param block The completion block is called after each login attempt.
*
*/
+ (void)presentLoginFromViewController:(UIViewController *)fromViewController
animated:(BOOL)animated
completionBlock:(nullable SumupCompletionBlock)block;


/**
* Logs in a merchant with an access token acquired via https://sumup.com/integration#APIAuth
* Make sure that no user is logged in already when calling this method.
* Logs in a merchant with an access token acquired via https://sumup.com/integration#APIAuth
* Make sure that no user is logged in already when calling this method.
*
* @param aToken an access token
* @param block a completion block that will run after login has succeeded/failed
*/
+ (void)loginWithToken:(NSString *)aToken completion:(nullable SumupCompletionBlock)block;

/**
\returns YES if the merchant is logged in. NO otherwise.
* @return YES if the merchant is logged in. NO otherwise.
*/
+ (BOOL)isLoggedIn;

/// Returns a copy of the currently logged in merchant or nil if no merchant is logged in.
+ (nullable SMPMerchant *)currentMerchant;


/**
\abstract Presents a checkout view with all necessary steps to charge a customer.
\param request The SMPCheckoutRequest encapsulates all transaction relevant data such as total amount, label, etc.
\param fromViewController The UIViewController instance from which the checkout should be presented modally.
\param completionBlock The completion block will be called when the view will be dismissed.
\discussion
Does nothing if merchant is not logged in or a checkout is already in progress.
The completion block is always called.
* Can be called in advance when a checkout is imminent and a user is logged in.
* You should use this method to let the SDK know that the user is most likely starting a
* checkout attempt soon, e.g. when entering an amount or adding products to a shopping cart.
* This allows the SDK to take appropriate measures, like attempting to wake a connected card terminal.
*/
+ (void)prepareForCheckout;

/**
*
* Presents a checkout view with all necessary steps to charge a customer.
*
* Does nothing if merchant is not logged in or a checkout is already in progress.
* The completion block is always called.
*
* @param request The SMPCheckoutRequest encapsulates all transaction relevant data such as total amount, label, etc.
* @param controller The UIViewController instance from which the checkout should be presented modally.
* @param block The completion block will be called when the view will be dismissed.
*/
+ (void)checkoutWithRequest:(SMPCheckoutRequest *)request
fromViewController:(UIViewController *)controller
Expand All @@ -126,7 +129,7 @@ typedef void (^SMPCheckoutCompletionBlock)(SMPCheckoutResult * _Nullable result
completion:(nullable SMPCheckoutCompletionBlock)block;

/**
\returns YES if a checkout is progress. NO otherwise.
* @return YES if a checkout is progress. NO otherwise.
*/
+ (BOOL)checkoutInProgress;

Expand All @@ -148,18 +151,18 @@ typedef void (^SMPCheckoutCompletionBlock)(SMPCheckoutResult * _Nullable result
completion:(nullable SumupCompletionBlock)block;

/**
Performs a logout of the current merchant and resets the remembered password.
\param block The completion block is called once the logout has finished.
* Performs a logout of the current merchant and resets the remembered password.
*
* @param block The completion block is called once the logout has finished.
*/
+ (void)logoutWithCompletionBlock:(nullable SumupCompletionBlock)block;

/**
\abstract If enabled the SDK automatically displays UI notifications (similar to the ringer UI notifications from iOS) to the user when the reader state changes. Default is YES.
\discussion
Notifications are only displayed once the SDK sees fit to do so. If you want to allow UI notifications to appear earlier,
call this method with YES at any point after +setupWithAPIKey:. Be aware that this will prompt the user to grant permissions
to your app to use the device's microphone.
* If enabled the SDK automatically displays UI notifications (similar to the ringer UI notifications from iOS) to the user when the reader state changes. Default is YES.
*
* Notifications are only displayed once the SDK sees fit to do so. If you want to allow UI notifications to appear earlier,
* call this method with YES at any point after +setupWithAPIKey:. Be aware that this will prompt the user to grant permissions
* to your app to use the device's microphone.
*/
+ (void)setUINotificationsForReaderStatusEnabled:(BOOL)enabled;

Expand All @@ -177,13 +180,12 @@ typedef void (^SMPCheckoutCompletionBlock)(SMPCheckoutResult * _Nullable result
*/
+ (NSString *)bundleVersionShortString;

#pragma mark - error domain and codes
#pragma mark - Error Domain and Codes

extern NSString * const SMPSumupSDKErrorDomain;

/*!
* @enum SMPSumupSDKError
*
* @discussion The error codes returned from the SDK
/**
* The error codes returned from the SDK
*/
typedef NS_ENUM(NSInteger, SMPSumupSDKError) {
SMPSumupSDKErrorGeneral = 0, // General error
Expand All @@ -195,6 +197,19 @@ typedef NS_ENUM(NSInteger, SMPSumupSDKError) {
SMPSumupSDKErrorCheckoutInProgress = 51, // Another checkout process is currently in progress.
};

#pragma mark - SDK Integration

/**
* You can use this method to test if you have integrated the SDK correctly.
*
* The method will log several tests to the console. If you see any errors, please check the README for setup instructions.
*
* @warning While not harmful, this method is not meant to be used in production. Use this in temporary code or in debug configurations only.
*
* @return YES if the SDK is set up correctly, NO if any error was found.
*/
+ (BOOL)testSDKIntegration;

@end

NS_ASSUME_NONNULL_END
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8 changes: 8 additions & 0 deletions SumupSDKSampleApp/SrcObjC/SUSAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
@implementation SUSAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#if DEBUG
/*
* Logs integration warnings in non-production code. Do not call this method in
* release builds.
*/
[SumupSDK testSDKIntegration];
#endif

/*
* This will setup the SumUpSDK.
*
Expand Down
Loading

0 comments on commit 452e1ea

Please sign in to comment.