cabloy 5.1.127 → 5.1.129
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cabloy-version +1 -1
- package/CHANGELOG.md +23 -0
- package/cabloy-docs/backend/i18n-guide.md +86 -7
- package/e2e/specs/a-commerce/commerce.spec.ts +93 -8
- package/package.json +1 -1
- package/vona/env/.env +2 -0
- package/vona/env/.env.prod +6 -2
- package/vona/packages-cli/cabloy-cli/package.json +1 -1
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-utils/module-glob/package.json +1 -1
- package/vona/packages-utils/utils/package.json +1 -1
- package/vona/packages-utils/utils/src/vona.ts +8 -1
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/packages-vona/vona-core/package.json +1 -1
- package/vona/packages-vona/vona-mock/package.json +1 -1
- package/vona/pnpm-lock.yaml +142 -21
- package/vona/pnpm-workspace.yaml +1 -1
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/.metadata/index.ts +1 -1
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productSelectResItem.tsx +3 -1
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/dto/productView.tsx +3 -1
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/entity/product.tsx +23 -3
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/model/product.ts +1 -0
- package/vona/src/suite/a-commerce/modules/commerce-catalog/src/service/product.ts +7 -2
- package/vona/src/suite/a-commerce/modules/commerce-catalog/test/productPresentation.test.ts +214 -0
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/bean/payScene.commerceOrder.ts +39 -3
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/commercePayScene.ts +14 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/src/service/paymentAttempt.ts +5 -1
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/.metadata/index.ts +17 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/controller/checkout.ts +18 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutCreate.tsx +3 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutPaymentMethod.tsx +19 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/checkoutPaymentMethods.tsx +17 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +51 -0
- package/vona/src/suite/a-commerce/modules/commerce-trade/test/paymentOutcome.test.ts +2 -1
- package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/.metadata/index.ts +94 -55
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/bean.payScene.ts +65 -1
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/bean/meta.redlock.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/paymentCallback.ts +32 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/controller/paymentSession.ts +26 -8
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentCallback.ts +99 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/paymentSession.ts +26 -3
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/providerOperation.ts +214 -82
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/refundOperation.ts +27 -2
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payScene.ts +9 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/types/payment.ts +5 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/src/bean/payProvider.mock.ts +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/bean/payProvider.paypal.ts +395 -84
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/lib/index.ts +1 -1
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/lib/paypalGateway.ts +129 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/src/types/index.ts +2 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/src/bean/payProvider.stripe.ts +7 -0
- package/vona/src/suite-vendor/a-pay/package.json +5 -5
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/packages-cli/cli/package.json +3 -3
- package/zova/packages-cli/cli-set-front/package.json +4 -4
- package/zova/packages-utils/zova-jsx/package.json +3 -3
- package/zova/packages-utils/zova-vite/package.json +2 -2
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +2 -2
- package/zova/pnpm-lock.yaml +41 -41
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/schemas.ts +8 -0
- package/zova/src/suite/a-commerce/modules/commerce-member/src/api/openapi/types.ts +175 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/cli/openapi.config.ts +1 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/commerceTradeCheckout.ts +16 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/schemas.ts +8 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +177 -2
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/apiSchema/commerceTradeCheckout.ts +12 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/cart.ts +11 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +25 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +27 -4
- package/zova/src/suite-vendor/a-pay/modules/a-pay/cli/openapi.config.ts +1 -1
- package/zova/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/schemas.ts +20 -8
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/openapi/types.ts +292 -32
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/api/paymentSession.ts +26 -4
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/apiSchema/paymentSession.ts +5 -0
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/component/paymentNextAction/controller.tsx +2 -1
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/model/paymentSession.ts +12 -0
- package/zova/src/suite-vendor/a-pay/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +4 -4
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
- /package/vona/patches/{zova-core@5.1.81.patch → zova-core@5.1.82.patch} +0 -0
|
@@ -17,7 +17,7 @@ import type { IEntityOptionsRefundOperation } from '../entity/refundOperation.ts
|
|
|
17
17
|
import type { IEntityOptionsWebhookInbox } from '../entity/webhookInbox.tsx';
|
|
18
18
|
import 'vona-module-a-orm';
|
|
19
19
|
declare module 'vona-module-a-orm' {
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
export interface IEntityRecord {
|
|
22
22
|
'a-pay:outboxEvent': IEntityOptionsOutboxEvent;
|
|
23
23
|
'a-pay:paymentAudit': IEntityOptionsPaymentAudit;
|
|
@@ -27,10 +27,10 @@ declare module 'vona-module-a-orm' {
|
|
|
27
27
|
'a-pay:webhookInbox': IEntityOptionsWebhookInbox;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
}
|
|
32
32
|
declare module 'vona-module-a-pay' {
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
}
|
|
35
35
|
/** entity: end */
|
|
36
36
|
/** entity: begin */
|
|
@@ -73,7 +73,7 @@ declare module 'vona-module-a-orm' {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
declare module 'vona-module-a-pay' {
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
export interface IEntityOptionsOutboxEvent {
|
|
78
78
|
fields?: TypeEntityOptionsFields<EntityOutboxEvent, IEntityOptionsOutboxEvent[TypeSymbolKeyFieldsMore]>;
|
|
79
79
|
}
|
|
@@ -114,7 +114,7 @@ import type { IModelOptionsRefundOperation } from '../model/refundOperation.ts';
|
|
|
114
114
|
import type { IModelOptionsWebhookInbox } from '../model/webhookInbox.ts';
|
|
115
115
|
import 'vona-module-a-orm';
|
|
116
116
|
declare module 'vona-module-a-orm' {
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
export interface IModelRecord {
|
|
119
119
|
'a-pay:outboxEvent': IModelOptionsOutboxEvent;
|
|
120
120
|
'a-pay:paymentAudit': IModelOptionsPaymentAudit;
|
|
@@ -124,10 +124,10 @@ declare module 'vona-module-a-orm' {
|
|
|
124
124
|
'a-pay:webhookInbox': IModelOptionsWebhookInbox;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
}
|
|
129
129
|
declare module 'vona-module-a-pay' {
|
|
130
|
-
|
|
130
|
+
|
|
131
131
|
export interface ModelOutboxEvent {
|
|
132
132
|
/** @internal */
|
|
133
133
|
get scope(): ScopeModuleAPay;
|
|
@@ -192,7 +192,7 @@ declare module 'vona-module-a-pay' {
|
|
|
192
192
|
get $beanFullName(): 'a-pay.model.webhookInbox';
|
|
193
193
|
get $onionName(): 'a-pay:webhookInbox';
|
|
194
194
|
get $onionOptions(): IModelOptionsWebhookInbox;
|
|
195
|
-
}
|
|
195
|
+
}
|
|
196
196
|
}
|
|
197
197
|
/** model: end */
|
|
198
198
|
/** model: begin */
|
|
@@ -229,7 +229,7 @@ declare module 'vona' {
|
|
|
229
229
|
import type { IModelGetOptions, IModelMethodOptions, IModelSelectParams, TypeModelSelectAndCount, TypeModelRelationResult, TypeModelWhere, IModelInsertOptions, TypeModelMutateRelationData, IModelDeleteOptions, IModelUpdateOptions, IModelMutateOptions, IModelSelectCountParams, IModelIncrementParams, IModelSelectAggrParams, TypeModelAggrRelationResult, IModelSelectGroupParams, TypeModelGroupRelationResult } from 'vona-module-a-orm';
|
|
230
230
|
import { SymbolKeyEntity, SymbolKeyEntityMeta, SymbolKeyModelOptions } from 'vona-module-a-orm';
|
|
231
231
|
declare module 'vona-module-a-pay' {
|
|
232
|
-
|
|
232
|
+
|
|
233
233
|
export interface ModelOutboxEvent {
|
|
234
234
|
[SymbolKeyEntity]: EntityOutboxEvent;
|
|
235
235
|
[SymbolKeyEntityMeta]: EntityOutboxEventMeta;
|
|
@@ -470,11 +470,11 @@ export * from '../bean/bean.payScene.ts';
|
|
|
470
470
|
|
|
471
471
|
import 'vona';
|
|
472
472
|
declare module 'vona' {
|
|
473
|
-
|
|
474
|
-
|
|
473
|
+
|
|
474
|
+
|
|
475
475
|
}
|
|
476
476
|
declare module 'vona-module-a-pay' {
|
|
477
|
-
|
|
477
|
+
|
|
478
478
|
export interface BeanPayProvider {
|
|
479
479
|
/** @internal */
|
|
480
480
|
get scope(): ScopeModuleAPay;
|
|
@@ -483,7 +483,7 @@ declare module 'vona-module-a-pay' {
|
|
|
483
483
|
export interface BeanPayScene {
|
|
484
484
|
/** @internal */
|
|
485
485
|
get scope(): ScopeModuleAPay;
|
|
486
|
-
}
|
|
486
|
+
}
|
|
487
487
|
}
|
|
488
488
|
/** bean: end */
|
|
489
489
|
/** bean: begin */
|
|
@@ -499,6 +499,7 @@ declare module 'vona' {
|
|
|
499
499
|
/** bean: end */
|
|
500
500
|
/** service: begin */
|
|
501
501
|
export * from '../service/outbox.ts';
|
|
502
|
+
export * from '../service/paymentCallback.ts';
|
|
502
503
|
export * from '../service/paymentSession.ts';
|
|
503
504
|
export * from '../service/providerOperation.ts';
|
|
504
505
|
export * from '../service/refundOperation.ts';
|
|
@@ -506,19 +507,20 @@ export * from '../service/webhook.ts';
|
|
|
506
507
|
|
|
507
508
|
import 'vona-module-a-bean';
|
|
508
509
|
declare module 'vona-module-a-bean' {
|
|
509
|
-
|
|
510
|
+
|
|
510
511
|
export interface IServiceRecord {
|
|
511
512
|
'a-pay:outbox': never;
|
|
513
|
+
'a-pay:paymentCallback': never;
|
|
512
514
|
'a-pay:paymentSession': never;
|
|
513
515
|
'a-pay:providerOperation': never;
|
|
514
516
|
'a-pay:refundOperation': never;
|
|
515
517
|
'a-pay:webhook': never;
|
|
516
518
|
}
|
|
517
519
|
|
|
518
|
-
|
|
520
|
+
|
|
519
521
|
}
|
|
520
522
|
declare module 'vona-module-a-pay' {
|
|
521
|
-
|
|
523
|
+
|
|
522
524
|
export interface ServiceOutbox {
|
|
523
525
|
/** @internal */
|
|
524
526
|
get scope(): ScopeModuleAPay;
|
|
@@ -527,7 +529,18 @@ declare module 'vona-module-a-pay' {
|
|
|
527
529
|
export interface ServiceOutbox {
|
|
528
530
|
get $beanFullName(): 'a-pay.service.outbox';
|
|
529
531
|
get $onionName(): 'a-pay:outbox';
|
|
530
|
-
|
|
532
|
+
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
export interface ServicePaymentCallback {
|
|
536
|
+
/** @internal */
|
|
537
|
+
get scope(): ScopeModuleAPay;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export interface ServicePaymentCallback {
|
|
541
|
+
get $beanFullName(): 'a-pay.service.paymentCallback';
|
|
542
|
+
get $onionName(): 'a-pay:paymentCallback';
|
|
543
|
+
|
|
531
544
|
}
|
|
532
545
|
|
|
533
546
|
export interface ServicePaymentSession {
|
|
@@ -538,7 +551,7 @@ declare module 'vona-module-a-pay' {
|
|
|
538
551
|
export interface ServicePaymentSession {
|
|
539
552
|
get $beanFullName(): 'a-pay.service.paymentSession';
|
|
540
553
|
get $onionName(): 'a-pay:paymentSession';
|
|
541
|
-
|
|
554
|
+
|
|
542
555
|
}
|
|
543
556
|
|
|
544
557
|
export interface ServiceProviderOperation {
|
|
@@ -549,7 +562,7 @@ declare module 'vona-module-a-pay' {
|
|
|
549
562
|
export interface ServiceProviderOperation {
|
|
550
563
|
get $beanFullName(): 'a-pay.service.providerOperation';
|
|
551
564
|
get $onionName(): 'a-pay:providerOperation';
|
|
552
|
-
|
|
565
|
+
|
|
553
566
|
}
|
|
554
567
|
|
|
555
568
|
export interface ServiceRefundOperation {
|
|
@@ -560,7 +573,7 @@ declare module 'vona-module-a-pay' {
|
|
|
560
573
|
export interface ServiceRefundOperation {
|
|
561
574
|
get $beanFullName(): 'a-pay.service.refundOperation';
|
|
562
575
|
get $onionName(): 'a-pay:refundOperation';
|
|
563
|
-
|
|
576
|
+
|
|
564
577
|
}
|
|
565
578
|
|
|
566
579
|
export interface ServiceWebhook {
|
|
@@ -571,18 +584,20 @@ declare module 'vona-module-a-pay' {
|
|
|
571
584
|
export interface ServiceWebhook {
|
|
572
585
|
get $beanFullName(): 'a-pay.service.webhook';
|
|
573
586
|
get $onionName(): 'a-pay:webhook';
|
|
574
|
-
|
|
575
|
-
}
|
|
587
|
+
|
|
588
|
+
}
|
|
576
589
|
}
|
|
577
590
|
/** service: end */
|
|
578
591
|
/** service: begin */
|
|
579
592
|
import type { ServiceOutbox } from '../service/outbox.ts';
|
|
593
|
+
import type { ServicePaymentCallback } from '../service/paymentCallback.ts';
|
|
580
594
|
import type { ServicePaymentSession } from '../service/paymentSession.ts';
|
|
581
595
|
import type { ServiceProviderOperation } from '../service/providerOperation.ts';
|
|
582
596
|
import type { ServiceRefundOperation } from '../service/refundOperation.ts';
|
|
583
597
|
import type { ServiceWebhook } from '../service/webhook.ts';
|
|
584
598
|
export interface IModuleService {
|
|
585
599
|
'outbox': ServiceOutbox;
|
|
600
|
+
'paymentCallback': ServicePaymentCallback;
|
|
586
601
|
'paymentSession': ServicePaymentSession;
|
|
587
602
|
'providerOperation': ServiceProviderOperation;
|
|
588
603
|
'refundOperation': ServiceRefundOperation;
|
|
@@ -595,6 +610,7 @@ import 'vona';
|
|
|
595
610
|
declare module 'vona' {
|
|
596
611
|
export interface IBeanRecordGeneral {
|
|
597
612
|
'a-pay.service.outbox': ServiceOutbox;
|
|
613
|
+
'a-pay.service.paymentCallback': ServicePaymentCallback;
|
|
598
614
|
'a-pay.service.paymentSession': ServicePaymentSession;
|
|
599
615
|
'a-pay.service.providerOperation': ServiceProviderOperation;
|
|
600
616
|
'a-pay.service.refundOperation': ServiceRefundOperation;
|
|
@@ -609,17 +625,17 @@ export * from '../bean/meta.version.ts';
|
|
|
609
625
|
import type { IMetaOptionsIndex } from 'vona-module-a-index';
|
|
610
626
|
import 'vona-module-a-meta';
|
|
611
627
|
declare module 'vona-module-a-meta' {
|
|
612
|
-
|
|
628
|
+
|
|
613
629
|
export interface IMetaRecord {
|
|
614
630
|
'a-pay:index': IMetaOptionsIndex;
|
|
615
631
|
'a-pay:redlock': never;
|
|
616
632
|
'a-pay:version': never;
|
|
617
633
|
}
|
|
618
634
|
|
|
619
|
-
|
|
635
|
+
|
|
620
636
|
}
|
|
621
637
|
declare module 'vona-module-a-pay' {
|
|
622
|
-
|
|
638
|
+
|
|
623
639
|
export interface MetaIndex {
|
|
624
640
|
/** @internal */
|
|
625
641
|
get scope(): ScopeModuleAPay;
|
|
@@ -639,7 +655,7 @@ declare module 'vona-module-a-pay' {
|
|
|
639
655
|
export interface MetaRedlock {
|
|
640
656
|
get $beanFullName(): 'a-pay.meta.redlock';
|
|
641
657
|
get $onionName(): 'a-pay:redlock';
|
|
642
|
-
|
|
658
|
+
|
|
643
659
|
}
|
|
644
660
|
|
|
645
661
|
export interface MetaVersion {
|
|
@@ -650,8 +666,8 @@ declare module 'vona-module-a-pay' {
|
|
|
650
666
|
export interface MetaVersion {
|
|
651
667
|
get $beanFullName(): 'a-pay.meta.version';
|
|
652
668
|
get $onionName(): 'a-pay:version';
|
|
653
|
-
|
|
654
|
-
}
|
|
669
|
+
|
|
670
|
+
}
|
|
655
671
|
}
|
|
656
672
|
/** meta: end */
|
|
657
673
|
/** meta redlock: begin */
|
|
@@ -662,15 +678,15 @@ export * from '../bean/queue.outboxDispatch.ts';
|
|
|
662
678
|
|
|
663
679
|
import { type IDecoratorQueueOptions } from 'vona-module-a-queue';
|
|
664
680
|
declare module 'vona-module-a-queue' {
|
|
665
|
-
|
|
681
|
+
|
|
666
682
|
export interface IQueueRecord {
|
|
667
683
|
'a-pay:outboxDispatch': IDecoratorQueueOptions;
|
|
668
684
|
}
|
|
669
685
|
|
|
670
|
-
|
|
686
|
+
|
|
671
687
|
}
|
|
672
688
|
declare module 'vona-module-a-pay' {
|
|
673
|
-
|
|
689
|
+
|
|
674
690
|
export interface QueueOutboxDispatch {
|
|
675
691
|
/** @internal */
|
|
676
692
|
get scope(): ScopeModuleAPay;
|
|
@@ -680,7 +696,7 @@ declare module 'vona-module-a-pay' {
|
|
|
680
696
|
get $beanFullName(): 'a-pay.queue.outboxDispatch';
|
|
681
697
|
get $onionName(): 'a-pay:outboxDispatch';
|
|
682
698
|
get $onionOptions(): IDecoratorQueueOptions;
|
|
683
|
-
}
|
|
699
|
+
}
|
|
684
700
|
}
|
|
685
701
|
/** queue: end */
|
|
686
702
|
/** queue: begin */
|
|
@@ -695,16 +711,16 @@ export * from '../bean/schedule.providerOperationDispatch.ts';
|
|
|
695
711
|
|
|
696
712
|
import { type IDecoratorScheduleOptions } from 'vona-module-a-schedule';
|
|
697
713
|
declare module 'vona-module-a-schedule' {
|
|
698
|
-
|
|
714
|
+
|
|
699
715
|
export interface IScheduleRecord {
|
|
700
716
|
'a-pay:outboxDispatch': IDecoratorScheduleOptions;
|
|
701
717
|
'a-pay:providerOperationDispatch': IDecoratorScheduleOptions;
|
|
702
718
|
}
|
|
703
719
|
|
|
704
|
-
|
|
720
|
+
|
|
705
721
|
}
|
|
706
722
|
declare module 'vona-module-a-pay' {
|
|
707
|
-
|
|
723
|
+
|
|
708
724
|
export interface ScheduleOutboxDispatch {
|
|
709
725
|
/** @internal */
|
|
710
726
|
get scope(): ScopeModuleAPay;
|
|
@@ -725,7 +741,7 @@ declare module 'vona-module-a-pay' {
|
|
|
725
741
|
get $beanFullName(): 'a-pay.schedule.providerOperationDispatch';
|
|
726
742
|
get $onionName(): 'a-pay:providerOperationDispatch';
|
|
727
743
|
get $onionOptions(): IDecoratorScheduleOptions;
|
|
728
|
-
}
|
|
744
|
+
}
|
|
729
745
|
}
|
|
730
746
|
/** schedule: end */
|
|
731
747
|
/** dto: begin */
|
|
@@ -737,17 +753,17 @@ import type { IDtoOptionsPaymentSessionView } from '../dto/paymentSessionView.ts
|
|
|
737
753
|
import type { IDtoOptionsWebhookReceipt } from '../dto/webhookReceipt.tsx';
|
|
738
754
|
import 'vona-module-a-web';
|
|
739
755
|
declare module 'vona-module-a-web' {
|
|
740
|
-
|
|
756
|
+
|
|
741
757
|
export interface IDtoRecord {
|
|
742
758
|
'a-pay:paymentSessionStart': IDtoOptionsPaymentSessionStart;
|
|
743
759
|
'a-pay:paymentSessionView': IDtoOptionsPaymentSessionView;
|
|
744
760
|
'a-pay:webhookReceipt': IDtoOptionsWebhookReceipt;
|
|
745
761
|
}
|
|
746
762
|
|
|
747
|
-
|
|
763
|
+
|
|
748
764
|
}
|
|
749
765
|
declare module 'vona-module-a-pay' {
|
|
750
|
-
|
|
766
|
+
|
|
751
767
|
}
|
|
752
768
|
/** dto: end */
|
|
753
769
|
/** dto: begin */
|
|
@@ -755,7 +771,7 @@ import type { DtoPaymentSessionStart } from '../dto/paymentSessionStart.tsx';
|
|
|
755
771
|
import type { DtoPaymentSessionView } from '../dto/paymentSessionView.tsx';
|
|
756
772
|
import type { DtoWebhookReceipt } from '../dto/webhookReceipt.tsx';
|
|
757
773
|
declare module 'vona-module-a-pay' {
|
|
758
|
-
|
|
774
|
+
|
|
759
775
|
export interface IDtoOptionsPaymentSessionStart {
|
|
760
776
|
fields?: TypeEntityOptionsFields<DtoPaymentSessionStart, IDtoOptionsPaymentSessionStart[TypeSymbolKeyFieldsMore]>;
|
|
761
777
|
}
|
|
@@ -770,22 +786,36 @@ declare module 'vona-module-a-pay' {
|
|
|
770
786
|
}
|
|
771
787
|
/** dto: end */
|
|
772
788
|
/** controller: begin */
|
|
789
|
+
export * from '../controller/paymentCallback.ts';
|
|
773
790
|
export * from '../controller/paymentSession.ts';
|
|
774
791
|
export * from '../controller/webhook.ts';
|
|
792
|
+
import type { IControllerOptionsPaymentCallback } from '../controller/paymentCallback.ts';
|
|
775
793
|
import type { IControllerOptionsPaymentSession } from '../controller/paymentSession.ts';
|
|
776
794
|
import type { IControllerOptionsWebhook } from '../controller/webhook.ts';
|
|
777
795
|
import 'vona-module-a-web';
|
|
778
796
|
declare module 'vona-module-a-web' {
|
|
779
|
-
|
|
797
|
+
|
|
780
798
|
export interface IControllerRecord {
|
|
781
|
-
'a-pay:
|
|
799
|
+
'a-pay:paymentCallback': IControllerOptionsPaymentCallback;
|
|
800
|
+
'a-pay:paymentSession': IControllerOptionsPaymentSession;
|
|
782
801
|
'a-pay:webhook': IControllerOptionsWebhook;
|
|
783
802
|
}
|
|
784
803
|
|
|
785
|
-
|
|
804
|
+
|
|
786
805
|
}
|
|
787
806
|
declare module 'vona-module-a-pay' {
|
|
788
|
-
|
|
807
|
+
|
|
808
|
+
export interface ControllerPaymentCallback {
|
|
809
|
+
/** @internal */
|
|
810
|
+
get scope(): ScopeModuleAPay;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
export interface ControllerPaymentCallback {
|
|
814
|
+
get $beanFullName(): 'a-pay.controller.paymentCallback';
|
|
815
|
+
get $onionName(): 'a-pay:paymentCallback';
|
|
816
|
+
get $onionOptions(): IControllerOptionsPaymentCallback;
|
|
817
|
+
}
|
|
818
|
+
|
|
789
819
|
export interface ControllerPaymentSession {
|
|
790
820
|
/** @internal */
|
|
791
821
|
get scope(): ScopeModuleAPay;
|
|
@@ -806,16 +836,22 @@ declare module 'vona-module-a-pay' {
|
|
|
806
836
|
get $beanFullName(): 'a-pay.controller.webhook';
|
|
807
837
|
get $onionName(): 'a-pay:webhook';
|
|
808
838
|
get $onionOptions(): IControllerOptionsWebhook;
|
|
809
|
-
}
|
|
839
|
+
}
|
|
810
840
|
}
|
|
811
841
|
/** controller: end */
|
|
812
842
|
/** controller: begin */
|
|
813
843
|
// @ts-ignore ignore
|
|
844
|
+
import type { ControllerPaymentCallback } from '../controller/paymentCallback.ts';
|
|
845
|
+
// @ts-ignore ignore
|
|
814
846
|
import type { ControllerPaymentSession } from '../controller/paymentSession.ts';
|
|
815
847
|
// @ts-ignore ignore
|
|
816
848
|
import type { ControllerWebhook } from '../controller/webhook.ts';
|
|
817
849
|
declare module 'vona-module-a-pay' {
|
|
818
|
-
|
|
850
|
+
|
|
851
|
+
export interface IControllerOptionsPaymentCallback {
|
|
852
|
+
actions?: TypeControllerOptionsActions<ControllerPaymentCallback>;
|
|
853
|
+
}
|
|
854
|
+
|
|
819
855
|
export interface IControllerOptionsPaymentSession {
|
|
820
856
|
actions?: TypeControllerOptionsActions<ControllerPaymentSession>;
|
|
821
857
|
}
|
|
@@ -825,12 +861,15 @@ declare module 'vona-module-a-pay' {
|
|
|
825
861
|
}
|
|
826
862
|
}
|
|
827
863
|
declare module 'vona-module-a-web' {
|
|
828
|
-
export interface
|
|
829
|
-
'/payment-
|
|
830
|
-
'/pay/
|
|
864
|
+
export interface IApiPathGetRecord{
|
|
865
|
+
'/pay/payment-callback/return': undefined;
|
|
866
|
+
'/pay/payment-callback/cancel': undefined;
|
|
867
|
+
'/pay/payment-session/:id': undefined;
|
|
831
868
|
}
|
|
832
|
-
export interface
|
|
833
|
-
'/payment-session/:id': undefined;
|
|
869
|
+
export interface IApiPathPostRecord{
|
|
870
|
+
'/pay/payment-session/:id/start': undefined;
|
|
871
|
+
'/pay/payment-session/:id/reconcile': undefined;
|
|
872
|
+
'/pay/webhook/:providerName/:clientName': undefined;
|
|
834
873
|
}
|
|
835
874
|
|
|
836
875
|
}
|
|
@@ -861,11 +900,11 @@ declare module 'vona' {
|
|
|
861
900
|
export interface IBeanScopeContainer {
|
|
862
901
|
pay: ScopeModuleAPay;
|
|
863
902
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
903
|
|
|
867
|
-
|
|
868
904
|
|
|
869
|
-
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
|
|
870
909
|
}
|
|
871
910
|
/** scope: end */
|
|
@@ -24,6 +24,24 @@ export class BeanPayScene extends BeanBase {
|
|
|
24
24
|
return onionSlice.beanOptions.options as IDecoratorPaySceneOptions;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
async getAvailableProviderCandidates<N extends keyof IPaySceneRecord>(
|
|
28
|
+
paySceneName: N,
|
|
29
|
+
input: {
|
|
30
|
+
userId: TableIdentity;
|
|
31
|
+
businessReference: string;
|
|
32
|
+
amountMinor: number;
|
|
33
|
+
currency: string;
|
|
34
|
+
providerCandidateKey?: string;
|
|
35
|
+
},
|
|
36
|
+
) {
|
|
37
|
+
const options = this.getOptions(paySceneName);
|
|
38
|
+
return await this._getAvailableProviderCandidates(options, {
|
|
39
|
+
payScene: paySceneName,
|
|
40
|
+
...input,
|
|
41
|
+
providers: this._getProviderCandidates(options),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
27
45
|
async resolveProvider<N extends keyof IPaySceneRecord>(
|
|
28
46
|
paySceneName: N,
|
|
29
47
|
input: {
|
|
@@ -31,10 +49,28 @@ export class BeanPayScene extends BeanBase {
|
|
|
31
49
|
businessReference: string;
|
|
32
50
|
amountMinor: number;
|
|
33
51
|
currency: string;
|
|
52
|
+
providerCandidateKey?: string;
|
|
34
53
|
},
|
|
35
54
|
) {
|
|
36
55
|
const options = this.getOptions(paySceneName);
|
|
37
|
-
const
|
|
56
|
+
const allProviders = this._getProviderCandidates(options);
|
|
57
|
+
if (
|
|
58
|
+
input.providerCandidateKey &&
|
|
59
|
+
!allProviders.some(item => item.key === input.providerCandidateKey)
|
|
60
|
+
) {
|
|
61
|
+
this.app.throw(422, 'payment provider candidate is unavailable');
|
|
62
|
+
}
|
|
63
|
+
const providers = await this._getAvailableProviderCandidates(options, {
|
|
64
|
+
payScene: paySceneName,
|
|
65
|
+
...input,
|
|
66
|
+
providers: allProviders,
|
|
67
|
+
});
|
|
68
|
+
if (
|
|
69
|
+
input.providerCandidateKey &&
|
|
70
|
+
!providers.some(item => item.key === input.providerCandidateKey)
|
|
71
|
+
) {
|
|
72
|
+
this.app.throw(422, 'payment provider candidate is unavailable');
|
|
73
|
+
}
|
|
38
74
|
const candidateKey = await this._resolveProviderCandidateKey(
|
|
39
75
|
paySceneName,
|
|
40
76
|
options,
|
|
@@ -59,6 +95,27 @@ export class BeanPayScene extends BeanBase {
|
|
|
59
95
|
};
|
|
60
96
|
}
|
|
61
97
|
|
|
98
|
+
private async _getAvailableProviderCandidates(
|
|
99
|
+
options: IDecoratorPaySceneOptions,
|
|
100
|
+
input: Omit<
|
|
101
|
+
Parameters<NonNullable<IDecoratorPaySceneOptions['isProviderAvailable']>>[1],
|
|
102
|
+
'candidate'
|
|
103
|
+
>,
|
|
104
|
+
) {
|
|
105
|
+
const providers = input.providers;
|
|
106
|
+
const available = await Promise.all(
|
|
107
|
+
providers.map(async candidate => ({
|
|
108
|
+
candidate,
|
|
109
|
+
available: options.isProviderAvailable
|
|
110
|
+
? await options.isProviderAvailable(this.ctx, { ...input, candidate })
|
|
111
|
+
: true,
|
|
112
|
+
})),
|
|
113
|
+
);
|
|
114
|
+
const result = available.filter(item => item.available).map(item => item.candidate);
|
|
115
|
+
if (!result.length) this.app.throw(409, 'payment scene has no available provider candidates');
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
|
|
62
119
|
private _getProviderCandidates(options: IDecoratorPaySceneOptions) {
|
|
63
120
|
const providers = options.providers;
|
|
64
121
|
if (!providers?.length) this.app.throw(500, 'payment scene has no provider candidates');
|
|
@@ -84,8 +141,15 @@ export class BeanPayScene extends BeanBase {
|
|
|
84
141
|
businessReference: string;
|
|
85
142
|
amountMinor: number;
|
|
86
143
|
currency: string;
|
|
144
|
+
providerCandidateKey?: string;
|
|
87
145
|
},
|
|
88
146
|
) {
|
|
147
|
+
if (input.providerCandidateKey) {
|
|
148
|
+
if (!providers.some(item => item.key === input.providerCandidateKey)) {
|
|
149
|
+
this.app.throw(422, 'payment provider candidate is unavailable');
|
|
150
|
+
}
|
|
151
|
+
return input.providerCandidateKey;
|
|
152
|
+
}
|
|
89
153
|
if (providers.length === 1 && !options.resolveProvider) return providers[0]!.key;
|
|
90
154
|
if (!options.resolveProvider) {
|
|
91
155
|
this.app.throw(500, 'payment scene requires a provider resolver for multiple candidates');
|
|
@@ -3,6 +3,8 @@ import { BeanRedlockBase } from 'vona-module-a-redlock';
|
|
|
3
3
|
|
|
4
4
|
export type TypeRedlockLockResource =
|
|
5
5
|
| `pay.providerOperation.start.${string}`
|
|
6
|
+
| `pay.providerOperation.confirm.${string}`
|
|
7
|
+
| `pay.providerOperation.query.${string}`
|
|
6
8
|
| `pay.webhook.${string}`;
|
|
7
9
|
export type TypeRedlockLockIsolateResource = never;
|
|
8
10
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { IDecoratorControllerOptions } from 'vona-module-a-web';
|
|
2
|
+
|
|
3
|
+
import { BeanBase } from 'vona';
|
|
4
|
+
import { Passport } from 'vona-module-a-user';
|
|
5
|
+
import { Arg, Controller, Web } from 'vona-module-a-web';
|
|
6
|
+
|
|
7
|
+
export interface IControllerOptionsPaymentCallback extends IDecoratorControllerOptions {}
|
|
8
|
+
|
|
9
|
+
@Controller<IControllerOptionsPaymentCallback>('payment-callback')
|
|
10
|
+
export class ControllerPaymentCallback extends BeanBase {
|
|
11
|
+
@Web.get('return')
|
|
12
|
+
@Passport.public()
|
|
13
|
+
async returned(@Arg.query('state') state: string) {
|
|
14
|
+
await this._handle('return', state);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@Web.get('cancel')
|
|
18
|
+
@Passport.public()
|
|
19
|
+
async cancelled(@Arg.query('state') state: string) {
|
|
20
|
+
await this._handle('cancel', state);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private async _handle(purpose: 'return' | 'cancel', token: string) {
|
|
24
|
+
const callback = await this.scope.service.paymentCallback.consume(purpose, token);
|
|
25
|
+
if (purpose === 'return') {
|
|
26
|
+
await this.scope.service.providerOperation.confirm(callback.paymentSessionId);
|
|
27
|
+
} else {
|
|
28
|
+
await this.scope.service.providerOperation.reconcile(callback.paymentSessionId);
|
|
29
|
+
}
|
|
30
|
+
this.ctx.redirect(callback.continuationPath);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -23,14 +23,21 @@ export class ControllerPaymentSession extends BeanBase {
|
|
|
23
23
|
this.app.throw(404, 'payment session not found');
|
|
24
24
|
}
|
|
25
25
|
const started = await this.scope.service.paymentSession.start(session.id);
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
return this._toView(started);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Web.post(':id/reconcile')
|
|
30
|
+
@Api.body(DtoPaymentSessionView)
|
|
31
|
+
async reconcile(
|
|
32
|
+
@Arg.user() user: IUser,
|
|
33
|
+
@Arg.param('id', v.tableIdentity()) id: TableIdentity,
|
|
34
|
+
): Promise<DtoPaymentSessionView> {
|
|
35
|
+
const session = await this.scope.model.paymentSession.getById(id);
|
|
36
|
+
if (!session || String(session.userId) !== String(user.id)) {
|
|
37
|
+
this.app.throw(404, 'payment session not found');
|
|
38
|
+
}
|
|
39
|
+
const reconciled = await this.scope.service.providerOperation.reconcile(session.id);
|
|
40
|
+
return this._toView(reconciled);
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
@Web.get(':id')
|
|
@@ -43,6 +50,17 @@ export class ControllerPaymentSession extends BeanBase {
|
|
|
43
50
|
if (!session || String(session.userId) !== String(user.id)) {
|
|
44
51
|
this.app.throw(404, 'payment session not found');
|
|
45
52
|
}
|
|
53
|
+
return this._toView(session);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private _toView(session: {
|
|
57
|
+
id: TableIdentity;
|
|
58
|
+
state: DtoPaymentSessionView['state'];
|
|
59
|
+
providerName: string;
|
|
60
|
+
nextAction?: DtoPaymentSessionView['nextAction'];
|
|
61
|
+
amountMinor: number;
|
|
62
|
+
currency: string;
|
|
63
|
+
}): DtoPaymentSessionView {
|
|
46
64
|
return {
|
|
47
65
|
id: session.id,
|
|
48
66
|
state: session.state,
|