Module: Pedicel::Validator

Defined in:
lib/pedicel/validator.rb

Overview

Validations for Apple Pay Payment Token and associated data: developer.apple.com/library/content/documentation/PassKit/Reference/PaymentTokenJSON/PaymentTokenJSON.html This purposefully only does syntactic validation (as opposed to semantic).

Defined Under Namespace

Modules: InstanceMethods, Predicates Classes: BaseSchema, Error, Token, TokenData

Constant Summary collapse

TokenHeaderSchema =
Dry::Validation.Schema(BaseSchema) do
  optional(:applicationData).filled(:str?, :hex?, :hex_sha256?)

  optional(:ephemeralPublicKey).filled(:str?, :base64?, :ec_public_key?)

  optional(:wrappedKey).filled(:str?, :base64?)

  rule('ephemeralPublicKey xor wrappedKey': [:ephemeralPublicKey, :wrappedKey]) do |e, w|
    e.filled? ^ w.filled?
  end

  required(:publicKeyHash).filled(:str?, :base64?, :base64_sha256?)

  required(:transactionId).filled(:str?, :hex?)
end
TokenSchema =
Dry::Validation.Schema(BaseSchema) do
  required(:data).filled(:str?, :base64?)

  required(:header).schema(TokenHeaderSchema)

  required(:signature).filled(:str?, :base64?, :pkcs7_signature?)

  required(:version).filled(:str?, included_in?: %w[EC_v1 RSA_v1])
end
TokenDataPaymentDataSchema =
Dry::Validation.Schema(BaseSchema) do
  optional(:onlinePaymentCryptogram).filled(:str?, :base64?)
  optional(:eciIndicator).filled(:str?, :eci?)

  optional(:emvData).filled(:str?, :base64?)
  optional(:encryptedPINData).filled(:str?, :hex?)
end
TokenDataSchema =
Dry::Validation.Schema(BaseSchema) do
  required(:applicationPrimaryAccountNumber).filled(:str?, :pan?)

  required(:applicationExpirationDate).filled(:str?, :yymmdd?)

  required(:currencyCode).filled(:str?, :iso4217_numeric?)

  required(:transactionAmount).filled(:int?)

  optional(:cardholderName).filled(:str?)

  required(:deviceManufacturerIdentifier).filled(:str?, :hex?)

  required(:paymentDataType).filled(:str?, included_in?: %w[3DSecure EMV])

  required(:paymentData).schema(TokenDataPaymentDataSchema)

  rule('when paymentDataType is 3DSecure, onlinePaymentCryptogram': [:paymentDataType, [:paymentData, :onlinePaymentCryptogram]]) do |type, cryptogram|
    type.eql?('3DSecure') > cryptogram.filled?
  end
  rule('when paymentDataType is 3DSecure, emvData': [:paymentDataType, [:paymentData, :emvData]]) do |type, emv|
    type.eql?('3DSecure') > emv.none?
  end
  rule('when paymentDataType is 3DSecure, encryptedPINData': [:paymentDataType, [:paymentData, :encryptedPINData]]) do |type, pin|
    type.eql?('3DSecure') > pin.none?
  end

  rule('when paymentDataType is EMV, onlinePaymentCryptogram': [:paymentDataType, [:paymentData, :onlinePaymentCryptogram]]) do |type, cryptogram|
    type.eql?('EMV') > cryptogram.none?
  end
  rule('when paymentDataType is EMV, eciIndicator': [:paymentDataType, [:paymentData, :eciIndicator]]) do |type, eci|
    type.eql?('EMV') > eci.none?
  end
  rule('when paymentDataType is EMV, emvData': [:paymentDataType, [:paymentData, :emvData]]) do |type, emv|
    type.eql?('EMV') > emv.filled?
  end
  rule('when paymentDataType is EMV, encryptedPINData': [:paymentDataType, [:paymentData, :encryptedPINData]]) do |type, pin|
    type.eql?('EMV') > pin.filled?
  end

end