Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // global.css ==================================================================================================
- ion-content {
- --background: aliceblue;
- }
- ion-input {
- --min-height: 30px !important;
- }
- ion-grid {
- margin-top: 10px;
- width: 100%;
- height: 100%;
- border-radius: 35px 35px 0px 0px;
- border-top: solid 10px;
- border-color: #14426E !important;
- &:before {
- background: none !important;
- z-index: 0;
- content: "CARGA DE SALDO";
- position: relative;
- top: -1px;
- left: 18%;
- height: 20px;
- width: 100%;
- //@include font(bold, 6vw, true, center);
- color: var(--ion-color-primary);
- }
- }
- ion-label {
- //@include font(regular, 3vw, false, left);
- color: var(--ion-color-tertiary) !important;
- text-transform: uppercase;
- font-weight: bold;
- font-size: 3.5vw !important;
- text-shadow: 1px 1px 3px #aaaa;
- }
- .select-text {
- margin-left: 10px;
- font-size: 1.4em !important;
- font-weight: bold;
- }
- ion-label.errorMsg {
- color: red !important;
- font-size: 0.8em !important;
- font-weight: inherit;
- text-transform: unset;
- }
- }
- // component.scss ==================================================================================================
- @import url('https://fonts.googleapis.com/css?family=Space+Mono:400,400i,700,700i');
- .card {
- margin: auto;
- margin-top: 4vw;
- $card-width: 90vw;
- $card-height: $card-width/1.6842;
- * {
- box-sizing: border-box !important;
- font-family: 'Space Mono', monospace !important;
- }
- width: $card-width;
- height: $card-height;
- -webkit-perspective: 600px;
- -moz-perspective: 600px;
- perspective:600px;
- &__part {
- box-shadow: 1px 1px 4px #a3a6aa;
- top: 0;
- position: absolute;
- z-index: 1000;
- left: 0;
- display: inline-block;
- width: $card-width;
- height: $card-height;
- background-image: url('https://image.ibb.co/bVnMrc/g3095.png'), linear-gradient(to right bottom, #36dfb3, #3778e4);
- // linear-gradient(to right bottom, #fd696b, #fa616e, #f65871, #f15075, #ec4879);
- /*linear-gradient(to right bottom, #fd8369, #fc7870, #f96e78, #f56581, #ee5d8a)*/
- /*linear-gradient(to right bottom,#20779A,#2397CA,#3ED598,#4E9949);*/
- background-repeat: no-repeat;
- background-position: center;
- background-size: cover;
- border-radius: 8px;
- -webkit-transition: all .5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- -moz-transition: all .5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- -ms-transition: all .5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- -o-transition: all .5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- transition: all .5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
- -webkit-transform-style: preserve-3d;
- -moz-transform-style: preserve-3d;
- transform-style: preserve-3d;
- -webkit-backface-visibility: hidden;
- -moz-backface-visibility: hidden;
- backface-visibility: hidden;
- }
- &__front {
- padding: 18px;
- -webkit-transform: rotateY(0);
- -moz-transform: rotateY(0);
- transform: rotateY(0);
- &-logo {
- position: absolute;
- top: 18px;
- right: 18px;
- }
- }
- &__back {
- padding: 18px 0;
- -webkit-transform: rotateY(-180deg);
- -moz-transform: rotateY(-180deg);
- transform: rotateY(-180deg);
- &-content {
- padding: 15px 15px 0;
- }
- &-logo {
- position: absolute;
- bottom: 15px;
- right: 15px;
- }
- &-square {
- position: absolute;
- bottom: 15px;
- left: 15px;
- }
- }
- &__black-line {
- margin-top: 5px;
- height: 38px;
- background-color: #303030;
- }
- &__logo {
- height: 16px;
- }
- &__square {
- border-radius: 5px;
- height: 30px;
- }
- &_numer {
- display: block;
- width: 100%;
- word-spacing: 4px;
- font-size: 20px;
- letter-spacing: 2px;
- color: #fff;
- text-align: center;
- margin-bottom: 20px;
- margin-top: 20px;
- }
- &__space-75 {
- width: 75%;
- float: left;
- }
- &__space-25 {
- width: 25%;
- float: left;
- }
- &__label {
- font-size: 10px;
- text-transform: uppercase;
- color: rgba(255, 255, 255, 0.8);
- letter-spacing: 1px;
- }
- &__info {
- margin-bottom: 0;
- margin-top: 5px;
- font-size: 16px;
- line-height: 18px;
- color: #fff;
- letter-spacing: 1px;
- text-transform: uppercase;
- }
- &__secret {
- padding: 5px 12px;
- background-color: #fff;
- position: relative;
- &:before {
- content: '';
- position: absolute;
- top: -3px;
- left: -3px;
- height: calc(100% + 6px);
- width: calc(100% - 42px);
- border-radius: 4px;
- background: repeating-linear-gradient(45deg, #ededed, #ededed 5px, #f9f9f9 5px, #f9f9f9 10px);
- }
- }
- &__secret--last {
- color: #303030;
- text-align: right !important;
- margin: 0;
- font-size: 14px;
- z-index: 10;
- }
- &:hover .card__front,
- .show-back.card__front {
- -webkit-transform: rotateY(180deg);
- -moz-transform: rotateY(180deg);
- transform: rotateY(180deg);
- }
- &:hover .card__back,
- .show-back.card__back {
- -webkit-transform: rotateY(0deg);
- -moz-transform: rotateY(0deg);
- transform: rotateY(0deg);
- }
- }
- //component.html ==================================================================================================
- <ion-content scrolly="false" class="ion-no-padding">
- <div class="card">
- <div class="card__front card__part" [ngClass]="{'show-back' : showingBackside }">
- <img class="card__front-square card__square" src="https://image.ibb.co/cZeFjx/little_square.png">
- <img class="card__front-logo card__logo"
- src="../../../assets/images/cliente/tarjeta-saldo/mp-version-horizontal-small.png">
- <p class="card_numer">
- {{cardNumber | slice:0:4 }}-{{cardNumber | slice:4:8 }}-{{cardNumber | slice:8:12 }}-{{cardNumber | slice:12:16 }}
- </p>
- <div class="card__space-75">
- <span class="card__label">Card holder</span>
- <p class="card__info">{{cardHolder}}</p>
- </div>
- <div class="card__space-25">
- <span class="card__label">Expires</span>
- <p class="card__info">{{expirationMonth}}/{{expirationYear}}</p>
- </div>
- </div>
- <div class="card__back card__part" [ngClass]="{'show-back' : showingBackside }">
- <div class="card__black-line"></div>
- <div class="card__back-content">
- <div class="card__secret">
- <p class="card__secret--last">{{ccv}}</p>
- </div>
- <img class="card__back-square card__square" src="https://image.ibb.co/cZeFjx/little_square.png">
- <img class="card__back-logo card__logo"
- src="../../../assets/images/cliente/tarjeta-saldo/mp-version-horizontal-small.png">
- </div>
- </div>
- </div>
- <!-- <div style="margin-top: 10em;">
- <ng-payment-card></ng-payment-card>
- </div> -->
- <form [formGroup]="form" action="" method="post" id="pay" name="pay">
- <ion-grid class="ion-padding">
- <ion-row>
- <ion-col>
- <ion-item class="ion-no-padding">
- <ion-label for="email" position="floating">Email</ion-label>
- <ion-input [formControl]="form.controls['email']" id="email" name="email" type="email" clear-input="true"
- [class.invalid]="!form.controls['email'].valid && submitAttempt">
- </ion-input>
- </ion-item>
- <ng-container *ngIf="!form.controls['email'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- <ion-label class="errorMsg">- Tiene que tener formato de e-mail.</ion-label><br>
- </ng-container>
- </ion-col>
- </ion-row>
- <ion-row>
- <ion-col>
- <ion-item class="ion-no-padding">
- <ion-label for="cardNumber" position="floating">Número de tarjeta</ion-label>
- <ion-input [formControl]="form.controls['cardNumber']" (ionChange)="guessingPaymentMethod( $event )"
- type="text" maxlength="16" id="cardNumber" data-checkout="cardNumber" onpaste="return false"
- onCopy="return false" onCut="return false" onDrag="return false" onDrop="return false" autocomplete=off
- clear-input="true" [class.invalid]="!form.controls['cardNumber'].valid && submitAttempt">
- </ion-input>
- </ion-item>
- <ng-container *ngIf="!form.controls['cardNumber'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- <ion-label class="errorMsg">- Tiene que tener 16 caracteres.</ion-label><br>
- <ion-label class="errorMsg">- Solo se permiten números.</ion-label><br>
- </ng-container>
- </ion-col>
- </ion-row>
- <ion-row>
- <ion-col>
- <ion-item class="ion-no-padding">
- <ion-label for="cardholderName" position="floating">Nombre del titular</ion-label>
- <ion-input (ionChange)="cardUpdater($event)" [formControl]="form.controls['cardholderName']" type="text"
- id="cardholderName" data-checkout="cardholderName" clearInput maxlength="30"
- [class.invalid]="!form.controls['cardholderName'].valid && submitAttempt">
- </ion-input>
- </ion-item>
- <ng-container *ngIf="!form.controls['cardholderName'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- <ion-label class="errorMsg">- No puede tener más de 30 caracteres.</ion-label><br>
- </ng-container>
- </ion-col>
- </ion-row>
- <ion-row>
- <ion-col size="4">
- <ion-item class="ion-no-padding">
- <ion-label for="cardExpirationMonth" position="floating">Mes Exp.</ion-label>
- <ion-input (ionChange)="cardUpdater($event)" [formControl]="form.controls['cardExpirationMonth']"
- type="text" maxlength="2" id="cardExpirationMonth" data-checkout="cardExpirationMonth"
- onselectstart="return false" onpaste="return false" onCopy="return false" onCut="return false"
- onDrag="return false" onDrop="return false" autocomplete=off clear-input="true"
- [class.invalid]="!form.controls['cardExpirationMonth'].valid && submitAttempt">
- </ion-input>
- </ion-item>
- <ng-container *ngIf="!form.controls['cardExpirationMonth'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- <ion-label class="errorMsg">- Solo se permiten valores entre 1 y 12.</ion-label><br>
- </ng-container>
- </ion-col>
- <ion-col size="4">
- <ion-item class="ion-no-padding">
- <ion-label for="cardExpirationYear" position="floating">Año Exp.</ion-label>
- <ion-input (ionChange)="cardUpdater($event)" [formControl]="form.controls['cardExpirationYear']" type="text"
- maxlength="4" id="cardExpirationYear" data-checkout="cardExpirationYear" onselectstart="return false"
- onpaste="return false" onCopy="return false" onCut="return false" onDrag="return false"
- onDrop="return false" autocomplete=off clearInput
- [class.invalid]="!form.controls['cardExpirationYear'].valid && submitAttempt">
- </ion-input>
- </ion-item>
- <ng-container *ngIf="!form.controls['cardExpirationYear'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- <ion-label class="errorMsg">- El año tiene que ser ayor al actual.</ion-label><br>
- <ion-label class="errorMsg">- Solo se permiten números.</ion-label><br>
- </ng-container>
- </ion-col>
- <ion-col size="4">
- <ion-item class="ion-no-padding">
- <ion-label for="securityCode" position="floating">CVV</ion-label>
- <ion-input (ionFocus)="flipCard('back')" (ionBlur)="flipCard('front')" (ionChange)="cardUpdater($event)" [formControl]="form.controls['securityCode']" type="text"
- maxlength="3" id="securityCode" data-checkout="securityCode" onselectstart="return false"
- onpaste="return false" onCopy="return false" onCut="return false" onDrag="return false"
- onDrop="return false" autocomplete=off autoclean clearInput
- [class.invalid]="!form.controls['securityCode'].valid && submitAttempt">
- </ion-input>
- </ion-item>
- <ng-container *ngIf="!form.controls['securityCode'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- <ion-label class="errorMsg">- Tiene que tener 3 caracteres.</ion-label><br>
- <ion-label class="errorMsg">- Solo se permiten números.</ion-label><br>
- </ng-container>
- </ion-col>
- </ion-row>
- <ion-row>
- <ion-col size="5">
- <ion-item class="ion-no-padding">
- <ion-label for="docType" position="stacked">Tipo D.</ion-label>
- <ion-select [formControl]="form.controls['docType']" class="select-full-width">
- <ion-select-option *ngFor="let idType of mercadoPagoService.identifications" data-checkout="docType"
- [value]="idType.id">{{idType.name}}</ion-select-option>
- </ion-select>
- </ion-item>
- <ng-container *ngIf="!form.controls['docType'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- </ng-container>
- </ion-col>
- <ion-col size="7">
- <ion-item class="ion-no-padding">
- <ion-label for="docNumber" position="floating">Nro. Documento</ion-label>
- <ion-input [formControl]="form.controls['docNumber']" type="text" maxlength="9" id="docNumber"
- data-checkout="docNumber" clearInput [class.invalid]="!form.controls['docNumber'].valid && submitAttempt">
- </ion-input>
- </ion-item>
- <ng-container *ngIf="!form.controls['docNumber'].valid && submitAttempt">
- <ion-label class="errorMsg">- No puede estar vacío.</ion-label><br>
- <ion-label class="errorMsg">- No se permiten números de menos de 7 dígitos.</ion-label><br>
- <ion-label class="errorMsg">- No se permiten números de más de 8 dígitos.</ion-label>
- <br>
- </ng-container>
- </ion-col>
- </ion-row>
- <ion-row>
- <ion-col>
- <ion-item class="ion-no-padding">
- <ion-label for="amountSelected" position="stacked">Cargas de saldo disponibles</ion-label>
- <ion-select placeholder="Elegi un monto a cargar" [formControl]="form.controls['amountSelected']" class="select-full-width">
- <ion-select-option *ngFor="let amount of amounts" [value]="amount.id">
- {{amount.monto}}
- </ion-select-option>
- </ion-select>
- </ion-item>
- <ng-container *ngIf="!form.controls['amountSelected'].valid && submitAttempt">
- <ion-label class="errorMsg">- Debe seleccionar un monto a cargar.</ion-label><br>
- </ng-container>
- </ion-col>
- </ion-row>
- <ion-row>
- <ion-col size="3">
- <ion-button expand="block" color="danger" (click)="cancelar();">
- <ion-icon color="light" name="chevron-back"></ion-icon>
- </ion-button>
- </ion-col>
- <ion-col size="9">
- <ion-button expand="block" color="primary" (click)="realizarPago()">
- <b>Realizar Pago</b>
- </ion-button>
- </ion-col>
- </ion-row>
- </ion-grid>
- </form>
- </ion-content>
- //component.ts ==================================================================================================
- import { Component, OnInit, Input, ChangeDetectorRef, ChangeDetectionStrategy } from '@angular/core';
- import { MercadoPagoService } from '../services/cliente-tarjeta-mercadopago.service';
- import { FormBuilder, FormGroup, Validators } from '@angular/forms';
- import { PaymentData } from 'src/app/cliente/models/payment_data';
- import { analyzeAndValidateNgModules } from '@angular/compiler';
- import { ModalController } from '@ionic/angular';
- import { LoadingController } from '@ionic/angular';
- import { ToastController } from '@ionic/angular';
- import { LoginService } from 'src/app/auth/services/auth.service';
- @Component({
- selector: 'app-saldo-tarjeta',
- templateUrl: '../views/cliente-tarjeta-saldo.html',
- styleUrls: ['../views/cliente-tarjeta-saldo.scss'],
- changeDetection: ChangeDetectionStrategy.OnPush
- })
- export class SaldoTarjetaComponent implements OnInit {
- form: FormGroup;
- public paymentMethod: any;
- @Input('nro_tarjeta') nro_tarjeta: string;
- amounts: any = [];
- amountSelected: any;
- submitAttempt = false;
- cardNumber: string;
- cardHolder: string;
- expirationMonth: string;
- expirationYear: string;
- ccv: number;
- showingBackside = false;
- constructor(
- private detector: ChangeDetectorRef,
- public mercadoPagoService: MercadoPagoService,
- public modalController: ModalController,
- public loadingController: LoadingController,
- public toastController: ToastController,
- private loginService: LoginService,
- private fb: FormBuilder
- ) {
- this.form = fb.group({
- email: ['', Validators.compose([
- Validators.required,
- Validators.email
- ])],
- cardNumber: ['', Validators.compose([
- Validators.required,
- Validators.minLength(16),
- Validators.maxLength(16),
- Validators.pattern('^[0-9]*$')
- ])],
- cardholderName: ['', Validators.compose([
- Validators.required,
- Validators.minLength(1),
- Validators.maxLength(30)
- ])],
- cardExpirationMonth: ['', Validators.compose([
- Validators.required,
- Validators.pattern('^[0-1][0-2]$')
- ])],
- cardExpirationYear: ['', Validators.compose([
- Validators.required,
- Validators.pattern('^20[1-9][0-9]$')
- ])],
- securityCode: ['', Validators.compose([
- Validators.required,
- Validators.pattern('^[0-9][0-9][0-9]$')
- ])],
- docType: ['DNI', Validators.required],
- docNumber: ['', Validators.compose([
- Validators.required,
- Validators.pattern('^(\\d{7,8})$')
- ])],
- paymentMethodId: ['', Validators.required],
- amountSelected: ['', Validators.required],
- token: ['']
- });
- this.mercadoPagoService.amounts(this.loginService.usuario.numero_sala).subscribe((data: any) => {
- this.amounts = data.response;
- }, (error: any) => {
- console.log(error);
- });
- }
- ngOnInit() {
- this.mercadoPagoService.getIdentificationTypes();
- }
- getBin() {
- const bin = document.querySelector('ion-input[data-checkout="cardNumber"]');
- return bin['value'].replace(/[ .-]/g, '').slice(0, 6);
- }
- guessingPaymentMethod(e: any) {
- const bin = this.getBin();
- this.cardUpdater(e);
- if (bin.length >= 6) {
- const paymentMethod = this.mercadoPagoService.getPaymentMethod(bin);
- if (paymentMethod) {
- this.paymentMethod = paymentMethod[0];
- document.getElementById('cardName').innerHTML = this.paymentMethod.name;
- }
- }
- }
- async realizarPago() {
- // indico que se estรก haciendo un submit del formulario
- this.submitAttempt = true;
- const form = this.form.getRawValue();
- if (this.form.valid) {
- // Activo el bloque de pantalla, para que el usuario sepa que se estรก procesando el pago
- this.showAutoHideLoader();
- // Esto se usa para poder generar el token sin problemas en varias cargas seguidas.
- this.mercadoPagoService.Mercadopago.clearSession();
- this.mercadoPagoService.Mercadopago.createToken(form, (status: any, response: any) => {
- if (response && status == 200) {
- const payment_data: any = {
- // tslint:disable-next-line: triple-equals
- transaction_amount: this.amounts.find(a => a.id == this.form.get('amountSelected').value).monto,
- token: response.id,
- description: 'Carga de Tarjeta desde Aplicacion',
- installments: 1,
- payment_method_id: this.paymentMethod.id,
- payer: { email: this.form.get('email').value },
- nro_tarjeta: this.nro_tarjeta
- };
- this.mercadoPagoService.pago(payment_data).subscribe(
- rta => {
- if (rta.success) {
- const indice = this.loginService.usuario.cliente.tarjetas.findIndex(r => r.nro_tarjeta === rta.tarjetaAct.nro_tarjeta);
- this.loginService.usuario.cliente.tarjetas[indice] = rta.tarjetaAct;
- this.hideLoader();
- this.modalController.dismiss({
- 'success': true
- });
- this.presentToast('Carga realizada', true);
- } else {
- this.hideLoader();
- this.presentToast('Error al realizar la carga', false);
- }
- },
- error => {
- this.hideLoader();
- this.presentToast('Error al realizar la carga', false);
- }
- );
- return response;
- } else {
- console.log(response);
- alert('Disculpe, pero no se pudo realizar el pago');
- return null;
- }
- });
- } else {
- return null;
- }
- }
- cancelar() {
- this.modalController.dismiss({
- 'success': false
- });
- }
- cardUpdater(e) {
- console.log(e.srcElement.id);
- switch (e.srcElement.id) {
- case 'cardNumber':
- this.cardNumber = e.detail.value;
- break;
- case 'cardholderName':
- this.cardHolder = e.detail.value;
- break;
- case 'cardExpirationMonth':
- this.expirationMonth = e.detail.value;
- break;
- case 'cardExpirationYear':
- this.expirationYear = e.detail.value;
- break;
- case 'securityCode':
- this.ccv = e.detail.value;
- break;
- }
- this.detector.detectChanges();
- }
- flipCard(desired_side: String) {
- if (desired_side === 'back') {
- this.showingBackside = true;
- } else {
- this.showingBackside = false;
- }
- }
- showAutoHideLoader() {
- this.loadingController.create({
- message: 'Registrando pago'
- }).then((res) => {
- res.present();
- });
- }
- hideLoader() {
- this.loadingController.dismiss();
- }
- async presentToast(message: string, success: boolean) {
- const color = success ? 'success' : 'danger';
- this.toastController.create({
- message: message,
- duration: 2000,
- color: color,
- // ! showCloseButton: true
- }).then(toast => {
- toast.present();
- });
- }
- }
Add Comment
Please, Sign In to add comment