/* * paymill-paybutton * https://github.com/Paymill/paymill-paybutton */ if ( !window.jQuery ) { throw new Error( "This script requires jQuery to be loaded" ); } (function($) { // on was added in 1.7, add support for 1.5+ (delegate exists since 1.4) if (!jQuery.fn.on) { jQuery.fn.on = function(event, selector, handler) { if (arguments.length === 3) { this.delegate(selector, event, handler); } else if (arguments.length === 2) { this.bind(event, selector); } else { throw new Error("jQuery.fn.on: Bad arguments: " + arguments); } }; } $.fn.placeholderFix = function() { // return early if browser does support placeholder attribute natively if ( "placeholder" in document.createElement( "input" ) ) { return this; } return this.each(function(){ var element = $(this), msg = element.attr('placeholder'); if ( element.val() === "" ) { element.val( msg ).addClass( "placeholder" ); } element.focus(function(){ if ( element.val() === msg ) { element.val( "" ).removeClass( "placeholder" ); } }).blur(function() { if (element.val().length === 0) { element.val( msg ).addClass( "placeholder" ); } }); }); }; var paybutton = { // starts iframe creation, usually runs when this script is executed init: function() { // the script itself is used to mark where iframes should be added // and provides a container for configuration // see also http://ejohn.org/blog/degrading-script-tags/ var script = $( "script:last" ), config = paybutton.readConfig( script ); // expose paymill key to Bridge, of not already loaded if ( !window.PAYMILL_PUBLIC_KEY ) { window.PAYMILL_PUBLIC_KEY = config.publicKey; } // unlike jQuery, we can load the Paymill bridge, as its not needed until form submit if ( !window.paymill ) { document.write( "" ); } // create popup first, since button needs a reference to the popup var popup = paybutton.createPopup( config, script ).appendTo( document.body ); paybutton.createButton( config, popup, script ); }, readConfig: function( script ) { var config = { currency: "EUR", label: "Pay With Card", lang: "en-GB", elv: false, inline: false, width: 220, height: 42, submitButton: null }, // supported data attributes; jQuery maps public-key to publicKey for us configProps = "label title description submitButton amount currency publicKey lang elv width height inline logo".split( " " ); // generate URL for default logo, based on src of this script config.logo = script.attr("src") + "/paymill-logo-signet.png"; $.each( configProps, function( index, prop ) { // in jQuery 1.5, the dash-normalization didn't exist yet var value = script.data( prop.replace(/([A-Z])/, function(match, group) { return "-" + group.toLowerCase(); })); // don't overwrite defaults if no value is provided if ( value !== undefined ) { config[ prop ] = value; } }); // make a list of missing and required (no default present) properties var missing = $.map( configProps, function( prop ) { if ( config[ prop ] === undefined ) { return prop; } }); if ( missing.length ) { // fail early throw new Error( "Paymill Paybutton Error - Missing required data-attributes: " + missing.join( ", ") ); } if ( !config.submitButton ) { var amount = (config.amount / 100).toString().replace(".", ","); if (/,\d$/.test(amount)) { amount += "0"; } config.submitButton = translate( "submitButton", config.lang ) + " " + amount + " " + config.currency; } return config; }, // popup is a fixed position fullscreen overlay // loads css for styling and shows the form createPopup: function( config, script ) { var ESCAPE = 27, // start with a blank document that includes a html5 doctype to avoid IE's quirksmode popup = $( "" ) .attr({ frameBorder: "0", allowtransparency: "true" }) .hide() .css({ position: "fixed", top: 0, left: 0, width: "100%", height: "100%", "z-index": 99999 }) .load(function() { /*jshint multistr:true*/ var doc = this.contentWindow.document; var body = $( doc.body ); // workarounds for IE8 support if ( doc.createStyleSheet ) { // allow html5 elements to be styled correctly doc.createElement('header'); doc.createElement('footer'); // see http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx doc.createStyleSheet( "https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700" ); //doc.createStyleSheet( "https://button.paymill.de/button.css" ); doc.createStyleSheet( "css/paymill-button.css" ); } var popupHtml = '\ \ \
\ '; body.get( 0 ).innerHTML = popupHtml; body.find( "input" ).placeholderFix(); body.on( "click", ".close-button", function() { popup.fadeOut(); }); body.on( "submit", "form", function( event ) { event.preventDefault(); if ( !window.paymill ) { var paymillMissing = "Error: Paymill bridge didn't load; make sure that brige.paymill.com was loaded as a script"; alert( paymillMissing ); throw new Error( paymillMissing ); } var elem = $(this), data = readValid( elem, config ); if ( data ) { // show loading indicator while we wait for the createToken request to finish var submitButton = elem.find( ".submit-button" ).addClass( "loading" ); paymill.createToken( data, function( error, result ) { // remove loading indicator, let user submit again in error case submitButton.removeClass( "loading" ); if ( error ) { mapError( error, elem, config ); return; } // close popup popup.fadeOut(); // expose token as with a custom event script.trigger( "token", [ result.token ] ); // look for a parent form to append token as hidden input var form = script.closest( "form" ); if ( form.length ) { form .append("") .submit(); } }); } }); // close popup when pressing escape, without submitting anything body.on( "keyup" , function( event ) { if ( event.keyCode === ESCAPE ) { popup.fadeOut(); } }); // catch key to avoid entering invalid chars into the expiry and cvc body.on( "keypress", "#card-expiry, #card-cvc", function( event ) { var keycode = event.charCode || event.keyCode; var allowedChars = [ 8, 9, 13, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 ]; // allow slash just once, only for expiry field if (this.id === "card-expiry" && !/\//.test(this.value)) { allowedChars.push( 47 ); } var pos = $.inArray( keycode, allowedChars ); if ( pos === -1 ) { return false; } }); // auto insert "/" after two numbers body.on( "keyup", "#card-expiry", function( event ) { // ignore deletion of slash var skipCodes = [ 8, 46 ]; if ( $.inArray( event.keyCode, skipCodes ) !== -1 ) { return; } if ( /^\d\d$/.test( this.value ) ) { this.value += "/"; } }); body.on( "keyup", "input#card-number", function() { var value = $.trim( this.value ), type = BrandDetection.detect( value ); var logoImage = body.find( ".card-type-logo" ); logoImage.toggleClass( "card-type-grayscale", !paymill.validateCardNumber( value ) ); if ( type ) { logoImage.addClass( "card-type-logo-visible" ).attr( "src", "images/32x20_" + type + ".png" ); } else { logoImage.removeClass( "card-type-logo-visible" ); } }); }); return popup; }, // creates the button that will open the popup createButton: function( config, popup, target ) { function events( button ) { // on click, show popup and focus first input button.on( "click", function() { popup .fadeIn(function(){ // workaround for broken popup display in Safari 6.1+ var form = popup.contents().find( "form" ); form.css( "display", "inline-block" ); setTimeout(function() { form.css( "display", "block" ); }); }) .contents().find( "input:first" ).focus(); }); // hook into the token event to disable the button target.on( "token", function() { button.prop( "disabled", true ); }); } if ( config.inline ) { var container = $( "" ); events(container); container.insertAfter( target ); return container; } return $( "") .attr({ frameBorder: "0", allowtransparency: "true" }) .css({ width: config.width, height: config.height }) .load(function() { /*jshint multistr:true*/ var doc = this.contentWindow.document; var body = $( doc.body ); body.addClass( "button" ); if ( doc.createStyleSheet ) { doc.createStyleSheet( "https://fonts.googleapis.com/css?family=Open+Sans:400,700" ); doc.createStyleSheet( "css/paymill-button.css" ); } body.get( 0 ).innerHTML = '\ \ \ '; events( body.find( "button" ) ); }) .insertAfter( target ); } }; var messages = { "de-DE": { "paybutton.3ds_cancelled":"3-D Secure abgebrochen", "paybutton.Bankleitzahl":"BLZ / BIC", "paybutton.Bezahlen":"Bezahlen", "paybutton.CVC":"CVC", "paybutton.CVC-Tooltip":"Hinter dem CVV-Code bzw. CVC verbirgt sich ein Sicherheitsmerkmal von Kreditkarten, üblicherweise handelt es sich dabei um eine drei- bis vierstelligen Nummer. Der CVV-Code befindet sich auf VISA-Kreditkarten. Der gleiche Code ist auch auf MasterCard-Kreditkarten zu finden, hier allerdings unter dem Namen CVC. Die Abkürzung CVC steht dabei für Card Validation Code. Bei VISA wird der Code als Card Verification Value-Code bezeichnet. Ähnlich wie bei Mastercard und VISA gibt es auch bei Diners Club, Discover und JCB eine dreistellige Nummer, die meist auf der Rückseite der Karte zu finden ist. Bei Maestro-Karten gibt es mit und ohne dreistelligen CVV. Wird eine Maestro-Karte ohne CVV verwendet kann einfach 000 eingetragen werden. American Express verwendet die CID (Card Identification Number). Dabei handelt es sich um eine vierstellige Nummer, die meist auf der Vorderseite der Karte, rechts oberhalb der Kartennummer zu finden ist.", "paybutton.Karteninhaber":"Karteninhaber", "paybutton.Kartennummer":"Kartennummer", "paybutton.Kontoinhaber":"Kontoinhaber", "paybutton.Kontonummer":"Konto Nr. / IBAN", "paybutton.Läuft ab":"Läuft ab", "paybutton.Prüfnummer":"Prüfnummer", "paybutton.Sichere Verbindung":"Sichere Verbindung", "paybutton.elv-info":"Direct Debit ist nur mit einem deutschen Firmenbankkonto verfügbar.", "paybutton.field_invalid_account_holder":"Der Name muss 4 bis 128 Zeichen enthalten", "paybutton.field_invalid_account_number":"Ungültige Kontonummer", "paybutton.field_invalid_amount":"Ungültiger Betrag", "paybutton.field_invalid_amount_int":"Ungültiger Integer Betrag", "paybutton.field_invalid_bank_code":"Ungültige Bankleitzahl", "paybutton.field_invalid_card_cvc":"Ungültige Prüfnummer", "paybutton.field_invalid_card_exp":"Ungültiges Ablaufdatum", "paybutton.field_invalid_card_exp_month":"Ungültiger Ablaufmonat", "paybutton.field_invalid_card_exp_year":"Ungültiges Ablaufjahr", "paybutton.field_invalid_card_holder":"Ungültiger Karteninhaber", "paybutton.field_invalid_card_number":"Ungültige Kreditkartennummer", "paybutton.field_invalid_currency":"Ungültige Währung", "paybutton.submitButton":"Bezahlen", "paybutton.unknown_error":"Es ist ein unbekannter Fehler aufgetreten." }, "en-GB": { "paybutton.3ds_cancelled":"3-D Secure process cancelled", "paybutton.Bankleitzahl":"(Direct debit n/a in en-GB)", "paybutton.Bezahlen":"Pay", "paybutton.CVC":"CVC", "paybutton.CVC-Tooltip":"What is a CVV/CVC number? Prospective credit cards will have a 3 to 4-digit number, usually on the back of the card. It ascertains that the payment is carried out by the credit card holder and the card account is legitimate. On Visa the CVV (Card Verification Value) appears after and to the right of your card number. Same goes for Mastercard's CVC (Card Verfication Code), which also appears after and to the right of your card number, and has 3-digits. Diners Club, Discover, and JCB credit and debit cards have a three-digit card security code which also appears after and to the right of your card number. The American Express CID (Card Identification Number) is a 4-digit number printed on the front of your card. It appears above and to the right of your card number. On Maestro the CVV appears after and to the right of your number. If you don’t have a CVV for your Maestro card you can use 000.", "paybutton.Karteninhaber":"Cardholder", "paybutton.Kartennummer":"Credit card number", "paybutton.Kontoinhaber":"(Direct debit n/a in en-GB)", "paybutton.Kontonummer":"(Direct debit n/a in en-GB)", "paybutton.Läuft ab":"Expires", "paybutton.Prüfnummer":"Verification number", "paybutton.Sichere Verbindung":"Secure connection", "paybutton.elv-info":"Direct debit is only available with a German company bank account.", "paybutton.field_invalid_account_holder":"Name must contain between 4 and 128 characters", "paybutton.field_invalid_account_number":"(Direct debit n/a in en-GB)", "paybutton.field_invalid_amount":"Invalid amount", "paybutton.field_invalid_amount_int":"Invalid integer amount", "paybutton.field_invalid_bank_code":"(Direct debit n/a in en-GB)", "paybutton.field_invalid_card_cvc":"Invalid verification number", "paybutton.field_invalid_card_exp":"Invalid expiration date", "paybutton.field_invalid_card_exp_month":"Expiration month invalid", "paybutton.field_invalid_card_exp_year":"Expiration year invalid", "paybutton.field_invalid_card_holder":"Invalid card holder", "paybutton.field_invalid_card_number":"Invalid credit card number", "paybutton.field_invalid_currency":"Invalid currency", "paybutton.submitButton":"Pay", "paybutton.unknown_error":"An unknown error occurred. Make sure all information was entered correctly." }, "fr-FR": { "paybutton.3ds_cancelled":"Processus 3-D Secure annulé", "paybutton.Bankleitzahl":"(Débit direct n'est pas disponible en fr)", "paybutton.Bezahlen":"Payer", "paybutton.CVC":"CVC", "paybutton.CVC-Tooltip":"Qu'est-ce que le code CVV/CVC ? Les cartes de paiement du futur auront un numéro de trois à quatre chiffres, généralement au dos de la carte. Ceci permet de vérifier que le paiement est effectué par le porteur de la carte, et que le compte associé à cette carte est légitime. Sur les cartes Visa, le code CVV (« Card Verification Value » - valeur de vérification de la carte) apparaît après votre numéro de carte, sur sa droite. Il en est de même pour le code CVC (« Card Verfication Code » - code de vérification de la carte) des cartes Mastercard, qui apparaît également à la suite de votre numéro de carte, sur sa droite, et qui comporte trois chiffres. Les cartes Diners Club, Discover et JCB ont un code de sécurité à trois chiffres qui apparaît également après votre numéro de carte, sur sa droite. Le code CID (« Card Identification Number » - numéro d'identification de la carte) des cartes American Express est un numéro à quatre chiffres imprimé au recto de votre carte. Il est situé au dessus de votre numéro de carte, sur sa droite. Sur les cartes Maestro, le code CVV apparaît à la suite de votre numéro de carte, sur sa droite. Si vous n'avez pas de code CVV sur votre carte Maestro, vous pouvez inscrire 000.", "paybutton.Karteninhaber":"Titulaire de la carte", "paybutton.Kartennummer":"Carte de crédit", "paybutton.Kontoinhaber":"(Débit direct n'est pas disponible en fr)", "paybutton.Kontonummer":"(Débit direct n'est pas disponible en fr)", "paybutton.Läuft ab":"Expire fin", "paybutton.Prüfnummer":"Numéro de vérification", "paybutton.Sichere Verbindung":"Connexion sécurisée", "paybutton.elv-info":"Le débit direct n'est possible qu'avec un compte bancaire de société allemand.", "paybutton.field_invalid_account_holder":"Le nom doit contenir entre 4 et 128 caractères", "paybutton.field_invalid_account_number":"(Débit direct n'est pas disponible en fr)", "paybutton.field_invalid_amount":"Montant invalide", "paybutton.field_invalid_amount_int":"Montant entier invalide", "paybutton.field_invalid_bank_code":"(Débit direct n'est pas disponible en fr)", "paybutton.field_invalid_card_cvc":"Numéro de vérification invalide", "paybutton.field_invalid_card_exp":"Date d'expiration invalide", "paybutton.field_invalid_card_exp_month":"Mois d'expiration invalide", "paybutton.field_invalid_card_exp_year":"Année d'expiration invalide", "paybutton.field_invalid_card_holder":"Titulaire de la carte de crédit invalide", "paybutton.field_invalid_card_number":"Numéro de carte de crédit invalide", "paybutton.field_invalid_currency":"Devise invalide", "paybutton.submitButton":"Payer", "paybutton.unknown_error":"Une erreur inconnue s'est produite. Assurez-vous que toutes les informations sont saisies correctement." }, "es-ES": { "paybutton.3ds_cancelled":"Proceso 3-D Secure cancelado", "paybutton.Bankleitzahl":"(Domiciliación bancaria no disponible en ES)", "paybutton.Bezahlen":"Pago", "paybutton.CVC":"CVC", "paybutton.CVC-Tooltip":"¿Qué es el número CVV/CVC? Las tarjetas de crédito futuras tendrán un número de 3 o 4 dÃgitos, normalmente en la parte trasera de la tarjeta. Este número verifica que el pago se lleva a cabo por el titular de la tarjeta de crédito y que la cuenta de la tarjeta es válida. En las tarjetas VISA, el CVV (Card Verification Value) o código de seguridad aparece tras el número de tarjeta a la derecha. Lo mismo ocurre con el CVC de las tarjetas Mastercard, que también aparece tras el número de tarjeta a la derecha y tiene 3 dÃgitos. Las tarjetas de crédito y débito Diners Club, Discover y JCB tienen un código de seguridad de tres dÃgitos que también se encuentra tras el número de tarjeta a la derecha. El CID (Card Identification Number) o número de identificación de las tarjetas American Express es un número de 4 dÃgitos impreso en la parte frontal de la tarjeta. Se encuentra en la parte superior y a la derecha del número de tarjeta. El las tarjetas Maestro, el CVV aparece tras el número de tarjeta a la derecha. Si no posee un CVV para su tarjeta Maestro, puede usar el 000.", "paybutton.Karteninhaber":"Propietario de la tarjeta", "paybutton.Kartennummer":"Tarjeta de crédito", "paybutton.Kontoinhaber":"(Domiciliación bancaria no disponible en inglés-Reino Unido)", "paybutton.Kontonummer":"(Domiciliación bancaria no disponible en ES)", "paybutton.Läuft ab":"Expira", "paybutton.Prüfnummer":"Número de verificación", "paybutton.Sichere Verbindung":"Conexión segura", "paybutton.elv-info":"El débito directo sólo está disponible con una cuenta bancaria de empresa alemana.", "paybutton.field_invalid_account_holder":"El nombre tiene que tener entre 4 y 128 caracteres", "paybutton.field_invalid_account_number":"(Domiciliación bancaria no disponible en ES)", "paybutton.field_invalid_amount":"Cantidad incorrecta", "paybutton.field_invalid_amount_int":"Cantidad integral incorrecta", "paybutton.field_invalid_bank_code":"(Domiciliación bancaria no disponible en ES)", "paybutton.field_invalid_card_cvc":"Número de verificación incorrecto", "paybutton.field_invalid_card_exp":"Fecha de expiración inválida", "paybutton.field_invalid_card_exp_month":"Mes de caducidad incorrecto", "paybutton.field_invalid_card_exp_year":"Año de caducidad incorrecto", "paybutton.field_invalid_card_holder":"Propietario de tarjeta incorrecto", "paybutton.field_invalid_card_number":"Número incorrecto de tarjeta de crédito", "paybutton.field_invalid_currency":"Moneda incorrecta", "paybutton.submitButton":"Pago", "paybutton.unknown_error":"Se ha producido un error desconocido. Compruebe que toda la información se ha introducido correctamente." }, "it-IT": { "paybutton.3ds_cancelled":"Il procedimento 3-D Secure è stato annullato", "paybutton.Bankleitzahl":"(Addebito diretto non è disponibile in Italia)", "paybutton.Bezahlen":"Pagare", "paybutton.CVC":"CVC", "paybutton.CVC-Tooltip":"Che cosa è il numero CVV o CVC? Le nuove carte di credito saranno caratterizzate da un numero di 3 o 4 cifre, posto di solito sul retro della carta. Tale numero assicura che il pagamento venga effettuato dal titolare della carta di credito e che il conto della carta sia legittimo. Sulla carta Visa il CVV (Card Validation Value - Valore di verifica della carta) è posto dopo ed a destra del numero della carta. Lo stesso discorso vale per la Mastercard dove il CVC (Card Validation Code - Codice di verifica della carta) appare ugualmente dopo sulla destra del numero della carta ed è composto da 3 cifre. La Diners Club, la Discover e le carte di credito e di debito JCB presentano un codice di sicurezza della carta a tre cifre che si trova anche a destra dopo il numero della carta. Il CID (Numero di identificazione della carta) dell'American Express è un numero a 4 cifre stampato sulla parte anteriore della carta. Si trova in alto a destra del numero della carta. Sulle carte Maestro, il CVV appare dopo e a destra del numero di carta. Se non è presente un numero CVV nella carta Maestro è possibile utilizzare il codice 000.", "paybutton.Karteninhaber":"Titolare di carta di credito", "paybutton.Kartennummer":"Numero di carta di credito", "paybutton.Kontoinhaber":"(Addebito diretto non è disponibile in Italia)", "paybutton.Kontonummer":"(Addebito diretto non è disponibile in Italia)", "paybutton.Läuft ab":"Scadenza", "paybutton.Prüfnummer":"Numero di verifica", "paybutton.Sichere Verbindung":"Connessione sicura", "paybutton.elv-info":"L'addebito diretto tramite RID è possibile solo con numero di conto corrente tedesco.", "paybutton.field_invalid_account_holder":"Il nome deve contenere min. 4 - max. 128 caratteri", "paybutton.field_invalid_account_number":"(Addebito diretto non è disponibile in Italia)", "paybutton.field_invalid_amount":"Importo non valido", "paybutton.field_invalid_amount_int":"Importo arrotondato non valido", "paybutton.field_invalid_bank_code":"(Addebito diretto non è disponibile in Italia)", "paybutton.field_invalid_card_cvc":"Numero di verifica non valido", "paybutton.field_invalid_card_exp":"Data scadenza non valida", "paybutton.field_invalid_card_exp_month":"Mese di scadenza non valido", "paybutton.field_invalid_card_exp_year":"Anno di scadenza non valido", "paybutton.field_invalid_card_holder":"Titolare della carta di credito non esistente", "paybutton.field_invalid_card_number":"Numero della carta di credito non valido", "paybutton.field_invalid_currency":"Valuta corrente non valida", "paybutton.submitButton":"Pagare", "paybutton.unknown_error":"Si è verificato un errore sconosciuto. Assicuratevi che le informazioni inserite siano corrette." }, "pt-PT": { "paybutton.3ds_cancelled":"Processo 3-D Secure cancelado", "paybutton.Bankleitzahl":"(Débito direto não disponÃvel em PT)", "paybutton.Bezahlen":"Pagar", "paybutton.CVC":"CVC", "paybutton.CVC-Tooltip":"O que é o número CVV / CVC? Os novos cartões de crédito terão um número de 3 ou 4 dÃgitos, geralmente na parte de trás do cartão, que serve para garantir que o pagamento é efetuado pelo titular do cartão de crédito e que a conta do cartão existe. Os cartões Visa utilizam o CVV (Card Verification Value) que aparece depois do número do cartão, à direita. O mesmo se passa com o CVC (Card Verification Code) da Mastercard, que também aparece depois do número do cartão, à direita, e tem 3 dÃgitos. Os cartões de crédito Diners Club, Discover e JCB têm um código de segurança de cartão de três dÃgitos, que também aparece depois do número de cartão, à direita. A American Express utiliza o CID (Card Identification Number) que é um número de 4 dÃgitos impresso na parte da frente do seu cartão. Aparece por cima do número do seu cartão, à direita. Nos cartões Maestro o CVV aparece depois do número do cartão, à direita. Se o seu Maestro não tiver um CVV, pode utilizar o 000.", "paybutton.Karteninhaber":"Titular de cartão", "paybutton.Kartennummer":"Número de cartão de crédito", "paybutton.Kontoinhaber":"(Débito direto não disponÃvel em PT)", "paybutton.Kontonummer":"(Débito direto não disponÃvel em PT)", "paybutton.Läuft ab":"Data de validade", "paybutton.Prüfnummer":"Número de verificação", "paybutton.Sichere Verbindung":"Ligação segura", "paybutton.elv-info":"Débito direto está apenas disponÃvel para uma conta bancária duma empresa Alemã.", "paybutton.field_invalid_account_holder":"O nome deve conter entre 4 e 128 carateres", "paybutton.field_invalid_account_number":"(Débito direto não disponÃvel em PT)", "paybutton.field_invalid_amount":"Montante inválido", "paybutton.field_invalid_amount_int":"Montante inteiro inválido", "paybutton.field_invalid_bank_code":"(Débito direto não disponÃvel em en-GB)", "paybutton.field_invalid_card_cvc":"Número de verificação inválido", "paybutton.field_invalid_card_exp":"Data de validade inválida", "paybutton.field_invalid_card_exp_month":"Mês de data de validade inválido", "paybutton.field_invalid_card_exp_year":"Ano de data de validade inválido", "paybutton.field_invalid_card_holder":"Titular de cartão de crédito inválido", "paybutton.field_invalid_card_number":"Número de cartão de crédito inválido", "paybutton.field_invalid_currency":"Moeda inválida", "paybutton.submitButton":"Pagar", "paybutton.unknown_error":"Ocorreu um erro desconhecido. Assegure-se de que introduziu toda a informação corretamente." } }; // Lookup a message in the messages hash and return the given key if the message doesn't exist. function translate( key, lang ) { key = "paybutton." + key; if ( !messages[ lang ] ) { throw new Error( "Unknown locale: " + lang ); } if ( !messages[ lang ][ key ] ) { return key; } return messages[ lang ][ key ]; } // Map an error key returned by the bridge to the corresponding form field. function mapError( error, elem, config ) { switch ( error.apierror ) { case "field_invalid_card_number": elem.find( ".card-number" ).addClass( "error" ); break; case "field_invalid_card_exp_month": elem.find( ".card-expiry" ).addClass( "error" ); break; case "field_invalid_card_exp_year": elem.find( ".card-expiry" ).addClass( "error" ); break; case "field_invalid_card_exp": elem.find( ".card-expiry" ).addClass( "error" ); break; case "field_invalid_card_cvc": elem.find( ".card-cvc" ).addClass( "error" ); break; case "field_invalid_account_holder": elem.find( ".card-holdername" ).addClass( "error" ); break; case "field_invalid_account_number": elem.find( ".bank-number" ).addClass( "error" ); break; case "field_invalid_bank_code": elem.find( ".bank-code" ).addClass( "error" ); break; case "field_invalid_account_holder": elem.find( ".bank-holder" ).addClass( "error" ); break; } elem.find( "div.error-message" ).html( translate( error.apierror, config.lang ) ); } // Reads the payment form and returns an object which can be passed to paymill.createToken() function readValid( elem, config ) { var data, lastError = null; if ( config.elv ) { data = { number: elem.find( ".bank-number" ).val(), bank: elem.find( ".bank-code" ).val(), accountholder: elem.find( ".bank-holder" ).val(), amount_int: config.amount, currency: config.currency }; // Remove the error class for every input and add it for those which are still invalid elem.find( "input" ).removeClass( "error" ); // Add the error class to the individual fields. if ( !paymill.validateAccountNumber( data.number ) && !new Iban().validate( data.number) ) { elem.find( ".bank-number" ).addClass( "error" ); lastError = lastError || "field_invalid_account_number"; } var bank = data.bank.replace(/[\s+|-]/g, ""); // characters without dashes and whitespace must be 8 or 11 for BLZ and BIC // BLZ is digits only, but BIC is alphanumeric if ( !/^(:?[a-z\d]{8}|[a-z\d]{11})$/i.test(bank) ) { elem.find( ".bank-code" ).addClass( "error" ); lastError = lastError || "field_invalid_bank_code"; } if ( !paymill.validateHolder( data.accountholder ) ) { elem.find(".bank-holder").addClass( "error" ); lastError = lastError || "field_invalid_account_holder"; } // Rename if valid SEPA data if (!lastError && /^\D{2}/.test( data.bank ) ) { data.bic = data.bank; delete data.bank; data.iban = data.number.replace(/\s+/g, ""); delete data.number; } } else { var expiry = elem.find('.card-expiry').val().split("/"); data = { number: elem.find('.card-number').val(), exp_month: expiry[ 0 ], exp_year: expiry[ 1 ], cvc: elem.find('.card-cvc').val(), cardholder: elem.find('.card-holdername').val(), amount_int: config.amount, currency: config.currency }; if ( data.exp_year && data.exp_year.length === 2 ) { data.exp_year = "20" + data.exp_year; } // Card holder is an optional parameter ... delete if empty. if ( data.cardholder === "" ) { delete data.cardHolder; } // Remove the error class for every input and add it for those which are still invalid elem.find( "input" ).removeClass( "error" ); // Add the error class to the individual fields. if ( !paymill.validateCardNumber( data.number ) ) { elem.find(".card-number").addClass( "error" ); lastError = lastError || "field_invalid_card_number"; } if ( !paymill.validateExpiry( data.exp_month, data.exp_year ) ) { elem.find(".card-expiry").addClass( "error" ); lastError = lastError || "field_invalid_card_exp"; } if ( !paymill.validateCvc( data.cvc ) ) { elem.find(".card-cvc").addClass( "error" ); lastError = lastError || "field_invalid_card_cvc"; } if ( data.cardholder && !paymill.validateHolder( data.cardholder ) ) { elem.find(".card-holdername").addClass( "error" ); lastError = lastError || "field_invalid_account_holder"; } } // Display the first error message if ( lastError ) { elem.find( "div.error-message" ).text( translate( lastError, config.lang ) ); return null; } return data; } var Iban = function() {}; Iban.prototype = { countries: { "AL": 28, "AD": 24, "AZ": 28, "BH": 22, "BE": 16, "BA": 20, "BR": 29, "BG": 22, "CR": 21, "DK": 18, "DE": 22, "DO": 28, "EE": 20, "FO": 18, "FI": 18, "FR": 27, "GF": 27, "PF": 27, "TF": 27, "GE": 22, "GI": 23, "GR": 27, "GL": 18, "GP": 27, "GT": 28, "HK": 16, "IE": 22, "IS": 26, "IL": 23, "IT": 27, "JO": 30, "VG": 24, "KZ": 20, "QA": 29, "HR": 21, "KW": 30, "LV": 21, "LB": 28, "LI": 21, "LT": 20, "LU": 20, "MT": 31, "MA": 24, "MQ": 27, "MR": 27, "MU": 30, "YT": 27, "MK": 19, "MD": 24, "MC": 27, "ME": 22, "NC": 27, "NL": 18, "NO": 15, "AT": 20, "PK": 24, "PS": 29, "PL": 28, "PT": 25, "RE": 27, "RO": 24, "BL": 27, "MF": 27, "SM": 27, "SA": 24, "SE": 24, "CH": 21, "RS": 22, "SK": 24, "SI": 19, "ES": 24, "PM": 27, "CZ": 24, "TN": 24, "TR": 26, "HU": 28, "AE": 23, "GB": 22, "WF": 27, "CY": 28 }, alphabet: { "A": "10", "B": "11", "C": "12", "D": "13", "E": "14", "F": "15", "G": "16", "H": "17", "I": "18", "J": "19", "K": "20", "L": "21", "M": "22", "N": "23", "O": "24", "P": "25", "Q": "26", "R": "27", "S": "28", "T": "29", "U": "30", "V": "31", "W": "32", "X": "33", "Y": "34", "Z": "35" }, validate: function(iban) { if (iban === undefined || iban === "") { return false; } // Removing spaces iban = iban.replace(/\s+/g, ""); this.iban = iban; if (!this.checkString) { return false; } if (!this.checkLength()) { return false; } this.changeCharacterPosition(iban); this.replaceLettersWithNumbers(); var ibanWithoutCheckDigits = this.iban.substr(0, this.iban.length - 2); var ibanWithZeroCheckDigits = ibanWithoutCheckDigits + "00"; var ibanCheckDigits = this.iban.substr(this.iban.length - 2, 2); var calcCheckDigits = (98 - this.calculate(ibanWithZeroCheckDigits)).toString(); if (calcCheckDigits.length === 1) { calcCheckDigits = "0" + calcCheckDigits; } if (calcCheckDigits !== ibanCheckDigits) { return false; } if (this.calculate(this.iban) !== "01") { return false; } return true; }, checkString: function() { return this.iban.match(/^[a-z]{2}[0-9]{2}[a-z0-9]+$/i) !== null; }, // Checking if the given IBAN has the right length based on the first two letters which have to be a country code checkLength: function() { var countryCode = this.iban.substr(0, 2); return this.countries[countryCode] === this.iban.length; }, // Replace Letters with Numbers A = 10,....,Z = 35 replaceLettersWithNumbers: function() { for (var character in this.alphabet) { var regex = new RegExp(character, "g"); this.iban = this.iban.replace(regex, this.alphabet[character]); } }, // Puts the first 4 Characters to the End changeCharacterPosition: function() { var firstFourCharacters = this.iban.substr(0, 4); var leftOverString = this.iban.substr(4); this.iban = leftOverString + firstFourCharacters; }, // Calculate the IBAN Hash with piece-wise manner modulo operations, since javascript cant handle 128 bit integer calculate: function(iban) { var start = 0; var length = 9; var loop = true; var remainder = ""; while (loop) { if (iban.substr(start, length).length < 7) { loop = false; length = iban.substr(start, length).length; } var tempInt = remainder + iban.substr(start, length); remainder = (tempInt % 97) + ""; if (remainder.length === 1) { remainder = "0" + remainder; } start = start + length; length = 7; } return remainder; } }; var BrandDetection = { creditcard: { 'carte-bleue': { 'pattern': /^(415006|497|407497|513)/, 'cardlength': [13, 16], 'cvc': [3] }, 'carta-si': { 'pattern': /^(45399[78]|432913|5255)/, 'cardlength': [16], 'cvc': [3] }, 'dankort': { 'pattern': /^(4571|5019)/, 'cardlength': [16], 'cvc': [3] }, 'unionpay': { 'pattern': /^(62|88)/, 'cardlength': [16, 17, 18, 19], 'cvc': [3] }, 'discover': { 'pattern': /^6(011|5)/, 'cardlength': [16], 'cvc': [3] }, 'dinersclub': { 'pattern': /^3(0[0-5]|[68])/, 'cardlength': [14], 'cvc': [3] }, 'maestro': { 'pattern': /^(5018|5020|5038|5893|6304|6759|6761|6762|6763|0604|6390)/, 'cardlength': [12, 13, 14, 15, 16, 17, 18, 19], 'cvc': [0, 3, 4] }, 'jcb': { 'pattern': /^(2131|1800|35)/, 'cardlength': [16], 'cvc': [3] }, 'amex': { 'pattern': /^(3[47])/, 'cardlength': [15], 'cvc': [3, 4] }, 'mastercard': { 'pattern': /^(5[1-5])/, 'cardlength': [16], 'cvc': [3] }, 'visa': { 'pattern': /^(4)/, 'cardlength': [13, 16], 'cvc': [3] } }, detect: function(cardnumber) { var cardinfo; // Only look at digits cardnumber = cardnumber.replace(/\D/g, ""); if (cardnumber.length > 5) { for ( cardinfo in this.creditcard ) { if ( this.creditcard[ cardinfo ].pattern.test( cardnumber ) ) { return cardinfo; } } } return null; } }; // when unit testing, export instead of init if ( window.QUnit ) { window.paybutton = paybutton; window.paybutton.Iban = Iban; window.paybutton.BrandDetection = BrandDetection; } else { paybutton.init(); } }( jQuery ));