1

I get the error:

core.js:5882 ERROR TypeError: Cannot read property 'configure' of undefined

when I implement a Hosted Session Integration for Mastercard in Angular 2. Here is my code:

payment-detail.component.ts

import { AfterViewInit, Component, OnInit } from '@angular/core';
declare var $: any;

@Component({
  selector: 'app-payment-detail',
  templateUrl: './payment-detail.component.html',
  styleUrls: ['./payment-detail.component.css'],
})
export class PaymentDetailComponent implements OnInit, AfterViewInit {
  // PaymentSession: any;

  constructor() {}

  ngAfterViewInit(): void {


    $.getScript(
      'https://ap-gateway.mastercard.com/form/version/57/merchant/<MERCHANTID>/session.js?debug=true',
      function () {
        $.PaymentSession.configure({
          fields: {
            // Attach hosted fields to your payment page
            card: {
              number: '#card-number',
              securityCode: '#security-code',
              expiryMonth: '#expiry-month',
              expiryYear: '#expiry-year',
              nameOnCard: '#cardholder-name',
            },
            giftCard: {
              number: '#gift-card-number',
              pin: '#gift-card-pin',
            },
            ach: {
              accountType: '#ach-account-type',
              bankAccountHolder: '#ach-account-holder',
              bankAccountNumber: '#ach-account-number',
              routingNumber: '#ach-routing-number',
            },
          },
          frameEmbeddingMitigation: ['javascript'],
          callbacks: {
            initialized: function (response) {
              // HANDLE INITIALIZATION RESPONSE
              if (response.status === 'ok') {
                document.getElementById('visaCheckoutButton').style.display =
                  'block';
              }
            },

            formSessionUpdate: function (response) {
              // HANDLE RESPONSE FOR UPDATE SESSION
              if (response.status) {
                if ('ok' == response.status) {
                  console.log(
                    'Session updated with data: ' + response.session.id
                  );

                  //check if the security code was provided by the user
                  if (response.sourceOfFunds.provided.card.securityCode) {
                    console.log('Security code was provided.');
                  }

                  //check if the user entered a MasterCard credit card
                  if (
                    response.sourceOfFunds.provided.card.scheme == 'MASTERCARD'
                  ) {
                    console.log('The user entered a MasterCard credit card.');
                  }
                } else if ('fields_in_error' == response.status) {
                  console.log('Session update failed with field errors.');
                  if (response.errors.cardNumber) {
                    console.log('Card number invalid or missing.');
                  }
                  if (response.errors.expiryYear) {
                    console.log('Expiry year invalid or missing.');
                  }
                  if (response.errors.expiryMonth) {
                    console.log('Expiry month invalid or missing.');
                  }
                  if (response.errors.securityCode) {
                    console.log('Security code invalid.');
                  }
                  if (response.errors.number) {
                    console.log('Gift card number invalid or missing.');
                  }
                  if (response.errors.pin) {
                    console.log('Pin invalid or missing.');
                  }
                  if (response.errors.bankAccountHolder) {
                    console.log('Bank account holder invalid.');
                  }
                  if (response.errors.bankAccountNumber) {
                    console.log('Bank account number invalid.');
                  }
                  if (response.errors.routingNumber) {
                    console.log('Routing number invalid.');
                  }
                } else if ('request_timeout' == response.status) {
                  console.log(
                    'Session update failed with request timeout: ' +
                      response.errors.message
                  );
                } else if ('system_error' == response.status) {
                  console.log(
                    'Session update failed with system error: ' +
                      response.errors.message
                  );
                }
              } else {
                console.log('Session update failed: ' + response);
              }
            },
            visaCheckout: function (response) {
              // HANDLE VISA CHECKOUT RESPONSE
            },
            amexExpressCheckout: function (response) {
              // HANDLE AMEX EXPRESS CHECKOUT RESPONSE
            },
          },
          interaction: {
            displayControl: {
              formatCard: 'EMBOSSED',
              invalidFieldCharacters: 'REJECT',
            },
          },
          order: {
            amount: 10.0,
            currency: 'AUD',
          },
          wallets: {
            visaCheckout: {
              enabled: true,
              // Add Visa Checkout API specific attributes here
              countryCode: 'AU',
              displayName: 'Display name',
              locale: 'en_au',
              logoUrl: 'http://logo.logo',
              payment: {
                cardBrands: ['VISA'],
              },
              review: {
                buttonAction: 'Pay',
                message: 'Message',
              },
              shipping: {
                acceptedRegions: ['AU'],
                collectShipping: true,
              },
            },
            amexExpressCheckout: {
              enabled: true,
              // Add Amex Express Checkout API specific attributes here
              initTags: {
                theme: 'responsive',
                env: 'qa',
                disable_btn: 'false',
                button_color: 'light',
                client_id:
                  '<MSO Client Id from the Amex Express Checkout configuration page in Merchant Administration>',
              },
            },
          },
        });
      }
    );
  }

  ngOnInit(): void {
  }

  load(): void {}
}

payment-detail.component.html

<div>Please enter your payment details:</div>
<div>Card Number: <input type="text" id="card-number" class="input-field" value="5123450000000008" readonly></div>
<div>Expiry Month:<input type="text" id="expiry-month" class="input-field" value="05"></div>
<div>Expiry Year:<input type="text" id="expiry-year" class="input-field" value="21"></div>
<div>Security Code:<input type="text" id="security-code" class="input-field" value="1234" readonly></div>
<div><button id="payButton" onclick="pay();">Pay Now</button></div>

If I remove the $. from $.PaymentSession.configure, I get cannot find PaymentSession.

Update

I used this code as suggested by Maxine Lafarie:

$.getScript( "your-script", function( data, textStatus, jqxhr ) {
  console.log( data ); // Data returned
  console.log( textStatus ); // Success
  console.log( jqxhr.status ); // 200
  console.log( "Load was performed." );
});

This is the result:

undefined payment-detail.component.ts:31 success payment-detail.component.ts:32 200 payment-detail.component.ts:33 Load was performed.

pasting the url to the browser I get a script: enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
Ibanez1408
  • 4,550
  • 10
  • 59
  • 110

1 Answers1

1

Have you tied to log the response of $.getScript?

You can do it so:

$.getScript( "your-script", function( data, textStatus, jqxhr ) {
  console.log( data ); // Data returned
  console.log( textStatus ); // Success
  console.log( jqxhr.status ); // 200
  console.log( "Load was performed." );
});

Anyway I don't know if you're using jQuery in the whole app or just here for the "benefits" of the getScript method, but I would recommend you to avoid mixing Angular and jQ, since Angular can do absolutely all what jQuery is capable of.

If you want to load a 3rd party script the Angular way, you can do as explained here.

So check if:

  • jQuery is well imported and/or loaded in your component when you call it
  • you have some success logs after the $.getScript method is called
  • the Angular way for importing 3rd party scripts works (maybe better)

EDIT:

Since you imported the script, you're calling the global property like that: $.PaymentSession.configure but I think you have to call it like that : PaymentSession.configure

Maxime Lafarie
  • 2,172
  • 1
  • 22
  • 41
  • @Maxine Lafarie, I ran the sample script you gave Sir and I get this: `undefined payment-detail.component.ts:31 success payment-detail.component.ts:32 200 payment-detail.component.ts:33 Load was performed.` Please see the update above. – Ibanez1408 Sep 23 '20 at 07:52
  • @Ibanez1408 ok so the `getScript` function is working well, it means jQuery is well loaded so that's not the issue. I guess it comes from the script itself, what happen if you get the whole script URL and putting it into your browser? Does it show you some code (or ask you to DL the script file)? – Maxime Lafarie Sep 23 '20 at 07:56
  • If I place the URL into the browser, I get a javascript. Please see my edit. – Ibanez1408 Sep 23 '20 at 08:04
  • Thank you @Ibanez1408, so we have some more info now! Have you try looking in your console / newtork developer's console tabs (in your browser) if the script file is in the list of the loaded scripts and/or if you have some CORS errors in your console? (btw, I edited my answer) – Maxime Lafarie Sep 23 '20 at 08:10
  • 1
    You are right Sir. Thank you for your precious time. The IDE is giving me a squigly line but I just ignored it. It wen through. The only problem now is I get another error: `Session update failed with system error: Form Session not found or expired.` – Ibanez1408 Sep 23 '20 at 08:36
  • Happy to see it solves your issue @Ibanez1408. For your other problem, there's already a topic on SO, you can read it here: https://stackoverflow.com/questions/55356800/mastercard-hosted-session-integration-issue ;) – Maxime Lafarie Sep 23 '20 at 08:47