首页 > 解决方案 > Angular PayPal 处理、子组件和生命周期

问题描述

我目前正在我自己的商店(Angular Frontend,dotnet core WebApi backend)中进行 PayPal 集成,显然我在主组件(CheckoutProcessComponent)和子组件(PaymentPayPalComponent)之间的生命周期以及使用必要的 PayPal javascript。

基本上,只要我使用静态变量,完整的 PayPal 工作流程就可以工作。这正是我的问题开始的地方。

CheckoutProcessComponent.ts

import { Component, OnInit } from '@angular/core';
import { CartService } from 'src/app/_services/shop/cart.service';
import { ISubscriptionCollection } from 'src/app/_models/misc/ISubscriptionCollection';
import { serialUnsubscriber } from 'src/app/shared/utility.module';
import { CheckoutService } from 'src/app/_services/checkout/checkout.service';
import { ICheckoutOrderData } from 'src/app/_models/shop/ICheckoutOrderData';
import { IOrderProcessSummary } from 'src/app/_models/shop/IOrderProcessSummary';

@Component({
  selector: 'app-checkout-process',
  templateUrl: './checkout-process.component.html',
  styleUrls: ['./checkout-process.component.css']
})
export class CheckoutProcessComponent implements OnInit {
  subscriptions: ISubscriptionCollection = {};

  checkoutOrderData = {} as ICheckoutOrderData;
  orderSummaryFromServer: IOrderProcessSummary;
  orderCreated: boolean = false;

  constructor(public checkoutService: CheckoutService, public cartService: CartService) { }

  ngOnInit() {    
    this.checkoutOrderData.Order = this.checkoutService.orderData;
    this.checkoutOrderData.Cart = this.cartService.shoppingCart;
    // Create Order
    this.subscriptions['createOrder'] = this.checkoutService.createOrder(this.checkoutOrderData)
      .subscribe((res: IOrderProcessSummary) => {
        this.checkoutService.checkoutSummary = res;
        this.orderSummaryFromServer = res;
        console.log('Order created: ' + res);
      }, error => {
        console.log('Error');
      });
  }

  ngOnDestroy(): void {
    serialUnsubscriber(...Object.values(this.subscriptions));
  }

  nextStep(step: number) {
    this.checkoutService.updateCheckoutStep(step);
  }
 ...
}

CheckoutProcessComponent.html

<app-payment-paypal [orderSummary]="orderSummaryFromServer" *ngIf="checkoutService.orderData.paymentMethod === 'PM_PAYPAL'"></app-payment-paypal>
<app-payment-stripe *ngIf="checkoutService.orderData.paymentMethod === 'PM_STRIPE'"></app-payment-stripe>
<app-payment-moneytransfer *ngIf="checkoutService.orderData.paymentMethod === 'PM_TRANSFER'"></app-payment-moneytransfer>

支付PayPalComponent.ts

import { Component, OnInit, AfterViewChecked, Input } from '@angular/core';
import { environment } from 'src/environments/environment';
import { IOrderProcessSummary } from 'src/app/_models/shop/IOrderProcessSummary';
import { CheckoutService } from 'src/app/_services/checkout/checkout.service';

declare let paypal: any;

@Component({
  selector: 'app-payment-paypal',
  templateUrl: './payment-paypal.component.html',
  styleUrls: ['./payment-paypal.component.css']
})
export class PaymentPaypalComponent implements OnInit, AfterViewChecked {
  @Input() orderSummary: IOrderProcessSummary;

  paypalClientId = environment.paymentPayPal.clientId;
  addScript: boolean = false;
  scriptTagElement: HTMLScriptElement;
  constructor(private checkoutService: CheckoutService) { }

  ngOnInit() {
  }

  ngOnDestroy(): void {
    if (this.scriptTagElement) {
      document.body.removeChild(this.scriptTagElement);
    }
  }

  ngAfterViewChecked(): void {
    if (!this.addScript) {
      this.addPayPalScript().then(() => {
        paypal.Buttons({
          createOrder: function() {
            return fetch('https://localhost:5021/api/payments/paypal-create-order', {
              method: 'post',
              headers: {
                'content-type': 'application/json'
              },
              body: JSON.stringify({
                orderId: 1234
              })
            }).then(function(res) {
              return res.json();
            }).then(function(data) {
              return data.id; // Use the same key name for order ID on the client and server
            });
          },
          onApprove: function(data, actions) {
            console.log('onApprove - transaction was approved, but not authorized', data, actions);
            actions.order.get().then(details => {
                    console.log('onApprove - you can get full order details inside onApprove: ', details);
            });

            return fetch('https://localhost:5021/api/payments/paypal-capture-order', {
              method: 'post',
              headers: {
                'content-type': 'application/json'
              },
              body: JSON.stringify({
                token:   data.orderID,
                payerID: data.payerID,
              })
            });
          },
          onClientAuthorization: (data) => {
            console.log('onClientAuthorization - you should probably inform your server about completed transaction at this point', data);
            // this.showSuccess = true;
          },
          onCancel: (data, actions) => {
            console.log('OnCancel', data, actions);
            // this.showCancel = true;
          },
          onError: err => {
            console.log('OnError', err);
            // this.showError = true;
          }
        }).render('#paypal-button-container');
      })
    }
  }

  addPayPalScript() {
    return new Promise((resolve, reject) => {
      this.scriptTagElement = document.createElement('script');
      this.scriptTagElement.src = 'https://www.paypal.com/sdk/js?currency=EUR&client-id=' + this.paypalClientId;
      this.scriptTagElement.onload = resolve;
      document.body.appendChild(this.scriptTagElement);
      this.addScript = true;
    })
  }

}

PaymentPayPalComponent.html

<div class="text-center" id="paypal-button-container"></div>

处理流程如下:

  1. CheckoutProcessComponent > 在服务器上使用购物车数据创建订单并将订单存储在数据库中(通用功能,与 PayPal 无关)
  2. 1. 的结果是 IOrderProcessSummary,其中包含订单 ID 和订单总额
  3. 根据选择的付款方式,将显示相应的付款-子组件。在这种情况下,PaymentPayPalComponent。
  4. 然后我使用 PayPal 功能“CreatePayPalOrderOnServer”,它在我的后端使用 PayPal Api 在 PayPal 服务器上创建订单。但为此我需要特定的 orderId,因为我需要使用系统中的特定订单数据填充 PayPal-Order 数据(在示例中,我有一个固定的 1234 订单 ID)。

对于第 4 步。我尝试使用 Input() 参数并将 CheckoutService 注入到 PaymentPayPalComponent 但我无法使用 PayPal-Button-Function (JavaScript) 中的任何类型的动态变量。在示例中,我需要使用 Input() orderSummary 中的值或 CheckoutService 中的相同值更改“orderId:1234”,但它们都保持未定义。

PayPal-Javascript 已正确加载,并且 PayPal-Buttons 显示并按技术预期工作。

如何将我的动态数据带入 PaymentPayPalComponent 和 PayPal.Buttons-Function?

感谢您的提示!

标签: javascriptangularpaypalpaypal-sandbox

解决方案


推荐阅读