CPF and CNPJ Validation

2

I've been doing research on Swift and have not seen examples that contemplates the validation of both CPF and CNPJ. So does any of your colleagues have a role that can validate them?

    
asked by anonymous 01.03.2017 / 02:30

1 answer

15

CPF Validation

To validate the first digit of the CPF you must multiply each digit (from 1st to 9th) starting with 10 and gradually decreasing to 2 and accumulating the total of multiplications. Then take 11 and subtract the rest of the accumulated divided by 11. If the result is greater than 9 the first checker digit is 0 otherwise it is the result itself.

For the second verification digit the method is practically the same only using the 1st to 10th digit and the multiplication starts at 11 instead of 10:

Swift 4 or later

extension StringProtocol {
    var isValidCPF: Bool {
        let numbers = compactMap({ Int(String($0)) })
        guard numbers.count == 11 && Set(numbers).count != 1 else { return false }
        func digitCalculator(_ slice: ArraySlice<Int>) -> Int {
            var number = slice.count + 2
            let digit = 11 - slice.reduce(into: 0) {
                number -= 1
                $0 += $1 * number
            } % 11
            return digit > 9 ? 0 : digit
        }
        let dv1 = digitCalculator(numbers.prefix(9))
        let dv2 = digitCalculator(numbers.prefix(10))
        return dv1 == numbers[9] && dv2 == numbers[10]
    }
}

CNPJ Validation

The validation of the verification digit of the CNPJ is very similar to that of the CPF. To validate the first digit of the CNPJ you must multiply each digit in the reverse order (from 12th to 1st) starting with 2 and increasing gradually to 9 and after 2 to 5 and accumulating the total multiplications. Then take 11 and subtract the rest of the accumulated divided by 11. If the result is greater than 9 the checker digit is 0 otherwise it is equal to the result itself.

For the second verification digit the method is practically the same only using the 13th to the 1st digit and the multiplication ends in 6 instead of 5:

extension StringProtocol {
    var isValidCNPJ: Bool {
        let numbers = compactMap({ Int(String($0)) })
        guard numbers.count == 14 && Set(numbers).count != 1 else { return false }
        func digitCalculator(_ slice: ArraySlice<Int>) -> Int {
            var number = 1
            let digit = 11 - slice.reversed().reduce(into: 0) {
                number += 1
                $0 += $1 * number
                if number == 9 { number = 1 }
            } % 11
            return digit > 9 ? 0 : digit
        }
        let dv1 = digitCalculator(numbers.prefix(12))
        let dv2 = digitCalculator(numbers.prefix(13))
        return dv1 == numbers[12] && dv2 == numbers[13]
    }
}

Playground

let cpf1 = "957.621.155-77"
let cpf2 = "746.043.382-99"
let cpf3 = "111.111.111-11"

cpf1.isValidCPF  // true
cpf2.isValidCPF  // true
cpf3.isValidCPF  // false

let cnpj1 = "25.559.813/0001-47"
let cnpj2 = "76.702.537/0001-65"
let cnpj3 = "22.222.222/2222-22"

cnpj1.isValidCNPJ  // true
cnpj2.isValidCNPJ  // true
cnpj3.isValidCNPJ  // false
    
02.03.2017 / 05:31