Integrating with CocoaPods
Importing DyScan
The easiest way to integrate DyScan is by using CocoaPods, which is covered in this guide.
Follow the instructions below corresponding with your DyScan version to access the necessary repositories.
After getting the access token for Dyneti's repo access, open up your Podfile
and above the target add this line:
source 'https://dyscan-fraud@github.com/dyneti/dyscan-ios-distribution-fraud.git'
Later when asked for a password for user "dyscan-fraud", paste the access token that we provided.
Then, inside the target with the other dependencies, add the line below:
pod 'DyScanFraud'
Include use_frameworks!
in your Podfile
if you have not done so already (see here for a sample Podfile
). Then in a terminal in the directory of your iOS project, run
$ pod install
If your app does not already ask for camera permissions, add the key “NSCameraUsageDescription” (Privacy - Camera Usage Description) to your app's Info.plist file. You should set the value to be the string a user sees when they are prompted for the camera permission (e.g. To scan credit cards).
Initializing DyScan
In your AppDelegate
add import DyScanFraud
and the following line to configure DyScan
.
class AppDelegate: UIResponder, UIApplicationDelegate {
//...
internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//...
DyScanApp.configure(apiKey: "{YOUR API KEY}")
//...
return true
}
}
Interfacing DyScan
DyScan can be used in two ways:
- As a view controller: Quick and easy. Create a view controller that is presented modally. The DyScan view controller handles all aspects of the UX. We currently support two view controllers. One is intended for when DyScan is optionally accessed from a checkout form. The other is intended for when DyScan is the default method of entering payment information, and provides an option to enter numbers manually instead.
- As a view: More flexible. Create a DyScanView to do card scanning only and manage everything else yourself. This enables a broader range of presentations, such as in-place transitions, but requires that you handle the rest of the UI yourself.
Regardless of which methodology you use, the failure callback will provide a reason for why scanning was not successful. You do not have to use this value (for example you could always go to manual entry on any failure), but this gives you the opportunity to react differently based on the reason, for example by requesting the user to enable the permissions. The possible values are:
Reason | Description |
---|---|
AuthError | There was an issue with the API key. Make sure that the API key has been set prior to calling prepare. |
CameraError | The camera setup has failed. For example, there might not be any cameras available for use at the time. |
NoPermissions | The user has not granted the app permissions to open the camera, so we have no way of proceeding with the scan. |
UserCancelled | The user chose to exit. |
ScanLogError | The scan data upload to the backend has failed. This is only returned when awaitScanStorage is set to true |
- View Controller as an Option
- View Controller as the Default
- View
import DyScanFraud
in the file that contains the view controller that will instantiate DyScan.
In your app, create an extension for your view controller that conforms to DyScanViewControllerDelegate
. This will require you to implement two functions, onFailure
, and onSuccess
. onFailure
is called whenever a scan event is unsuccessful (for any reason, including the user choosing to cancel).
Optionally, you can implement the function onProgressUpdate
to access information about the card being scanned while the scan is ongoing (available for version 1.2.9
of DyScan and up). The DyScanProgressUpdate
class has two attributes (both of string type): lastFourDigits
and network
, which correspond to the last four digits and network of the credit card (e.g., Visa or Mastercard) being scanned, respectively. You may choose to surface this information to your users to give them more feedback as they are waiting for their card to scan.
extension ExampleViewController: DyScanViewControllerDelegate{
func onFailure(_ paymentViewController: DyScanViewController!, reason: DyScanExitReason) {
paymentViewController.dismiss(animated: true, completion: nil)
// Implement functionality for failure cases
}
func onSuccess(_ cardInfo: DyScanCreditCardInfo!, in paymentViewController: DyScanViewController!) {
paymentViewController.dismiss(animated: true, completion: nil)
// Implement functionality after card is read (information is stored in cardInfo)
}
func onProgressUpdate(_ progressUpdate: DyScanProgressUpdate, in paymentViewController: DyScanViewController!){
let network = progressUpdate.network
let lastFourDigits = progressUpdate.lastFourDigits
// Implement functionality to use this info mid-scan
}
}
To instantiate DyScan, create an instance of DyScanViewController
, and set the paymentDelegate
attribute of it to your view controller (using self
). Then, present the view controller.
let viewController = DyScanViewController()
viewController.paymentDelegate = self
let navigationController = UINavigationController(rootViewController: viewController)
navigationController.modalPresentationStyle = .fullScreen
present(navigationController, animated: true, completion: nil)
import DyScanFraud
in the file that contains the view controller that will instantiate DyScan.
In your app, create an extension for your view controller that conforms to DyScanDefaultViewControllerDelegate
. This will require you to implement three functions, onFailure
, onSuccess
, and userChoseManual
. onFailure
is called whenever a scan event is unsuccessful (for any reason, even if the user chose to cancel).
Optionally, you can implement the function onProgressUpdate
to access information about the card being scanned while the scan is ongoing (available for version 1.2.9
of DyScan and up). The DyScanProgressUpdate
class has two attributes (both of string type): lastFourDigits
and network
, which correspond to the last four digits and network of the credit card (e.g., Visa or Mastercard) being scanned, respectively. You may choose to surface this information to your users to give them more feedback as they are waiting for their card to scan.
extension ExampleViewController: DyScanViewControllerDelegate{
func onFailure(_ paymentViewController: DyScanViewController!, reason: DyScanExitReason) {
paymentViewController.dismiss(animated: true, completion: nil)
// Implement functionality after user cancels
}
func onSuccess(_ cardInfo: DyScanCreditCardInfo!, in paymentViewController: DyScanViewController!) {
paymentViewController.dismiss(animated: true, completion: nil)
// Implement functionality after card is read (information is stored in cardInfo)
}
func userChoseManual(_ paymentViewController: DyScanDefaultViewController!){
paymentViewController.dismiss(animated: true, completion: nil)
// Implement functionality for transitioning manual entry
}
func onProgressUpdate(_ progressUpdate: DyScanProgressUpdate, in paymentViewController: DyScanViewController!){
let network = progressUpdate.network
let lastFourDigits = progressUpdate.lastFourDigits
// Implement functionality to use this info mid-scan
}
}
To instantiate DyScan, create an instance of DyScanDefaultViewController
, and set the paymentDelegate
attribute of it to your view controller (using self
). Then, present the view controller.
let viewController = DyScanDefaultViewController()
viewController.paymentDelegate = self
let navigationController = UINavigationController(rootViewController: viewController)
navigationController.modalPresentationStyle = .fullScreen
present(navigationController, animated: true, completion: nil)
If you would like to disable the manual entry option, you can do so by setting the key viewController.allowManualEntry=false
.
import DyScanFraud
in the file that contains the view controller that will instantiate DyScan.
In your app, create an extension for your view that conforms to DyScanViewDelegate
. This will require you to implement two functions, onFailure
, and onSuccess
.
Optionally, you can implement the function onProgressUpdate
to access information about the card being scanned while the scan is ongoing (available for version 1.2.9
of DyScan and up). The DyScanProgressUpdate
class has two attributes (both of string type): lastFourDigits
and network
, which correspond to the last four digits and network of the credit card (e.g., Visa or Mastercard) being scanned, respectively. You may choose to surface this information to your users to give them more feedback as they are waiting for their card to scan.
extension ExampleViewController: DyScanViewDelegate{
func onFailure(_ dyScanView: DyScanView!, reason: DyScanExitReason) {
//Implement functionality when we could not scan
}
func onSuccess(_ dyScanView: DyScanView!, cardInfo: DyScanCreditCardInfo?) {
//Implement functionality when scanning completes (information is stored in cardInfo)
}
func onProgressUpdate(_ dyScanIOView: DyScanView!, progressUpdate: DyScanProgressUpdate) {
let network = progressUpdate.network
let lastFourDigits = progressUpdate.lastFourDigits
// Implement functionality to use this info mid-scan
}
}
To instantiate DyScan, create an instance of DyScanView
, and set the delegate
attribute of it to your view controller (using self
). You will need to call the prepare()
function to fully initialize the view before adding it as a subview. For example, DyScanView
could be added like this:
dyScanView = DyScanView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
dyScanView?.delegate = self
dyScanView?.prepare()
self.view.addSubview(dyScanView!)
DyScanCreditCardInfo
has the following fields:
Output | Description |
---|---|
scanId:String | The scan UUID |
payloadId:String | A unique identifier for the payload. To be used with the Integrity Check API. |
cardNumber:String | The card number read, as a string. |
expiryMonth:UInt | If read, the expiration month of the card, otherwise 0. To maintain good style, we recommend using nullableExpiryMonth if writing in Swift. |
nullableExpiryMonth:NSNumber? | If read, the expiration month of the card, otherwise nil. The value is accessed asnullableExpiryMonth.uintValue . |
expiryYear:UInt | If read, the expiration year of the card, otherwise 0. To maintain good style, we recommend using nullableExpiryYear if writing in Swift. |
nullableExpiryYear:NSNumber? | If read, the expiration year of the card, otherwise nil. The value is accessed asnullableExpiryYear.uintValue . |
isFraud:Bool | a boolean indicating card legitimacy. isFraud is true when the card is fraudulent, and false if card is legitimate |
nullableIsFraud:NSNumber? | If read, the card legitimacy indication, otherwise nil. The value is accessed asnullableIsFraud.boolValue . |
timestamp:UInt | an ISO8601 timestamp indicating when the scan occurred |
declineReasons:DyScanDeclineReasons? | a class containing reasons why a card scanned is declared as fraudulent |
cardOrientation:String | Whether the card scanned was vertical or horizontal. |
Reasons for decline include the following:
formatMismatch
: a boolean that indicates that the card assets do not match the card type as detected by the BIN (e.g., the card number or logo are not where we expect them to be).numberMismatch
: a boolean that indicates that the BIN and last four digits of the scanned card do not match with what we expect. Note this reason is only available if you provide us with the expected BIN and last four.generatedImage
: a boolean that indicates that the image is likely generated (e.g., the image is being scanned through a screen, or does not have corners or wear and tear).rateLimited
: a boolean that indicates that an attacker has been attempting multiple scans in rapid succession using the same device.tamperedFeatures
: a boolean that indicates that at least one of the other features has been tampered with
Customizing the Appearance
The DyScan UI is customizable through the following options
Option | Description | Default Value |
---|---|---|
language:String | The language to display | NSLocale.current.languageCode |
showNumberOnCompletion:Bool | Whether to display the credit card number to the user after the card has been read. | false |
numberOnCompletionAlwaysHorizontal:Bool | Whether to display number on completion horizontally in fixed position. | false |
showDynetiLogo:Bool | Whether to display the Dyneti logo and wordmark above the scan region. | true |
showNumberOverlay:Bool | Whether to show the number overlay. | true |
numberOverlayColor:UIColor | The color of the number overlay text. | UIColor.white |
numberOverlayOpacity:CGFloat | The opacity of the number overlay text. | 0.3 |
defaultCardNumberText:String | The card number shown in the number overlay text. | "4242 4242 4242 4242" |
defaultExpirationDate:String | The expiration shown in the number overlay text. | "11/11" |
showCorners:Bool | Whether to show the corners found by the scanner or not. | true |
cornerThickness:int | The thickness of lines that show the corners. | 5 |
cornerInactiveColor:UIColor | The color of the corner in its normal, no corner found state. | UIColor.gray |
cornerActiveColor:UIColor | The color of the corner when it has found a corner. | UIColor.cyan |
cornerCompletedColor:UIColor | The color of the corner when scanning is completed. | UIColor.green |
bgColor:UIColor | The color of the background. | UIColor.gray |
bgOpacity:CGFloat | The opacity of the background. | 0.8 |
lightTorchWhenDark:Bool | Whether to use the torch automatically in dark environments. If set to false, torch toggle button will appear. | true |
vibrateOnCompletion:Bool | Whether to cause the phone to vibrate on a successful scan. | true |
cardFrameAccessibilityLabel:String? | The accessibility label of card scan frame. | "Align your card to this frame" |
enableSidewaysScanning:Bool | Whether to allow cards to scan in sideways orientation. If set to true, vertical cards will be able to be scanned when positioned in the horizontal scan window. Note that enableSidewaysScanning and showRotateButton should not simultaneously be set to true when using the view controller, and that isVertical should not be used when enableSidewaysScanning is set to true when using DyScan as a view. | false |
awaitScanStorage:Bool | Whether to strictly wait for the scan data to be successfully uploaded to the backend before returning a scan result | false |
The following fields can only be used in the view controller:
Option | Description | Default Value |
---|---|---|
showHelperText:Bool | Whether to show the helper text. | true |
helperTextString:String? | The text displayed in helper text. If this is set, it will override the set language. By default, the text is displayed in one line and font size is automatically shrunk to fit on the screen. To display it in multiple lines, use\n for line breaks. | nil |
helperTextColor:UIColor | The color of the helper text. | UIColor.white |
helperTextFont:UIFont | The font and text size of the helper text. | System font, size: 25 |
helperTextPosition:Enum``<br/> DyScanHelperTextPosition` | The position of the helper text. DyScanHelperTextPosition enum values: top, center, bottom | bottom |
showRotateButton:Bool | Whether to show a rotate button to support vertical cards better. | false |
Additionally, there are some public fields you can use to easily add buttons with additional functionality to your scan screen. Note that these are available only if you are using DyScan as a view. The fields are described below:
Public fields
Name | Description |
---|---|
Name | Description |
isVertical:Bool | Whether to set scan region to vertical card orientation
Also can be used to get current scan region orientation (true when vertical). |
isTorchEnabled:Bool | Whether to turn torch on or off. Also can be used to check if torch is currently turned on (true when torch is on). |