Skip to content

Commit

Permalink
Adds CVV, custom validators and savePayment method.
Browse files Browse the repository at this point in the history
  • Loading branch information
wjames111 committed Nov 4, 2024
1 parent 70452db commit 65c4157
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 12 deletions.
110 changes: 104 additions & 6 deletions src/common/components/paymentMethods/paymentMethodDisplay.component.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,124 @@
import angular from 'angular'
import appConfig from 'common/app.config'

import get from 'lodash/get'
import template from './paymentMethodDisplay.tpl.html'

import creditCardForm from './creditCardForm/creditCardForm.component'
import tsys from 'common/services/api/tsys.service'
import { Observable } from 'rxjs/Observable'
import * as cruPayments from '@cruglobal/cru-payments/dist/cru-payments'
import { scrollModalToTop } from 'common/services/modalState.service'
import analyticsFactory from 'app/analytics/analytics.factory'
import showErrors from 'common/filters/showErrors.filter'
import creditCardNumberDirective from '../../directives/creditCardNumber.directive'
import 'rxjs/add/observable/of'
import 'rxjs/add/operator/combineLatest'
import 'rxjs/add/operator/mergeMap'
const componentName = 'paymentMethodDisplay'

class PaymentMethodDisplayController {
/* @ngInject */
constructor (envService) {
this.imgDomain = envService.read('imgDomain')
constructor ($scope, $log, analyticsFactory, envService, tsysService) {
this.imgDomain = envService.read('imgDomain');
this.tsysService = tsysService
this.$log = $log
this.envService = envService
this.analyticsFactory = analyticsFactory
this.$scope = $scope;
}

$onInit () {
this.addCustomValidators()
}

addCustomValidators () {
this.$scope.$watch('$ctrl.creditCardPaymentForm.securityCode', (value) => {
console.log('value', value)
this.creditCardPaymentForm.securityCode.$validators.minLength = cruPayments.creditCard.cvv.validate.minLength
this.creditCardPaymentForm.securityCode.$validators.maxLength = cruPayments.creditCard.cvv.validate.maxLength
this.creditCardPaymentForm.securityCode.$validate()
})
}

savePayment () {
this.creditCardPaymentForm.$setSubmitted()
if (this.creditCardPaymentForm.$valid) {

this.onPaymentFormStateChange({
$event: {
state: 'encrypting'
}
})
const tokenObservable = this.paymentMethod
? Observable.of({
tsepToken: this.paymentMethod['last-four-digits'],
maskedCardNumber: this.paymentMethod['last-four-digits']
}) // Send masked card number when card number is not updated
: this.tsysService.getManifest()
.mergeMap(data => {
const productionEnvironments = ['production', 'prodcloud', 'preprod']
const actualEnvironment = this.envService.get()
const ccpEnvironment = productionEnvironments.includes(actualEnvironment) ? 'production' : actualEnvironment

cruPayments.creditCard.init(ccpEnvironment, data.deviceId, data.manifest)
return cruPayments.creditCard.encrypt(this.paymentMethod['card-number'], this.creditCardPayment.securityCode, this.paymentMethod['expiry-month'], this.paymentMethod['expiry-year'])
})
tokenObservable.subscribe(tokenObj => {
console.log('loading')
this.onPaymentFormStateChange({
$event: {
state: 'loading',
payload: {
creditCard: {
address: this.paymentMethod['address'],
'card-number': tokenObj.tsepToken,
'card-type': this.paymentMethod['card-type'], /* eslint-disable-line no-mixed-operators */
'cardholder-name': this.paymentMethod['cardholder-name'],
'expiry-month': this.paymentMethod['expiry-month'],
'expiry-year': this.paymentMethod['expiry-year'],
'last-four-digits': tokenObj.maskedCardNumber,
transactionId: tokenObj.transactionID,
cvv: this.creditCardPayment.securityCode
}
}
}
})
}, error => {
this.$log.error('Error tokenizing credit card', error)
this.analyticsFactory.checkoutFieldError('tokenizeCard', 'failed')
this.onPaymentFormStateChange({
$event: {
state: 'error',
error: error
}
})
scrollModalToTop()
})
} else {
this.analyticsFactory.handleCheckoutFormErrors(this.creditCardPaymentForm)
this.onPaymentFormStateChange({
$event: {
state: 'unsubmitted'
}
})
}
}
}

export default angular
.module(componentName, [
appConfig.name
'ngMessages',
showErrors.name,
analyticsFactory.name,
tsys.name,
creditCardNumberDirective.name
])
.component(componentName, {
controller: PaymentMethodDisplayController,
templateUrl: template,
bindings: {
paymentFormState: '<',
paymentMethod: '<',
expired: '<'
expired: '<',
onPaymentFormStateChange: '&'
}
})
34 changes: 28 additions & 6 deletions src/common/components/paymentMethods/paymentMethodDisplay.tpl.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<form novalidate name="$ctrl.creditCardPaymentForm" ng-keyup="$event.key === 'Enter' && $ctrl.savePayment()">
<span class="account-management">
<span ng-if="$ctrl.paymentMethod['card-type']">
<span ng-switch="$ctrl.paymentMethod['card-type']">
Expand All @@ -10,12 +11,32 @@
</span>
<strong>{{$ctrl.paymentMethod['card-type']}}</strong>
<span>ends in ****{{$ctrl.paymentMethod['last-four-digits']}}</span>
<small class="number" ng-class="{'text-danger': $ctrl.expired}">
<span class="hidden-xs" ng-if="!$ctrl.expired" translate>EXPIRES</span>
<span class="hidden-xs" ng-if="$ctrl.expired" translate>EXPIRED</span>
<span class="visible-xs-inline">EXP</span>
{{$ctrl.paymentMethod['expiry-month']}}/<span class="hidden-xs">{{$ctrl.paymentMethod['expiry-year'] | limitTo : 2}}</span>{{$ctrl.paymentMethod['expiry-year'] | limitTo : 2 : 2}}
</small>
<small class="number" ng-class="{'text-danger': $ctrl.expired}">
<span class="hidden-xs" ng-if="!$ctrl.expired" translate>EXPIRES</span>
<span class="hidden-xs" ng-if="$ctrl.expired" translate>EXPIRED</span>
<span class="visible-xs-inline">EXP</span>
{{$ctrl.paymentMethod['expiry-month']}}/<span class="hidden-xs">{{$ctrl.paymentMethod['expiry-year'] | limitTo : 2}}</span>{{$ctrl.paymentMethod['expiry-year'] | limitTo : 2 : 2}}
</small>

<div class="form-group" ng-class="{'has-error': ($ctrl.creditCardPaymentForm.securityCode | showErrors), 'is-required': true}">
<label translate>{{'SEC_CODE'}}</label>
<input type="text"
name="securityCode"
autocomplete="cc-csc"
class="form-control form-control-subtle"
ng-model="$ctrl.creditCardPayment.securityCode"
/>
<div role="alert" ng-messages="$ctrl.creditCardPaymentForm.securityCode.$error" ng-if="($ctrl.creditCardPaymentForm.securityCode | showErrors)">
<div class="help-block" ng-message="required" translate>{{'CARD_SEC_CODE_ERROR'}}</div>
<div class="help-block" ng-message="minLength" translate>{{'MIN_LENGTH_CARD_SEC_CODE'}}</div>
<div class="help-block" ng-message="maxLength" translate>{{'MAX_LENGTH_CARD_SEC_CODE'}}</div>
<div class="help-block" ng-message="cardTypeLength" ng-init="isAmex = $ctrl.cardInfo.type($ctrl.creditCardPayment.cardNumber) === 'American Express'">
<translate ng-if="!isAmex">{{'LOCATION_OF_CODE_OTHER'}}</translate>
<translate ng-if="isAmex">{{'LOCATION_OF_CODE_AMEX'}}</translate>
</div>
</div>
</div>

</span>
<span ng-if="!$ctrl.paymentMethod['card-type']">
<img class="payment-icon hidden-xs" ng-src="{{$ctrl.imgDomain}}/assets/img/cc-icons/bank-curved-128px.png" />
Expand All @@ -27,3 +48,4 @@
<span>ends in ****{{$ctrl.paymentMethod['display-account-number']}}</span>
</span>
</span>
</form>

0 comments on commit 65c4157

Please sign in to comment.