Search code examples
angulartypescriptpayment-gatewaypaymentworldpay

How to integrate worldpay with angular2


I am trying to integrate Worldpay in an angular2 app.

I am using own form (own-form) approach where it is necessary to include their script in page: <script src="https://cdn.worldpay.com/v1/worldpay.js"></script> Add specific attibutes for some inputs: data-worldpay and attach the Worldpay.js logic to the form...

I managed to make the steps:
1. Include Worldpay.js in your page
2. Create a payment form with the relevant attributes

How can I continue to make next steps... I am stuck on that problem:

5. Attach Worldpay.js to your form:

<script type="text/javascript">
var form = document.getElementById('paymentForm');

Worldpay.useOwnForm({
  'clientKey': 'your-test-client-key',
  'form': form,
  'reusable': false,
  'callback': function(status, response) {
    document.getElementById('paymentErrors').innerHTML = '';
    if (response.error) {             
      Worldpay.handleError(form, document.getElementById('paymentErrors'), response.error); 
    } else {
      var token = response.token;
      Worldpay.formBuilder(form, 'input', 'hidden', 'token', token);
      form.submit();
    }
  }
});
</script>

Why?
angular2 removes all tags <script from templates.
Supposing with a workaround it would be possible to inject some scripts in page in ngAfterViewInit() method (like i did for 1st step)

ngAfterViewInit(): void {        
  let s = document.createElement("script");
  s.type = "text/javascript";
  s.src = "https://cdn.worldpay.com/v1/worldpay.js";
  this.worldPayScriptElement.nativeElement.appendChild(s);        
}

where this.worldPayScriptElement is a ViewChild of the div from template: <div #worldPayScriptElement hidden></div>

But, As result of their processing rules, worldpay will replace sensitive data from my form with a field called CreditCardToken

From source: Finally, in Worldpay.formBuilder() all sensitive card data is removed from the form, replaced with the token and only then is the form submitted back to your server. source: https://developer.worldpay.com/jsonapi/docs/own-form

How to continue integrating this ... Cannot understand.
If they would have an API returning the CreditCardToken based on a GET/POST request it would be perfect, but from documentation I didn't found yet the right method for that...

I will really appreciate any kind of suggestions.


Solution

  • I have resolved that considering another approach :)

    I have used Worldpay API to get the token.
    API url: https://api.worldpay.com/v1/tokens

    The endpoint waits a POST request in the form:

    '{
        "reusable": true/false,
        "paymentMethod": {
            "name": "name",
            "expiryMonth": 2,
            "expiryYear": 2015,
            "issueNumber": 1,
            "startMonth": 2,
            "startYear": 2013,
            "cardNumber": "4444 3333 2222 1111",
            "type": "Card",
            "cvc": "123"
        },
        "clientKey": "T_C_client_key"
    }'
    

    where the Header should contain these options: "Content-type: application/json"

    Having that, no more need to include worldpay.js in page.
    Also, no more need to include in payment form worldpay specific attributes (like data-worldpay="")

    Simply should invoke the API, wait for the response, which will have the form:

    {
        "token": "UUID of token",
        "reusable": true/false,
        "paymentMethod": {
            "type" : "ObfuscatedCard",     
            "name": "name",
            "expiryMonth": 2,
            "expiryYear": 2015,
            "issueNumber": 1,
            "startMonth": 2,
            "startYear": 2013,
            "cardType": "VISA_CREDIT",
            "maskedCardNumber": "xxxx xxxx xxxx 1111",
            "cardSchemeType": "consumer",
            "cardSchemeName": "VISA CREDIT",
            "cardProductTypeDescNonContactless": "Visa Credit Personal",
            "cardProductTypeDescContactless": "CL Visa Credit Pers",
            "cardIssuer": "LLOYDS BANK PLC",
            "countryCode": "GBR",
            "cardClass": "credit",
            "prepaid": "false"
        }
    }
    

    From response you are ready to use the response.token in order to proceed to next step: payment.

    You should make sure that specific WorldPay attributes will be sent (CreditCardToken, Enrolled)

    How I invoked the worldpay API in angular2?

    public getWorldpayToken(request: any): Observable<any>{
        let worldPayApiUrl = `https://api.worldpay.com/v1/tokens`;
        let body = JSON.stringify(request);
        let headers = new Headers({ 'Content-Type':'application/json;charset=UTF-8'});
        let options = new RequestOptions({ headers: headers });
    
        return this.http.post(worldPayApiUrl, body, options)
          .map(response => response.json())
          .catch(this.handleError);
    }
    

    Documentation: https://developer.worldpay.com/jsonapi/api#tokens

    For any other details, do not hesitate to comment/ask :)