paypal configs

Co-authored-by: Pete Matsyburka <pete@docuseal.com>
master^2
Alex Turchyn 6 days ago committed by Pete Matsyburka
parent 972f38242e
commit b8c29324b8

@ -37,7 +37,7 @@ class AccountConfigsController < ApplicationController
end
def destroy
raise InvalidKey unless allowed_keys.include?(@account_config.key)
raise InvalidKey unless allowed_destroy_keys.include?(@account_config.key)
@account_config.destroy!
@ -50,6 +50,10 @@ class AccountConfigsController < ApplicationController
ALLOWED_KEYS
end
def allowed_destroy_keys
ALLOWED_KEYS
end
def load_account_config
raise InvalidKey unless allowed_keys.include?(account_config_params[:key])

@ -18,6 +18,6 @@ class TemplatesFormPreviewController < ApplicationController
@attachments_index = ActiveStorage::Attachment.where(record: @submitter.submission.submitters, name: :attachments)
.preload(:blob).index_by(&:uuid)
@form_configs = Submitters::FormConfigs.call(@submitter)
@form_configs = Submitters::FormConfigs.call(@submitter, SubmitFormController::CONFIG_KEYS)
end
end

@ -181,7 +181,10 @@ safeRegisterElement('template-builder', class extends HTMLElement {
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content,
withCustomFields: true,
withPayment: this.dataset.withPayment === 'true',
isPaymentConnected: this.dataset.isPaymentConnected === 'true',
isStripeConnected: this.dataset.isPaymentConnected === 'true' || this.dataset.isStripeConnected === 'true',
withStripe: this.dataset.withStripe !== 'false',
withPaypal: this.dataset.withPaypal === 'true',
isPaypalConnected: this.dataset.isPaypalConnected === 'true',
withFormula: this.dataset.withFormula === 'true',
withSendButton: this.dataset.withSendButton !== 'false',
withSignYourselfButton: this.dataset.withSignYourselfButton !== 'false',

@ -35,6 +35,7 @@ safeRegisterElement('submission-form', class extends HTMLElement {
scrollPadding: this.dataset.scrollPadding || '-80px',
signatureText: this.dataset.signatureText,
language: this.dataset.language,
paymentProvider: this.dataset.paymentProvider,
dryRun: this.dataset.dryRun === 'true',
expand: ['true', 'false'].includes(this.dataset.expand) ? this.dataset.expand === 'true' : null,
withSignatureId: this.dataset.withSignatureId === 'true',

@ -560,6 +560,7 @@
:fields="formulaFields"
:values="values"
:readonly-values="readonlyFieldValues"
:provider="paymentProvider"
@attached="attachments.push($event)"
@focus="scrollIntoField(currentField)"
@submit="!isSubmitting && submitStep()"
@ -1000,6 +1001,11 @@ export default {
required: false,
default: ''
},
paymentProvider: {
type: String,
required: false,
default: ''
},
values: {
type: Object,
required: false,

@ -107,6 +107,7 @@ const en = {
email_has_been_sent: 'Email has been sent',
processing: 'Processing',
pay_with_stripe: 'Pay with Stripe',
pay_with_paypal: 'Pay with PayPal',
reupload: 'Reupload',
upload: 'Upload',
files: 'Files',
@ -225,6 +226,7 @@ const es = {
email_has_been_sent: 'El correo electrónico ha sido enviado',
processing: 'Procesando',
pay_with_stripe: 'Pagar con Stripe',
pay_with_paypal: 'Pagar con PayPal',
reupload: 'Volver a subir',
upload: 'Subir',
files: 'Archivos',
@ -343,6 +345,7 @@ const it = {
email_has_been_sent: "L'email è stata inviata",
processing: 'Elaborazione',
pay_with_stripe: 'Paga con Stripe',
pay_with_paypal: 'Paga con PayPal',
reupload: 'Ricarica',
upload: 'Carica',
files: 'File',
@ -461,6 +464,7 @@ const de = {
email_has_been_sent: 'E-Mail wurde gesendet',
processing: 'Verarbeitung',
pay_with_stripe: 'Mit Stripe bezahlen',
pay_with_paypal: 'Mit PayPal bezahlen',
reupload: 'Erneut hochladen',
upload: 'Hochladen',
files: 'Dateien',
@ -579,6 +583,7 @@ const fr = {
email_has_been_sent: "L'e-mail a été envoyé",
processing: 'Traitement en cours',
pay_with_stripe: 'Payer avec Stripe',
pay_with_paypal: 'Payer avec PayPal',
reupload: 'Retéléverser',
upload: 'Téléverser',
files: 'Fichiers',
@ -697,6 +702,7 @@ const pl = {
email_has_been_sent: 'E-mail został wysłany',
processing: 'Przetwarzanie',
pay_with_stripe: 'Zapłać za pomocą Stripe',
pay_with_paypal: 'Zapłać za pomocą PayPal',
reupload: 'Ponowne przesłanie',
upload: 'Przesyłanie',
files: 'Pliki',
@ -815,6 +821,7 @@ const uk = {
email_has_been_sent: 'Електронний лист був відправлений',
processing: 'Обробка',
pay_with_stripe: 'Сплатити за допомогою Stripe',
pay_with_paypal: 'Сплатити за допомогою PayPal',
reupload: 'Перезавантажити',
upload: 'Завантажити',
files: 'Файли',
@ -933,6 +940,7 @@ const cs = {
email_has_been_sent: 'E-mail byl odeslán',
processing: 'Zpracování',
pay_with_stripe: 'Zaplatit přes Stripe',
pay_with_paypal: 'Zaplatit přes PayPal',
reupload: 'Znovu nahrát',
upload: 'Nahrát',
files: 'Soubory',
@ -1051,6 +1059,7 @@ const pt = {
email_has_been_sent: 'Email enviado',
processing: 'Processamento',
pay_with_stripe: 'Pagar com Stripe',
pay_with_paypal: 'Pagar com PayPal',
reupload: 'Recarregar',
upload: 'Carregar',
files: 'Arquivos',
@ -1169,6 +1178,7 @@ const he = {
email_has_been_sent: 'האימייל נשלח',
processing: 'מעבד',
pay_with_stripe: 'שלם עם סטרייפ',
pay_with_paypal: 'שלם עם פייפאל',
reupload: 'העלה שוב',
upload: 'העלאה',
files: 'קבצים',
@ -1287,6 +1297,7 @@ const nl = {
email_has_been_sent: 'E-mail is verzonden',
processing: 'Verwerken',
pay_with_stripe: 'Betalen met Stripe',
pay_with_paypal: 'Betalen met PayPal',
reupload: 'Opnieuw uploaden',
upload: 'Uploaden',
files: 'Bestanden',
@ -1405,6 +1416,7 @@ const ar = {
email_has_been_sent: 'تم إرسال البريد الإلكتروني',
processing: 'جارٍ المعالجة',
pay_with_stripe: 'الدفع بواسطة Stripe',
pay_with_paypal: 'الدفع بواسطة PayPal',
reupload: 'إعادة التحميل',
upload: 'تحميل',
files: 'الملفات',
@ -1523,6 +1535,7 @@ const ko = {
email_has_been_sent: '이메일이 전송되었습니다',
processing: '처리 중',
pay_with_stripe: '스트라이프로 결제',
pay_with_paypal: 'PayPal로 결제',
reupload: '다시 업로드',
upload: '업로드',
files: '파일',
@ -1641,6 +1654,7 @@ const ja = {
email_has_been_sent: 'メールが送信されました',
processing: '処理中',
pay_with_stripe: 'Stripeで支払う',
pay_with_paypal: 'PayPalで支払う',
reupload: '再アップロード',
upload: 'アップロード',
files: 'ファイル',

@ -1,6 +1,6 @@
<template>
<label
v-if="!modelValue && !sessionId"
v-if="!modelValue && !isProcessing"
class="label text-xl sm:text-2xl py-0 mb-2 sm:mb-3.5 field-name-label"
>
<MarkdownContent
@ -25,14 +25,14 @@
class="hidden"
>
<div
v-if="modelValue && !sessionId"
v-if="modelValue && !isProcessing"
class=" text-2xl mb-2"
>
{{ t('already_paid') }}
</div>
<div v-else>
<button
v-if="sessionId"
v-if="isProcessing"
type="button"
disabled
class="base-button w-full modal-save-button"
@ -49,8 +49,8 @@
v-else
:id="field.uuid"
type="button"
class="btn bg-[#7B73FF] text-white hover:bg-[#0A2540] text-lg w-full"
:class="{ disabled: isCreatingCheckout }"
class="btn text-white text-lg w-full"
:class="[isPaypal ? 'bg-[#003087] hover:bg-[#012169]' : 'bg-[#7B73FF] hover:bg-[#0A2540]', { disabled: isCreatingCheckout }]"
:disabled="isCreatingCheckout"
@click.prevent="postCheckout"
>
@ -59,12 +59,16 @@
width="22"
class="animate-spin"
/>
<IconBrandPaypal
v-else-if="isPaypal"
width="22"
/>
<IconBrandStripe
v-else
width="22"
/>
<span>
{{ t('pay_with_stripe') }}
{{ isPaypal ? t('pay_with_paypal') : t('pay_with_stripe') }}
</span>
</button>
</div>
@ -72,13 +76,14 @@
</template>
<script>
import { IconBrandStripe, IconInnerShadowTop, IconLoader } from '@tabler/icons-vue'
import { IconBrandStripe, IconBrandPaypal, IconInnerShadowTop, IconLoader } from '@tabler/icons-vue'
import MarkdownContent from './markdown_content'
export default {
name: 'PaymentStep',
components: {
IconBrandStripe,
IconBrandPaypal,
MarkdownContent,
IconInnerShadowTop,
IconLoader
@ -111,12 +116,18 @@ export default {
submitterSlug: {
type: String,
required: true
},
provider: {
type: String,
required: false,
default: ''
}
},
emits: ['focus', 'submit', 'update:model-value', 'attached'],
data () {
return {
isCreatingCheckout: false,
isProcessing: false,
isMathLoaded: false
}
},
@ -131,8 +142,14 @@ export default {
queryParams () {
return new URLSearchParams(window.location.search)
},
isPaypal () {
return this.provider === 'paypal'
},
paymentEndpoint () {
return this.isPaypal ? '/api/paypal_payments' : '/api/stripe_payments'
},
sessionId () {
return this.queryParams.get('stripe_session_id')
return this.queryParams.get('stripe_session_id') || this.queryParams.get('paypal_order_id') || (this.isPaypal && this.queryParams.get('token'))
},
defaultName () {
if (this.field.preferences?.price_id || this.field.preferences?.payment_link_id) {
@ -159,6 +176,8 @@ export default {
},
async mounted () {
if (this.sessionId) {
this.isProcessing = true
this.$emit('submit')
}
@ -175,6 +194,21 @@ export default {
}
},
methods: {
normalizedPaymentUrl () {
const url = new URL(window.location.href)
const keys = ['stripe_session_id', 'paypal_order_id', 'field_uuid']
if (this.isPaypal) {
keys.push('token', 'PayerID')
}
keys.forEach((key) => url.searchParams.delete(key))
return url.toString()
},
normalizedPaymentParams () {
window.history.replaceState({}, document.title, this.normalizedPaymentUrl())
},
calculateFormula () {
const transformedFormula = this.normalizeFormula(this.field.preferences.formula).replace(/{{(.*?)}}/g, (match, uuid) => {
return this.readonlyValues[uuid] || this.values[uuid] || 0.0
@ -195,7 +229,7 @@ export default {
},
async submit () {
if (this.sessionId) {
return fetch(this.baseUrl + '/api/stripe_payments/' + this.sessionId, {
return fetch(this.baseUrl + this.paymentEndpoint + '/' + this.sessionId, {
method: 'PUT',
body: JSON.stringify({
submitter_slug: this.submitterSlug
@ -203,16 +237,22 @@ export default {
headers: { 'Content-Type': 'application/json' }
}).then(async (resp) => {
if (resp.status === 422 || resp.status === 500) {
this.isProcessing = false
const data = await resp.json()
alert(data.error || 'Unexpected error')
if (data.error) {
alert(data.error)
}
return Promise.reject(new Error(data.error))
}
const attachment = await resp.json()
window.history.replaceState({}, document.title, window.location.pathname)
this.isProcessing = false
this.normalizedPaymentParams()
this.$emit('update:model-value', attachment.uuid)
this.$emit('attached', attachment)
@ -226,13 +266,13 @@ export default {
postCheckout ({ checkStatus } = {}) {
this.isCreatingCheckout = true
fetch(this.baseUrl + '/api/stripe_payments', {
fetch(this.baseUrl + this.paymentEndpoint, {
method: 'POST',
body: JSON.stringify({
submitter_slug: this.submitterSlug,
field_uuid: this.field.uuid,
check_status: checkStatus,
referer: document.location.href
referer: this.normalizedPaymentUrl()
}),
headers: { 'Content-Type': 'application/json' }
}).then(async (resp) => {

@ -779,7 +779,10 @@ export default {
withVerification: this.withVerification,
withKba: this.withKba,
withPayment: this.withPayment,
isPaymentConnected: this.isPaymentConnected,
isStripeConnected: this.isStripeConnected,
withStripe: this.withStripe,
withPaypal: this.withPaypal,
isPaypalConnected: this.isPaypalConnected,
withFormula: this.withFormula,
withConditions: this.withConditions,
withCustomFields: this.withCustomFields,
@ -1049,7 +1052,22 @@ export default {
required: false,
default: false
},
isPaymentConnected: {
isStripeConnected: {
type: Boolean,
required: false,
default: false
},
withStripe: {
type: Boolean,
required: false,
default: true
},
withPaypal: {
type: Boolean,
required: false,
default: false
},
isPaypalConnected: {
type: Boolean,
required: false,
default: false
@ -1363,6 +1381,10 @@ export default {
if (document.location.search?.includes('stripe_connect_success')) {
document.querySelector('form[action="/auth/stripe_connect"]')?.closest('.dropdown')?.querySelector('label')?.focus()
}
if (document.location.search?.includes('paypal_connect_success')) {
document.querySelector('a[href^="/auth/paypal_connect"]')?.closest('.dropdown')?.querySelector('label')?.focus()
}
})
this.template.schema.forEach((item) => {

@ -494,6 +494,7 @@ import FieldType from './field_type.vue'
import FieldSettings from './field_settings.vue'
import ContextSubmenu from './field_context_submenu.vue'
import ContextModal from './field_context_modal.vue'
import { stripeConnectedRef } from './payment_settings'
export default {
name: 'FieldContextMenu',
@ -716,12 +717,18 @@ export default {
currentCurrency () {
return this.field.preferences?.currency || 'USD'
},
isStripeConnected: () => stripeConnectedRef.value,
priceTypeOptions () {
return [
const options = [
{ value: 'one_off', label: this.t('fixed') },
{ value: 'formula', label: this.t('formula') },
{ value: 'payment_link', label: this.t('payment_link') }
{ value: 'formula', label: this.t('formula') }
]
if (this.isStripeConnected) {
options.push({ value: 'payment_link', label: this.t('payment_link') })
}
return options
},
currentPriceType () {
if (this.field.preferences?.formula) {

@ -1,7 +1,7 @@
<template>
<span
class="dropdown dropdown-end field-settings-dropdown"
:class="{ 'dropdown-open': withForceOpen && ((!field.preferences?.price && !field.preferences?.formula && !field.preferences?.price_id && !field.preferences?.payment_link_id) || !isConnected) && !isLoading }"
:class="{ 'dropdown-open': withForceOpen && !field.preferences?.price && !field.preferences?.formula && !field.preferences?.price_id && !field.preferences?.payment_link_id && !isLoading }"
>
<label
tabindex="0"
@ -21,7 +21,7 @@
@click="closeDropdown"
>
<div
v-if="!('price_id' in field.preferences) && !('payment_link_id' in field.preferences)"
v-if="isPaypal || (!('price_id' in field.preferences) && !('payment_link_id' in field.preferences))"
class="field-settings-currency py-1.5 px-1 relative"
@click.stop
>
@ -52,14 +52,14 @@
@click.stop
>
<input
v-if="'payment_link_id' in field.preferences"
v-if="isStripe && 'payment_link_id' in field.preferences"
v-model="field.preferences.payment_link_id"
placeholder="plink_XXXXX"
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0"
@blur="save"
>
<input
v-else-if="'price_id' in field.preferences"
v-else-if="isStripe && 'price_id' in field.preferences"
v-model="field.preferences.price_id"
placeholder="Price ID: price_XXXXX"
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0"
@ -89,7 +89,10 @@
>
{{ 'payment_link_id' in field.preferences ? t('payment_link') : t('price') }}
</label>
<div class="flex items-center justify-center">
<div
v-if="isStripe && stripeConnected"
class="flex items-center justify-center"
>
<a
href="#"
class="hover:underline"
@ -120,21 +123,22 @@
</div>
</div>
<div
v-if="!isConnected || isOauthSuccess"
class="field-settings-stripe-connect py-1.5 px-1 relative"
v-if="!stripeConnected && !paypalConnected"
class="flex flex-col gap-1 py-1.5 px-1"
@click.stop
>
<div
v-if="isConnected && isOauthSuccess"
class="text-sm text-center"
<a
v-if="withPaypal"
:href="paypalConnectUrl"
target="_blank"
data-turbo="false"
class="btn bg-[#003087] hover:bg-[#012169] btn-sm text-white w-full"
>
<IconCircleCheck
class="inline text-green-600 w-4 h-4"
/>
Stripe Connected
</div>
<IconBrandPaypal class="w-4 h-4 inline" />
<span>Connect PayPal</span>
</a>
<form
v-if="!isConnected"
v-if="withStripe"
data-turbo="false"
action="/auth/stripe_connect"
accept-charset="UTF-8"
@ -170,33 +174,25 @@
:disabled="isLoading"
class="btn bg-[#7B73FF] hover:bg-[#0A2540] btn-sm text-white w-full"
>
<span
<IconInnerShadowTop
v-if="isLoading"
class="flex items-center space-x-1"
>
<IconInnerShadowTop
class="w-4 h-4 animate-spin inline"
/>
<span>
Connect Stripe
</span>
</span>
<span
class="w-4 h-4 animate-spin inline"
/>
<IconBrandStripe
v-else
class="flex items-center space-x-1"
>
<IconBrandStripe
class="w-4 h-4 inline"
/>
<span>
Connect Stripe
</span>
</span>
class="w-4 h-4 inline"
/>
<span>Connect Stripe</span>
</button>
</form>
</div>
<div
v-if="isStripe && !stripeConnected"
class="px-1 pb-1.5"
@click.stop
>
<a
v-if="!isConnected"
class="block link text-center mt-1"
class="block link text-center text-xs"
href="https://www.docuseal.com/blog/accept-payments-and-request-signatures-with-ease"
target="_blank"
data-turbo="false"
@ -272,24 +268,25 @@
</template>
<script>
import { IconMathFunction, IconSettings, IconCircleCheck, IconInfoCircle, IconBrandStripe, IconInnerShadowTop, IconRouteAltLeft, IconForms } from '@tabler/icons-vue'
import { IconMathFunction, IconSettings, IconInfoCircle, IconBrandStripe, IconBrandPaypal, IconInnerShadowTop, IconRouteAltLeft, IconForms } from '@tabler/icons-vue'
import { ref } from 'vue'
const isConnected = ref(false)
export const stripeConnectedRef = ref(false)
export const paypalConnectedRef = ref(false)
export default {
name: 'PaymentSettings',
components: {
IconSettings,
IconCircleCheck,
IconRouteAltLeft,
IconInfoCircle,
IconForms,
IconMathFunction,
IconInnerShadowTop,
IconBrandStripe
IconBrandStripe,
IconBrandPaypal
},
inject: ['backgroundColor', 'save', 'currencies', 't', 'isPaymentConnected'],
inject: ['backgroundColor', 'save', 'currencies', 't', 'isStripeConnected', 'isPaypalConnected', 'withStripe', 'withPaypal'],
props: {
field: {
type: Object,
@ -318,13 +315,27 @@ export default {
}
},
computed: {
isConnected: () => isConnected.value,
isOauthSuccess () {
return document.location.search?.includes('stripe_connect_success')
stripeConnected: () => stripeConnectedRef.value,
paypalConnected: () => paypalConnectedRef.value,
provider () {
if (this.paypalConnected && !this.stripeConnected) return 'paypal'
if (this.stripeConnected && !this.paypalConnected) return 'stripe'
if (this.withPaypal && !this.withStripe) return 'paypal'
return 'stripe'
},
isStripe () {
return this.provider === 'stripe'
},
isPaypal () {
return this.provider === 'paypal'
},
redirectUri () {
return document.location.origin + '/auth/stripe_connect/callback'
},
paypalConnectUrl () {
return `/auth/paypal_connect?redir=${encodeURIComponent(document.location.href)}`
},
defaultCurrencies () {
return ['USD', 'EUR', 'GBP', 'CAD', 'AUD']
},
@ -363,26 +374,53 @@ export default {
mounted () {
this.field.preferences.currency ||= this.defaultCurrency
isConnected.value ||= this.isPaymentConnected
stripeConnectedRef.value ||= this.isStripeConnected
paypalConnectedRef.value ||= this.isPaypalConnected
if (this.withStripe && !this.stripeConnected && !this.paypalConnected) {
this.checkStripeStatus()
}
if (!this.isConnected) {
this.checkStatus()
if (this.withPaypal && !this.paypalConnected && !this.stripeConnected) {
this.checkPaypalStatus()
window.addEventListener('focus', this.onWindowFocus)
}
},
beforeUnmount () {
window.removeEventListener('focus', this.onWindowFocus)
},
methods: {
checkStatus () {
onWindowFocus () {
if (this.withPaypal && !this.paypalConnected) {
this.checkPaypalStatus()
}
},
checkStripeStatus () {
this.isLoading = true
fetch('/api/stripe_connect').then(async (resp) => {
const { status } = await resp.json()
if (status === 'connected') {
isConnected.value = true
stripeConnectedRef.value = true
window.removeEventListener('focus', this.onWindowFocus)
}
}).finally(() => {
this.isLoading = false
})
},
checkPaypalStatus () {
fetch('/api/paypal_connect').then(async (resp) => {
const { status } = await resp.json()
if (status === 'connected') {
paypalConnectedRef.value = true
window.removeEventListener('focus', this.onWindowFocus)
}
})
},
closeDropdown () {
document.activeElement.blur()
}

@ -53,6 +53,25 @@ en: &en
require_all_recipients: Require all recipients
stripe_account_has_been_connected: Stripe account has been connected.
re_connect_stripe: Re-connect Stripe
paypal_integration: PayPal Integration
paypal_account_has_been_connected: PayPal account has been connected.
re_connect_paypal: Re-connect PayPal
disconnect: Disconnect
failed_to_connect_paypal: Failed to connect PayPal. Please try again.
paypal_connect_not_completed: PayPal connection was not completed.
payment_receipt: Payment Receipt
amount_paid: Amount paid
transaction: Transaction
transaction_id: Transaction ID
order_id: Order ID
payment_date: Date
paid_by: Paid by
paid_to: Paid to
business: Business
country: Country
payer_id: Payer ID
merchant_id: Merchant ID
breakdown: Breakdown
bcc_recipients: BCC recipients
resend_pending: Re-send pending
always_enforce_signing_order: Always enforce the signing order
@ -1124,6 +1143,24 @@ es: &es
stripe_integration: Integración con Stripe
stripe_account_has_been_connected: La cuenta de Stripe ha sido conectada.
re_connect_stripe: Volver a conectar Stripe
paypal_integration: Integración con PayPal
paypal_account_has_been_connected: La cuenta de PayPal ha sido conectada.
re_connect_paypal: Volver a conectar PayPal
failed_to_connect_paypal: No se pudo conectar PayPal. Por favor, inténtalo de nuevo.
paypal_connect_not_completed: La conexión con PayPal no se completó.
payment_receipt: Recibo de pago
amount_paid: Importe pagado
transaction: Transacción
transaction_id: ID de transacción
order_id: ID de pedido
payment_date: Fecha
paid_by: Pagado por
paid_to: Pagado a
business: Empresa
country: País
payer_id: ID de pagador
merchant_id: ID de comerciante
breakdown: Desglose
private: Privado
_variables: Variables
your_email_address_has_been_released_immediately_you_can_now_be_added_to_your_company_team_without_waiting_for_the_deletion_period_to_end: Su dirección de correo electrónico ha sido liberada inmediatamente. Si se une a un equipo, ahora puede ser invitado al equipo de su empresa sin esperar a que finalice el período de eliminación.
@ -2202,6 +2239,24 @@ it: &it
stripe_integration: Integrazione Stripe
stripe_account_has_been_connected: L'account Stripe è stato collegato.
re_connect_stripe: Ricollega Stripe
paypal_integration: Integrazione PayPal
paypal_account_has_been_connected: L'account PayPal è stato collegato.
re_connect_paypal: Ricollega PayPal
failed_to_connect_paypal: Impossibile collegare PayPal. Riprova.
paypal_connect_not_completed: La connessione con PayPal non è stata completata.
payment_receipt: Ricevuta di pagamento
amount_paid: Importo pagato
transaction: Transazione
transaction_id: ID transazione
order_id: ID ordine
payment_date: Data
paid_by: Pagato da
paid_to: Pagato a
business: Azienda
country: Paese
payer_id: ID pagatore
merchant_id: ID esercente
breakdown: Dettaglio
private: Privato
_variables: Variabili
your_email_address_has_been_released_immediately_you_can_now_be_added_to_your_company_team_without_waiting_for_the_deletion_period_to_end: Il tuo indirizzo email è stato rilasciato immediatamente. Se stai per unirti a un team, ora puoi essere invitato nel team della tua azienda senza aspettare la fine del periodo di eliminazione.
@ -3280,6 +3335,24 @@ fr: &fr
stripe_integration: Intégration Stripe
stripe_account_has_been_connected: Le compte Stripe a été connecté.
re_connect_stripe: Reconnecter Stripe
paypal_integration: Intégration PayPal
paypal_account_has_been_connected: Le compte PayPal a été connecté.
re_connect_paypal: Reconnecter PayPal
failed_to_connect_paypal: Échec de la connexion à PayPal. Veuillez réessayer.
paypal_connect_not_completed: La connexion à PayPal n'a pas été complétée.
payment_receipt: Reçu de paiement
amount_paid: Montant payé
transaction: Transaction
transaction_id: ID de transaction
order_id: ID de commande
payment_date: Date
paid_by: Payé par
paid_to: Payé à
business: Entreprise
country: Pays
payer_id: ID payeur
merchant_id: ID marchand
breakdown: Détail
private: Privé
_variables: Variables
your_email_address_has_been_released_immediately_you_can_now_be_added_to_your_company_team_without_waiting_for_the_deletion_period_to_end: Votre adresse e-mail a été libérée immédiatement. Si vous rejoignez une équipe, vous pouvez maintenant être invité dans l'équipe de votre entreprise sans attendre la fin de la période de suppression.
@ -4355,6 +4428,24 @@ pt: &pt
stripe_integration: Integração com Stripe
stripe_account_has_been_connected: Conta Stripe foi conectada.
re_connect_stripe: Reconectar Stripe
paypal_integration: Integração com PayPal
paypal_account_has_been_connected: Conta PayPal foi conectada.
re_connect_paypal: Reconectar PayPal
failed_to_connect_paypal: Falha ao conectar PayPal. Tente novamente.
paypal_connect_not_completed: A conexão com PayPal não foi concluída.
payment_receipt: Recibo de pagamento
amount_paid: Valor pago
transaction: Transação
transaction_id: ID da transação
order_id: ID do pedido
payment_date: Data
paid_by: Pago por
paid_to: Pago a
business: Empresa
country: País
payer_id: ID do pagador
merchant_id: ID do comerciante
breakdown: Detalhamento
private: Privado
_variables: Variáveis
your_email_address_has_been_released_immediately_you_can_now_be_added_to_your_company_team_without_waiting_for_the_deletion_period_to_end: Seu endereço de e-mail foi liberado imediatamente. Se você estiver entrando em uma equipe, agora pode ser convidado para a equipe da sua empresa sem esperar o fim do período de exclusão.
@ -5443,6 +5534,24 @@ de: &de
require_all_recipients: Alle Empfänger verpflichten
stripe_account_has_been_connected: Stripe-Konto wurde verbunden.
re_connect_stripe: Stripe erneut verbinden
paypal_integration: PayPal-Integration
paypal_account_has_been_connected: PayPal-Konto wurde verbunden.
re_connect_paypal: PayPal erneut verbinden
failed_to_connect_paypal: PayPal konnte nicht verbunden werden. Bitte erneut versuchen.
paypal_connect_not_completed: Die PayPal-Verbindung wurde nicht abgeschlossen.
payment_receipt: Zahlungsbeleg
amount_paid: Gezahlter Betrag
transaction: Transaktion
transaction_id: Transaktions-ID
order_id: Bestell-ID
payment_date: Datum
paid_by: Gezahlt von
paid_to: Gezahlt an
business: Unternehmen
country: Land
payer_id: Zahler-ID
merchant_id: Händler-ID
breakdown: Aufschlüsselung
bcc_recipients: BCC-Empfänger
resend_pending: Ausstehende erneut versenden
always_enforce_signing_order: Reihenfolge der Unterschriften immer erzwingen
@ -6925,6 +7034,24 @@ nl: &nl
require_all_recipients: Alle ontvangers verplichten
stripe_account_has_been_connected: Stripe-account is verbonden.
re_connect_stripe: Stripe opnieuw verbinden
paypal_integration: PayPal-integratie
paypal_account_has_been_connected: PayPal-account is verbonden.
re_connect_paypal: PayPal opnieuw verbinden
failed_to_connect_paypal: PayPal kon niet worden verbonden. Probeer het opnieuw.
paypal_connect_not_completed: De verbinding met PayPal is niet voltooid.
payment_receipt: Betalingsbewijs
amount_paid: Betaald bedrag
transaction: Transactie
transaction_id: Transactie-ID
order_id: Order-ID
payment_date: Datum
paid_by: Betaald door
paid_to: Betaald aan
business: Bedrijf
country: Land
payer_id: Betaler-ID
merchant_id: Verkoper-ID
breakdown: Specificatie
bcc_recipients: BCC-ontvangers
resend_pending: Opnieuw verzenden in behandeling
always_enforce_signing_order: Ondertekenvolgorde altijd afdwingen

Loading…
Cancel
Save