В настоящее время я работаю над интеграцией PayPal в своем собственном магазине (Angular Frontend, сделайте tnet core WebApi backend) и, по-видимому, у меня есть проблема с жизненным циклом между основным компонентом (CheckoutProcessComponent) и дочерним компонентом (PaymentPayPalComponent) и с использованием необходимого PayPal javascript.
По сути, полный рабочий процесс PayPal работает, пока я использую переменные stati c. И именно здесь начинается моя проблема.
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>
PaymentPayPalComponent.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>
Процесс обработки выглядит следующим образом:
- CheckoutProcessComponent> создает заказ на сервере с данными корзины и сохраняет заказ в база данных (общая функция, не связанная с PayPal)
- Результатом из 1. является IOrderProcessSummary, который содержит идентификатор заказа и сумму заказа
- В зависимости от выбранного способа оплаты соответствующий Компонент Payment-Child будет отображаться. В этом случае PaymentPayPalComponent.
- Затем я использую функцию PayPal «CreatePayPalOrderOnServer», которая использует Api PayPal в моем бэкэнде для создания заказа на сервере PayPal. Но для этого мне нужен указанный c orderId, потому что мне нужно заполнить данные PayPal-Order указанными c данными заказа из моей системы (в этом примере у меня фиксированный идентификатор заказа 1234).
Для шага 4. Я пробовал это с параметром Input () и с внедрением CheckoutService в PaymentPayPalComponent, но я не могу работать с любым видом динамических c переменных внутри PayPal-Button-Function (JavaScript). В этом примере мне нужно изменить "orderId: 1234" со значением из InputSummary () или с тем же значением из CheckoutService, но оба они остаются неопределенными.
PayPal- Javascript загружены правильно, и кнопки PayPal отображаются и работают технически, как предполагалось.
Как мне перенести мои динамические c данные в PaymentPayPalComponent и в PayPal.Buttons-Function?
Спасибо за советы!