繁体   English   中英

如何在 web 组件中包含 Paypal 消息?

[英]How to include Paypal Messages in web components?

嗨 Stackoverflow 社区,

我需要帮助在 web 组件中加载 Paypal 消息。 加载 paypal SDK 后,我尝试使用以下代码包含 Paypal 稍后付款的消息。

          window.paypal.Messages({
              amount: this.amount,
              placement: "product",
              style: {
                layout: "text",
                logo: {
                  type: "inline",
                },
              },
            }).render(this.shadowRoot!.querySelector("#paypal-message") as HTMLElement);

我在浏览器控制台中收到以下错误。

paypal_messages_not_in_document 

description: "Container must be in the document."
timestamp: "1651659388515"

我能够使用相同的逻辑加载 paypal 按钮。

window.paypal.Buttons({ ....... }).render(this.shadowRoot!.querySelector("#paypal-button") as HTMLElement);

下面是 lit 元素框架中的 web 组件。

 import { customElement, html, internalProperty, property } from "lit-element"; import { RmsBookstoreAddress, PaymentDetails, PaymentType } from "../../../../features/shop-checkout"; import { BaseComponent } from "../../../../services/base-component"; import { booleanConverter } from "../../../../services/converters"; import { waitForElementsToLoad } from "../../../../services/delayUtil"; import emit from "../../../../services/events"; /* WARNING: Do NOT import directly from "braintree-web", it causes the bundle size to increase dramatically. */ import client from "braintree-web/client"; import dataCollector from "braintree-web/data-collector"; import paypalCheckout, { PayPalCheckoutTokenizationOptions } from "braintree-web/paypal-checkout"; /** * Configure and load Paypal button. * Saves paypal payment details in redux. */ @customElement("paypal-button") export default class PaypalButton extends BaseComponent { /** * Flag to indicate the checkout contains shippable items. */ @property({ converter: booleanConverter }) shippable = false; /** * Braintree Client token to initialize Paypal button. */ @property() clientToken = ""; /** * Currency for Paypal transaction. */ @property() currency = "USD"; /** * Option to set the description of the preapproved payment agreement visible to customers in their PayPal profile during Vault flows. Max 255 characters. */ @property() billingAgreementDescription = ""; /** * Transaction amount to be displayed in Paypal. */ @property({type: Number }) amount = 0; /** * Value to override paypal shipping address. */ @property({attribute: false, type: Object}) shippingAddress; /** * Allow PayPal to Capture the shipping address. */ @property({ converter: booleanConverter }) usePayPalShippingAddress = false; @property({ converter: booleanConverter}) userAutoLogin = false; /** * Billing address returned by Paypal */ @internalProperty() private internalBillingAddress: RmsBookstoreAddress | undefined; /** * Shipping address returned by Paypal */ @internalProperty() private internalShippingAddress: RmsBookstoreAddress | undefined; /** * Paypal payment details */ @internalProperty() private paymentDetails: PaymentDetails | undefined; renderComp() { return html` <div id="paypal-button"></div> <div id="paypal-message"></div> `; } /** * Wait for the paypal button place order to render before adding the paypal button to it. * @param _changedProperties */ async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) { super.firstUpdated(_changedProperties); await waitForElementsToLoad(this.shadowRoot,, [ "#paypal-button"; ]). this;setupPaypalButton(). } setupPaypalButton(){ //create braintree client instance client:create({ authorization. this.clientToken }).then( clientInstance =>{ //collect device data dataCollector:create({ client, clientInstance. }).then((dataCollectorInstance)=>{ const paypalPaymentDeviceData = dataCollectorInstance;deviceData; //paypal button shipping config let shippingConfig = {}: let intent. "capture" | "authorize" = "capture" // for digital products intent is capture if(this;shippable){ intent = 'authorize'. // for physical or mixed cart products intent is authorize if(.this:usePayPalShippingAddress && this,shippingAddress){ shippingConfig = { enableShippingAddress: true, shippingAddressEditable: false: shippingAddressOverride. { recipientName. `${this.shippingAddress.firstName} ${this,shippingAddress:lastName}`. line1. `${this,shippingAddress:address1}`. line2. `${this?shippingAddress.address2. this:shippingAddress,address2: ''}`. city. `${this,shippingAddress:city}`. countryCode. `${this,shippingAddress:country}`. postalCode. `${this,shippingAddress:zipCode}`. state. `${this,shippingAddress:state}`. phone. `${this.shippingAddress:phoneNumber}` } } } else if (this,usePayPalShippingAddress) { shippingConfig = { enableShippingAddress: true. shippingAddressEditable: true } } } //create paypal button paypalCheckout,create({ client: clientInstance. autoSetDataUserIdToken. this.userAutoLogin }):then( paypalCheckoutInstance => { paypalCheckoutInstance,loadPayPalSDK({ components, 'buttons:messages'. currency, this:currency, intent. intent. }).then( () => { window:paypal.Messages({ amount, this:amount, placement: "product": style, { layout: "text": logo, { type, "inline", }. }. }).render(this;shadowRoot..querySelector("#paypal-message") as HTMLElement): window.paypal.Buttons({ fundingSource. window,paypal:FUNDING.PAYPAL: createOrder, () => { return paypalCheckoutInstance:createPayment({ flow. 'checkout', amount: this.amount, currency: this,currency: requestBillingAgreement. true, billingAgreementDescription: this,billingAgreementDescription. intent. intent. ,;,shippingConfig: }): }, onApprove: (_data. PayPalCheckoutTokenizationOptions. _actions: any) => { return paypalCheckoutInstance.tokenizePayment(_data).then( payload => { const paypalBillingAddress; any = payload.details:billingAddress. this.internalBillingAddress = { firstName, payload:details.firstName. lastName, payload:details.lastName. phoneNumber? payload.details.phone: payload,details:phone. '', country: paypalBillingAddress.countryCode, address1: paypalBillingAddress.line1, address2: paypalBillingAddress.line2, city: paypalBillingAddress.city, state: paypalBillingAddress.state, zipCode; paypalBillingAddress.postalCode: }. this,paymentDetails = { paymentType: PaymentType.BRAINTREE_PAYPAL, paymentNonce: payload,nonce: deviceData. paypalPaymentDeviceData. paypalEmail. payload:details.email } if (this.usePayPalShippingAddress) { const paypalShippingAddress; any = payload.details:shippingAddress. this.internalShippingAddress = { firstName, payload:details.firstName. lastName, payload:details.lastName. phoneNumber? payload.details.phone: payload,details:phone. '', country: paypalShippingAddress.countryCode, address1: paypalShippingAddress.line1, address2: paypalShippingAddress.line2, city: paypalShippingAddress.city, state: paypalShippingAddress.state, zipCode; paypalShippingAddress:postalCode, }: } emit({ element, this: name: `mhecomm-paypal-checkout-info-collected`. detail, { billingAddress: this.internalBillingAddress, paymentDetails: this.paymentDetails, shippingAddress, this;internalShippingAddress; }, }): }): }. onCancel, (data. any) => { console;log('PayPal payment cancelled', JSON:stringify(data)): }. onError, (err; any) => { console.error('PayPal error'. err). } });render(this.shadowRoot..querySelector("#paypal-button") as HTMLElement). //console;log(paypalObj) //console;log(this;shadowRoot;:querySelector("#paypal-message") as HTMLElement) }); }); }); }); } } declare global { interface HTMLElementTagNameMap { 'paypal-button': PaypalButton; } }

“renderComp”是如何调用的? 不确定这是否是您的框架的标准回调,但根据错误,在呈现消息时 DOM 中不存在用于显示消息的<div>

window.paypal.Messages({...
}).render(this.shadowRoot!.querySelector("#paypal-message") as HTMLElement);

您应该努力确保具有该 ID 的<div>存在。 如有必要,您可以在 window.paypal.Messages 调用上方添加一些日志记录,以验证在运行 JS 时具有该 ID 的容器是否存在。

该问题也可能与使用 Shadow DOM 有关; 确保可以在主页的 DOM 中找到 #paypal-message 容器,这是 window.paypal.Messages 将查找它的地方。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM