release: @marketplaces/payment 0.1.0 (5ffc1b1)
This commit is contained in:
2
dist/.npmignore
vendored
Normal file
2
dist/.npmignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Nested package.json's are only needed for development.
|
||||||
|
**/package.json
|
||||||
210
dist/fesm2022/marketplaces-payment.mjs
vendored
Normal file
210
dist/fesm2022/marketplaces-payment.mjs
vendored
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
import * as i0 from '@angular/core';
|
||||||
|
import { InjectionToken, makeEnvironmentProviders, inject, Injectable, input, booleanAttribute, output, signal, DestroyRef, Component } from '@angular/core';
|
||||||
|
import * as QRCode from 'qrcode';
|
||||||
|
import { catchError, throwError, timer, switchMap } from 'rxjs';
|
||||||
|
import { HttpHeaders, HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||||
|
|
||||||
|
const MARKETPLACES_PAYMENT_CONFIG = new InjectionToken('@marketplaces/payment config');
|
||||||
|
function provideMarketplacesPayment(config) {
|
||||||
|
return makeEnvironmentProviders([{
|
||||||
|
provide: MARKETPLACES_PAYMENT_CONFIG,
|
||||||
|
useValue: {
|
||||||
|
...config,
|
||||||
|
apiUrl: config.apiUrl.replace(/\/$/, ''),
|
||||||
|
paymentsPath: config.paymentsPath ?? '/api/v1/payments',
|
||||||
|
pollIntervalMs: config.pollIntervalMs ?? 1500,
|
||||||
|
},
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const MARKETPLACE_DOMAIN_HEADER = 'X-Marketplace-Domain';
|
||||||
|
function normalizeMarketplaceDomain(domain) {
|
||||||
|
return domain.trim().toLowerCase().replace(/\.$/, '');
|
||||||
|
}
|
||||||
|
class PaymentMarketplaceContext {
|
||||||
|
constructor() {
|
||||||
|
this.config = inject(MARKETPLACES_PAYMENT_CONFIG);
|
||||||
|
}
|
||||||
|
domain() {
|
||||||
|
const configured = this.config.marketplaceDomain;
|
||||||
|
const domain = typeof configured === 'function' ? configured() : configured ?? (typeof location === 'undefined' ? '' : location.hostname);
|
||||||
|
return normalizeMarketplaceDomain(domain);
|
||||||
|
}
|
||||||
|
headers() {
|
||||||
|
const domain = this.domain();
|
||||||
|
if (!domain)
|
||||||
|
throw new Error('Marketplace domain cannot be resolved');
|
||||||
|
return new HttpHeaders({ [MARKETPLACE_DOMAIN_HEADER]: domain });
|
||||||
|
}
|
||||||
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PaymentMarketplaceContext, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
||||||
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PaymentMarketplaceContext, providedIn: 'root' }); }
|
||||||
|
}
|
||||||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: PaymentMarketplaceContext, decorators: [{
|
||||||
|
type: Injectable,
|
||||||
|
args: [{ providedIn: 'root' }]
|
||||||
|
}] });
|
||||||
|
|
||||||
|
const MARKETPLACES_PAYMENT_GATEWAY = new InjectionToken('@marketplaces/payment gateway', { providedIn: 'root', factory: () => inject(HttpMarketplacesPaymentGateway) });
|
||||||
|
class HttpMarketplacesPaymentGateway {
|
||||||
|
constructor() {
|
||||||
|
this.http = inject(HttpClient);
|
||||||
|
this.config = inject(MARKETPLACES_PAYMENT_CONFIG);
|
||||||
|
this.context = inject(PaymentMarketplaceContext);
|
||||||
|
}
|
||||||
|
create(method, request) {
|
||||||
|
return this.http.post(this.baseUrl(), { ...request, method }, { headers: this.context.headers() }).pipe(this.handle(method));
|
||||||
|
}
|
||||||
|
status(paymentId, method) {
|
||||||
|
return this.http.get(`${this.baseUrl()}/${encodeURIComponent(paymentId)}`, { headers: this.context.headers() }).pipe(this.handle(method));
|
||||||
|
}
|
||||||
|
cancel(paymentId) {
|
||||||
|
return this.http.post(`${this.baseUrl()}/${encodeURIComponent(paymentId)}/cancel`, {}, { headers: this.context.headers() });
|
||||||
|
}
|
||||||
|
baseUrl() {
|
||||||
|
const path = this.config.paymentsPath ?? '';
|
||||||
|
return `${this.config.apiUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
||||||
|
}
|
||||||
|
handle(method) {
|
||||||
|
return (source) => source.pipe(catchError(cause => {
|
||||||
|
const response = cause instanceof HttpErrorResponse ? cause : null;
|
||||||
|
const failure = {
|
||||||
|
method, code: response?.status === 402 ? 'declined' : 'backend',
|
||||||
|
message: response?.error?.message || response?.message || 'Payment failed', cause,
|
||||||
|
};
|
||||||
|
return throwError(() => failure);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HttpMarketplacesPaymentGateway, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
||||||
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HttpMarketplacesPaymentGateway, providedIn: 'root' }); }
|
||||||
|
}
|
||||||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HttpMarketplacesPaymentGateway, decorators: [{
|
||||||
|
type: Injectable,
|
||||||
|
args: [{ providedIn: 'root' }]
|
||||||
|
}] });
|
||||||
|
|
||||||
|
class MarketplacesPaymentComponent {
|
||||||
|
constructor() {
|
||||||
|
this.qr = input(false, { ...(ngDevMode ? { debugName: "qr" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
||||||
|
this.card = input(false, { ...(ngDevMode ? { debugName: "card" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
||||||
|
this.sbp = input(false, { ...(ngDevMode ? { debugName: "sbp" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
||||||
|
this.yandexPay = input(false, { ...(ngDevMode ? { debugName: "yandexPay" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
||||||
|
this.request = input.required(/* @ts-ignore */
|
||||||
|
...(ngDevMode ? [{ debugName: "request" }] : /* istanbul ignore next */ []));
|
||||||
|
this.title = input('Оплата', /* @ts-ignore */
|
||||||
|
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
||||||
|
this.completed = output();
|
||||||
|
this.paymentError = output();
|
||||||
|
this.cancelled = output();
|
||||||
|
this.busy = signal(false, /* @ts-ignore */
|
||||||
|
...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
|
||||||
|
this.error = signal(null, /* @ts-ignore */
|
||||||
|
...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
||||||
|
this.attempt = signal(null, /* @ts-ignore */
|
||||||
|
...(ngDevMode ? [{ debugName: "attempt" }] : /* istanbul ignore next */ []));
|
||||||
|
this.qrImage = signal(null, /* @ts-ignore */
|
||||||
|
...(ngDevMode ? [{ debugName: "qrImage" }] : /* istanbul ignore next */ []));
|
||||||
|
this.actionUrl = signal(null, /* @ts-ignore */
|
||||||
|
...(ngDevMode ? [{ debugName: "actionUrl" }] : /* istanbul ignore next */ []));
|
||||||
|
this.gateway = inject(MARKETPLACES_PAYMENT_GATEWAY);
|
||||||
|
this.config = inject(MARKETPLACES_PAYMENT_CONFIG);
|
||||||
|
inject(DestroyRef).onDestroy(() => this.poll?.unsubscribe());
|
||||||
|
}
|
||||||
|
pay(method) {
|
||||||
|
this.poll?.unsubscribe();
|
||||||
|
this.error.set(null);
|
||||||
|
this.busy.set(true);
|
||||||
|
this.qrImage.set(null);
|
||||||
|
this.gateway.create(method, this.request()).subscribe({
|
||||||
|
next: created => void this.handleCreated(created).catch(cause => this.fail(method, cause)),
|
||||||
|
error: cause => this.fail(method, cause),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cancel() {
|
||||||
|
const current = this.attempt();
|
||||||
|
this.poll?.unsubscribe();
|
||||||
|
this.busy.set(false);
|
||||||
|
this.attempt.set(null);
|
||||||
|
if (current)
|
||||||
|
this.gateway.cancel(current.paymentId).subscribe({ error: () => undefined });
|
||||||
|
this.cancelled.emit();
|
||||||
|
}
|
||||||
|
async handleCreated(created) {
|
||||||
|
this.attempt.set(created);
|
||||||
|
if (created.action?.url) {
|
||||||
|
this.actionUrl.set(created.action.url);
|
||||||
|
if (created.action.type === 'qr')
|
||||||
|
this.qrImage.set(await QRCode.toDataURL(created.action.url, { width: 320, margin: 1 }));
|
||||||
|
else if (typeof window !== 'undefined' && !window.open(created.action.url, '_blank', 'noopener')) {
|
||||||
|
this.fail(created.method, { method: created.method, code: 'popup_blocked', message: 'Браузер заблокировал окно оплаты' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (created.status === 'paid' || created.status === 'authorized') {
|
||||||
|
this.finish(created);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (created.status === 'failed' || created.status === 'expired') {
|
||||||
|
this.fail(created.method, created.failureMessage ?? 'Платёж отклонён');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.poll = timer(0, this.config.pollIntervalMs ?? 1500).pipe(switchMap(() => this.gateway.status(created.paymentId, created.method)))
|
||||||
|
.subscribe({ next: status => this.handleStatus(status), error: cause => this.fail(created.method, cause) });
|
||||||
|
}
|
||||||
|
handleStatus(current) {
|
||||||
|
this.attempt.set(current);
|
||||||
|
if (current.status === 'paid' || current.status === 'authorized')
|
||||||
|
this.finish(current);
|
||||||
|
else if (current.status === 'failed' || current.status === 'expired' || current.status === 'cancelled')
|
||||||
|
this.fail(current.method, current.failureMessage ?? 'Платёж не завершён');
|
||||||
|
}
|
||||||
|
finish(attempt) { this.poll?.unsubscribe(); this.busy.set(false); this.attempt.set(null); this.completed.emit(attempt); }
|
||||||
|
fail(method, cause) {
|
||||||
|
this.poll?.unsubscribe();
|
||||||
|
this.busy.set(false);
|
||||||
|
const failure = this.isFailure(cause) ? cause : { method, code: 'backend', message: typeof cause === 'string' ? cause : 'Не удалось провести платёж', cause };
|
||||||
|
this.error.set(failure);
|
||||||
|
this.paymentError.emit(failure);
|
||||||
|
}
|
||||||
|
isFailure(value) { return !!value && typeof value === 'object' && 'code' in value && 'message' in value; }
|
||||||
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MarketplacesPaymentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
||||||
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MarketplacesPaymentComponent, isStandalone: true, selector: "mp-payment, marketplaces-payment", inputs: { qr: { classPropertyName: "qr", publicName: "qr", isSignal: true, isRequired: false, transformFunction: null }, card: { classPropertyName: "card", publicName: "card", isSignal: true, isRequired: false, transformFunction: null }, sbp: { classPropertyName: "sbp", publicName: "sbp", isSignal: true, isRequired: false, transformFunction: null }, yandexPay: { classPropertyName: "yandexPay", publicName: "yandexPay", isSignal: true, isRequired: false, transformFunction: null }, request: { classPropertyName: "request", publicName: "request", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { completed: "completed", paymentError: "paymentError", cancelled: "cancelled" }, ngImport: i0, template: `
|
||||||
|
<section class="mp-payment" aria-labelledby="mp-payment-title">
|
||||||
|
<h2 id="mp-payment-title">{{ title() }}</h2>
|
||||||
|
<div class="methods">
|
||||||
|
@if (qr()) { <button type="button" (click)="pay('qr')" [disabled]="busy()">QR</button> }
|
||||||
|
@if (card()) { <button type="button" (click)="pay('card')" [disabled]="busy()">Карта</button> }
|
||||||
|
@if (sbp()) { <button type="button" (click)="pay('sbp')" [disabled]="busy()">СБП</button> }
|
||||||
|
@if (yandexPay()) { <button type="button" (click)="pay('yandex-pay')" [disabled]="busy()">Яндекс Pay</button> }
|
||||||
|
</div>
|
||||||
|
@if (qrImage()) { <a [href]="actionUrl()!" target="_blank" rel="noopener"><img [src]="qrImage()!" alt="QR-код оплаты" /></a> }
|
||||||
|
@if (busy()) { <p role="status">Проверяем оплату…</p> }
|
||||||
|
@if (error()) { <p class="error" role="alert">{{ error()!.message }}</p> }
|
||||||
|
@if (attempt()) { <button type="button" class="cancel" (click)="cancel()">Отменить</button> }
|
||||||
|
</section>
|
||||||
|
`, isInline: true, styles: [":host{display:block}.mp-payment{font:inherit;color:inherit;display:grid;gap:1rem;max-width:26rem}h2,p{margin:0}.methods{display:flex;gap:.6rem;flex-wrap:wrap}button{font:inherit;cursor:pointer;border:1px solid #111;border-radius:.65rem;padding:.75rem 1rem;background:#111;color:#fff}button:disabled{opacity:.55;cursor:wait}.cancel{background:transparent;color:inherit;border-color:#c7c7c7}img{display:block;width:min(15rem,100%);height:auto}.error{color:#b42318}\n"] }); }
|
||||||
|
}
|
||||||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MarketplacesPaymentComponent, decorators: [{
|
||||||
|
type: Component,
|
||||||
|
args: [{ selector: 'mp-payment, marketplaces-payment', standalone: true, template: `
|
||||||
|
<section class="mp-payment" aria-labelledby="mp-payment-title">
|
||||||
|
<h2 id="mp-payment-title">{{ title() }}</h2>
|
||||||
|
<div class="methods">
|
||||||
|
@if (qr()) { <button type="button" (click)="pay('qr')" [disabled]="busy()">QR</button> }
|
||||||
|
@if (card()) { <button type="button" (click)="pay('card')" [disabled]="busy()">Карта</button> }
|
||||||
|
@if (sbp()) { <button type="button" (click)="pay('sbp')" [disabled]="busy()">СБП</button> }
|
||||||
|
@if (yandexPay()) { <button type="button" (click)="pay('yandex-pay')" [disabled]="busy()">Яндекс Pay</button> }
|
||||||
|
</div>
|
||||||
|
@if (qrImage()) { <a [href]="actionUrl()!" target="_blank" rel="noopener"><img [src]="qrImage()!" alt="QR-код оплаты" /></a> }
|
||||||
|
@if (busy()) { <p role="status">Проверяем оплату…</p> }
|
||||||
|
@if (error()) { <p class="error" role="alert">{{ error()!.message }}</p> }
|
||||||
|
@if (attempt()) { <button type="button" class="cancel" (click)="cancel()">Отменить</button> }
|
||||||
|
</section>
|
||||||
|
`, styles: [":host{display:block}.mp-payment{font:inherit;color:inherit;display:grid;gap:1rem;max-width:26rem}h2,p{margin:0}.methods{display:flex;gap:.6rem;flex-wrap:wrap}button{font:inherit;cursor:pointer;border:1px solid #111;border-radius:.65rem;padding:.75rem 1rem;background:#111;color:#fff}button:disabled{opacity:.55;cursor:wait}.cancel{background:transparent;color:inherit;border-color:#c7c7c7}img{display:block;width:min(15rem,100%);height:auto}.error{color:#b42318}\n"] }]
|
||||||
|
}], ctorParameters: () => [], propDecorators: { qr: [{ type: i0.Input, args: [{ isSignal: true, alias: "qr", required: false }] }], card: [{ type: i0.Input, args: [{ isSignal: true, alias: "card", required: false }] }], sbp: [{ type: i0.Input, args: [{ isSignal: true, alias: "sbp", required: false }] }], yandexPay: [{ type: i0.Input, args: [{ isSignal: true, alias: "yandexPay", required: false }] }], request: [{ type: i0.Input, args: [{ isSignal: true, alias: "request", required: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], completed: [{ type: i0.Output, args: ["completed"] }], paymentError: [{ type: i0.Output, args: ["paymentError"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }] } });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generated bundle index. Do not edit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { HttpMarketplacesPaymentGateway, MARKETPLACES_PAYMENT_CONFIG, MARKETPLACES_PAYMENT_GATEWAY, MARKETPLACE_DOMAIN_HEADER, MarketplacesPaymentComponent, PaymentMarketplaceContext, normalizeMarketplaceDomain, provideMarketplacesPayment };
|
||||||
|
//# sourceMappingURL=marketplaces-payment.mjs.map
|
||||||
1
dist/fesm2022/marketplaces-payment.mjs.map
vendored
Normal file
1
dist/fesm2022/marketplaces-payment.mjs.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/index.d.ts
vendored
1
dist/index.d.ts
vendored
@@ -1 +0,0 @@
|
|||||||
export {};
|
|
||||||
1
dist/index.js
vendored
1
dist/index.js
vendored
@@ -1 +0,0 @@
|
|||||||
export {};
|
|
||||||
34
dist/package.json
vendored
Normal file
34
dist/package.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "@marketplaces/payment",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Standalone Angular payment UI and central payment API client.",
|
||||||
|
"module": "fesm2022/marketplaces-payment.mjs",
|
||||||
|
"typings": "types/marketplaces-payment.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"qrcode": "^1.5.4",
|
||||||
|
"tslib": "^2.8.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/core": ">=22.0.0",
|
||||||
|
"@angular/common": ">=22.0.0",
|
||||||
|
"rxjs": ">=7.8.0"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "restricted"
|
||||||
|
},
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"exports": {
|
||||||
|
"./package.json": {
|
||||||
|
"default": "./package.json"
|
||||||
|
},
|
||||||
|
".": {
|
||||||
|
"types": "./types/marketplaces-payment.d.ts",
|
||||||
|
"default": "./fesm2022/marketplaces-payment.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sideEffects": false,
|
||||||
|
"type": "module"
|
||||||
|
}
|
||||||
104
dist/types/marketplaces-payment.d.ts
vendored
Normal file
104
dist/types/marketplaces-payment.d.ts
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import * as _angular_core from '@angular/core';
|
||||||
|
import { InjectionToken, EnvironmentProviders } from '@angular/core';
|
||||||
|
import { HttpHeaders } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
type PaymentMethod = 'qr' | 'card' | 'sbp' | 'yandex-pay';
|
||||||
|
type PaymentStatus = 'created' | 'pending' | 'authorized' | 'paid' | 'failed' | 'cancelled' | 'expired';
|
||||||
|
/** Central payment API resolves amount/currency/routing from this server checkout id. */
|
||||||
|
interface PaymentRequest {
|
||||||
|
checkoutSessionId: string;
|
||||||
|
returnUrl?: string;
|
||||||
|
metadata?: Readonly<Record<string, string>>;
|
||||||
|
}
|
||||||
|
interface PaymentAttempt {
|
||||||
|
paymentId: string;
|
||||||
|
method: PaymentMethod;
|
||||||
|
status: PaymentStatus;
|
||||||
|
action?: {
|
||||||
|
type: 'redirect' | 'qr';
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
failureMessage?: string;
|
||||||
|
}
|
||||||
|
interface PaymentResult extends PaymentAttempt {
|
||||||
|
status: 'paid' | 'authorized';
|
||||||
|
}
|
||||||
|
interface PaymentFailure {
|
||||||
|
method: PaymentMethod;
|
||||||
|
code: 'configuration' | 'backend' | 'declined' | 'expired' | 'popup_blocked';
|
||||||
|
message: string;
|
||||||
|
cause?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class MarketplacesPaymentComponent {
|
||||||
|
readonly qr: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
||||||
|
readonly card: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
||||||
|
readonly sbp: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
||||||
|
readonly yandexPay: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
||||||
|
readonly request: _angular_core.InputSignal<PaymentRequest>;
|
||||||
|
readonly title: _angular_core.InputSignal<string>;
|
||||||
|
readonly completed: _angular_core.OutputEmitterRef<PaymentResult>;
|
||||||
|
readonly paymentError: _angular_core.OutputEmitterRef<PaymentFailure>;
|
||||||
|
readonly cancelled: _angular_core.OutputEmitterRef<void>;
|
||||||
|
readonly busy: _angular_core.WritableSignal<boolean>;
|
||||||
|
readonly error: _angular_core.WritableSignal<PaymentFailure | null>;
|
||||||
|
readonly attempt: _angular_core.WritableSignal<PaymentAttempt | null>;
|
||||||
|
readonly qrImage: _angular_core.WritableSignal<string | null>;
|
||||||
|
readonly actionUrl: _angular_core.WritableSignal<string | null>;
|
||||||
|
private readonly gateway;
|
||||||
|
private readonly config;
|
||||||
|
private poll?;
|
||||||
|
constructor();
|
||||||
|
pay(method: PaymentMethod): void;
|
||||||
|
cancel(): void;
|
||||||
|
private handleCreated;
|
||||||
|
private handleStatus;
|
||||||
|
private finish;
|
||||||
|
private fail;
|
||||||
|
private isFailure;
|
||||||
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MarketplacesPaymentComponent, never>;
|
||||||
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<MarketplacesPaymentComponent, "mp-payment, marketplaces-payment", never, { "qr": { "alias": "qr"; "required": false; "isSignal": true; }; "card": { "alias": "card"; "required": false; "isSignal": true; }; "sbp": { "alias": "sbp"; "required": false; "isSignal": true; }; "yandexPay": { "alias": "yandexPay"; "required": false; "isSignal": true; }; "request": { "alias": "request"; "required": true; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; }, { "completed": "completed"; "paymentError": "paymentError"; "cancelled": "cancelled"; }, never, never, true, never>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MarketplacesPaymentConfig {
|
||||||
|
/** Central payment service URL. It is not the tenant API URL. */
|
||||||
|
apiUrl: string;
|
||||||
|
marketplaceDomain?: string | (() => string);
|
||||||
|
paymentsPath?: string;
|
||||||
|
pollIntervalMs?: number;
|
||||||
|
}
|
||||||
|
declare const MARKETPLACES_PAYMENT_CONFIG: InjectionToken<MarketplacesPaymentConfig>;
|
||||||
|
declare function provideMarketplacesPayment(config: MarketplacesPaymentConfig): EnvironmentProviders;
|
||||||
|
|
||||||
|
declare const MARKETPLACE_DOMAIN_HEADER = "X-Marketplace-Domain";
|
||||||
|
declare function normalizeMarketplaceDomain(domain: string): string;
|
||||||
|
declare class PaymentMarketplaceContext {
|
||||||
|
private readonly config;
|
||||||
|
domain(): string;
|
||||||
|
headers(): HttpHeaders;
|
||||||
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PaymentMarketplaceContext, never>;
|
||||||
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<PaymentMarketplaceContext>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MarketplacesPaymentGateway {
|
||||||
|
create(method: PaymentMethod, request: PaymentRequest): Observable<PaymentAttempt>;
|
||||||
|
status(paymentId: string, method: PaymentMethod): Observable<PaymentAttempt>;
|
||||||
|
cancel(paymentId: string): Observable<void>;
|
||||||
|
}
|
||||||
|
declare const MARKETPLACES_PAYMENT_GATEWAY: InjectionToken<MarketplacesPaymentGateway>;
|
||||||
|
declare class HttpMarketplacesPaymentGateway implements MarketplacesPaymentGateway {
|
||||||
|
private readonly http;
|
||||||
|
private readonly config;
|
||||||
|
private readonly context;
|
||||||
|
create(method: PaymentMethod, request: PaymentRequest): Observable<PaymentAttempt>;
|
||||||
|
status(paymentId: string, method: PaymentMethod): Observable<PaymentAttempt>;
|
||||||
|
cancel(paymentId: string): Observable<void>;
|
||||||
|
private baseUrl;
|
||||||
|
private handle;
|
||||||
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HttpMarketplacesPaymentGateway, never>;
|
||||||
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<HttpMarketplacesPaymentGateway>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { HttpMarketplacesPaymentGateway, MARKETPLACES_PAYMENT_CONFIG, MARKETPLACES_PAYMENT_GATEWAY, MARKETPLACE_DOMAIN_HEADER, MarketplacesPaymentComponent, PaymentMarketplaceContext, normalizeMarketplaceDomain, provideMarketplacesPayment };
|
||||||
|
export type { MarketplacesPaymentConfig, MarketplacesPaymentGateway, PaymentAttempt, PaymentFailure, PaymentMethod, PaymentRequest, PaymentResult, PaymentStatus };
|
||||||
17
package.json
17
package.json
@@ -1,14 +1,25 @@
|
|||||||
{
|
{
|
||||||
"name": "@marketplaces/payment",
|
"name": "@marketplaces/payment",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "Shared payment/finance client (FX, pricing, checkout gateways) for marketplaces projects. Thin by design — payment business logic stays server-side per the Phase 1/7 backend contracts.",
|
"description": "Standalone Angular payment UI and central payment API client.",
|
||||||
"main": "dist/index.js",
|
"module": "dist/fesm2022/marketplaces-payment.mjs",
|
||||||
"types": "dist/index.d.ts",
|
"typings": "dist/types/marketplaces-payment.d.ts",
|
||||||
"files": ["dist"],
|
"files": ["dist"],
|
||||||
|
"scripts": {
|
||||||
|
"build": "ng-packagr -p ng-package.json -c tsconfig.json",
|
||||||
|
"test": "node --test test/*.test.mjs"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"qrcode": "^1.5.4",
|
||||||
|
"tslib": "^2.8.0"
|
||||||
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@angular/core": ">=22.0.0",
|
"@angular/core": ">=22.0.0",
|
||||||
"@angular/common": ">=22.0.0",
|
"@angular/common": ">=22.0.0",
|
||||||
"rxjs": ">=7.8.0"
|
"rxjs": ">=7.8.0"
|
||||||
},
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "restricted"
|
||||||
|
},
|
||||||
"license": "UNLICENSED"
|
"license": "UNLICENSED"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user