# iOS Core SDK
source: https://developer.mastercard.com/mastercard-merchant-presented-qr/documentation/device-sdks/ios-core-sdk/index.md

The iOS Core SDK can be used by:

* Originating Institutions and Wallet Providers to parse and verify QR code content for iOS applications
* Receiving Institutions to generate QR codes for iOS applications

This SDK only provides the core functionality to parse and generate the content of the QR code. If you need a UI component to scan the QR code, you can use the [iOS QR Scan SDK](https://developer.mastercard.com/mastercard-merchant-presented-qr/documentation/device-sdks/ios-qr-scan-sdk/index.md).

This SDK is developed in Objective-C and it works with Swift.

## Requirements {#requirements}

* Xcode 9.0+
* iOS 8.0+

## Features {#features}

* Capabilities to parse and validate Push Payment QR code string
* Generate Push Payment QR code string

## Installation {#installation}

### Swift {#swift}

1. Download the latest release of [MPQR Core SDK](https://static.developer.mastercard.com/content/mastercard-merchant-presented-qr/sdk-files/mpqrcoresdk.zip).
2. Unzip the file and place its contents in the project folder.
3. Go to your Xcode project's General settings. Add **MPQRCoreSDK.xcframework** in Frameworks, Libraries and Embedded content.

### Objective-C {#objective-c}

Follow the same instructions as Swift.

## Usage {#usage}

### Parse QR Code Content {#parse-qr-code-content}

This function can be used to parse QR code content. This function throws an exception when a QR code is not compliant with the EMVCo Merchant Presented QR specification.
* Swift
* Objective-C

```Swift
import MPQRCoreSDK

func parseQRCode(code: String) {
    do {
            // Parse qr code
            let pushData = try MPQRParser.parse(string: code)
            // Print data in string format
            print(pushData.dumpData())
            
        } catch let error as MPQRError{
            if let str = error.getString(){
                print("Error: \(str)")
            }else
            {
                print("Unknown error occurred \(error)")
            }
        } catch {
            print("Unknown error occurred \(error)")
        }
}
```

```Objective-C
@import MPQRCoreSDK;

-(void)parseQRCode:(NSString *)code{
    MPQRError* error;
    
    // Parse QR code
    PushPaymentData *data = [MPQRParser parse:code error:&error];
    if (data != nil) {
        // Print data in string format
        NSLog(@"data : %@", [data dumpData]);    
    }
    if (error != nil) {
        // Print error
        NSLog(@"error string : %@",[error getString]);
    }
}
```

### Parse QR Code Content with Validation Warnings {#parse-qr-code-content-with-validation-warnings}

Unlike the *parseQRCode* function above, this function will not throw an exception for InvalidTagValue, RFU Tag and Missing Tag. Instead it returns a PushPaymentData object with validation error when the scanned QR code is not compliant with the EMVCo Merchant Presented QR specification.
* Swift
* Objective-C

```Swift
import MPQRCoreSDK

func parseQRCode(code: String) {
    do {
        // Parse QR code
        let pushData = try MPQRParser.parseWithValidationWarnings(string: code)
        // Print data in string format
        print(pushData.dumpData())

        // check if validation errors present
        if pushData.validationErrors != nil{
            // Print data in validation errors
            for err in pushData.validationErrors!{
                print("Error type: \(getErrorTypeString(error: err))")
                print("Error message: \(err.getString())")
                print("Error tag: \(err.getTag())")
                print("Error value: \(err.getValue())")
            }
        }
    
    } catch let error as MPQRError{
        if let str = error.getString(){
            print("Error: \(str)")
        }else
        {
            print("Unknown error occurred \(error)")
        }
    } catch {
        print("Unknown error occurred \(error)")
    }
}

func getErrorTypeString(error : MPQRError) -> String {
    switch (error.errorType) {
    case .MissingTag:
        return "MissingTag";
    case .InvalidFormat:
        return "InvalidFormat";
    case .InvalidTagValue:
        return "InvalidTagValue";
    case .ConflictingTag:
        return "ConflictingTag";
    case .Limit:
        return "Limit";
    case .DuplicateTag:
        return "DuplicateTag";
    case .RFUTag:
        return "RFUTag";
    default:
        return "UnknownTag";
    }
}
```

```Objective-C
#import <MPQRCoreSDK/MPQRCoreSDK.h>


-(void)parseQRCode:(NSString *)code{
    MPQRError* error;
    
    // Parse QR code
    PushPaymentData *data = [MPQRParser parseWithValidationWarnings:code error:&error];
    if (data != nil) {
        // Print data in string format
        NSLog(@"data : %@", [data dumpData]);
        
        // check if validation errors present
        if (data.validationErrors != nil) {
            
            // Print data in validation errors
            for (MPQRError * err in data.validationErrors) {
                NSLog(@"error type : %@", [self getErrorTypeString:err]);
                NSLog(@"error tag : %@", err.getTag.tag);
                NSLog(@"error string : %@", err.getString);
            }
        }
        
    }
    if (error != nil) {
        // Print error
        NSLog(@"error string : %@",[error getString]);
    }
}


-(NSString *) getErrorTypeString:(MPQRError *)err {
    switch (err.errorType) {
        case MissingTag:
            return @"MissingTag";
        case InvalidFormat:
            return @"InvalidFormat";
        case InvalidTagValue:
            return @"InvalidTagValue";
        case ConflictingTag:
            return @"ConflictingTag";
        case Limit:
            return @"Limit";
        case DuplicateTag:
            return @"DuplicateTag";
        case RFUTag:
            return @"RFUTag";
        default:
            return @"UnknownTag";
    }
}
```

### Generate QR Code {#generate-qr-code}

This function can be used to generate a QR code.
* Swift
* Objective-C

```Swift
import CoreImage

func generateQRCode(from string: String) -> UIImage? {
    let data = string.data(using: String.Encoding.utf8)

    if let filter = CIFilter(name: "CIQRCodeGenerator") {
        filter.setValue(data, forKey: "inputMessage")
        // Set scale according to your device display. If the qr code is blurry then increase scale
        let transform = CGAffineTransform(scaleX: 3, y: 3)

        if let output = filter.outputImage?.transformed(by: transform) {
            return UIImage(ciImage: output)
        }
    }
    return nil
}

func generatePushPaymentQR() {
        do {
            // Generate
            let pushPaymentData = PushPaymentData()
                    
            // Payload format indicator
            pushPaymentData.payloadFormatIndicator = "01"
            
            // Point of initiation method
            pushPaymentData.pointOfInitiationMethod = "12"
            
            // Additional data
            let addData = AdditionalData()
            addData.storeId = "A6008"
            addData.loyaltyNumber = "***"
            addData.terminalId = "A6008667"
            addData.additionalConsumerDataRequest = "ME"
            addData.merchantChannel = "182"
            addData.merchantTaxId = "9788999"
            try addData.setTagInfoValue("239684", forTagString: AdditionalDataTag.TAG_00.tag)
            pushPaymentData.additionalData = addData
            
            let mastercardData = MasterCardData()
            mastercardData.alias = "testAlias"
            mastercardData.maid = "A92836"
            mastercardData.pfid = "JS08838"
            mastercardData.marketSpecificAlias = "malias*12983"
            try mastercardData.setValue("test74", forTag: MasterCardDataTag.TAG_74_MASTERCARD_DATA_SUB_TAG.tag)
            pushPaymentData.masterCardData = mastercardData
        
            // Merchant category code
            pushPaymentData.merchantCategoryCode = "1434"
            
            // Transaction currency code
            pushPaymentData.transactionCurrencyCode = "156"
            
            // Transaction amount
            pushPaymentData.transactionAmount = "83.80"
            
            // Country code
            pushPaymentData.countryCode = "CN"
            
            // Merchant name
            pushPaymentData.merchantName = "BEST TRANSPORT"
            
            // Merchant city
            pushPaymentData.merchantCity = "New York"
            
            // Postal code
            pushPaymentData.postalCode = "56748"
                        
            // Genarate QR code string
            let qrCodeString = try pushPaymentData.generatePushPaymentString()
            
            // Generate image
            let image = generateQRCode(from: qrCodeString)
            
        } catch {
            print("Error occurred while creating PushPaymentData object \(error)")
            return
        }
    }
```

```Objective-C
#import <MPQRCoreSDK/MPQRCoreSDK.h>

- (UIImage *)generateQRCode:(NSString *)string {
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
    if (!filter || !data)
        return nil;

    [filter setValue:data forKey:@"inputMessage"];
    CGAffineTransform transform = CGAffineTransformMakeScale(3, 3);
    CIImage *image = [[filter outputImage] imageByApplyingTransform:transform];
    return [UIImage imageWithCIImage:image];
}


-(void)generatePushPaymentQR{
    // Generate
    PushPaymentData *pushPaymentData = [[PushPaymentData alloc] init];

    // Payload format indicator
    pushPaymentData.payloadFormatIndicator = @"01";

    // Point of initiation method
    pushPaymentData.pointOfInitiationMethod = @"12";
        
    MPQRError* error;
    
    AdditionalData* addData = [AdditionalData new];
    addData.storeId = @"A6008";
    addData.loyaltyNumber = @"***";
    addData.terminalId = @"A6008667";
    addData.additionalConsumerDataRequest = @"ME";
    addData.merchantTaxId = @"91273284";
    addData.merchantChannel = @"400";
    [addData setTagInfoValue:@"612763" forTagString:AdditionalDataTag.TAG_00.tag error:&error];
    pushPaymentData.additionalData = addData;

    // MasterCardData for tag 05
    MasterCardData *masterCardData = [MasterCardData new];
    masterCardData.alias = @"TestAlias";
    masterCardData.MAID = @"A4865SIEUI";
    masterCardData.PFID = @"2C2P";
    masterCardData.marketSpecificAlias = @"market92384k";
    [masterCardData setValue:@"100" forTag:MasterCardDataTag.TAG_78_MASTERCARD_DATA_SUB_TAG.tag error:&error];
    pushPaymentData.masterCardData = masterCardData;
    
    // Merchant category code
    pushPaymentData.merchantCategoryCode = @"1434";

    // Transaction currency code
    pushPaymentData.transactionCurrencyCode = @"156";

    // Transaction amount
    pushPaymentData.transactionAmount = @"83.80";
        
    // Country code
    pushPaymentData.countryCode = @"CN";

    // Merchant name
    pushPaymentData.merchantName = @"BEST TRANSPORT";

    // Merchant city
    pushPaymentData.merchantCity = @"New York";

    // Postal code
    pushPaymentData.postalCode = @"56748";

    NSString* strQRCode = [pushPaymentData generatePushPaymentString:&error];

    if (error) {
        NSLog(@"Error: %@", error);
    } else {
        // Generate image
        UIImage *image = [self generateQRCode: strQRCode];
    }
}
```

### Get Additional Data Value {#get-additional-data-value}

This function can be used to retrieve the additional data tag value (TAG_62) from a QR code string.
* Swift
* Objective-C

```Swift
import MPQRCoreSDK

func getAdditionalDataValueFromQRString(qrCode : String){
     do {
          let additionalData = try MPQRParser.getAdditionalDataValue(fromQRString: qrCode)
          print(additionalData)
     } catch {
          print("Error occurred during validation \(error)")
     }
 } 
```

```Objective-C
#import <MPQRCoreSDK/MPQRCoreSDK.h>

-(void)getAdditionalDataValueFromQRString:(NSString *) qrCode{
    MPQRError* error;
    NSString *additionalDataVal = [MPQRParser getAdditionalDataValueFromQRString:qrCode error:&error];
    NSLog(@"Additional Data value : %@", additionalDataVal);
}
```

