Issue
I am trying to integrate paypal with Angular. When I call an injected service inside a function of the promise returned I am unable to do it. I need help in achieving it.
Here are the steps I am trying to do.
- Click on the load PayPal button.
- Load the dynamically injected Braintree and PayPal sdk.
- Authorize into PayPal and get the nonce token.
- Pass the nonce token generated into the service which is injected into the component.
Code below
app.component.html
<button (click)="initializePayPal()">load paypal</button> <div></div> app.component.ts
export class AppComponent { constructor(private backEndService: BackEndService) {} initializePayPal() { get("", () => { get( "", () => { console.log("loaded"); this.loadPayPalSDK(); } ); }); } private loadPayPalSDK(): void { braintree.client .create({ authorization: "sandbox_5rnr7xqg_kx8tzdyvfcrnxq5y" }) .then(clientInstance => { // Create a PayPal Checkout component. return braintree.paypalCheckout.create({ client: clientInstance }); }) .then(paypalCheckoutInstance => { return paypalCheckoutInstance.loadPayPalSDK({ vault: true }); }) .then(paypalCheckoutInstance => { return paypal .Buttons({ locale: "en_US", fundingSource: paypal.FUNDING.PAYPAL, style: { height: 40 }, createBillingAgreement() { return paypalCheckoutInstance.createPayment({ flow: "vault" }); }, onApprove(data, actions) { return paypalCheckoutInstance .tokenizePayment(data) .then(payload => { console.log(payload.nonce); this.backEndService.addToken(payload); }); }, onCancel(data) {}, onError(err) { // } }) .render("#pay-pal-btn"); }); } } Back End Service backend.service.ts
import { Injectable } from "@angular/core"; @Injectable({ providedIn: "root" }) export class BackEndService { addToken(token: string) { // here is am going to use the token generated and pass this value to backend service using http request. console.log("token" + token); } } Expected Resolution
I need to call the injected service upon the tokenizePayment method is called.
Thanks a lot in advance
StackBlitz URL
21 Answer
The problem you are having right now is related to the scope.
// you are losing the scope on calling paypal.Buttons // because this function has its own scope and it is not possible to // get the backend service which has another scope (this) return paypal.Buttons({ onApprove() { return paypalCheckoutInstance .tokenizePayment(data) .then(payload => { this.backendservice // <- this is undefined because of scope }); } }) However, I found two ways to handle this case.
- Use a static method.
return paypal.Buttons({ onApprove() { return paypalCheckoutInstance .tokenizePayment(data) .then(payload => { BackEndService.sendToken(payload.nonce); }); } }) backend.service.ts
export class BackEndService { // our static method static sendToken(token: string) { console.log("[backend service] send token", token); } - Pass our scope indirectly using an object with our service reference.
// create an object with my scope calling our service // we need to pass this object to our // method loadPayPalSDK config = { onApprove: (token: string) => { this.backEndService.addToken(token); } }; // I need my config here private loadPayPalSDK(config = this.config): void { // code omitted ... return paypal.Buttons({ onApprove() { return paypalCheckoutInstance .tokenizePayment(data) .then(payload => { config.onApprove(payload.nonce); }); } }) } 4