@@ -13,6 +13,17 @@ const client = trolley({
13
13
secret : TROLLEY_SECRET_KEY ,
14
14
} ) ;
15
15
16
+ /**
17
+ * Determines if the provided validation errors indicate an "insufficient funds" error.
18
+ */
19
+ const isInsufficientFundsError = ( {
20
+ validationErrors,
21
+ } : {
22
+ validationErrors : { code : string } [ ] ;
23
+ } ) =>
24
+ validationErrors . length === 1 &&
25
+ validationErrors [ 0 ] . code === 'non_sufficient_funds' ;
26
+
16
27
@Injectable ( )
17
28
export class TrolleyService {
18
29
private readonly logger = new Logger ( `global/TrolleyService` ) ;
@@ -78,24 +89,64 @@ export class TrolleyService {
78
89
return ;
79
90
}
80
91
92
+ const paymentPayload = {
93
+ recipient : {
94
+ id : recipientId ,
95
+ } ,
96
+ sourceAmount : totalAmount . toString ( ) ,
97
+ sourceCurrency : 'USD' ,
98
+ memo : 'Topcoder payment' ,
99
+ // TODO: remove `,${Date.now()}`
100
+ // if externalId is present, it must be unique
101
+ externalId : `${ winningsIds . join ( ',' ) } ,${ Date . now ( ) } ` ,
102
+ } ;
103
+
81
104
try {
82
- const payment = await this . client . payment . create ( paymentBatch . id , {
83
- recipient : {
84
- id : recipientId ,
85
- } ,
86
- sourceAmount : totalAmount . toString ( ) ,
87
- sourceCurrency : 'USD' ,
88
- memo : 'Topcoder payment' ,
89
- // TODO: remove `,${Date.now()}`
90
- // if externalId is present, it must be unique
91
- externalId : `${ winningsIds . join ( ',' ) } ,${ Date . now ( ) } ` ,
92
- } ) ;
105
+ const payment = await this . client . payment . create (
106
+ paymentBatch . id ,
107
+ paymentPayload ,
108
+ ) ;
93
109
94
110
this . logger . debug ( `Created payment with id ${ payment . id } ` ) ;
95
111
96
112
return paymentBatch ;
97
113
} catch ( e ) {
98
- this . logger . error ( `Failed to create payment, error '${ e . message } '!` ) ;
114
+ console . log ( e ) ;
115
+ this . logger . error (
116
+ `Failed to create payment, error '${ e . message } '!` ,
117
+ paymentPayload ,
118
+ e . validationErrors
119
+ ? { validationErrors : e . validationErrors }
120
+ : undefined ,
121
+ ) ;
122
+ }
123
+ }
124
+
125
+ async startProcessingPayment ( paymentBatchId : string ) {
126
+ try {
127
+ // generate quote
128
+ await this . client . batch . generateQuote ( paymentBatchId ) ;
129
+
130
+ // trigger trolley payment (batch) process
131
+ await this . client . batch . startProcessing ( paymentBatchId ) ;
132
+ } catch ( error ) {
133
+ // payments with insufficient funds error are still created in trolley,
134
+ // and they are storred as "pending".
135
+ // no need to do anything. just log a warning, and move on
136
+ if ( isInsufficientFundsError ( error ) ) {
137
+ this . logger . warn (
138
+ `Insufficient funds while processing payment: ${ error . validationErrors } ` ,
139
+ ) ;
140
+ return ;
141
+ }
142
+
143
+ this . logger . error (
144
+ `Failed to process trolley payment batch: ${ error . message } ` ,
145
+ error . validationErrors
146
+ ? { validationErrors : error . validationErrors }
147
+ : undefined ,
148
+ ) ;
149
+ throw new Error ( 'Failed to process trolley payment batch!' ) ;
99
150
}
100
151
}
101
152
}
0 commit comments