How to include Paypal Messages in web components? - paypal

Hi Stackoverflow community,
I need help in loading Paypal messages in web components.
After loading the paypal SDK, I am trying to include the Paypal pay later messages with the code below.
window.paypal.Messages({
amount: this.amount,
placement: "product",
style: {
layout: "text",
logo: {
type: "inline",
},
},
}).render(this.shadowRoot!.querySelector("#paypal-message") as HTMLElement);
I am getting the following error in the browser console.
paypal_messages_not_in_document
description: "Container must be in the document."
timestamp: "1651659388515"
I am able to load the paypal buttons with the same logic.
window.paypal.Buttons({ ....... }).render(this.shadowRoot!.querySelector("#paypal-button") as HTMLElement);
Below is the web component in lit element framework.
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;
}
}

How is 'renderComp' called? Not sure if that's a standard callback for your framework, but based on the error it would appear the that the <div> for displaying the messages does not exist in the DOM at the time the messages are being rendered:
window.paypal.Messages({...
}).render(this.shadowRoot!.querySelector("#paypal-message") as HTMLElement);
You should work to ensure the <div> with that id exists. If necessary, you can add some logging above the window.paypal.Messages invocation to verify the container with that id exists at the moment that JS is being run.
Also the problem could be related to the use of a Shadow DOM; ensure that the #paypal-message container can be found in the main page's DOM which is where window.paypal.Messages will look for it.

Related

ConnectorError Prisma with MongoDB

I am developing an API with Nestjs and MongoDB. Well sometimes I have this problem. It doesn't always happen and that's what I have to solve because this error rarely happens.
This is the error:
{
"status": "error",
"message": "\nInvalid this.prisma.people.findMany() invocation in\nC:\ima\empresas\datec\api-official\src\modules\Events\services\utils.service.ts:57: 28\n\n 54 }),\n 55 \n 56 // Get attendees by id\n→ 57 this.prisma.people.findMany(\nError in batch request 3: Error occurred during query execution:\nConnectorError(ConnectorError { user_facing_error: None, kind: RawDatabaseError { code: "unknown", message: "An existing connection was forced to be terminated by the remote host. (os error 10054)" } })"
}
I really can't find much information to solve this error. I have followed the steps in the documentation on Nestjs when using prisma with nestjs. I need help to solve this error, since it is essential to find a solution as soon as possible. Thanks so much for read this question
UPDATE
The Prisma service
// Librarys
import { Injectable } from '#nestjs/common'
import { PrismaClient } from '#prisma/client'
// Interfaces
import { INestApplication, OnModuleInit, OnModuleDestroy } from '#nestjs/common'
#Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
async onModuleInit() {
await this.$connect()
}
async onModuleDestroy() {
await this.$disconnect()
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close()
})
}
}
File that starts the application
//Libraries
import { NestFactory } from '#nestjs/core'
import { ValidationPipe } from '#nestjs/common'
import { SwaggerModule, DocumentBuilder } from '#nestjs/swagger'
import { useContainer } from 'class-validator'
// Modules
import { MainModule } from './main.module'
// config
import pk from '#root/package.json'
import { corstOptions } from '#config/cors'
import { PORT, APP_NAME, PUBLIC_URL } from '#config/env'
// Exceptions
import { HttpExceptionFilter } from '#utils/HttpExceptionFilter'
import { PrismaService } from '#root/src/services/prisma'
async function bootstrap() {
// Create application
const app = await NestFactory.create(MainModule)
// Enable cors
app.enableCors(corstOptions)
// Use global 'api' prefix, all calls will come after '/api/*'
app.setGlobalPrefix('api')
// Globally define custom response
app.useGlobalFilters(new HttpExceptionFilter())
// Enable prism on custom validations
useContainer(app.select(MainModule), { fallbackOnErrors: true })
// Get service from primsa and enable 'shutdowns'
const prismaService = app.get(PrismaService)
await prismaService.enableShutdownHooks(app)
// Use 'pipe' validation to validate the 'body' structure
app.useGlobalPipes(
newValidationPipe({
whitelist: true,
transform: true,
forbidUnknownValues: true,
forbidNonWhitelisted: true,
transformOptions: { enableImplicitConversion: true }
})
)
// Create API documentation
const config = new DocumentBuilder()
.addBearerAuth()
.setTitle(`API | ${APP_NAME}`)
.setContact(pk.author.name, pk.author.url, pk.author.email)
.setDescription(pk.description)
.setVersion(pk.version)
.build()
const document = SwaggerModule.createDocument(app, config)
SwaggerModule.setup('/', app, document)
// Listen to the application on the PORT defined in the environment variables
await app.listen(PORT || 0, () => {
// eslint-disable-next-line no-console
console.log(
'\x1b[33m%s\x1b[0m',
`[INFO] The server has been started at '${PUBLIC_URL}'`
)
})
}
bootstrap() // Run application
utils.service of Event module
// Librarys
import { Prisma } from '#prisma/client'
import { Inject, Injectable } from '#nestjs/common'
// Services
import { PrismaService } from '#services/prisma'
// DTO
import { EventBodyDTO } from '#modules/Events/events.dto'
// Arguments
import { EventsArgs } from '#modules/Events/events.args'
#Injectable()
export class UtilsService {
#Inject(PrismaService)
private readonly prisma: PrismaService
private readonly selects = {
'id.title': { id: true, title: true },
'id.fullname': { id: true, fullname: true },
'id.title.attributes': { id: true, title: true, attributes: true },
'id.code.description.attributes': {
id: true,
code: true,
description: true,
attributes: true
}
}
/**
* Get reminders, types of activities, case, client and attendees of an event
* #param {EventBodyDTO} payload Event data
*/
async getEventFields(payload: EventBodyDTO) {
const [activityType, eventCase, client, assistants, reminders] =
await Promise.all([
// Get an activity type by id
this.prisma.parameters.findUnique({
select: this.selects['id.title'],
where: { id: payload.activityType }
}),
// Get a case by id
this.prisma.expedients.findUnique({
where: { id: payload.case },
select: this.selects['id.code.description.attributes']
}),
// Get a person by id
this.prisma.people.findFirst({
select: this.selects['id.fullname'],
where: { isClient: true, id: payload.client }
}),
// Get attendees by id
this.prisma.people.findMany({
select: this.selects['id.fullname'],
where: {
isEmployee: true,
id: { in: payload.assistants }
}
}),
// Get reminders by id
this.prisma.parameters.findMany({
select: this.selects['id.title.attributes'],
where: {
id: { in: payload.reminders }
}
})
])
return {
reminders: reminders,
assistants: assistants,
client: client === null ? {} : client,
case: eventCase === null ? {} : eventCase,
activityType: activityType === null ? {} : activityType
}
/**
* Create filters to filter by customer or event attendees
* #param {EventsArgs} args Arguments to filter
* #returns {Promise<Prisma.EventsFindManyArgs['where']>} Returns an object with filters
*/
async createEventFilters(
args: EventsArgs
): Promise<Prisma.EventsFindManyArgs['where']> {
const filters: Prism.EventsFindManyArgs['where'] = {
userId: args.user
}
// Filter by customer
if (typeof args.client === 'string') {
const clients = await this.prisma.people.findMany({
where: {
isClient: true,
fullname: {
mode: 'insensitive',
contains: args.client
}
},
select: {
id: true,
fullname: true
}
})
filters.OR = []
for (const client of clients) {
filters.OR.push({
client: { equals: client }
})
}
}
// Filter by attendees
if (Array.isArray(args.assistants)) {
const assistants = await this.prisma.people.findMany({
where: {
isEmployee: true,
id: {
in: args.assistants
}
},
select: {
id: true,
fullname: true
}
})
if (!Array.isArray(filters.OR)) {
filters.OR = []
}
filters.OR.push({
assistants: { hasSome: assistants }
})
}
return filters
}
}

Paypal v2 express checkout integration in .NET

I am currently checking integration process of v2 express checkout and lot of documentation making confusion.
So far i am using checkout.js from paypal domain and using below code for order creation in client side as below
paypal.Button.render({
env: 'sandbox', // Or 'sandbox',
commit: true, // Show a 'Pay Now' button
style: {
color: 'gold',
shape: 'rect',
label: 'paypal',
size: 'medium',
tagline: false,
width: 150
},
payment: function (data, actions) {
/* Set up a url on your server to create the payment */
var CREATE_URL = '/paypal/createpaypalPayment';
/* Make a call to your server to set up the payment */
return paypal.request.post(CREATE_URL)
.then(function ({ result }) {
var test = JSON.parse(result);
return test.id;
});
},
onAuthorize: function (data, actions) {
/* Set up a url on your server to execute the payment */
var EXECUTE_URL = '/paypal/executepaypalPayment';
/* Set up the data you need to pass to your server */
var data = {
paymentID: data.paymentID,
payerID: data.payerID
};
return paypal.request.post(EXECUTE_URL, data)
.then(function (res) {
return null;
});
}
}, '#paypalcheckout');
});
Please find the server side code for create order.
[HttpPost]
public JsonResult createpaypalpayment()
{
var client = new WebClient();
string credentials = clientid + secretid;
client.Headers.Add("authorization", "Basic " + credentials);
client.Headers.Add("content-type", "application/json");
client.Headers.Add("accept-language", "en_US");
client.Headers.Add("accept", "application/json");
var body = #"{
""intent"": ""AUTHORIZE"",
""purchase_units"": [{
""amount"": {
""currency_code"": ""USD"",
""value"": ""100.00""
}
}]
}";
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var response = client.UploadString("https://api.sandbox.paypal.com/v2/checkout/orders/", "POST", body);
return Json(new { result = response }, JsonRequestBehavior.AllowGet);
}
}
}
I referred below documentation
https://developer.paypal.com/docs/archive/orders-integration-guide/#integration-steps
I am struct with how to show order details after order creation and get approval from customer end ?
Can anyone provide suggestion for this.
Thanks in advance
checkout.js is deprecated and that documentation is archived, so my suggestion is that you follow the current documentation on developer.paypal.com
In your other question, links were provided to that documentation.

Cannot read property forEach of undefined

The title of this question is just the error I am currently receiving, but what I really need help with is understanding observables and API calls. For whatever reason, I just haven't been able to get a good grasp of this concept, and I am hoping that someone might have an explanation that will finally click.
I am trying to create a new Angular service that retrieves JSON from an API. I then need to map the response to a model. Due to weird naming conventions, job descriptions and job requirements are used interchangeably here. Here is my service class.
import { CommunicationService } from './communication.service';
import { AiDescription } from '../models/ai-description.model';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class AiDescriptionService {
requirements: Observable<AiDescription[]>;
private aiDescriptionUrl: string = '/api/core/company/jobdescriptions';
private dataStore: {
requirements: AiDescription[]
};
private _requirements: BehaviorSubject<AiDescription[]>;
private emptyRequestParams = {
"company_id": "",
"carotene_id": "",
"carotene_version": "",
"city": "",
"state": "",
"country": ""
};
readonly caroteneVersion: string = "caroteneV3";
constructor(
private communicationService: CommunicationService
) {
this.dataStore = { requirements: [] };
this._requirements = new BehaviorSubject<AiDescription[]>([]);
this.requirements = this._requirements.asObservable();
}
LoadRequirements(params: Object) {
this.communicationService.postData(this.aiDescriptionUrl, params)
.subscribe(res => {
let jobDescriptions = [];
jobDescriptions = res.jobdescriptions;
jobDescriptions.forEach((desc: { id: string; description: string; }) => {
let aiDescription = new AiDescription();
aiDescription.id = desc.id;
aiDescription.description = desc.description;
});
this.dataStore.requirements = res;
this._requirements.next(Object.assign({}, this.dataStore).requirements);
});
}
CreateRequest(
companyID : string,
caroteneID : string,
city: string,
state: string,
country: string
): Object {
let newRequestParams = this.emptyRequestParams;
newRequestParams.company_id = companyID;
newRequestParams.carotene_id = caroteneID;
newRequestParams.carotene_version = this.caroteneVersion;
newRequestParams.city = city;
newRequestParams.state = state;
newRequestParams.country = country;
this.LoadRequirements(newRequestParams);
return this.dataStore;
}
}
The postData() function being called by this.communicationService is here:
postData(url: string, jobInformation: any): Observable<any> {
const start = new Date();
const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
const body = JSON.stringify(jobInformation);
const options = { headers };
return this.http.post(url, body, options)
.catch(err => Observable.throw(err))
.do(() => {
this.analyticsLoggingService.TrackTiming('JobPostingService', 'PostSuccess', new Date().getTime() - start.getTime());
}, () => {
this.analyticsLoggingService.TrackError('JobPostingService', 'PostFailure');
});
}
I didn't write the postData function, and I would not be able to modify it. When running a unit test, I am getting this error: "TypeError: Cannot read property 'forEach' of undefined".
But more than simply fixing the error, I am really trying to get a better understanding of using Observables, which is something I haven't been able to get a good understanding of from other sources.
In your example, I recommend replacing any and Object with explicitly defined models.
Here's an example for Angular 8 for Subscription, Promise, and Observable API calls. You can get more info here: https://angular.io/tutorial/toh-pt6.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs';
import { User } from './user.model';
#Injectable({ providedIn: 'root' })
export class UserService {
users: User[];
authHeaders = new HttpHeaders()
.set('Content-Type', 'application/json');
constructor(
private readonly http: HttpClient
) { }
getUsers() {
this.http.get(`https://myApi/users`, { headers: this.authHeaders })
.subscribe(
(data: User[]) => {
this.users = data;
}, (error: HttpErrorResponse) => { /* handle error */ });
}
async getUserPromise(userID: number): Promise<User> {
const url = `https://myApi/users/${userID}`;
return this.http.get<User>(url, { headers: this.authHeaders })
.toPromise();
}
getUserObservable(userID: number): Observable<User> {
const url = `https://myApi/users/${userID}`;
return this.http.get<User>(url, { headers: this.authHeaders });
}
}
I like to keep my class models in separate files. This example would have user.model.ts with content like:
export class User {
constructor(
public id: number,
public username: string,
public displayName: string,
public email: string
) { }
}
I've not included authentication headers or error handling for brevity; however, you might want to add those as needed.

Braintree PCI compliance issue

I have been continuously getting an email by brain tree on PCI Compliance regards and need confirmation on following two things which have been asked.
What is the Braintree payment integration method on our website? (Hint: It’s one of these)
Drop in UI or hosted field
Braintree SDK Custom integration
Following is the javascript code we've used . I went through the Braintree site on this regards but couldn't conclude upon this.
Additional Notes : We've made some changes on braintree vendor file.
var subscribed_user = "1";
$('#cc').on('click', function (e) {
$('#cc-info').show().attr('aria-hidden', true).css('visibility', 'visible');
});
var button = document.querySelector('#paypal-button');
var button1 = document.querySelector('#card-button');
var form = document.querySelector('#checkout-form');
var authorization = 'AuthHeaderxxxxxxxx=';
// Create a client.
braintree.client.create({
authorization: authorization
}, function (clientErr, clientInstance) {
// Stop if there was a problem creating the client.
// This could happen if there is a network error or if the authorization
// is invalid.
if (clientErr) {
console.error('Error creating client:', clientErr);
return;
}
/* Braintree - Hosted Fields component */
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {
'font-size': '10pt',
'color': '#e3e3e3 !important; ',
'border-radius': '0px'
},
'input.invalid': {
'color': 'red'
},
'input.valid': {
'color': 'green'
}
},
fields: {
number: {
selector: '#card-number',
placeholder: '4111 1111 1111 1111',
},
cvv: {
selector: '#cvv',
placeholder: '123'
},
expirationDate: {
selector: '#expiration-date',
placeholder: '10/2019'
}
}
}, function (hostedFieldsErr, hostedFieldsInstance) {
if (hostedFieldsErr) { /*Handle error in Hosted Fields creation*/
return;
}
button1.addEventListener('click', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (tokenizeErr, payload) {
if (tokenizeErr) { /* Handle error in Hosted Fields tokenization*/
document.getElementById('invalid-field-error').style.display = 'inline';
return;
}
/* Put `payload.nonce` into the `payment-method-nonce` input, and thensubmit the form. Alternatively, you could send the nonce to your serverwith AJAX.*/
/* document.querySelector('form#bt-hsf-checkout-form input[name="payment_method_nonce"]').value = payload.nonce;*/
document.querySelector('input[name="payment-method-nonce"]').value = payload.nonce;
form.submit();
button1.setAttribute('disabled', 'disabled');
});
}, false);
});
// Create a PayPal component.
braintree.paypal.create({
client: clientInstance,
paypal: true
}, function (paypalErr, paypalInstance) {
// Stop if there was a problem creating PayPal.
// This could happen if there was a network error or if it's incorrectly
// configured.
if (paypalErr) {
console.error('Error creating PayPal:', paypalErr);
return;
}
if ($('select#paypal-subs-selector option:selected').val() == '') {
button.setAttribute('disabled', 'disabled');
}
$('select#paypal-subs-selector').change(function () {
if ($('select#paypal-subs-selector option:selected').val() == '') {
button.setAttribute('disabled', 'disabled');
} else {
// Enable the button.
button.removeAttribute('disabled');
}
});
button.addEventListener('click', function () {
if(subscribed_user) {
// Popup Error for changing subscription.
swal({
html: true,
title: "",
text: "You are cancelling in the middle of subscription.<br/>If you do so you will not be refunded remaining days of your subscription.",
confirmButtonColor: '#605ca8',
confirmButtonText: 'Yes',
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Proceed !",
closeOnConfirm: true
}, function (isConfirm) {
if (isConfirm) {
show_payment_methods(paypalInstance);
}
});
} else{
show_payment_methods(paypalInstance);
}
}, false);
});
});
Any help would be highly appreciated.
Your code says Braintree - Hosted Field component And you don’t use anything like this which I found by searching “Braintree api”. I think you’re safe to say you use hosted fields.

FormArray validator in Angular 2

I have 4 formBuilder in Angular 2
- Personal information
- Adress information
- Financy information
- Partners information
for Personal, Adress and Financy I have a ready validator.
On partners, I have 2 fields : 'Name' and '% of company'.
On this part of form, I have a ArrayForm to add more than 1 partner, code below:
this.form4 = this.formBuilder.group({
cadSocios: [{value: true, disabled: false}],
socios: this.formBuilder.array([
this.initSocios(),
])
});
initSocios() {
// initialize our address
return this.formBuilder.group({
nome: ['', Validators.required],
participacao: ['', [Validators.required,
Validators.pattern("[0-9]*")]]
}, {validator: PartValidator.valPart()}));
}
I have a custom validator to sum the percentage of the partners, that it needs to be 100%.(valPart()).
But, how can I access the values of array portentagem inside de function valPart()?
valPart() ->
import {FormGroup} from '#angular/forms';
export class PartValidator{
static valPart(){
return (group: FormGroup): {[key: string]: any} => {
//CODE HERE
return null;
}//return
}//valPart
};
I got it.
unless calling valPart() in initSocios(), I call it in this.form4:
this.form4 = this.formBuilder.group({
cadSocios: [{value: true, disabled: false}],
socios: this.formBuilder.array([
this.initAddress(),
])
}, {validator: PartValidator.valPart()});
so, I get access the value in valPart():
import {FormGroup} from '#angular/forms';
export class PartValidator{
static valPart(){
return (group: FormGroup): {[key: string]: any} => {
let parts = [];
let soma = 0;
if(group.get('cadSocios').value == true){
parts.push(group.get('socios').value);
parts[0].forEach((data) => {
soma += parseInt(data.participacao);
});
if(soma !== 100){
return {
valPart: true
}
}//if
}
return null;
}//return
}//valPart
};