@@ -17,12 +17,12 @@ import { subscriptionItemSchema } from './schemas/subscription_item'
17
17
import { subscriptionScheduleSchema } from './schemas/subscription_schedules'
18
18
import { subscriptionSchema } from './schemas/subscription'
19
19
import { StripeSyncConfig , Sync , SyncBackfill , SyncBackfillParams } from './types'
20
+ import { earlyFraudWarningSchema } from './schemas/early_fraud_warning'
20
21
21
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- function getUniqueIds ( entries : any [ ] , key : string ) : string [ ] {
22
+ function getUniqueIds < T > ( entries : T [ ] , key : string ) : string [ ] {
23
23
const set = new Set (
24
24
entries
25
- . map ( ( subscription ) => subscription ?. [ key ] ?. toString ( ) )
25
+ . map ( ( subscription ) => subscription ?. [ key as keyof T ] ?. toString ( ) )
26
26
. filter ( ( it ) : it is string => Boolean ( it ) )
27
27
)
28
28
@@ -367,6 +367,22 @@ export class StripeSync {
367
367
break
368
368
}
369
369
370
+ case 'radar.early_fraud_warning.created' :
371
+ case 'radar.early_fraud_warning.updated' : {
372
+ const earlyFraudWarning = await this . fetchOrUseWebhookData (
373
+ event . data . object as Stripe . Radar . EarlyFraudWarning ,
374
+ ( id ) => this . stripe . radar . earlyFraudWarnings . retrieve ( id )
375
+ )
376
+
377
+ this . config . logger ?. info (
378
+ `Received webhook ${ event . id } : ${ event . type } for earlyFraudWarning ${ earlyFraudWarning . id } `
379
+ )
380
+
381
+ await this . upsertEarlyFraudWarning ( [ earlyFraudWarning ] )
382
+
383
+ break
384
+ }
385
+
370
386
default :
371
387
throw new Error ( 'Unhandled webhook event' )
372
388
}
@@ -420,6 +436,10 @@ export class StripeSync {
420
436
return this . stripe . taxIds . retrieve ( stripeId ) . then ( ( it ) => this . upsertTaxIds ( [ it ] ) )
421
437
} else if ( stripeId . startsWith ( 'cn_' ) ) {
422
438
return this . stripe . creditNotes . retrieve ( stripeId ) . then ( ( it ) => this . upsertCreditNotes ( [ it ] ) )
439
+ } else if ( stripeId . startsWith ( 'issfr_' ) ) {
440
+ return this . stripe . radar . earlyFraudWarnings
441
+ . retrieve ( stripeId )
442
+ . then ( ( it ) => this . upsertEarlyFraudWarning ( [ it ] ) )
423
443
}
424
444
}
425
445
@@ -438,7 +458,8 @@ export class StripeSync {
438
458
paymentIntents ,
439
459
plans ,
440
460
taxIds ,
441
- creditNotes
461
+ creditNotes ,
462
+ earlyFraudWarnings
442
463
443
464
switch ( object ) {
444
465
case 'all' :
@@ -456,6 +477,7 @@ export class StripeSync {
456
477
taxIds = await this . syncTaxIds ( params )
457
478
creditNotes = await this . syncCreditNotes ( params )
458
479
disputes = await this . syncDisputes ( params )
480
+ earlyFraudWarnings = await this . syncEarlyFraudWarnings ( params )
459
481
break
460
482
case 'customer' :
461
483
customers = await this . syncCustomers ( params )
@@ -498,6 +520,9 @@ export class StripeSync {
498
520
case 'credit_note' :
499
521
creditNotes = await this . syncCreditNotes ( params )
500
522
break
523
+ case 'early_fraud_warning' :
524
+ earlyFraudWarnings = await this . syncEarlyFraudWarnings ( params )
525
+ break
501
526
default :
502
527
break
503
528
}
@@ -517,6 +542,7 @@ export class StripeSync {
517
542
plans,
518
543
taxIds,
519
544
creditNotes,
545
+ earlyFraudWarnings,
520
546
}
521
547
}
522
548
@@ -701,6 +727,18 @@ export class StripeSync {
701
727
)
702
728
}
703
729
730
+ async syncEarlyFraudWarnings ( syncParams ?: SyncBackfillParams ) : Promise < Sync > {
731
+ this . config . logger ?. info ( 'Syncing early fraud warnings' )
732
+
733
+ const params : Stripe . Radar . EarlyFraudWarningListParams = { limit : 100 }
734
+ if ( syncParams ?. created ) params . created = syncParams . created
735
+
736
+ return this . fetchAndUpsert (
737
+ ( ) => this . stripe . radar . earlyFraudWarnings . list ( params ) ,
738
+ ( items ) => this . upsertEarlyFraudWarning ( items , syncParams ?. backfillRelatedEntities )
739
+ )
740
+ }
741
+
704
742
async syncCreditNotes ( syncParams ?: SyncBackfillParams ) : Promise < Sync > {
705
743
this . config . logger ?. info ( 'Syncing credit notes' )
706
744
@@ -749,8 +787,6 @@ export class StripeSync {
749
787
] )
750
788
}
751
789
752
- // Stripe only sends the first 10 refunds by default, the option will actively fetch all refunds
753
-
754
790
await this . expandEntity ( charges , 'refunds' , ( id ) =>
755
791
this . stripe . refunds . list ( { charge : id , limit : 100 } )
756
792
)
@@ -766,6 +802,17 @@ export class StripeSync {
766
802
) . then ( ( charges ) => this . upsertCharges ( charges ) )
767
803
}
768
804
805
+ private async backfillPaymentIntents ( paymentIntentIds : string [ ] ) {
806
+ const missingIds = await this . postgresClient . findMissingEntries (
807
+ 'payment_intents' ,
808
+ paymentIntentIds
809
+ )
810
+
811
+ await this . fetchMissingEntities ( missingIds , ( id ) =>
812
+ this . stripe . paymentIntents . retrieve ( id )
813
+ ) . then ( ( paymentIntents ) => this . upsertPaymentIntents ( paymentIntents ) )
814
+ }
815
+
769
816
private async upsertCreditNotes (
770
817
creditNotes : Stripe . CreditNote [ ] ,
771
818
backfillRelatedEntities ?: boolean
@@ -777,14 +824,31 @@ export class StripeSync {
777
824
] )
778
825
}
779
826
780
- // Stripe only sends the first 10 line items by default, the option will actively fetch all line items
781
827
await this . expandEntity ( creditNotes , 'lines' , ( id ) =>
782
828
this . stripe . creditNotes . listLineItems ( id , { limit : 100 } )
783
829
)
784
830
785
831
return this . postgresClient . upsertMany ( creditNotes , 'credit_notes' , creditNoteSchema )
786
832
}
787
833
834
+ private async upsertEarlyFraudWarning (
835
+ earlyFraudWarnings : Stripe . Radar . EarlyFraudWarning [ ] ,
836
+ backfillRelatedEntities ?: boolean
837
+ ) : Promise < Stripe . Radar . EarlyFraudWarning [ ] > {
838
+ if ( backfillRelatedEntities ?? this . config . backfillRelatedEntities ) {
839
+ await Promise . all ( [
840
+ this . backfillPaymentIntents ( getUniqueIds ( earlyFraudWarnings , 'payment_intent' ) ) ,
841
+ this . backfillCharges ( getUniqueIds ( earlyFraudWarnings , 'charge' ) ) ,
842
+ ] )
843
+ }
844
+
845
+ return this . postgresClient . upsertMany (
846
+ earlyFraudWarnings ,
847
+ 'early_fraud_warnings' ,
848
+ earlyFraudWarningSchema
849
+ )
850
+ }
851
+
788
852
async upsertCustomers (
789
853
customers : ( Stripe . Customer | Stripe . DeletedCustomer ) [ ]
790
854
) : Promise < ( Stripe . Customer | Stripe . DeletedCustomer ) [ ] > {
@@ -830,8 +894,6 @@ export class StripeSync {
830
894
] )
831
895
}
832
896
833
- // Stripe only sends the first 10 line items by default, the option will actively fetch all line items
834
-
835
897
await this . expandEntity ( invoices , 'lines' , ( id ) =>
836
898
this . stripe . invoices . listLineItems ( id , { limit : 100 } )
837
899
)
@@ -1022,7 +1084,6 @@ export class StripeSync {
1022
1084
await this . backfillCustomers ( customerIds )
1023
1085
}
1024
1086
1025
- // Stripe only sends the first 10 items by default, the option will actively fetch all items
1026
1087
await this . expandEntity ( subscriptions , 'items' , ( id ) =>
1027
1088
this . stripe . subscriptionItems . list ( { subscription : id , limit : 100 } )
1028
1089
)
@@ -1076,9 +1137,12 @@ export class StripeSync {
1076
1137
) . then ( ( subscriptionSchedules ) => this . upsertSubscriptionSchedules ( subscriptionSchedules ) )
1077
1138
}
1078
1139
1140
+ /**
1141
+ * Stripe only sends the first 10 entries by default, the option will actively fetch all entries.
1142
+ */
1079
1143
private async expandEntity <
1080
1144
K ,
1081
- P extends string ,
1145
+ P extends keyof T ,
1082
1146
T extends { id ?: string } & { [ key in P ] ?: Stripe . ApiList < K > | null } ,
1083
1147
> ( entities : T [ ] , property : P , listFn : ( id : string ) => Stripe . ApiListPromise < K > ) {
1084
1148
if ( ! this . config . autoExpandLists ) return
0 commit comments