Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC - Settings tweaks #49

Open
wants to merge 11 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/Resources/app/administration/src/app/acl/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
Shopware.Service('privileges').addPrivilegeMappingEntry({
category: 'permissions',
parent: 'swag_paypal',
key: 'swag_paypal',
roles: {
viewer: {
privileges: [
'sales_channel:read',
'sales_channel_payment_method:read',
'system_config:read',
],
dependencies: [],
},
editor: {
privileges: [
'sales_channel:update',
'sales_channel_payment_method:create',
'sales_channel_payment_method:update',
'system_config:update',
'system_config:create',
'system_config:delete',
],
dependencies: [
'swag_paypal.viewer',
],
},
},
});

Shopware.Service('privileges').addPrivilegeMappingEntry({
category: 'permissions',
parent: null,
key: 'sales_channel',
roles: {
viewer: {
privileges: [
'swag_paypal_pos_sales_channel:read',
'swag_paypal_pos_sales_channel_run:read',
'swag_paypal_pos_sales_channel_run:update',
'swag_paypal_pos_sales_channel_run:create',
'swag_paypal_pos_sales_channel_run_log:read',
'sales_channel_payment_method:read',
],
},
editor: {
privileges: [
'swag_paypal_pos_sales_channel:update',
'swag_paypal_pos_sales_channel_run:delete',
'payment_method:update',
],
},
creator: {
privileges: [
'swag_paypal_pos_sales_channel:create',
'payment_method:create',
'shipping_method:create',
'delivery_time:create',
],
},
deleter: {
privileges: [
'swag_paypal_pos_sales_channel:delete',
],
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import template from './swag-paypal-onboarding-button.html.twig';
import './swag-paypal-onboarding-button.scss';

/**
* @private - The component has a stable public API (props), but expect that implementation details may change.
*/
export default Shopware.Component.wrapComponentConfig({
template,

compatConfig: Shopware.compatConfig,

inject: [
'acl',
'SwagPayPalApiCredentialsService',
],

emits: ['onboarded'],

mixins: [
Shopware.Mixin.getByName('notification'),
],

props: {
type: {
type: String as PropType<'live' | 'sandbox'>,
required: true,
},
variant: {
type: String as PropType<'ghost' | 'link'>,
required: false,
default: 'ghost',
},
disabled: {
type: Boolean,
required: false,
default: false,
},
},

data() {
return {
callbackId: Shopware.Utils.createId(),

isLoading: false,

scriptId: 'paypal-js',
scriptURL: 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js',

live: {
partnerId: 'DYKPBPEAW5JNA',
partnerClientId: 'AR1aQ13lHxH1c6b3CDd8wSY6SWad2Lt5fv5WkNIZg-qChBoGNfHr2kT180otUmvE_xXtwkgahXUBBurW',
sellerNonce: `${Shopware.Utils.createId()}${Shopware.Utils.createId()}`,
},
sandbox: {
partnerId: '45KXQA7PULGAG',
partnerClientId: 'AQ9g8qMYHpE8s028VCq_GO3Roy9pjeqGDjKTkR_sxzX0FtncBb3QUWbFtoQMtdpe2lG9NpnDT419dK8s',
sellerNonce: `${Shopware.Utils.createId()}${Shopware.Utils.createId()}`,
},
commonRequestParams: {
channelId: 'partner',
product: 'ppcp',
secondaryProducts: 'advanced_vaulting,PAYMENT_METHODS',
capabilities: [
'APPLE_PAY',
'GOOGLE_PAY',
'PAY_UPON_INVOICE',
'PAYPAL_WALLET_VAULTING_ADVANCED',
].join(','),
integrationType: 'FO',
features: [
'PAYMENT',
'REFUND',
'READ_SELLER_DISPUTE',
'UPDATE_SELLER_DISPUTE',
'ADVANCED_TRANSACTIONS_SEARCH',
'ACCESS_MERCHANT_INFORMATION',
'TRACKING_SHIPMENT_READWRITE',
'VAULT',
'BILLING_AGREEMENT',
].join(','),
displayMode: 'minibrowser',
partnerLogoUrl: 'https://assets.shopware.com/media/logos/shopware_logo_blue.svg',
},
};
},

computed: {
settingsStore() {
return Shopware.Store.get('swagPayPalSettings');
},

merchantInformationStore() {
return Shopware.Store.get('swagPayPalMerchantInformation');
},

isSandbox() {
return this.type === 'sandbox';
},

suffix() {
return this.isSandbox ? 'Sandbox' : '';
},

returnUrl(): string {
return `${window.location.origin}${window.location.pathname}#${this.$route.path}`;
},

requestParams() {
return this.isSandbox ? this.sandbox : this.live;
},

onboardingUrl() {
const url = new URL('/bizsignup/partner/entry', this.isSandbox ? 'https://www.sandbox.paypal.com' : 'https://www.paypal.com');

url.search = (new URLSearchParams({
...this.commonRequestParams,
...this.requestParams,
returnToPartnerUrl: this.returnUrl,
})).toString();

return url.href;
},

buttonTitle(): string {
if (!this.settingsStore.get(`SwagPayPal.settings.clientSecret${this.suffix}`)) {
return this.$t(`swag-paypal-onboarding-button.${this.type}.title`);
}

if (!this.merchantInformationStore.canPPCP) {
return this.$t(`swag-paypal-onboarding-button.${this.type}.onboardingTitle`);
}

if (this.merchantInformationStore.needsReonboarding) {
return this.$t(`swag-paypal-onboarding-button.${this.type}.restartOnboardingTitle`);
}

return this.$t(`swag-paypal-onboarding-button.${this.type}.changeTitle`);
},

callbackName(): `onboardingCallback${string}` {
return `onboardingCallback${this.callbackId}`;
},

isDisabled() {
return !this.acl.can('swag_paypal.editor') || this.isLoading || this.disabled;
},

classes() {
return {
'is--sandbox': this.isSandbox,
'is--live': !this.isSandbox,
'is--link': this.variant === 'link',
'sw-button': this.variant === 'ghost',
'sw-button--ghost': this.variant === 'ghost',
'sw-button--disabled': this.isDisabled,
};
},
},

mounted() {
if (!this.acl.can('swag_paypal.editor')) {
return;
}

window[this.callbackName] = (authCode, sharedId) => {
this.fetchCredentials(authCode, sharedId);
};

this.loadPayPalScript();
},

beforeUnmount() {
delete window[this.callbackName];
},

methods: {
createScriptElement(): HTMLScriptElement {
const payPalScript = document.createElement('script');
payPalScript.id = this.scriptId;
payPalScript.type = 'text/javascript';
payPalScript.src = this.scriptURL;
payPalScript.async = true;

document.head.appendChild(payPalScript);

return payPalScript;
},

loadPayPalScript() {
const el = document.getElementById(this.scriptId) ?? this.createScriptElement();

if (window.PAYPAL) {
window.PAYPAL.apps.Signup.setup();
} else {
el.addEventListener('load', this.renderPayPalButton.bind(this), false);
}
},

renderPayPalButton() {
// The original render function inside the partner.js is overwritten here.
// The function gets overwritten again, as soon as PayPals signup.js is loaded.
// A loop is created and the render() function is executed until the real render() function is available.
// PayPal does originally nearly the same, but only once and not in a loop.
// If the signup.js is loaded to slow the button is not rendered.
window.PAYPAL!.apps.Signup.render = function proxyPPrender() {
if (window.PAYPAL!.apps.Signup.timeout) {
clearTimeout(window.PAYPAL!.apps.Signup.timeout);
}

window.PAYPAL!.apps.Signup.timeout = setTimeout(window.PAYPAL!.apps.Signup.render, 300);
};

window.PAYPAL!.apps.Signup.render();
},

async fetchCredentials(authCode: string, sharedId: string) {
if (this.isLoading) {
return;
}

const response = await this.SwagPayPalApiCredentialsService.getApiCredentials(
authCode,
sharedId,
this.requestParams.sellerNonce,
this.isSandbox,
).catch(() => {
this.createNotificationError({
message: this.$t('swag-paypal.settingForm.credentials.button.messageFetchedError'),
// @ts-expect-error - wrongly typed as string
duration: 10000,
});

return {} as Record<string, string>;
});

this.setConfig(response.client_id, response.client_secret, response.payer_id);

this.isLoading = false;
},

setConfig(clientId?: string, clientSecret?: string, merchantPayerId?: string) {
this.settingsStore.set(`SwagPayPal.settings.clientId${this.suffix}`, clientId);
this.settingsStore.set(`SwagPayPal.settings.clientSecret${this.suffix}`, clientSecret);
this.settingsStore.set(`SwagPayPal.settings.merchantPayerId${this.suffix}`, merchantPayerId);

// First time onboarding
if (!this.merchantInformationStore.canPPCP) {
this.settingsStore.set('SwagPayPal.settings.sandbox', this.isSandbox);
}

this.$emit('onboarded');
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<a
:href="onboardingUrl"
:disabled="isDisabled"
:class="classes"
class="swag-paypal-onboarding-button"
target="_blank"
:data-paypal-onboard-complete="callbackName"
data-paypal-button="true"
>
<slot>
{{ buttonTitle }}
</slot>
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@import "~scss/variables";

.swag-paypal-onboarding-button {
display: flex;
align-items: center;
gap: 12px;

&.is--link {
font-weight: $font-weight-semi-bold;
font-size: $font-size-xs;
}

// Multiple buttons side by side and visible
&:not([style*="none"]) + & {
margin-left: 12px;
}
}

.isu-minibrowser-component {
z-index: 2000; // above all shopware components (like modals)
}
Loading
Loading